Skip to content

Commit af1798d

Browse files
PM-9000 - User can save empty PIN (#730)
1 parent 6702c20 commit af1798d

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

BitwardenShared/UI/Platform/Application/Utilities/Alert/Alert/TestHelpers/Alert+TestHelpers.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
import Foundation
1+
import UIKit
22

33
@testable import BitwardenShared
44

55
enum AlertError: LocalizedError {
66
case alertActionNotFound(title: String)
7+
case alertTextFieldNotFound(id: String)
78

89
var errorDescription: String? {
910
switch self {
1011
case let .alertActionNotFound(title):
1112
"Unable to locate an alert action for the title: \(title)"
13+
case let .alertTextFieldNotFound(id):
14+
"Unable to locate a TextField with id: \(id)"
1215
}
1316
}
1417
}
@@ -20,10 +23,32 @@ extension Alert {
2023
/// - title: The title of the alert action to trigger.
2124
/// - alertTextFields: `AlertTextField` list to execute the action.
2225
/// - Throws: Throws an `AlertError` if the alert action cannot be found.
23-
func tapAction(title: String, alertTextFields: [AlertTextField]? = nil) async throws {
26+
func tapAction(
27+
title: String,
28+
alertTextFields: [AlertTextField]? = nil
29+
) async throws {
2430
guard let alertAction = alertActions.first(where: { $0.title == title }) else {
2531
throw AlertError.alertActionNotFound(title: title)
2632
}
2733
await alertAction.handler?(alertAction, alertTextFields ?? self.alertTextFields)
2834
}
35+
36+
/// Sets the text for the alert text field with the specified identifier.
37+
///
38+
/// - Parameters:
39+
/// - text: The text to set in the alert text field.
40+
/// - id: The identifier of the alert text field to set the text for.
41+
/// - Throws: Throws an `AlertError` if the alert text field cannot be found.
42+
func setText(
43+
_ text: String,
44+
forTextFieldWithId id: String
45+
) throws {
46+
guard let textField = alertTextFields.first(where: { $0.id == id }) else {
47+
throw AlertError.alertTextFieldNotFound(id: id)
48+
}
49+
50+
let simulatedTextField = UITextField()
51+
simulatedTextField.text = "1234"
52+
textField.textChanged(in: simulatedTextField)
53+
}
2954
}

BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityProcessor.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ final class AccountSecurityProcessor: StateProcessor<
305305
private func toggleUnlockWithPIN(_ isOn: Bool) {
306306
if isOn {
307307
coordinator.showAlert(.enterPINCode { pin in
308+
guard !pin.isEmpty else { return }
309+
308310
do {
309311
let userHasMasterPassword = try await self.services.stateService.getUserHasMasterPassword()
310312
if userHasMasterPassword {

BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityProcessorTests.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,20 +468,34 @@ class AccountSecurityProcessorTests: BitwardenTestCase { // swiftlint:disable:th
468468
}
469469

470470
/// `receive(_:)` with `.toggleUnlockWithPINCode` displays an alert and updates the state when submit has been
471-
/// pressed.
472-
func test_receive_toggleUnlockWithPINCode_toggleOn() async throws {
471+
/// pressed and the user has entered in a pin.
472+
func test_receive_toggleUnlockWithPINCode_toggleOn_withPIN() async throws {
473473
stateService.activeAccount = .fixture()
474474
subject.state.isUnlockWithPINCodeOn = false
475475
subject.receive(.toggleUnlockWithPINCode(true))
476476

477477
var alert = try XCTUnwrap(coordinator.alertShown.last)
478+
try alert.setText("1234", forTextFieldWithId: "pin")
478479
try await alert.tapAction(title: Localizations.submit)
479480

480481
alert = try XCTUnwrap(coordinator.alertShown.last)
481482
try await alert.tapAction(title: Localizations.yes)
482483
XCTAssertTrue(subject.state.isUnlockWithPINCodeOn)
483484
}
484485

486+
/// `receive(_:)` with `.toggleUnlockWithPINCode` displays an alert and updates the state when submit has been
487+
/// pressed but an empty pin was passed.
488+
func test_receive_toggleUnlockWithPINCode_toggleOn_withEmptyPIN() async throws {
489+
stateService.activeAccount = .fixture()
490+
subject.state.isUnlockWithPINCodeOn = false
491+
subject.receive(.toggleUnlockWithPINCode(true))
492+
493+
let alert = try XCTUnwrap(coordinator.alertShown.last)
494+
try await alert.tapAction(title: Localizations.submit)
495+
496+
XCTAssertFalse(subject.state.isUnlockWithPINCodeOn)
497+
}
498+
485499
/// `receive(_:)` with `.toggleUnlockWithPINCode` displays an error if one occurs while setting
486500
/// the user's pin.
487501
func test_receive_toggleUnlockWithPINCode_toggleOn_error() async throws {
@@ -492,6 +506,7 @@ class AccountSecurityProcessorTests: BitwardenTestCase { // swiftlint:disable:th
492506
subject.receive(.toggleUnlockWithPINCode(true))
493507

494508
let enterPinAlert = try XCTUnwrap(coordinator.alertShown.last)
509+
try enterPinAlert.setText("1234", forTextFieldWithId: "pin")
495510
try await enterPinAlert.tapAction(title: Localizations.submit)
496511

497512
let requireMasterPasswordAlert = try XCTUnwrap(coordinator.alertShown.last)
@@ -511,6 +526,7 @@ class AccountSecurityProcessorTests: BitwardenTestCase { // swiftlint:disable:th
511526
subject.receive(.toggleUnlockWithPINCode(true))
512527

513528
let alert = try XCTUnwrap(coordinator.alertShown.last)
529+
try alert.setText("1234", forTextFieldWithId: "pin")
514530
try await alert.tapAction(title: Localizations.submit)
515531

516532
XCTAssertTrue(subject.state.isUnlockWithPINCodeOn)
@@ -539,6 +555,7 @@ class AccountSecurityProcessorTests: BitwardenTestCase { // swiftlint:disable:th
539555
subject.receive(.toggleUnlockWithPINCode(true))
540556

541557
let enterPinAlert = try XCTUnwrap(coordinator.alertShown.last)
558+
try enterPinAlert.setText("1234", forTextFieldWithId: "pin")
542559
try await enterPinAlert.tapAction(title: Localizations.submit)
543560

544561
let errorAlert = try XCTUnwrap(coordinator.alertShown.last)

0 commit comments

Comments
 (0)