Skip to content

Commit 4c1428d

Browse files
authored
Merge pull request #5391 from woocommerce/issue/5300-maintain-reader-software-update-required-correctly
[Mobile Payments] Maintain reader software update Required/Optional state correctly
2 parents dbea534 + 5d3c215 commit 4c1428d

File tree

5 files changed

+99
-15
lines changed

5 files changed

+99
-15
lines changed

Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,12 @@ extension StripeCardReaderService: BluetoothReaderDelegate {
503503
error: CardReaderServiceError.softwareUpdate(underlyingError: UnderlyingError(with: error),
504504
batteryLevel: reader.batteryLevel?.doubleValue))
505505
)
506-
softwareUpdateSubject.send(.available)
506+
if let requiredDate = update?.requiredAt,
507+
requiredDate > Date() {
508+
softwareUpdateSubject.send(.available)
509+
} else {
510+
softwareUpdateSubject.send(.none)
511+
}
507512
} else {
508513
softwareUpdateSubject.send(.completed)
509514
softwareUpdateSubject.send(.none)

WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private extension CardReaderSettingsConnectedViewController {
6868
guard let viewModel = viewModel else {
6969
return false
7070
}
71-
return viewModel.readerUpdateAvailable == true
71+
return viewModel.optionalReaderUpdateAvailable == true
7272
}
7373

7474
/// Set the title and back button.

WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewModel.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
1111
private var connectedReaders = [CardReader]()
1212
private let knownReaderProvider: CardReaderSettingsKnownReaderProvider?
1313

14-
private(set) var readerUpdateAvailable: Bool = false
14+
private(set) var optionalReaderUpdateAvailable: Bool = false
1515
var readerUpdateInProgress: Bool {
1616
readerUpdateProgress != nil
1717
}
@@ -27,9 +27,14 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
2727
var connectedReaderBatteryLevel: String?
2828
var connectedReaderSoftwareVersion: String?
2929

30-
init(didChangeShouldShow: ((CardReaderSettingsTriState) -> Void)?, knownReaderProvider: CardReaderSettingsKnownReaderProvider? = nil) {
30+
let delayToShowUpdateSuccessMessage: DispatchTimeInterval
31+
32+
init(didChangeShouldShow: ((CardReaderSettingsTriState) -> Void)?,
33+
knownReaderProvider: CardReaderSettingsKnownReaderProvider? = nil,
34+
delayToShowUpdateSuccessMessage: DispatchTimeInterval = .seconds(1)) {
3135
self.didChangeShouldShow = didChangeShouldShow
3236
self.knownReaderProvider = knownReaderProvider
37+
self.delayToShowUpdateSuccessMessage = delayToShowUpdateSuccessMessage
3338
beginObservation()
3439
}
3540

@@ -77,13 +82,13 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
7782
ServiceLocator.analytics.track(.cardReaderSoftwareUpdateSuccess)
7883
// If we were installing a software update, introduce a small delay so the user can
7984
// actually see a success message showing the installation was complete
80-
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { [weak self] in
85+
DispatchQueue.main.asyncAfter(deadline: .now() + self.delayToShowUpdateSuccessMessage) { [weak self] in
8186
self?.completeCardReaderUpdate(success: true)
8287
}
8388
case .available:
84-
self.readerUpdateAvailable = true
89+
self.optionalReaderUpdateAvailable = true
8590
case .none:
86-
self.readerUpdateAvailable = false
91+
self.optionalReaderUpdateAvailable = false
8792
}
8893
self.didUpdate?()
8994
}
@@ -148,7 +153,8 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
148153
}
149154

150155
private func completeCardReaderUpdate(success: Bool) {
151-
readerUpdateAvailable = !success
156+
//Avoids a failed mandatory reader update being shown as optional
157+
optionalReaderUpdateAvailable = optionalReaderUpdateAvailable && !success
152158
readerUpdateProgress = nil
153159
didUpdate?()
154160
}

WooCommerce/WooCommerceTests/Mocks/MockCardPresentPaymentsStoresManager.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,8 @@ extension MockCardPresentPaymentsStoresManager {
111111
func simulateUpdateStarted() {
112112
softwareUpdateSubject.send(.started(cancelable: nil))
113113
}
114+
115+
func simulateOptionalUpdateAvailable() {
116+
softwareUpdateSubject.send(.available)
117+
}
114118
}

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/CardReaderSettingsConnectedViewModelTests.swift

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
1919
analytics = MockAnalyticsProvider()
2020
ServiceLocator.setAnalytics(WooAnalytics(analyticsProvider: analytics))
2121

22-
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil)
22+
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil,
23+
delayToShowUpdateSuccessMessage: .milliseconds(1))
2324
}
2425

