Skip to content

Conversation

@fedemkr
Copy link
Member

@fedemkr fedemkr commented Nov 14, 2025

🎟️ Tracking

PM-27049

📔 Objective

Build a new Test Harness app to act as a playground to fire Bitwarden flows externally like Autofill or opening URLs.

📸 Screenshots

Scenarios

Scenarios View

Simple Login Form

Simple Login Form

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@github-actions
Copy link
Contributor

github-actions bot commented Nov 14, 2025

Logo
Checkmarx One – Scan Summary & Detailsa66bbb62-88d2-4835-83a0-417e26bc4f66

Great job! No new security vulnerabilities introduced in this pull request

@codecov
Copy link

codecov bot commented Nov 17, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.39%. Comparing base (fc2dafc) to head (3c93758).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2142   +/-   ##
=======================================
  Coverage   85.38%   85.39%           
=======================================
  Files        1726     1726           
  Lines      145626   145626           
=======================================
+ Hits       124350   124352    +2     
+ Misses      21276    21274    -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 4 to 5
BASE_BUNDLE_ID = $(ORGANIZATION_IDENTIFIER).testharness
SHARED_APP_GROUP_IDENTIFIER = group.${ORGANIZATION_IDENTIFIER}.test-harness
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Do we want these suffixes to mach? testharness vs test-harness?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Indeed I'll fix that.

Comment on lines 6 to 10
/// The username field was updated.
case usernameChanged(String)

/// The password field was updated.
case passwordChanged(String)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ Does Claude know about our convention for alphabetizing cases, properties, functions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, although sometimes it makes mistakes dunno why as it should be following the contributor's code styles https://contributing.bitwarden.com/contributing/code-style/swift#alphabetization.
I'll fix that.

@fedemkr fedemkr marked this pull request as ready for review November 20, 2025 16:12
@fedemkr fedemkr requested a review from a team as a code owner November 20, 2025 16:12
@claude
Copy link

claude bot commented Nov 20, 2025

Claude finished @fedemkr's task —— View job


Code Review Complete

Summary of Changes Since Last Review

This PR introduces an initial Test Harness app for the Bitwarden iOS project. The app serves as a playground to test Bitwarden flows externally (Autofill, URL opening, etc.). The implementation follows Bitwarden's established architectural patterns with coordinator-based navigation, processor/state/action/effect patterns, and proper dependency injection via ServiceContainer.

Recent commits addressed previous feedback including:

  • Refactoring scenarios to use an array-based configuration
  • Localizing the Test Harness app
  • Adding .gitignore files for Sourcery-generated content
  • Removing ignored files

Critical Issues

Finding 5: Insufficient test coverage (28.57% patch coverage)

The Codecov report shows only 28.57% patch coverage with 15 lines missing coverage. Per Bitwarden's testing guidelines (Testing.md), processors, services, and coordinators should have 80-100% test coverage.

Missing tests:

  • ScenarioPickerProcessor - No tests for scenario selection logic (TestHarnessShared/UI/Platform/Root/ScenarioPicker/ScenarioPickerProcessor.swift:1-40)
  • SimpleLoginFormProcessor - No tests for form field updates (TestHarnessShared/UI/Autofill/SimpleLoginForm/SimpleLoginFormProcessor.swift:1-42)
  • RootCoordinator - No tests for navigation logic (TestHarnessShared/UI/Platform/Root/RootCoordinator.swift:1-75)
  • AppCoordinator - No tests for event handling and root navigation (TestHarnessShared/UI/Platform/Application/AppCoordinator.swift:1-101)
  • Views - No ViewInspector or snapshot tests for SimpleLoginFormView or ScenarioPickerView

Action Required: Add comprehensive test coverage following the patterns in Testing.md before merge.

Example test structure needed

For ScenarioPickerProcessor:

class ScenarioPickerProcessorTests: BitwardenTestCase {
    var subject: ScenarioPickerProcessor!
    var coordinator: MockCoordinator<RootRoute, Void>!
    
