Files
honeyDueKMP/iosApp/HoneyDueTests/ValidationHelpersTests.swift
Trey t 1e2adf7660 Rebrand from Casera/MyCrib to honeyDue
Total rebrand across KMM project:
- Kotlin package: com.example.casera -> com.tt.honeyDue (dirs + declarations)
- Gradle: rootProject.name, namespace, applicationId
- Android: manifest, strings.xml (all languages), widget resources
- iOS: pbxproj bundle IDs, Info.plist, entitlements, xcconfig
- iOS directories: Casera/ -> HoneyDue/, CaseraTests/ -> HoneyDueTests/, etc.
- Swift source: all class/struct/enum renames
- Deep links: casera:// -> honeydue://, .casera -> .honeydue
- App icons replaced with honeyDue honeycomb icon
- Domains: casera.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- Database table names preserved

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 06:33:57 -06:00

446 lines
13 KiB
Swift

//
// ValidationHelpersTests.swift
// honeyDueTests
//
// Unit tests for ValidationHelpers, FormValidator, and related types.
//
import Testing
@testable import honeyDue
// MARK: - ValidationResult Tests
struct ValidationResultTests {
@Test func validResultIsValid() {
let result = ValidationResult.valid
#expect(result.isValid)
#expect(result.errorMessage == nil)
}
@Test func invalidResultIsNotValid() {
let result = ValidationResult.invalid("Error")
#expect(!result.isValid)
#expect(result.errorMessage == "Error")
}
}
// MARK: - Email Validation Tests
struct EmailValidationTests {
@Test func validEmailPasses() {
let result = ValidationHelpers.validateEmail("user@example.com")
#expect(result.isValid)
}
@Test func emptyEmailFails() {
let result = ValidationHelpers.validateEmail("")
#expect(!result.isValid)
#expect(result.errorMessage == "Email is required")
}
@Test func whitespaceOnlyEmailFails() {
let result = ValidationHelpers.validateEmail(" ")
#expect(!result.isValid)
#expect(result.errorMessage == "Email is required")
}
@Test func emailWithoutAtSignFails() {
let result = ValidationHelpers.validateEmail("userexample.com")
#expect(!result.isValid)
#expect(result.errorMessage == "Please enter a valid email address")
}
@Test func emailWithoutDomainFails() {
let result = ValidationHelpers.validateEmail("user@")
#expect(!result.isValid)
}
@Test func emailWithSubdomainPasses() {
let result = ValidationHelpers.validateEmail("user@mail.example.com")
#expect(result.isValid)
}
@Test func emailWithPlusAddressingPasses() {
let result = ValidationHelpers.validateEmail("user+tag@example.com")
#expect(result.isValid)
}
@Test func emailWithDotsInLocalPartPasses() {
let result = ValidationHelpers.validateEmail("first.last@example.com")
#expect(result.isValid)
}
}
// MARK: - Password Validation Tests
struct PasswordValidationTests {
@Test func validPasswordPasses() {
let result = ValidationHelpers.validatePassword("StrongPass1")
#expect(result.isValid)
}
@Test func emptyPasswordFails() {
let result = ValidationHelpers.validatePassword("")
#expect(!result.isValid)
#expect(result.errorMessage == "Password is required")
}
@Test func shortPasswordFails() {
let result = ValidationHelpers.validatePassword("short")
#expect(!result.isValid)
#expect(result.errorMessage == "Password must be at least 8 characters")
}
@Test func exactMinLengthPasswordPasses() {
let result = ValidationHelpers.validatePassword("12345678")
#expect(result.isValid)
}
@Test func customMinLengthEnforced() {
let result = ValidationHelpers.validatePassword("1234", minLength: 6)
#expect(!result.isValid)
#expect(result.errorMessage == "Password must be at least 6 characters")
}
@Test func customMinLengthPassesWhenMet() {
let result = ValidationHelpers.validatePassword("123456", minLength: 6)
#expect(result.isValid)
}
}
// MARK: - Password Confirmation Tests
struct PasswordConfirmationTests {
@Test func matchingPasswordsPasses() {
let result = ValidationHelpers.validatePasswordConfirmation("password123", confirmation: "password123")
#expect(result.isValid)
}
@Test func mismatchedPasswordsFails() {
let result = ValidationHelpers.validatePasswordConfirmation("password123", confirmation: "password456")
#expect(!result.isValid)
#expect(result.errorMessage == "Passwords do not match")
}
@Test func emptyConfirmationFails() {
let result = ValidationHelpers.validatePasswordConfirmation("password123", confirmation: "")
#expect(!result.isValid)
}
@Test func caseSensitiveMismatchFails() {
let result = ValidationHelpers.validatePasswordConfirmation("Password", confirmation: "password")
#expect(!result.isValid)
}
}
// MARK: - Name Validation Tests
struct NameValidationTests {
@Test func validNamePasses() {
let result = ValidationHelpers.validateName("John")
#expect(result.isValid)
}
@Test func emptyNameFails() {
let result = ValidationHelpers.validateName("")
#expect(!result.isValid)
#expect(result.errorMessage == "Name is required")
}
@Test func singleCharNameFails() {
let result = ValidationHelpers.validateName("J")
#expect(!result.isValid)
#expect(result.errorMessage == "Name must be at least 2 characters")
}
@Test func twoCharNamePasses() {
let result = ValidationHelpers.validateName("Jo")
#expect(result.isValid)
}
@Test func customFieldNameInError() {
let result = ValidationHelpers.validateName("", fieldName: "Username")
#expect(result.errorMessage == "Username is required")
}
@Test func whitespaceOnlyNameFails() {
let result = ValidationHelpers.validateName(" ")
#expect(!result.isValid)
}
}
// MARK: - Phone Validation Tests
struct PhoneValidationTests {
@Test func validUSPhonePasses() {
let result = ValidationHelpers.validatePhone("(555) 123-4567")
#expect(result.isValid)
}
@Test func emptyPhoneFails() {
let result = ValidationHelpers.validatePhone("")
#expect(!result.isValid)
#expect(result.errorMessage == "Phone number is required")
}
@Test func shortPhoneFails() {
let result = ValidationHelpers.validatePhone("12345")
#expect(!result.isValid)
#expect(result.errorMessage == "Please enter a valid phone number")
}
@Test func phoneWithCountryCodePasses() {
let result = ValidationHelpers.validatePhone("+1 555-123-4567")
#expect(result.isValid)
}
@Test func digitsOnlyPhonePasses() {
let result = ValidationHelpers.validatePhone("5551234567")
#expect(result.isValid)
}
}
// MARK: - Required Field Validation Tests
struct RequiredFieldValidationTests {
@Test func nonEmptyPasses() {
let result = ValidationHelpers.validateRequired("value", fieldName: "Field")
#expect(result.isValid)
}
@Test func emptyFails() {
let result = ValidationHelpers.validateRequired("", fieldName: "Title")
#expect(!result.isValid)
#expect(result.errorMessage == "Title is required")
}
@Test func whitespaceOnlyFails() {
let result = ValidationHelpers.validateRequired(" ", fieldName: "Description")
#expect(!result.isValid)
}
}
// MARK: - Number Validation Tests
struct NumberValidationTests {
@Test func validNumberPasses() {
let result = ValidationHelpers.validateNumber("42.5", fieldName: "Cost")
#expect(result.isValid)
}
@Test func emptyNumberFails() {
let result = ValidationHelpers.validateNumber("", fieldName: "Cost")
#expect(!result.isValid)
#expect(result.errorMessage == "Cost is required")
}
@Test func nonNumericFails() {
let result = ValidationHelpers.validateNumber("abc", fieldName: "Cost")
#expect(!result.isValid)
#expect(result.errorMessage == "Cost must be a valid number")
}
@Test func belowMinFails() {
let result = ValidationHelpers.validateNumber("5", fieldName: "Cost", min: 10)
#expect(!result.isValid)
#expect(result.errorMessage == "Cost must be at least 10.0")
}
@Test func aboveMaxFails() {
let result = ValidationHelpers.validateNumber("100", fieldName: "Cost", max: 50)
#expect(!result.isValid)
#expect(result.errorMessage == "Cost must be at most 50.0")
}
@Test func withinRangePasses() {
let result = ValidationHelpers.validateNumber("25", fieldName: "Cost", min: 10, max: 50)
#expect(result.isValid)
}
@Test func negativeNumberValidated() {
let result = ValidationHelpers.validateNumber("-5", fieldName: "Value", min: 0)
#expect(!result.isValid)
}
}
// MARK: - Integer Validation Tests
struct IntegerValidationTests {
@Test func validIntegerPasses() {
let result = ValidationHelpers.validateInteger("42", fieldName: "Bedrooms")
#expect(result.isValid)
}
@Test func decimalFails() {
let result = ValidationHelpers.validateInteger("3.5", fieldName: "Bedrooms")
#expect(!result.isValid)
#expect(result.errorMessage == "Bedrooms must be a whole number")
}
@Test func belowMinFails() {
let result = ValidationHelpers.validateInteger("0", fieldName: "Bedrooms", min: 1)
#expect(!result.isValid)
}
@Test func aboveMaxFails() {
let result = ValidationHelpers.validateInteger("100", fieldName: "Bedrooms", max: 50)
#expect(!result.isValid)
}
}
// MARK: - Length Validation Tests
struct LengthValidationTests {
@Test func withinLengthPasses() {
let result = ValidationHelpers.validateLength("hello", fieldName: "Title", min: 2, max: 100)
#expect(result.isValid)
}
@Test func tooShortFails() {
let result = ValidationHelpers.validateLength("a", fieldName: "Title", min: 3)
#expect(!result.isValid)
#expect(result.errorMessage == "Title must be at least 3 characters")
}
@Test func tooLongFails() {
let result = ValidationHelpers.validateLength("abcdef", fieldName: "Code", max: 5)
#expect(!result.isValid)
#expect(result.errorMessage == "Code must be at most 5 characters")
}
@Test func emptyWithNoMinPasses() {
let result = ValidationHelpers.validateLength("", fieldName: "Notes")
#expect(result.isValid)
}
}
// MARK: - URL Validation Tests
struct URLValidationTests {
@Test func validURLPasses() {
let result = ValidationHelpers.validateURL("https://example.com")
#expect(result.isValid)
}
@Test func emptyURLFails() {
let result = ValidationHelpers.validateURL("")
#expect(!result.isValid)
#expect(result.errorMessage == "URL is required")
}
@Test func httpURLPasses() {
let result = ValidationHelpers.validateURL("http://example.com/path")
#expect(result.isValid)
}
}
// MARK: - Custom Validation Tests
struct CustomValidationTests {
@Test func passingCustomValidatorPasses() {
let result = ValidationHelpers.validateCustom(
"abc123",
fieldName: "Code",
validator: { $0.count == 6 },
errorMessage: "Code must be exactly 6 characters"
)
#expect(result.isValid)
}
@Test func failingCustomValidatorFails() {
let result = ValidationHelpers.validateCustom(
"abc",
fieldName: "Code",
validator: { $0.count == 6 },
errorMessage: "Code must be exactly 6 characters"
)
#expect(!result.isValid)
#expect(result.errorMessage == "Code must be exactly 6 characters")
}
@Test func emptyValueInCustomValidatorFails() {
let result = ValidationHelpers.validateCustom(
"",
fieldName: "Code",
validator: { _ in true },
errorMessage: "Unused"
)
#expect(!result.isValid)
#expect(result.errorMessage == "Code is required")
}
}
// MARK: - FormValidator Tests
struct FormValidatorTests {
@Test func allValidFieldsPass() {
let validator = FormValidator()
validator.add(fieldName: "email") { ValidationHelpers.validateEmail("user@example.com") }
validator.add(fieldName: "name") { ValidationHelpers.validateName("John") }
let result = validator.validate()
#expect(result.isValid)
#expect(result.errors.isEmpty)
}
@Test func singleInvalidFieldFails() {
let validator = FormValidator()
validator.add(fieldName: "email") { ValidationHelpers.validateEmail("") }
validator.add(fieldName: "name") { ValidationHelpers.validateName("John") }
let result = validator.validate()
#expect(!result.isValid)
#expect(result.errors.count == 1)
#expect(result.errors["email"] != nil)
}
@Test func multipleInvalidFieldsFail() {
let validator = FormValidator()
validator.add(fieldName: "email") { ValidationHelpers.validateEmail("") }
validator.add(fieldName: "password") { ValidationHelpers.validatePassword("") }
let result = validator.validate()
#expect(!result.isValid)
#expect(result.errors.count == 2)
}
@Test func clearRemovesValidations() {
let validator = FormValidator()
validator.add(fieldName: "email") { ValidationHelpers.validateEmail("") }
validator.clear()
let result = validator.validate()
#expect(result.isValid)
}
}
// MARK: - FormValidationResult Tests
struct FormValidationResultTests {
@Test func validResultHasNoErrors() {
let result = FormValidationResult.valid
#expect(result.isValid)
#expect(result.errors.isEmpty)
}
@Test func invalidResultHasErrors() {
let result = FormValidationResult.invalid(["email": "Email is required"])
#expect(!result.isValid)
#expect(result.errors["email"] == "Email is required")
}
}