2526
func test_did_change_should_show_returns_false_if_no_connected_readers() {
@@ -34,7 +35,8 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
3435
let _ = CardReaderSettingsConnectedViewModel(didChangeShouldShow: { shouldShow in
3536
XCTAssertTrue(shouldShow == .isFalse)
3637
expectation.fulfill()
37-
} )
38+
},
39+
delayToShowUpdateSuccessMessage: .milliseconds(1))
3840

3941
wait(for: [expectation], timeout: Constants.expectationTimeout)
4042
}
@@ -45,7 +47,8 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
4547
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: { shouldShow in
4648
XCTAssertTrue(shouldShow == .isTrue)
4749
expectation.fulfill()
48-
} )
50+
},
51+
delayToShowUpdateSuccessMessage: .milliseconds(1))
4952

5053
wait(for: [expectation], timeout: Constants.expectationTimeout)
5154
}
@@ -63,12 +66,14 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
6366
)
6467
ServiceLocator.setStores(mockStoresManager)
6568

66-
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil)
69+
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil,
70+
delayToShowUpdateSuccessMessage: .milliseconds(1))
6771
XCTAssertEqual(viewModel.connectedReaderBatteryLevel, "Unknown Battery Level")
6872
}
6973

7074
func test_view_model_correctly_formats_connected_card_reader_software_version() {
71-
let viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil)
75+
let viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil,
76+
delayToShowUpdateSuccessMessage: .milliseconds(1))
7277
XCTAssertEqual(viewModel.connectedReaderSoftwareVersion, "Version: 1.00.03.34-SZZZ_Generic_v45-300001")
7378
}
7479

@@ -80,7 +85,8 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
8085
)
8186
ServiceLocator.setStores(mockStoresManager)
8287

83-
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil)
88+
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil,
89+
delayToShowUpdateSuccessMessage: .milliseconds(1))
8490
XCTAssertEqual(viewModel.connectedReaderSoftwareVersion, "Unknown Software Version")
8591
}
8692

@@ -124,7 +130,8 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
124130
)
125131
ServiceLocator.setStores(mockStoresManager)
126132

127-
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil)
133+
viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil,
134+
delayToShowUpdateSuccessMessage: .milliseconds(1))
128135

129136
var updateDidBegin = false
130137

@@ -232,4 +239,66 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase {
232239
wait(for: [expectation], timeout: Constants.expectationTimeout)
233240
XCTAssertFalse(analytics.receivedEvents.contains(WooAnalyticsStat.cardReaderSoftwareUpdateFailed.rawValue))
234241
}
242+
243+
func test_when_a_mandatory_update_succeeds_optional_updates_are_not_available() {
244+
// Given
245+
// .available is not sent
246+
mockStoresManager.simulateUpdateStarted()
247+
let expectation = self.expectation(description: #function)
248+
viewModel.didUpdate = { [weak self] in
249+
if self?.viewModel.readerUpdateProgress == nil { //ensures that we wait until completeCardReaderUpdate()
250+
expectation.fulfill()
251+
}
252+
}
253+
254+
// When
255+
mockStoresManager.simulateSuccessfulUpdate()
256+
257+
// Then
258+
wait(for: [expectation], timeout: Constants.expectationTimeout)
259+
XCTAssertFalse(viewModel.optionalReaderUpdateAvailable)
260+
}
261+
262+
func test_when_an_optional_update_succeeds_optional_updates_are_not_available() {
263+
// Given
264+
mockStoresManager.simulateOptionalUpdateAvailable()
265+
mockStoresManager.simulateUpdateStarted()
266+
let expectation = self.expectation(description: #function)
267+
viewModel.didUpdate = { [weak self] in
268+
if self?.viewModel.readerUpdateProgress == nil { //ensures that we wait until completeCardReaderUpdate()
269+
expectation.fulfill()
270+
}
271+
}
272+
273+
// When
274+
mockStoresManager.simulateSuccessfulUpdate()
275+
276+
// Then
277+
wait(for: [expectation], timeout: Constants.expectationTimeout)
278+
XCTAssertFalse(viewModel.optionalReaderUpdateAvailable)
279+
}
280+
281+
func test_when_a_mandatory_update_fails_optional_updates_are_not_available() {
282+
// Given
283+
// .available is not sent
284+
mockStoresManager.simulateUpdateStarted()
285+
286+
// When
287+
mockStoresManager.simulateFailedUpdate(error: CardReaderServiceError.bluetoothDenied)
288+
289+
// Then
290+
XCTAssertFalse(viewModel.optionalReaderUpdateAvailable)
291+
}
292+
293+
func test_when_an_optional_update_fails_optional_updates_are_available() {
294+
// Given
295+
mockStoresManager.simulateOptionalUpdateAvailable()
296+
mockStoresManager.simulateUpdateStarted()
297+
298+
// When
299+
mockStoresManager.simulateFailedUpdate(error: CardReaderServiceError.bluetoothDenied)
300+
301+
// Then
302+
XCTAssertTrue(viewModel.optionalReaderUpdateAvailable)
303+
}
235304
}

0 commit comments

Comments
 (0)