    override func setUp() {
        super.setUp()
        coordinator = MockCoordinator()
        subject = ScenarioPickerProcessor(coordinator: coordinator.asAnyCoordinator())
    }
    
    func test_receive_scenarioTapped_withRoute_navigates() {
        let scenario = ScenarioItem(id: "test", title: "Test", route: .simpleLoginForm)
        subject.receive(.scenarioTapped(scenario))
        XCTAssertEqual(coordinator.routes.last, .simpleLoginForm)
    }
    
    func test_receive_scenarioTapped_withoutRoute_doesNotNavigate() {
        let scenario = ScenarioItem(id: "test", title: "Test", route: nil)
        subject.receive(.scenarioTapped(scenario))
        XCTAssertTrue(coordinator.routes.isEmpty)
    }
}

Minor Findings

⚠️ Finding 1: TestingAppDelegate.swift file location (TestHarness/Application/TestHelpers/Support/TestingAppDelegate.swift:24)

File is in TestHelpers/Support/ subdirectory. While the project-bwth.yml correctly excludes **/TestHelpers/*, having this extra Support subdirectory adds unnecessary nesting. Consider moving to TestHarness/Application/TestHelpers/TestingAppDelegate.swift for clearer organization.

💭 Finding 2: Naming consistency question (Configs/Common-bwth.xcconfig:4)

Bundle ID uses testharness (no hyphen) while PR branch uses test-harness-app. @matt-livefront previously flagged this. If testharness is the intentional final choice, this is acceptable, but please confirm this decision has been made.

📝 Finding 4: Incomplete DocC documentation (TestHarnessShared/Core/Platform/ServiceContainer.swift:20)

Parameter documentation for errorReportBuilder is cut off mid-sentence: "A helper for building an error report containing the details of an" - needs completion.

♻️ Finding 6: Missing mock generation setup

While TestHarnessShared/Sourcery/sourcery.yml is configured, no protocols are marked with // sourcery: AutoMockable. This is acceptable for the initial implementation, but as the app grows, consider marking protocols like StateService for mock generation to support comprehensive testing.


Suggested Improvements

🎨 Consider adding snapshot tests for views

Per Testing.md requirements, all user-facing views should have snapshot tests covering:

  • Light mode
  • Dark mode
  • Large dynamic type (accessibility)

This would catch visual regressions as the Test Harness evolves.

🎨 Consider extracting scenario configuration

Currently scenarios are defined inline in ScenarioPickerState.swift:27-31. As more scenarios are added, consider extracting this to a dedicated configuration file or factory for easier maintenance.


Good Practices Observed

  • ✅ Proper architectural patterns (Coordinator + Processor + State)
  • ✅ Comprehensive DocC documentation on most types
  • ✅ Correct dependency injection via ServiceContainer
  • ✅ Proper .gitignore for generated files
  • ✅ Following established project structure and naming conventions
  • ✅ Proper use of unidirectional data flow pattern
  • ✅ Clear separation between app targets (TestHarness, TestHarnessShared)

Previous Review Comments Status

RESOLVED: @matt-livefront's comment about alphabetization - SimpleLoginFormAction cases are correctly alphabetized (passwordChanged before usernameChanged)

PENDING: @matt-livefront's comment about naming consistency (testharness vs test-harness) - needs clarification

ADDRESSED: @matt-livefront's comment about TestingAppDelegate.swift location - while excluded from target, still in nested Support subdirectory (minor organizational issue)

ADDRESSED: @matt-livefront's comment about generated Localizations.swift - .gitignore added but generated file doesn't exist yet (will be created on first build)


Action Items for Author

  1. CRITICAL: Add unit tests for all processors (ScenarioPickerProcessor, SimpleLoginFormProcessor, AppProcessor edge cases)
  2. CRITICAL: Add coordinator tests (RootCoordinator, AppCoordinator)
  3. RECOMMENDED: Add ViewInspector tests for user interactions
  4. RECOMMENDED: Add snapshot tests for views (light/dark/accessibility)
  5. MINOR: Complete DocC documentation for ServiceContainer init parameter
  6. MINOR: Clarify naming decision (testharness vs test-harness)

Security Considerations

✅ No security concerns identified for this test harness app:

  • No sensitive data handling
  • No keychain operations
  • No network requests
  • Not intended for production/App Store distribution
  • Follows zero-knowledge architecture patterns where applicable

Compilation & Build Verification

⚠️ Unable to verify compilation without running build. However, based on code review:

  • All imports appear correct
  • Type usage is consistent
  • No obvious compilation issues detected
  • SwiftLint and SwiftFormat configured in project-bwth.yml

Recommendation: Ensure CI builds pass before merge.


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ I think this should be in a TestHelpers folder otherwise it's going to be included in the app itself.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ I think we added this to a .gitignore in other targets.

) -> Bool {
true
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Finding 1: File location violates test organization standards

This file should be in a TestHelpers folder that's properly excluded from the main app target. Currently, it's at TestHarness/Application/TestHelpers/Support/TestingAppDelegate.swift, which suggests it will be included in the main app bundle.

Per the Testing.md guidelines, test helper files should be properly organized and excluded from the main app. The project-bwth.yml correctly excludes **/TestHelpers/* from the TestHarness target sources, but having this file in TestHelpers/Support/ may cause confusion.

Recommendation: Move this file to TestHarness/Application/TestHelpers/TestingAppDelegate.swift (remove the Support subdirectory) for clearer organization, or ensure the exclusion pattern is working as expected.

CODE_SIGN_STYLE = Automatic
DEVELOPMENT_TEAM = LTZ2PFU5D6
ORGANIZATION_IDENTIFIER = com.bitwarden
BASE_BUNDLE_ID = $(ORGANIZATION_IDENTIFIER).testharness
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Finding 2: Naming inconsistency between bundle ID and shared app group

The bundle ID uses testharness (no hyphen) while the comment from @matt-livefront previously noted this inconsistency. The shared app group also uses testharness.

For consistency with the PR branch name (test-harness-app) and typical naming conventions, consider whether test-harness would be more appropriate. However, if testharness is the intentional choice, this is acceptable.

Note: This was previously flagged by @matt-livefront. Has this been addressed or is testharness the final decision?


/// The username field was updated.
case usernameChanged(String)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Finding 3: Action cases not alphabetized

Per the Swift Code Style Guidelines, enum cases should be alphabetized. Currently:

  • passwordChanged (line 7)
  • usernameChanged (line 10)

Should be:

Suggested change
}
/// Actions that can be processed by a `SimpleLoginFormProcessor`.
///
enum SimpleLoginFormAction: Equatable {
/// The password field was updated.
case passwordChanged(String)
/// The username field was updated.
case usernameChanged(String)
}

Wait - they ARE already alphabetized (p before u). This appears to be correct.

Correction: After review, these cases are properly alphabetized. The previous review comment may have been about a different file or has since been fixed.

/// Initialize a `ServiceContainer`.
///
/// - Parameters:
/// - errorReportBuilder: A helper for building an error report containing the details of an
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Finding 4: Incomplete DocC documentation

The DocC comment for the init method is incomplete. The parameter description cuts off mid-sentence:

///   - errorReportBuilder: A helper for building an error report containing the details of an

Should be completed to something like:

Suggested change
/// - errorReportBuilder: A helper for building an error report containing the details of an
/// Initialize a `ServiceContainer`.
///
/// - Parameters:
/// - errorReportBuilder: A helper for building an error report containing the details of an error that occurred.
public init(

@github-actions
Copy link
Contributor

Warning

@fedemkr Uploading code coverage report failed. Please check the "Upload to codecov.io" step of Process Test Reports job for more details.

@fedemkr fedemkr merged commit 2046d8a into main Nov 21, 2025
34 of 42 checks passed
@fedemkr fedemkr deleted the PM-27049/test-harness-app branch November 21, 2025 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants