Skip to content

Comments

feat: add e2e support#6

Merged
sirily11 merged 1 commit intomainfrom
e2e
Feb 11, 2026
Merged

feat: add e2e support#6
sirily11 merged 1 commit intomainfrom
e2e

Conversation

@sirily11
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings February 11, 2026 10:22
@autopilot-project-manager autopilot-project-manager bot added the enhancement New feature or request label Feb 11, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a macOS “test” host app plus XCUITest UI automation to exercise the RxAuthSwift sign-in flow end-to-end, and wires it into CI.

Changes:

  • Introduces a test/ Xcode project containing a SwiftUI app (test) and a UI test target (testUITests) with helpers for app launch, dotenv loading, and sign-in automation.
  • Updates RxAuthSwift/RxAuthSwiftUI to better support E2E automation (new in-memory token storage, UI accessibility identifier change, macOS web auth window URL display).
  • Adds a new CI job intended to execute the Xcode test plan on macOS.

Reviewed changes

Copilot reviewed 19 out of 21 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/testUITests/testUITests.swift Adds a basic UI test that launches the app and performs sign-in.
test/testUITests/helper/signIn.swift Implements the UI automation flow for OAuth sign-in using dotenv/env credentials.
test/testUITests/helper/launch.swift Launch helper that passes --reset-auth for deterministic E2E runs.
test/testUITests/helper/dotenv.swift Adds a lightweight .env loader with CI environment fallback.
test/test/testApp.swift Adds a macOS SwiftUI host app configured to reset auth and optionally use in-memory token storage.
test/test/ContentView.swift Adds a minimal UI that renders RxAuthSwiftUI sign-in and an authenticated “home” state.
test/test/Assets.xcassets/** Adds default app assets required by Xcode app target.
test/test.xcodeproj/** Adds Xcode project, schemes, SwiftPM resolved file, and workspace metadata for the test app and UI tests.
test/TestPlan.xctestplan Adds an Xcode test plan targeting the UI tests.
Sources/RxAuthSwiftUI/RxSignInView.swift Minor import ordering change.
Sources/RxAuthSwiftUI/Components/PrimaryAuthButton.swift Changes the sign-in button accessibility identifier for UI testing.
Sources/RxAuthSwift/Platform/MacOSWebAuthSession.swift Adds a URL display field above the WKWebView and updates it during navigation.
Sources/RxAuthSwift/InMemoryTokenStorage.swift Adds an in-memory token storage for test/ephemeral sessions.
.gitignore Ignores .env, .netrc, and common Xcode/SwiftPM generated files.
.github/workflows/ci.yml Adds a self-hosted macOS job to run the TestPlan via xcodebuild.
Files not reviewed (1)
  • test/test.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +50 to +61
// Use a longer timeout and provide better error message
let emailFieldExists = emailField.waitForExistence(timeout: 30)
NSLog("✅ Email field found, entering credentials...")
logger.info("✅ Email field found, entering credentials...")

// Fill in credentials from environment
// WebView elements need extra handling for keyboard focus in CI
emailField.tap()
sleep(1) // Give WebView time to establish keyboard focus
// Type the email
emailField.typeText(testEmail)
NSLog("✅ Email entered")
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

In the iOS flow, emailFieldExists is computed but never asserted/used, and the code proceeds to tap/type into the email field regardless. If the OAuth page doesn’t load, this will fail with a less-informative element interaction error; assert emailFieldExists (and similarly for passwordField) before interacting.

Copilot uses AI. Check for mistakes.
let emailFieldExists = emailField.waitForExistence(timeout: 30)
XCTAssertTrue(emailFieldExists, "Failed to sign in and reach dashboard")

let passwordField = self/*@START_MENU_TOKEN@*/ .secureTextFields["Enter your password"].firstMatch/*[[".groups",".secureTextFields[\"Password\"].firstMatch",".secureTextFields[\"Enter your password\"].firstMatch",".secureTextFields",".containing(.group, identifier: nil).firstMatch",".firstMatch"],[[[-1,2],[-1,1],[-1,3,2],[-1,0,1]],[[-1,2],[-1,1]],[[-1,5],[-1,4]]],[0]]@END_MENU_TOKEN@*/
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The macOS passwordField locator still contains an Xcode recorder @START_MENU_TOKEN@...@END_MENU_TOKEN@ artifact and unusual spacing (self/*...*/ .secureTextFields...). This is hard to maintain and can break easily; replace it with a stable query (preferably using accessibility identifiers) and remove the recorder token markup.

Suggested change
let passwordField = self/*@START_MENU_TOKEN@*/ .secureTextFields["Enter your password"].firstMatch/*[[".groups",".secureTextFields[\"Password\"].firstMatch",".secureTextFields[\"Enter your password\"].firstMatch",".secureTextFields",".containing(.group, identifier: nil).firstMatch",".firstMatch"],[[[-1,2],[-1,1],[-1,3,2],[-1,0,1]],[[-1,2],[-1,1]],[[-1,5],[-1,4]]],[0]]@END_MENU_TOKEN@*/
let passwordField = secureTextFields["Enter your password"].firstMatch

Copilot uses AI. Check for mistakes.
.foregroundStyle(.green)

