Files
honeyDueKMP/iosApp/CaseraTests/ValidationRulesTests.swift
treyt 0c803af9bc Add 4 new unit test suites for greenfield test plan coverage
Add 87 new tests (384 total) covering ValidationRules/ValidationError,
PasswordResetViewModel navigation and client-side validation, WidgetAction
Codable/Equatable/accessors, parseDate, and ThemeID enum properties.
Updates greenfield CSV for AUTH-012/017/018, NOTIF-006/007, WID-003, THEME-002.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:29:12 -06:00

267 lines
8.5 KiB
Swift

//
// ValidationRulesTests.swift
// CaseraTests
//
// Unit tests for ValidationError and ValidationRules (distinct from ValidationHelpers).
//
import Testing
@testable import Casera
// MARK: - ValidationError errorDescription Tests
struct ValidationErrorTests {
@Test func requiredFieldErrorDescription() {
let error = ValidationError.required(field: "Email")
#expect(error.errorDescription == "Email is required")
}
@Test func invalidEmailErrorDescription() {
let error = ValidationError.invalidEmail
#expect(error.errorDescription == "Please enter a valid email address")
}
@Test func passwordTooShortErrorDescription() {
let error = ValidationError.passwordTooShort(minLength: 8)
#expect(error.errorDescription == "Password must be at least 8 characters")
}
@Test func passwordMismatchErrorDescription() {
let error = ValidationError.passwordMismatch
#expect(error.errorDescription == "Passwords do not match")
}
@Test func passwordMissingLetterErrorDescription() {
let error = ValidationError.passwordMissingLetter
#expect(error.errorDescription == "Password must contain at least one letter")
}
@Test func passwordMissingNumberErrorDescription() {
let error = ValidationError.passwordMissingNumber
#expect(error.errorDescription == "Password must contain at least one number")
}
@Test func invalidCodeErrorDescription() {
let error = ValidationError.invalidCode(expectedLength: 6)
#expect(error.errorDescription == "Code must be 6 digits")
}
@Test func invalidUsernameErrorDescription() {
let error = ValidationError.invalidUsername
#expect(error.errorDescription == "Username can only contain letters, numbers, and underscores")
}
@Test func customMessageErrorDescription() {
let error = ValidationError.custom(message: "Something went wrong")
#expect(error.errorDescription == "Something went wrong")
}
}
// MARK: - Email Validation Tests
struct ValidationRulesEmailTests {
@Test func emptyEmailReturnsRequired() {
let error = ValidationRules.validateEmail("")
#expect(error?.errorDescription == "Email is required")
}
@Test func whitespaceOnlyEmailReturnsRequired() {
let error = ValidationRules.validateEmail(" ")
#expect(error?.errorDescription == "Email is required")
}
@Test func invalidEmailReturnsInvalidEmail() {
let error = ValidationRules.validateEmail("notanemail")
#expect(error?.errorDescription == "Please enter a valid email address")
}
@Test func validEmailReturnsNil() {
let error = ValidationRules.validateEmail("user@example.com")
#expect(error == nil)
}
@Test func isValidEmailReturnsTrueForValid() {
#expect(ValidationRules.isValidEmail("user@example.com"))
}
@Test func isValidEmailReturnsFalseForInvalid() {
#expect(!ValidationRules.isValidEmail("notanemail"))
}
}
// MARK: - Password Validation Tests
struct ValidationRulesPasswordTests {
@Test func emptyPasswordReturnsRequired() {
let error = ValidationRules.validatePassword("")
#expect(error?.errorDescription == "Password is required")
}
@Test func shortPasswordReturnsTooShort() {
let error = ValidationRules.validatePassword("abc")
#expect(error?.errorDescription == "Password must be at least 8 characters")
}
@Test func validPasswordReturnsNil() {
let error = ValidationRules.validatePassword("longpassword")
#expect(error == nil)
}
@Test func exactMinLengthPasswordReturnsNil() {
let error = ValidationRules.validatePassword("12345678")
#expect(error == nil)
}
}
// MARK: - Password Strength Tests
struct ValidationRulesPasswordStrengthTests {
@Test func emptyPasswordReturnsRequired() {
let error = ValidationRules.validatePasswordStrength("")
#expect(error?.errorDescription == "Password is required")
}
@Test func noLetterReturnsMissingLetter() {
let error = ValidationRules.validatePasswordStrength("123456")
#expect(error?.errorDescription == "Password must contain at least one letter")
}
@Test func noNumberReturnsMissingNumber() {
let error = ValidationRules.validatePasswordStrength("abcdef")
#expect(error?.errorDescription == "Password must contain at least one number")
}
@Test func letterAndNumberReturnsNil() {
let error = ValidationRules.validatePasswordStrength("abc123")
#expect(error == nil)
}
@Test func isValidPasswordReturnsTrueForStrong() {
#expect(ValidationRules.isValidPassword("abc123"))
}
@Test func isValidPasswordReturnsFalseForLettersOnly() {
#expect(!ValidationRules.isValidPassword("abcdef"))
}
@Test func isValidPasswordReturnsFalseForNumbersOnly() {
#expect(!ValidationRules.isValidPassword("123456"))
}
}
// MARK: - Password Match Tests
struct ValidationRulesPasswordMatchTests {
@Test func matchingPasswordsReturnsNil() {
let error = ValidationRules.validatePasswordMatch("abc123", "abc123")
#expect(error == nil)
}
@Test func mismatchedPasswordsReturnsMismatch() {
let error = ValidationRules.validatePasswordMatch("abc123", "xyz789")
#expect(error?.errorDescription == "Passwords do not match")
}
@Test func caseSensitiveMismatch() {
let error = ValidationRules.validatePasswordMatch("Password", "password")
#expect(error?.errorDescription == "Passwords do not match")
}
}
// MARK: - Code Validation Tests
struct ValidationRulesCodeTests {
@Test func emptyCodeReturnsRequired() {
let error = ValidationRules.validateCode("")
#expect(error?.errorDescription == "Code is required")
}
@Test func wrongLengthReturnsInvalidCode() {
let error = ValidationRules.validateCode("123")
#expect(error?.errorDescription == "Code must be 6 digits")
}
@Test func nonNumericCodeReturnsInvalidCode() {
let error = ValidationRules.validateCode("abcdef")
#expect(error?.errorDescription == "Code must be 6 digits")
}
@Test func validSixDigitCodeReturnsNil() {
let error = ValidationRules.validateCode("123456")
#expect(error == nil)
}
@Test func customLengthFourDigitCode() {
let error = ValidationRules.validateCode("1234", expectedLength: 4)
#expect(error == nil)
}
@Test func customLengthWrongDigitCount() {
let error = ValidationRules.validateCode("123", expectedLength: 4)
#expect(error?.errorDescription == "Code must be 4 digits")
}
}
// MARK: - Username Validation Tests
struct ValidationRulesUsernameTests {
@Test func emptyUsernameReturnsRequired() {
let error = ValidationRules.validateUsername("")
#expect(error?.errorDescription == "Username is required")
}
@Test func validAlphanumericUsernameReturnsNil() {
let error = ValidationRules.validateUsername("john_doe123")
#expect(error == nil)
}
@Test func usernameWithSpacesReturnsInvalid() {
let error = ValidationRules.validateUsername("john doe")
#expect(error?.errorDescription == "Username can only contain letters, numbers, and underscores")
}
@Test func usernameWithSpecialCharsReturnsInvalid() {
let error = ValidationRules.validateUsername("user@name!")
#expect(error?.errorDescription == "Username can only contain letters, numbers, and underscores")
}
}
// MARK: - Required Field Validation Tests
struct ValidationRulesRequiredTests {
@Test func emptyValueReturnsRequired() {
let error = ValidationRules.validateRequired("", fieldName: "Name")
#expect(error?.errorDescription == "Name is required")
}
@Test func whitespaceOnlyReturnsRequired() {
let error = ValidationRules.validateRequired(" ", fieldName: "Name")
#expect(error?.errorDescription == "Name is required")
}
@Test func nonEmptyReturnsNil() {
let error = ValidationRules.validateRequired("hello", fieldName: "Name")
#expect(error == nil)
}
@Test func isNotEmptyReturnsTrueForNonEmpty() {
#expect(ValidationRules.isNotEmpty("hello"))
}
@Test func isNotEmptyReturnsFalseForEmpty() {
#expect(!ValidationRules.isNotEmpty(""))
}
@Test func isNotEmptyReturnsFalseForWhitespace() {
#expect(!ValidationRules.isNotEmpty(" "))
}
}