Files
honeyDueKMP/iosApp/XCUITEST_DEBUGGING_GUIDE.md
Trey t 74a474007b Add project documentation and test setup guides
Added comprehensive documentation for the KMM project structure, build
commands, and UI testing setup/troubleshooting.

Documentation added:
- CLAUDE.md: Complete KMM project guide for Claude Code with architecture,
  build commands, common tasks, and development patterns
- iosApp/UI_TESTS_*.md: UI testing strategy, implementation guides, summaries
- iosApp/XCUITEST_*.md: XCUITest implementation and debugging guides
- iosApp/TEST_FAILURES_ANALYSIS.md: Analysis of common test failures
- iosApp/ACCESSIBILITY_IDENTIFIERS_FIX.md: Guide for fixing accessibility issues
- iosApp/FIX_TEST_TARGET*.md: Guides for fixing test target configuration
- iosApp/fix_test_target.sh: Script to automate test target setup

The CLAUDE.md serves as the primary documentation for working with this
repository, providing quick access to build commands, architecture overview,
and common development tasks for both iOS and Android platforms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 23:07:14 -06:00

7.3 KiB

XCUITest Debugging Guide

Current Status

Completed:

  • Created comprehensive XCUITest infrastructure (34 tests)
  • Added AccessibilityIdentifiers.swift with centralized identifiers
  • Added accessibility identifiers to critical views (LoginView, RegisterView, MainTabView, Residence views, ProfileView)
  • Updated TestHelpers.swift to use accessibility identifiers
  • Project builds successfully for testing

Issue:

  • ALL tests are failing within ~0.5 seconds
  • Tests fail during setUp() when trying to login
  • The login helper cannot find UI elements by their accessibility identifiers

Root Cause Analysis

The tests fail at this line in TestHelpers.swift:44:

let usernameField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField]
XCTAssertTrue(usernameField.waitForExistence(timeout: 5), "Username field should exist")
// ❌ This assertion fails - field not found

Possible Causes:

  1. Accessibility identifiers not set at runtime - The .accessibilityIdentifier() modifiers might not be working
  2. App not rendering properly in test mode - The app might be crashing or showing a different screen
  3. Timing issue - The login screen might not be fully loaded when the test runs
  4. Kotlin initialization blocking - The TokenStorage/Kotlin framework might be blocking UI rendering

This is the fastest way to diagnose the issue:

  1. Open the project in Xcode:

    cd /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp
    open iosApp.xcodeproj
    
  2. Select the Test target and a simulator:

    • Select "iPhone 17 Pro" simulator from the device dropdown
    • Select the MyCribTests scheme
  3. Use UI Recording to see what elements exist:

    • Open DebugLoginTest.swift
    • Place your cursor in testAppLaunches() method
    • Click the red record button at the bottom of the editor
    • The app will launch in the simulator
    • Tap on UI elements - Xcode will generate code showing the actual identifiers
    • Stop recording and examine the generated code
  4. Check console output:

    • Run testAppLaunches() test (Cmd+U or click diamond icon in gutter)
    • View console output (Cmd+Shift+Y) to see the XCTContext activity logs
    • This will show actual counts of UI elements found
  5. Use Accessibility Inspector:

    • Open Accessibility Inspector (Xcode → Open Developer Tool → Accessibility Inspector)
    • Run the app normally (not in test mode)
    • Inspect the login fields to verify accessibility identifiers are set

Option 2: Add Debug Output to App

Modify LoginView.swift to print when it renders:

var body: some View {
    // ... existing code ...
    .onAppear {
        print("🟢 LoginView appeared")
        print("🔍 Username field identifier: \(AccessibilityIdentifiers.Authentication.usernameField)")
    }
}

Then run tests and check if "LoginView appeared" prints in console.

Option 3: Simplify the Test

The DebugLoginTest.swift is already simplified. Try running it:

cd /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp
xcodebuild test \
  -project iosApp.xcodeproj \
  -scheme iosApp \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  -only-testing:MyCribTests/DebugLoginTest/testAppLaunches

Check if it passes (meaning the app launches and has SOME UI elements).

Known Issues to Check

1. AccessibilityIdentifiers Not in Test Target

Verify that AccessibilityIdentifiers.swift is included in the iosApp target (not MyCribTests):

  • In Xcode, select Helpers/AccessibilityIdentifiers.swift
  • In File Inspector (right panel), check "Target Membership"
  • iosApp should be checked
  • MyCribTests should NOT be checked

2. LoginView Not Using Correct Identifiers

Double-check Login/LoginView.swift:

grep "accessibilityIdentifier" /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Login/LoginView.swift

Should output:

.accessibilityIdentifier(AccessibilityIdentifiers.Authentication.usernameField)
.accessibilityIdentifier(AccessibilityIdentifiers.Authentication.passwordField)
.accessibilityIdentifier(AccessibilityIdentifiers.Authentication.loginButton)

3. App Showing Different Screen in Test Mode

The app might be checking for existing auth token and bypassing login. Check if TokenStorage has a stored token from previous runs:

// In iOSApp.swift init(), add for testing:
#if DEBUG
if ProcessInfo.processInfo.arguments.contains("--uitesting") {
    TokenStorage.shared.clearToken()  // Force logout for tests
}
#endif

4. Kotlin Framework Initialization Blocking

The app initializes TokenStorage in iOSApp.init(). This might be blocking:

init() {
    // This could be blocking UI rendering:
    TokenStorage.shared.initialize(manager: TokenManager())
}

Try moving initialization to background thread or making it async.

Quick Verification Commands

# Check if identifiers are in LoginView
grep -c "accessibilityIdentifier" /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Login/LoginView.swift
# Should output: 6

# Check if AccessibilityIdentifiers exists
ls -la /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Helpers/AccessibilityIdentifiers.swift
# Should show the file

# Run simplified debug test
cd /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp
xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  -only-testing:MyCribTests/DebugLoginTest/testAppLaunches 2>&1 | grep "Test Case"

Expected Output When Working

When tests work properly, you should see:

Test Case '-[MyCribTests.DebugLoginTest testAppLaunches]' started.
Activity 'Found 1 text fields' started
Activity 'Found 1 secure fields' started
Activity 'Found 5 buttons' started
Activity 'Email field exists: true' started
Activity 'Password field exists: true' started
Test Case '-[MyCribTests.DebugLoginTest testAppLaunches]' passed (5.234 seconds).

Currently seeing:

Test Case '-[MyCribTests.DebugLoginTest testAppLaunches]' failed (0.540 seconds)

The ~0.5 second failure suggests the app isn't even launching or is crashing immediately.

Files Modified

  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Helpers/AccessibilityIdentifiers.swift - Created
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Login/LoginView.swift - Added 6 identifiers
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Login/RegisterView.swift - Added 6 identifiers
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/MainTabView.swift - Added 5 tab identifiers
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Residence/* - Added 15+ identifiers
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/iosApp/Profile/ProfileTabView.swift - Added logout identifier
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/MyCribTests/TestHelpers.swift - Updated to use identifiers
  • /Users/treyt/Desktop/code/MyCrib/MyCribKMM/iosApp/MyCribTests/DebugLoginTest.swift - Simplified debug test

Next Action

Open the project in Xcode and use the UI Recording feature. This will immediately show you what identifiers are actually available and why the tests can't find them.