Text("Welcome!")
.accessibilityLabel("home-view-title")
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The UI test waits for staticTexts["home-view-title"], but the view sets this as an accessibilityLabel, not an accessibilityIdentifier. This can cause the test to fail depending on how XCTest resolves queries. Set accessibilityIdentifier("home-view-title") on the element used for the dashboard assertion (and keep the user-facing label as "Welcome!").

Suggested change
.accessibilityLabel("home-view-title")
.accessibilityIdentifier("home-view-title")

Copilot uses AI. Check for mistakes.
Comment on lines +46 to 47
.accessibilityIdentifier("sign-in-button")
.accessibilityHint(isLoading ? "Authentication in progress" : "Double tap to sign in")
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

This changes the accessibility identifier from primaryAuthButton to sign-in-button on a public UI component. That’s effectively a breaking change for any downstream UI automation relying on the old identifier. Consider keeping the existing identifier (or making it configurable) and updating the UI tests to use it, or document this as a breaking change in release notes.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +86
// Give Safari time to launch
sleep(2)

// Wait for Safari OAuth page to appear
#if os(iOS)
let safariViewServiceApp = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
NSLog("⏱️ Waiting for Safari OAuth page to load...")
logger.info("⏱️ Waiting for Safari OAuth page to load...")

// Wait for email field to appear (OAuth page loaded)
let emailField = safariViewServiceApp.textFields["you@example.com"].firstMatch
let passwordField = safariViewServiceApp.secureTextFields["Enter your password"].firstMatch

// Use a longer timeout and provide better error message
let emailFieldExists = emailField.waitForExistence(timeout: 30)
NSLog("✅ Email field found, entering credentials...")
logger.info("✅ Email field found, entering credentials...")

// Fill in credentials from environment
// WebView elements need extra handling for keyboard focus in CI
emailField.tap()
sleep(1) // Give WebView time to establish keyboard focus
// Type the email
emailField.typeText(testEmail)
NSLog("✅ Email entered")
logger.info("✅ Email entered")

// Small delay before pressing Enter
sleep(1)
emailField.typeText("\n") // Press Enter to move to next field
#elseif os(macOS)

let emailField = textFields["you@example.com"].firstMatch
let emailFieldExists = emailField.waitForExistence(timeout: 30)
XCTAssertTrue(emailFieldExists, "Failed to sign in and reach dashboard")

let passwordField = self/*@START_MENU_TOKEN@*/ .secureTextFields["Enter your password"].firstMatch/*[[".groups",".secureTextFields[\"Password\"].firstMatch",".secureTextFields[\"Enter your password\"].firstMatch",".secureTextFields",".containing(.group, identifier: nil).firstMatch",".firstMatch"],[[[-1,2],[-1,1],[-1,3,2],[-1,0,1]],[[-1,2],[-1,1]],[[-1,5],[-1,4]]],[0]]@END_MENU_TOKEN@*/

emailField.click()
emailField.typeText(testEmail)
#endif
// WebView password field also needs focus handling
passwordField.tap()
sleep(1) // Give WebView time to establish keyboard focus

passwordField.typeText(testPassword)
NSLog("✅ Password entered, submitting...")
logger.info("✅ Password entered, submitting...")
sleep(1)
passwordField.typeText("\n") // Press Enter to submit
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

There are multiple fixed sleep(...) calls used for synchronization. These tend to make UI tests slower and flaky across machines/CI. Prefer waiting on specific UI conditions (e.g., waitForExistence, XCTWaiter/expectations, or polling for hittable state) instead of hard sleeps.

Copilot uses AI. Check for mistakes.

import XCTest

final class testUITests: XCTestCase {
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

XCTestCase subclass names should be UpperCamelCase in Swift. final class testUITests deviates from Swift naming conventions and makes test discovery/debug output harder to read. Rename to TestUITests (and keep the file name aligned).

Suggested change
final class testUITests: XCTestCase {
final class TestUITests: XCTestCase {

Copilot uses AI. Check for mistakes.
import SwiftUI

@main
struct testApp: App {
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Swift type names should be UpperCamelCase. struct testApp: App deviates from standard conventions and will read oddly in crash logs / debugging. Rename to TestApp (and consider matching module/target naming if this is a sample app).

Suggested change
struct testApp: App {
struct TestApp: App {

Copilot uses AI. Check for mistakes.
@sirily11 sirily11 force-pushed the e2e branch 4 times, most recently from 353c885 to b8d3217 Compare February 11, 2026 11:11
@autopilot-project-manager
Copy link
Contributor

Autopilot PR Check Issues

The following potential issues were detected in this PR:

Sources/RxAuthSwift/InMemoryTokenStorage.swift

  • 🎭 Line 3 (Mock Implementation): InMemoryTokenStorage appears to be a test double (Fake) implementation using in-memory variables instead of persistent storage. This is typically intended for testing, not production.
    public final class InMemoryTokenStorage: TokenStorageProtocol, @unchecked Sendable {
    

Please review and address these issues before merging.

@sirily11 sirily11 merged commit 82236a3 into main Feb 11, 2026
4 of 5 checks passed
@sirily11 sirily11 deleted the e2e branch February 11, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant