Add comprehensive iOS unit and UI test suites for greenfield test plan

- Create unit tests: DataLayerTests (27 tests for DATA-001–007), DataManagerExtendedTests
  (20 tests for TASK-005, TASK-012, TCOMP-003, THEME-001, QA-002), plus ValidationHelpers,
  TaskMetrics, StringExtensions, DoubleExtensions, DateUtils, DocumentHelpers, ErrorMessageParser
- Create UI tests: AuthenticationTests, PasswordResetTests, OnboardingTests, TaskIntegration,
  ContractorIntegration, ResidenceIntegration, DocumentIntegration, DataLayer, Stability
- Add UI test framework: AuthenticatedTestCase, ScreenObjects, TestFlows, TestAccountManager,
  TestAccountAPIClient, TestDataCleaner, TestDataSeeder
- Add accessibility identifiers to password reset views for UI test support
- Add greenfield test plan CSVs and update automated column for 27 test IDs
- All 297 unit tests pass across 60 suites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
treyt
2026-02-24 15:37:56 -06:00
parent fe28034f3d
commit fc0e0688eb
34 changed files with 6699 additions and 1 deletions

View File

@@ -0,0 +1,203 @@
//
// StringExtensionsTests.swift
// CaseraTests
//
// Unit tests for String and Optional<String> extensions.
//
import Testing
@testable import Casera
// MARK: - isBlank Tests
struct IsBlankTests {
@Test func emptyStringIsBlank() {
#expect("".isBlank)
}
@Test func whitespaceOnlyIsBlank() {
#expect(" ".isBlank)
}
@Test func nonEmptyIsNotBlank() {
#expect(!"hello".isBlank)
}
@Test func stringWithWhitespacePaddingIsNotBlank() {
#expect(!" hello ".isBlank)
}
}
// MARK: - nilIfBlank Tests
struct NilIfBlankTests {
@Test func emptyReturnsNil() {
#expect("".nilIfBlank == nil)
}
@Test func whitespaceOnlyReturnsNil() {
#expect(" ".nilIfBlank == nil)
}
@Test func nonEmptyReturnsTrimmed() {
#expect(" hello ".nilIfBlank == "hello")
}
@Test func plainStringReturnsSelf() {
#expect("test".nilIfBlank == "test")
}
}
// MARK: - capitalizedFirst Tests
struct CapitalizedFirstTests {
@Test func lowercaseFirstCapitalized() {
#expect("hello".capitalizedFirst == "Hello")
}
@Test func alreadyCapitalizedUnchanged() {
#expect("Hello".capitalizedFirst == "Hello")
}
@Test func allUppercaseOnlyFirstKept() {
#expect("hELLO".capitalizedFirst == "HELLO")
}
@Test func emptyStringReturnsEmpty() {
#expect("".capitalizedFirst == "")
}
@Test func singleCharCapitalized() {
#expect("a".capitalizedFirst == "A")
}
}
// MARK: - truncated Tests
struct TruncatedTests {
@Test func shortStringNotTruncated() {
#expect("hi".truncated(to: 10) == "hi")
}
@Test func longStringTruncatedWithEllipsis() {
#expect("Hello World".truncated(to: 5) == "Hello...")
}
@Test func longStringTruncatedWithoutEllipsis() {
#expect("Hello World".truncated(to: 5, addEllipsis: false) == "Hello")
}
@Test func exactLengthNotTruncated() {
#expect("Hello".truncated(to: 5) == "Hello")
}
}
// MARK: - isValidEmail Tests
struct IsValidEmailTests {
@Test func standardEmailValid() {
#expect("user@example.com".isValidEmail)
}
@Test func emailWithSubdomainValid() {
#expect("user@mail.example.com".isValidEmail)
}
@Test func emailWithPlusValid() {
#expect("user+tag@example.com".isValidEmail)
}
@Test func emailWithDotsValid() {
#expect("first.last@example.com".isValidEmail)
}
@Test func noAtSignInvalid() {
#expect(!"userexample.com".isValidEmail)
}
@Test func noDomainInvalid() {
#expect(!"user@".isValidEmail)
}
@Test func noTLDInvalid() {
#expect(!"user@example".isValidEmail)
}
@Test func emptyStringInvalid() {
#expect(!"".isValidEmail)
}
@Test func numericLocalPartValid() {
#expect("123@example.com".isValidEmail)
}
}
// MARK: - isValidPhone Tests
struct IsValidPhoneTests {
@Test func tenDigitsValid() {
#expect("5551234567".isValidPhone)
}
@Test func formattedUSPhoneValid() {
#expect("(555) 123-4567".isValidPhone)
}
@Test func internationalFormatValid() {
#expect("+1 555-123-4567".isValidPhone)
}
@Test func tooShortInvalid() {
#expect(!"12345".isValidPhone)
}
@Test func lettersInvalid() {
#expect(!"555-ABC-DEFG".isValidPhone)
}
}
// MARK: - Optional String Tests
struct OptionalStringTests {
@Test func nilIsNilOrBlank() {
let s: String? = nil
#expect(s.isNilOrBlank)
}
@Test func emptyIsNilOrBlank() {
let s: String? = ""
#expect(s.isNilOrBlank)
}
@Test func whitespaceIsNilOrBlank() {
let s: String? = " "
#expect(s.isNilOrBlank)
}
@Test func valueIsNotNilOrBlank() {
let s: String? = "hello"
#expect(!s.isNilOrBlank)
}
@Test func nilNilIfBlankReturnsNil() {
let s: String? = nil
#expect(s.nilIfBlank == nil)
}
@Test func blankOptionalNilIfBlankReturnsNil() {
let s: String? = " "
#expect(s.nilIfBlank == nil)
}
@Test func valueOptionalNilIfBlankReturnsTrimmed() {
let s: String? = " hello "
#expect(s.nilIfBlank == "hello")
}
}