Add signup UI end to end test

Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2025-10-22 14:25:38 -07:00
parent 67d2b249b6
commit fe09f9da99
7 changed files with 142 additions and 0 deletions

View File

@@ -25,6 +25,23 @@ enum AppAccessibilityIdentifiers: String {
case sign_in_confirm_button
// MARK: Sign Up / Create Account
// Prefix: `sign_up`
/// Button to navigate to create account view
case sign_up_option_button
/// Text field for entering name during account creation
case sign_up_name_field
/// Text field for entering bio during account creation
case sign_up_bio_field
/// Button to proceed to the next step after entering profile info
case sign_up_next_button
/// Button to save keys after account creation
case sign_up_save_keys_button
/// Button to skip saving keys
case sign_up_skip_save_keys_button
// MARK: Onboarding
// Prefix: `onboarding`
@@ -60,6 +77,12 @@ enum AppAccessibilityIdentifiers: String {
/// The profile option in the side menu
case side_menu_profile_button
/// The logout button in the side menu
case side_menu_logout_button
/// The logout confirmation button in the alert dialog
case side_menu_logout_confirm_button
// MARK: Items specific to the user's own profile
// Prefix: `own_profile`

View File

@@ -55,10 +55,12 @@ struct CreateAccountView: View, KeyboardReadable {
.foregroundColor(DamusColors.neutral6)
FormTextInput(NSLocalizedString("Satoshi Nakamoto", comment: "Name of Bitcoin creator(s)."), text: $account.name)
.textInputAutocapitalization(.words)
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_name_field.rawValue)
FormLabel(NSLocalizedString("Bio", comment: "Label to prompt bio entry for user to describe themself."), optional: true)
.foregroundColor(DamusColors.neutral6)
FormTextInput(NSLocalizedString("Absolute legend.", comment: "Example Bio"), text: $account.about)
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_bio_field.rawValue)
}
.padding(.top, 25)
@@ -75,6 +77,7 @@ struct CreateAccountView: View, KeyboardReadable {
.disabled(profileUploadObserver.isLoading || account.name.isEmpty)
.opacity(profileUploadObserver.isLoading || account.name.isEmpty ? 0.5 : 1)
.padding(.top, 20)
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_next_button.rawValue)
LoginPrompt()
.padding(.top)

View File

@@ -452,6 +452,7 @@ struct CreateAccountPrompt: View {
Button(NSLocalizedString("Create account", comment: "Button to navigate to create account view.")) {
nav.push(route: Route.CreateAccount)
}
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_option_button.rawValue)
Spacer()
}

View File

@@ -99,6 +99,7 @@ struct SaveKeysView: View {
}
.buttonStyle(GradientButtonStyle())
.padding(.top, 20)
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_save_keys_button.rawValue)
Button(action: {
Task { await complete_account_creation(account) }
@@ -111,6 +112,7 @@ struct SaveKeysView: View {
}
.buttonStyle(NeutralButtonStyle(padding: EdgeInsets(top: 15, leading: 15, bottom: 15, trailing: 15), cornerRadius: 12))
.padding(.top, 20)
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_skip_save_keys_button.rawValue)
}
}
.padding(20)

View File

@@ -44,6 +44,7 @@ struct SetupView: View {
.frame(minWidth: 300, maxWidth: .infinity, maxHeight: 12, alignment: .center)
}
.buttonStyle(GradientButtonStyle())
.accessibilityIdentifier(AppAccessibilityIdentifiers.sign_up_option_button.rawValue)
.padding(.horizontal)
Button(action: {

View File

@@ -87,6 +87,7 @@ struct SideMenuView: View {
}, label: {
navLabel(title: NSLocalizedString("Logout", comment: "Sidebar menu label to sign out of the account."), img: "logout")
})
.accessibilityIdentifier(AppAccessibilityIdentifiers.side_menu_logout_button.rawValue)
}
}
@@ -211,6 +212,7 @@ struct SideMenuView: View {
Button(NSLocalizedString("Logout", comment: "Button for logging out the user."), role: .destructive) {
logout(damus_state)
}
.accessibilityIdentifier(AppAccessibilityIdentifiers.side_menu_logout_confirm_button.rawValue)
} message: {
Text("Make sure your nsec account key is saved before you logout or you will lose access to this account", comment: "Reminder message in alert to get customer to verify that their private security account key is saved saved before logging out.")
}

