Skip to content

Commit

Permalink
[PM-9842] Show expired link screen (bitwarden#862)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrebispo5 authored Aug 22, 2024
1 parent 9e77f16 commit 0b1afe3
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 20 deletions.
31 changes: 16 additions & 15 deletions BitwardenShared/UI/Auth/AuthCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -304,21 +304,6 @@ final class AuthCoordinator: NSObject, // swiftlint:disable:this type_body_lengt
stackNavigator?.present(navController)
}

/// Shows the expired link screen.
///
private func showExpiredLink() {
let view = ExpiredLinkView(
store: Store(
processor: ExpiredLinkProcessor(
coordinator: asAnyCoordinator(),
state: ExpiredLinkState()
)
)
)
let navController = UINavigationController(rootViewController: UIHostingController(rootView: view))
stackNavigator?.present(navController)
}

/// Shows the create account screen.
///
private func showCreateAccount() {
Expand Down Expand Up @@ -404,6 +389,22 @@ final class AuthCoordinator: NSObject, // swiftlint:disable:this type_body_lengt
session.start()
}

/// Shows the expired link screen.
///
private func showExpiredLink() {
let view = ExpiredLinkView(
store: Store(
processor: ExpiredLinkProcessor(
coordinator: asAnyCoordinator(),
state: ExpiredLinkState()
)
)
)
let navController = UINavigationController(rootViewController: UIHostingController(rootView: view))
navController.isModalInPresentation = true
stackNavigator?.present(navController)
}

/// Shows the enterprise single sign-on screen.
///
/// - Parameter email: The user's email address.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,21 @@ class CompleteRegistrationProcessor: StateProcessor<
defer { coordinator.hideLoadingOverlay() }

if state.fromEmail {
state.toast = Toast(text: Localizations.emailVerified)
coordinator.showLoadingOverlay(title: Localizations.verifying)

do {
try await services.accountAPIService.verifyEmailToken(
email: state.userEmail,
emailVerificationToken: state.emailVerificationToken
)
state.toast = Toast(text: Localizations.emailVerified)
} catch VerifyEmailTokenRequestError.tokenExpired {
coordinator.navigate(to: .expiredLink)
} catch {
coordinator.showAlert(.networkResponseError(error) {
await self.verifyUserEmail()
})
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,18 @@ class CompleteRegistrationProcessorTests: BitwardenTestCase {
XCTAssertEqual(environmentService.setPreAuthEnvironmentUrlsData, nil)
}

/// `perform(.appeared)` verify user email show toast.
/// `perform(.appeared)` verify user email show toast on success.
@MainActor
func test_perform_appeared_verifyuseremail_toast() async {
func test_perform_appeared_verifyuseremail_success() async {
client.results = [.httpSuccess(testData: .emptyResponse)]
subject.state.fromEmail = true
await subject.perform(.appeared)
XCTAssertEqual(subject.state.toast?.text, Localizations.emailVerified)
}

/// `perform(.appeared)` verify user email show no toast.
@MainActor
func test_perform_appeared_verifyuseremail_notoast() async {
func test_perform_appeared_verifyuseremail_notFromEmail() async {
subject.state.fromEmail = false
await subject.perform(.appeared)
XCTAssertNil(subject.state.toast)
Expand All @@ -94,12 +95,64 @@ class CompleteRegistrationProcessorTests: BitwardenTestCase {
@MainActor
func test_perform_appeared_verifyuseremail_hideloading() async {
coordinator.isLoadingOverlayShowing = true
subject.state.fromEmail = true
subject.state.fromEmail = false
await subject.perform(.appeared)

XCTAssertFalse(coordinator.isLoadingOverlayShowing)
XCTAssertNotNil(coordinator.loadingOverlaysShown)
}

/// `perform(.appeared)` verify user email with token expired error shows expired link screen.
@MainActor
func test_perform_appeared_verifyuseremail_tokenexpired() async {
client.results = [
.httpFailure(
statusCode: 400,
headers: [:],
data: APITestData.verifyEmailTokenExpiredLink.data
),
]
subject.state.fromEmail = true
await subject.perform(.appeared)
XCTAssertEqual(coordinator.routes.last, .expiredLink)
}

/// `perform(.appeared)` verify user email presents an alert when there is no internet connection.
/// When the user taps `Try again`, the verify user email request is made again.
@MainActor
func test_perform_appeared_verifyuseremail_error() async throws {
subject.state = .fixture()
subject.state.fromEmail = true

let urlError = URLError(.notConnectedToInternet) as Error
client.results = [.httpFailure(urlError), .httpSuccess(testData: .emptyResponse)]

await subject.perform(.appeared)

let alert = try XCTUnwrap(coordinator.alertShown.last)
XCTAssertEqual(alert, Alert.networkResponseError(urlError) {
await self.subject.perform(.appeared)
})

try await alert.tapAction(title: Localizations.tryAgain)

XCTAssertEqual(subject.state.toast?.text, Localizations.emailVerified)
XCTAssertEqual(client.requests.count, 2)
XCTAssertEqual(client.requests[0].url, URL(
string: "https://example.com/identity/accounts/register/verification-email-clicked"
))
XCTAssertEqual(client.requests[1].url, URL(
string: "https://example.com/identity/accounts/register/verification-email-clicked"
))

XCTAssertFalse(coordinator.isLoadingOverlayShowing)
XCTAssertEqual(
coordinator.loadingOverlaysShown,
[
LoadingOverlayState(title: Localizations.verifying),
LoadingOverlayState(title: Localizations.verifying),
]
)
}

/// `perform(_:)` with `.completeRegistration` will still make the `CompleteRegistrationRequest` when the HIBP
Expand Down

0 comments on commit 0b1afe3

Please sign in to comment.