Skip to content

Commit

Permalink
Merge branch 'main' into phil/PM-12662-mass-update-app-icons
Browse files Browse the repository at this point in the history
  • Loading branch information
phil-livefront committed Oct 16, 2024
2 parents 38f205c + edbe5f6 commit a94614b
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
"ItemUpdated" = "Item saved";
"Submitting" = "Submitting...";
"Syncing" = "Syncing...";
"SyncingLogins" = "Syncing logins...";
"SyncingComplete" = "Syncing complete";
"SyncingFailed" = "Syncing failed";
"SyncVaultNow" = "Sync vault now";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ extension Navigator {
///
func showLoadingOverlay(_ state: LoadingOverlayState) {
guard let rootViewController else { return }
LoadingOverlayDisplayHelper.show(in: rootViewController, state: state)
LoadingOverlayDisplayHelper.show(in: rootViewController.topmostViewController(), state: state)
}

/// Hides the loading overlay view.
///
func hideLoadingOverlay() {
guard let rootViewController else { return }
LoadingOverlayDisplayHelper.hide(from: rootViewController)
LoadingOverlayDisplayHelper.hide(from: rootViewController.topmostViewController())
}

/// Shows the toast.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
/// Actions that can be processed by a `ImportLoginsProcessor`.
///
enum ImportLoginsAction: Equatable {
/// Advance to the next page of instructions.
case advanceNextPage

/// Advance to the previous page of instructions.
case advancePreviousPage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
/// Effects handled by the `ImportLoginsProcessor`.
///
enum ImportLoginsEffect: Equatable {
/// Advance to the next page of instructions.
case advanceNextPage

/// The view appeared on screen.
case appeared

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio
// MARK: Types

typealias Services = HasErrorReporter
& HasSettingsRepository
& HasStateService

// MARK: Private Properties
Expand Down Expand Up @@ -39,6 +40,8 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio

override func perform(_ effect: ImportLoginsEffect) async {
switch effect {
case .advanceNextPage:
await advanceNextPage()
case .appeared:
await loadData()
case .importLoginsLater:
Expand All @@ -48,8 +51,6 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio

override func receive(_ action: ImportLoginsAction) {
switch action {
case .advanceNextPage:
advanceNextPage()
case .advancePreviousPage:
advancePreviousPage()
case .dismiss:
Expand All @@ -63,9 +64,10 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio

/// Advances the view to show the next page of instructions.
///
private func advanceNextPage() {
private func advanceNextPage() async {
guard let next = state.page.next else {
// TODO: PM-11159 Sync vault
// On the last page, hitting next initiates a vault sync.
await syncVault()
return
}
state.page = next
Expand Down Expand Up @@ -93,7 +95,7 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio
///
private func showGetStartAlert() {
coordinator.showAlert(.importLoginsComputerAvailable {
self.advanceNextPage()
await self.advanceNextPage()
})
}

Expand All @@ -109,4 +111,19 @@ class ImportLoginsProcessor: StateProcessor<ImportLoginsState, ImportLoginsActio
self.coordinator.navigate(to: .dismiss)
})
}

/// Syncs the user's vault to fetch any imported logins.
///
private func syncVault() async {
coordinator.showLoadingOverlay(LoadingOverlayState(title: Localizations.syncingLogins))
defer { coordinator.hideLoadingOverlay() }

do {
try await services.settingsRepository.fetchSync()
// TODO: PM-11160 Navigate to import successful
} catch {
coordinator.showAlert(.networkResponseError(error))
services.errorReporter.log(error: error)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class ImportLoginsProcessorTests: BitwardenTestCase {

var coordinator: MockCoordinator<VaultRoute, AuthAction>!
var errorReporter: MockErrorReporter!
var settingsRepository: MockSettingsRepository!
var stateService: MockStateService!
var subject: ImportLoginsProcessor!

Expand All @@ -17,12 +18,14 @@ class ImportLoginsProcessorTests: BitwardenTestCase {

coordinator = MockCoordinator()
errorReporter = MockErrorReporter()
settingsRepository = MockSettingsRepository()
stateService = MockStateService()

subject = ImportLoginsProcessor(
coordinator: coordinator.asAnyCoordinator(),
services: ServiceContainer.withMocks(
errorReporter: errorReporter,
settingsRepository: settingsRepository,
stateService: stateService
),
state: ImportLoginsState()
Expand All @@ -34,48 +37,54 @@ class ImportLoginsProcessorTests: BitwardenTestCase {

coordinator = nil
errorReporter = nil
settingsRepository = nil
stateService = nil
subject = nil
}

// MARK: Tests

/// `receive(_:)` with `.advanceNextPage` advances to the next page.
/// `perform(_:)` with `.advanceNextPage` advances to the next page.
@MainActor
func test_receive_advanceNextPage() {
func test_perform_advanceNextPage() async {
XCTAssertEqual(subject.state.page, .intro)

subject.receive(.advanceNextPage)
await subject.perform(.advanceNextPage)
XCTAssertEqual(subject.state.page, .step1)

subject.receive(.advanceNextPage)
await subject.perform(.advanceNextPage)
XCTAssertEqual(subject.state.page, .step2)

subject.receive(.advanceNextPage)
XCTAssertEqual(subject.state.page, .step3)

// TODO: PM-11159 Sync vault
subject.receive(.advanceNextPage)
await subject.perform(.advanceNextPage)
XCTAssertEqual(subject.state.page, .step3)
}

/// `receive(_:)` with `.advancePreviousPage` advances to the previous page.
/// `perform(_:)` with `.advanceNextPage` initiates a vault sync when on the last page.
@MainActor
func test_receive_advancePreviousPage() {
func test_perform_advanceNextPage_sync() async {
subject.state.page = .step3

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .step2)
await subject.perform(.advanceNextPage)

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .step1)
XCTAssertEqual(coordinator.loadingOverlaysShown, [LoadingOverlayState(title: Localizations.syncingLogins)])
XCTAssertFalse(coordinator.isLoadingOverlayShowing)
XCTAssertTrue(settingsRepository.fetchSyncCalled)
}

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .intro)
/// `perform(_:)` with `.advanceNextPage` initiates a vault sync when on the last page and
/// handles a sync error.
@MainActor
func test_perform_advanceNextPage_syncError() async {
subject.state.page = .step3
settingsRepository.fetchSyncResult = .failure(BitwardenTestError.example)

// Advancing again stays at the first page.
subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .intro)
await subject.perform(.advanceNextPage)

XCTAssertEqual(coordinator.loadingOverlaysShown, [LoadingOverlayState(title: Localizations.syncingLogins)])
XCTAssertFalse(coordinator.isLoadingOverlayShowing)
XCTAssertEqual(coordinator.alertShown, [.networkResponseError(BitwardenTestError.example)])
XCTAssertEqual(errorReporter.errors as? [BitwardenTestError], [BitwardenTestError.example])
XCTAssertTrue(settingsRepository.fetchSyncCalled)
}

/// `perform(_:)` with `.appeared` loads the user's web vault host.
Expand Down Expand Up @@ -141,6 +150,25 @@ class ImportLoginsProcessorTests: BitwardenTestCase {
XCTAssertEqual(errorReporter.errors as? [StateServiceError], [.noActiveAccount])
}

/// `receive(_:)` with `.advancePreviousPage` advances to the previous page.
@MainActor
func test_receive_advancePreviousPage() {
subject.state.page = .step3

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .step2)

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .step1)

subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .intro)

// Advancing again stays at the first page.
subject.receive(.advancePreviousPage)
XCTAssertEqual(subject.state.page, .intro)
}

/// `receive(_:)` with `.dismiss` dismisses the view.
@MainActor
func test_receive_dismiss() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ struct ImportLoginsView: View {
.tint(Asset.Colors.textInteraction.swiftUIColor)

VStack(spacing: 12) {
Button(Localizations.continue) {
store.send(.advanceNextPage)
AsyncButton(Localizations.continue) {
await store.perform(.advanceNextPage)
}
.buttonStyle(.primary())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ class ImportLoginsViewTests: BitwardenTestCase {

/// Tapping the continue button for a step dispatches the `advanceNextPage` action.
@MainActor
func test_step_continue_tap() throws {
func test_step_continue_tap() async throws {
processor.state.page = .step1
let button = try subject.inspect().find(button: Localizations.continue)
try button.tap()
XCTAssertEqual(processor.dispatchedActions.last, .advanceNextPage)
let button = try subject.inspect().find(asyncButton: Localizations.continue)
try await button.tap()
XCTAssertEqual(processor.effects.last, .advanceNextPage)
}

// MARK: Snapshots
Expand Down
1 change: 1 addition & 0 deletions BitwardenShared/UI/Vault/Vault/VaultCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ final class VaultCoordinator: Coordinator, HasStackNavigator {
& HasFido2UserInterfaceHelper
& HasLocalAuthService
& HasNotificationService
& HasSettingsRepository
& HasStateService
& HasTimeProvider
& HasVaultRepository
Expand Down

0 comments on commit a94614b

Please sign in to comment.