View File

@@ -57,6 +57,116 @@ class damusUITests: XCTestCase {
guard app.buttons[AID.own_profile_banner_image_edit_from_url.rawValue].waitForExistence(timeout: 5) else { throw DamusUITestError.timeout_waiting_for_element }
}
/// Tests the sign up flow to ensure users can successfully create a new account.
/// This test verifies:
/// 1. The "Create account" button is accessible
/// 2. Users can enter their name and bio
/// 3. The "Next" button becomes enabled after entering required information
/// 4. Users reach the save keys screen
/// 5. Users can skip saving keys and complete onboarding
func testSignUpFlow() throws {
try logoutIfNotAlready()
// Verify we're on the initial screen with sign up option
guard app.buttons[AID.sign_up_option_button.rawValue].waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
// Tap the create account button
app.buttons[AID.sign_up_option_button.rawValue].tap()
// Wait for the create account screen to appear
guard app.textFields[AID.sign_up_name_field.rawValue].waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
// Enter name (required field)
let nameField = app.textFields[AID.sign_up_name_field.rawValue]
nameField.tap()
nameField.typeText("Test User")
// Enter bio (optional field)
let bioField = app.textFields[AID.sign_up_bio_field.rawValue]
bioField.tap()
bioField.typeText("This is a test bio")
// Verify the Next button is present and enabled
let nextButton = app.buttons[AID.sign_up_next_button.rawValue]
guard nextButton.waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
// Tap Next to proceed to save keys screen
nextButton.tap()
// Verify we reached the save keys screen by checking for the save button
guard app.buttons[AID.sign_up_save_keys_button.rawValue].waitForExistence(timeout: 10) else {
throw DamusUITestError.timeout_waiting_for_element
}
// Verify both save options are present
XCTAssertTrue(app.buttons[AID.sign_up_skip_save_keys_button.rawValue].exists,
"Skip save keys button should be visible")
// Tap "Not now" to skip saving keys and continue to onboarding
app.buttons[AID.sign_up_skip_save_keys_button.rawValue].tap()
// Go through onboarding flow (similar to loginIfNotAlready)
// Select an interest if the interests page appears
app.buttons[AID.onboarding_interest_option_button.rawValue].firstMatch.tapIfExists(timeout: 5)
app.buttons[AID.onboarding_interest_page_next_page.rawValue].tapIfExists(timeout: 5)
// Continue through content settings page
app.buttons[AID.onboarding_content_settings_page_next_page.rawValue].tapIfExists(timeout: 5)
// Skip any remaining onboarding sheets
app.buttons[AID.onboarding_sheet_skip_button.rawValue].tapIfExists(timeout: 5)
// Cancel post composer if it appears
app.buttons[AID.post_composer_cancel_button.rawValue].tapIfExists(timeout: 5)
// Verify we've reached the main app interface by checking for the side menu button
guard app.buttons[AID.main_side_menu_button.rawValue].waitForExistence(timeout: 10) else {
throw DamusUITestError.timeout_waiting_for_element
}
}
func logoutIfNotAlready() throws {
// First, check if user is already logged in and logout if needed
if app.buttons[AID.main_side_menu_button.rawValue].waitForExistence(timeout: 5) {
// User is already logged in, need to logout first
try logout()
}
}
func logout() throws {
app.buttons[AID.main_side_menu_button.rawValue].tap()
guard app.buttons[AID.side_menu_logout_button.rawValue].waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
app.buttons[AID.side_menu_logout_button.rawValue].tap()
// Handle logout confirmation dialog (system alert)
// Wait for the alert to appear
let alert = app.alerts.firstMatch
guard alert.waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
// Tap the confirm button in the alert
let confirmButton = alert.buttons[AID.side_menu_logout_confirm_button.rawValue].firstMatch
guard confirmButton.waitForExistence(timeout: 5) else {
throw DamusUITestError.timeout_waiting_for_element
}
confirmButton.tap()
// Wait a moment for logout to complete
sleep(2)
}
func loginIfNotAlready() throws {
if app.buttons[AID.sign_in_option_button.rawValue].waitForExistence(timeout: 5) {
try self.login()