Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BWA-19] Add Backup setting #98

Merged
merged 2 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ enum ExternalLinksConstants {
/// A link to the app review page within the app store.
static let appReview = URL(string: "https://itunes.apple.com/us/app/id1137397744?action=write-review")

static let backupInformation = URL(string: "https://support.apple.com/guide/iphone/back-up-iphone-iph3ecf67d29/ios")

/// A link to Bitwarden's help page for learning more about the account fingerprint phrase.
static let fingerprintPhrase = URL(string: "https://bitwarden.com/help/fingerprint-phrase/")!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
"Important" = "Important";
"YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" = "Your master password cannot be recovered if you forget it! %1$@ characters minimum.";
"ThereAreNoItemsThatMatchTheSearch" = "There are no items that match the search";
"Vault" = "Vault";
"Appearance" = "Appearance";
"BitwardenHelpCenter" = "Bitwarden Help Center";
"ContinueToWebApp" = "Continue to web app?";
Expand Down Expand Up @@ -119,3 +118,6 @@
"ItemsExported" = "Verification codes exported";
"ItemsImported" = "Vertification codes imported";
"VerificationCodeAdded" = "Verification code added";
"Data" = "Data";
"Backup" = "Backup";
"BitwardenAuthenticatorDataIsBackedUpAndCanBeRestored" = "Bitwarden Authenticator data is backed up and can be restored with your regularly scheduled device backups.";
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
extension Alert {
// MARK: Methods

/// Provide information about data backup.
///
/// - Parameters:
/// - action: The action to perform if the user selects Learn More.
/// - Returns: An alert for providing backup information.
///
static func backupInformation(action: @escaping () -> Void) -> Alert {
Alert(
title: Localizations.bitwardenAuthenticatorDataIsBackedUpAndCanBeRestored,
message: nil,
alertActions: [
AlertAction(title: Localizations.learnMore, style: .default) { _ in
action()
},
AlertAction(title: Localizations.ok, style: .default),
]
)
}

/// Confirm deleting the folder.
///
/// - Parameter action: The action to perform if the user selects yes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@ import XCTest
@testable import AuthenticatorShared

class AlertSettingsTests: AuthenticatorTestCase {
/// `backupInformation(action:)` constructs an `Alert`
/// with the correct title, message, and buttons.
func test_backupInformationAlert() {
let subject = Alert.backupInformation {}

XCTAssertEqual(subject.preferredStyle, .alert)
XCTAssertEqual(subject.title, Localizations.bitwardenAuthenticatorDataIsBackedUpAndCanBeRestored)
XCTAssertNil(subject.message)
XCTAssertEqual(subject.alertActions.count, 2)
XCTAssertEqual(subject.alertActions.first?.title, Localizations.learnMore)
XCTAssertEqual(subject.alertActions.first?.style, .default)
XCTAssertEqual(subject.alertActions.last?.title, Localizations.ok)
XCTAssertEqual(subject.alertActions.last?.style, .default)
}

/// `confirmDeleteFolder(action:)` constructs an `Alert` with the title,
/// message, yes, and cancel buttons to confirm deleting a folder.
func test_confirmDeleteFolder() {
Expand Down Expand Up @@ -37,7 +52,7 @@ class AlertSettingsTests: AuthenticatorTestCase {
XCTAssertEqual(subject.alertActions.first?.style, .default)
}

/// `privacyPolicyAlert(encrypted:action:)` constructs an `Alert`
/// `privacyPolicyAlert(action:)` constructs an `Alert`
/// with the correct title, message, and Cancel and Continue buttons.
func test_privacyPolicyAlert() {
let subject = Alert.privacyPolicyAlert {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ enum SettingsAction: Equatable {
/// The default color theme was changed.
case appThemeChanged(AppTheme)

/// The backup button was tapped.
case backupTapped

/// The url has been opened so clear the value in the state.
case clearURL

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ final class SettingsProcessor: StateProcessor<SettingsState, SettingsAction, Set
Task {
await services.stateService.setAppTheme(appTheme)
}
case .backupTapped:
coordinator.showAlert(.backupInformation {
self.state.url = ExternalLinksConstants.backupInformation
})
case .clearURL:
state.url = nil
case .exportItemsTapped:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ class SettingsProcessorTests: AuthenticatorTestCase {

// MARK: Tests

/// Receiving `.backupTapped` shows an alert for the backup information.
func test_receive_backupTapped() async throws {
subject.receive(.backupTapped)

let alert = try XCTUnwrap(coordinator.alertShown.last)
try await alert.tapAction(title: Localizations.learnMore)
XCTAssertEqual(subject.state.url, ExternalLinksConstants.backupInformation)
}

/// Receiving `.exportItemsTapped` navigates to the export vault screen.
func test_receive_exportVaultTapped() {
subject.receive(.exportItemsTapped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,19 @@ struct SettingsView: View {
VStack(spacing: 0) {
biometricsSetting

SectionView(Localizations.vault, contentSpacing: 0) {
SectionView(Localizations.data, contentSpacing: 0) {
VStack(spacing: 0) {
SettingsListItem(Localizations.import) {
store.send(.importItemsTapped)
}

SettingsListItem(Localizations.export, hasDivider: false) {
SettingsListItem(Localizations.export) {
store.send(.exportItemsTapped)
}

SettingsListItem(Localizations.backup, hasDivider: false) {
store.send(.backupTapped)
}
}
.cornerRadius(10)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class SettingsViewTests: AuthenticatorTestCase {
XCTAssertEqual(processor.dispatchedActions.last, .appThemeChanged(.dark))
}

/// Tapping the backup button dispatches the `.backupTapped` action.
func test_backupButton_tap() throws {
let button = try subject.inspect().find(button: Localizations.backup)
try button.tap()
XCTAssertEqual(processor.dispatchedActions.last, .backupTapped)
}

/// Tapping the export button dispatches the `.exportItemsTapped` action.
func test_exportButton_tap() throws {
let button = try subject.inspect().find(button: Localizations.export)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading