diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/BluetoothCardReaderSettingsConnectedViewModel.swift similarity index 90% rename from WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewModel.swift rename to WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/BluetoothCardReaderSettingsConnectedViewModel.swift index 4cd583fd9b9..f51cd60ef0d 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/BluetoothCardReaderSettingsConnectedViewModel.swift @@ -2,7 +2,7 @@ import Combine import Foundation import Yosemite -final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedViewModel { +final class BluetoothCardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedViewModel { private(set) var shouldShow: CardReaderSettingsTriState = .isUnknown var didChangeShouldShow: ((CardReaderSettingsTriState) -> Void)? var didUpdate: (() -> Void)? @@ -97,6 +97,8 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie guard let self = self else { return } + + self.disconnectFromBuiltInReader(in: readers) self.readerUpdateError = nil self.didGetConnectedReaders = true self.connectedReaders = readers @@ -145,6 +147,15 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie ServiceLocator.stores.dispatch(softwareUpdateAction) } + /// This screen is only used for managing Bluetooth card readers. + /// If we're connected to the built-in reader, we should disconnect, as users are unlikely to consider + /// another part of their phone as something they connect to and manage. + private func disconnectFromBuiltInReader(in readers: [CardReader]) { + if readers.includesBuiltInReader() { + self.disconnect() + } + } + private func updateProperties() { updateReaderID() updateBatteryLevel() @@ -152,6 +163,11 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie didUpdate?() } + private func disconnect() { + let action = CardPresentPaymentAction.disconnect { _ in } + ServiceLocator.stores.dispatch(action) + } + private func updateReaderID() { connectedReaderID = connectedReaders.first?.id } @@ -249,6 +265,10 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie newShouldShow = .isUnknown } else if connectedReaders.isEmpty { newShouldShow = .isFalse + } else if connectedReaders.includesBuiltInReader() { + /// This screen only supports management of Bluetooth readers, and will have started disconnection + /// the built-in reader in this instance. + newShouldShow = .isFalse } else { newShouldShow = .isTrue } @@ -263,9 +283,15 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie } } +private extension [CardReader] { + func includesBuiltInReader() -> Bool { + return self.first(where: { $0.readerType == .appleBuiltIn }) != nil + } +} + // MARK: - Localization // -private extension CardReaderSettingsConnectedViewModel { +private extension BluetoothCardReaderSettingsConnectedViewModel { enum Localization { static let title = NSLocalizedString( "Connected Reader", diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift index a834db71cbc..5df4d0a27dd 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift @@ -13,7 +13,7 @@ final class CardReaderSettingsConnectedViewController: UIViewController, CardRea /// ViewModel /// - private var viewModel: CardReaderSettingsConnectedViewModel? + private var viewModel: BluetoothCardReaderSettingsConnectedViewModel? /// Table Sections to be rendered /// @@ -24,7 +24,7 @@ final class CardReaderSettingsConnectedViewController: UIViewController, CardRea /// Accept our viewmodel /// func configure(viewModel: CardReaderSettingsPresentedViewModel) { - self.viewModel = viewModel as? CardReaderSettingsConnectedViewModel + self.viewModel = viewModel as? BluetoothCardReaderSettingsConnectedViewModel guard self.viewModel != nil else { DDLogError("Unexpectedly unable to downcast to CardReaderSettingsConnectedViewModel") diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsViewModelsOrderedList.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsViewModelsOrderedList.swift index d2f1ee25265..0e8fac852be 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsViewModelsOrderedList.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsViewModelsOrderedList.swift @@ -49,7 +49,7 @@ final class CardReaderSettingsViewModelsOrderedList: CardReaderSettingsPrioritiz viewModelsAndViews.append( CardReaderSettingsViewModelAndView( - viewModel: CardReaderSettingsConnectedViewModel( + viewModel: BluetoothCardReaderSettingsConnectedViewModel( didChangeShouldShow: { [weak self] state in self?.onDidChangeShouldShow(state) }, diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index fb3e6829321..52f80383177 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -735,8 +735,8 @@ 31595CAD25E966380033F0FF /* ConnectedReaderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 31595CAC25E966380033F0FF /* ConnectedReaderTableViewCell.xib */; }; 315E14F42698DA24000AD5FF /* PassKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 315E14F32698DA24000AD5FF /* PassKit.framework */; }; 316837DA25CCA90C00E36B2F /* OrderStatusListDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 316837D925CCA90C00E36B2F /* OrderStatusListDataSource.swift */; }; - 3178C1F726409216000D771A /* CardReaderSettingsConnectedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3178C1F626409216000D771A /* CardReaderSettingsConnectedViewModel.swift */; }; - 3178C1FD26409360000D771A /* CardReaderSettingsConnectedViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3178C1FC26409360000D771A /* CardReaderSettingsConnectedViewModelTests.swift */; }; + 3178C1F726409216000D771A /* BluetoothCardReaderSettingsConnectedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3178C1F626409216000D771A /* BluetoothCardReaderSettingsConnectedViewModel.swift */; }; + 3178C1FD26409360000D771A /* BluetoothCardReaderSettingsConnectedViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3178C1FC26409360000D771A /* BluetoothCardReaderSettingsConnectedViewModelTests.swift */; }; 317F679826420E9D00BA2A7A /* CardReaderSettingsViewModelsOrderedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317F679726420E9D00BA2A7A /* CardReaderSettingsViewModelsOrderedList.swift */; }; 318109DC25E5B51900EE0BE7 /* ImageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 318109DB25E5B51900EE0BE7 /* ImageTableViewCell.swift */; }; 318109E225E5B55C00EE0BE7 /* ImageTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 318109E125E5B55C00EE0BE7 /* ImageTableViewCell.xib */; }; @@ -2793,8 +2793,8 @@ 31595CAC25E966380033F0FF /* ConnectedReaderTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConnectedReaderTableViewCell.xib; sourceTree = ""; }; 315E14F32698DA24000AD5FF /* PassKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PassKit.framework; path = System/Library/Frameworks/PassKit.framework; sourceTree = SDKROOT; }; 316837D925CCA90C00E36B2F /* OrderStatusListDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderStatusListDataSource.swift; sourceTree = ""; }; - 3178C1F626409216000D771A /* CardReaderSettingsConnectedViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardReaderSettingsConnectedViewModel.swift; sourceTree = ""; }; - 3178C1FC26409360000D771A /* CardReaderSettingsConnectedViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardReaderSettingsConnectedViewModelTests.swift; sourceTree = ""; }; + 3178C1F626409216000D771A /* BluetoothCardReaderSettingsConnectedViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothCardReaderSettingsConnectedViewModel.swift; sourceTree = ""; }; + 3178C1FC26409360000D771A /* BluetoothCardReaderSettingsConnectedViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothCardReaderSettingsConnectedViewModelTests.swift; sourceTree = ""; }; 317F679726420E9D00BA2A7A /* CardReaderSettingsViewModelsOrderedList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardReaderSettingsViewModelsOrderedList.swift; sourceTree = ""; }; 318109DB25E5B51900EE0BE7 /* ImageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTableViewCell.swift; sourceTree = ""; }; 318109E125E5B55C00EE0BE7 /* ImageTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageTableViewCell.xib; sourceTree = ""; }; @@ -5813,7 +5813,7 @@ 03E471C1293A1F6B001A58AD /* BluetoothReaderConnectionAlertsProvider.swift */, 03E471C3293A1F8D001A58AD /* BuiltInReaderConnectionAlertsProvider.swift */, 03E471D32942096B001A58AD /* BuiltInCardReaderPaymentAlertsProvider.swift */, - 3178C1F626409216000D771A /* CardReaderSettingsConnectedViewModel.swift */, + 3178C1F626409216000D771A /* BluetoothCardReaderSettingsConnectedViewModel.swift */, 035C6DEA273EA12D00F70406 /* SoftwareUpdateTypeProperty.swift */, 314265B02645A07800500598 /* CardReaderSettingsConnectedViewController.swift */, 3188533B2639FE5800F66A9C /* CardReaderSettingsPresentedViewViewModel.swift */, @@ -5834,7 +5834,7 @@ 31F21B07263C8E1F0035B50A /* CardReaderSettings */ = { isa = PBXGroup; children = ( - 3178C1FC26409360000D771A /* CardReaderSettingsConnectedViewModelTests.swift */, + 3178C1FC26409360000D771A /* BluetoothCardReaderSettingsConnectedViewModelTests.swift */, 31F21B01263C8E150035B50A /* CardReaderSettingsSearchingViewModelTests.swift */, 314DC4C0268D28B100444C9E /* CardReaderSettingsKnownReadersStorageTests.swift */, ); @@ -11066,7 +11066,7 @@ B9E4364E287589E200883CFA /* BadgeView.swift in Sources */, CC254F3826C43B52005F3C82 /* ShippingLabelCustomPackageFormViewModel.swift in Sources */, 02F49ADC23BF3A0100FA0BFA /* ErrorSectionHeaderView.swift in Sources */, - 3178C1F726409216000D771A /* CardReaderSettingsConnectedViewModel.swift in Sources */, + 3178C1F726409216000D771A /* BluetoothCardReaderSettingsConnectedViewModel.swift in Sources */, CC6923AC26010D8D002FB669 /* LoginProloguePageViewController.swift in Sources */, 4515C88D25D6BE540099C8E3 /* ShippingLabelAddressFormViewController.swift in Sources */, CE5F462A23AACA0A006B1A5C /* RefundDetailsDataSource.swift in Sources */, @@ -11219,7 +11219,7 @@ buildActionMask = 2147483647; files = ( 45C8B2692316B2440002FA77 /* BillingAddressTableViewCellTests.swift in Sources */, - 3178C1FD26409360000D771A /* CardReaderSettingsConnectedViewModelTests.swift in Sources */, + 3178C1FD26409360000D771A /* BluetoothCardReaderSettingsConnectedViewModelTests.swift in Sources */, 02FE89C7231FAA4100E85EF8 /* MainTabBarControllerTests.swift in Sources */, B63AAF4B254AD2C6000B28A2 /* URL+SurveyViewControllerTests.swift in Sources */, D802548C26552F41001B2CC1 /* CardPresentModalProcessingTests.swift in Sources */, diff --git a/WooCommerce/WooCommerceTests/Mocks/MockCardPresentPaymentsStoresManager.swift b/WooCommerce/WooCommerceTests/Mocks/MockCardPresentPaymentsStoresManager.swift index 6b04ac16c40..389f4004ad6 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockCardPresentPaymentsStoresManager.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockCardPresentPaymentsStoresManager.swift @@ -19,6 +19,8 @@ final class MockCardPresentPaymentsStoresManager: DefaultStoresManager { private var softwareUpdateSubject: CurrentValueSubject = .init(.none) private var paymentExtension: CardPresentPaymentGatewayExtension + var receivedActions: [CardPresentPaymentAction] = [] + init(connectedReaders: [CardReader], discoveredReaders: [CardReader], sessionManager: SessionManager, @@ -47,6 +49,7 @@ final class MockCardPresentPaymentsStoresManager: DefaultStoresManager { } private func onCardPresentPaymentAction(action: CardPresentPaymentAction) { + receivedActions.append(action) switch action { case .observeConnectedReaders(let onCompletion): onCompletion(connectedReaders) @@ -88,6 +91,8 @@ final class MockCardPresentPaymentsStoresManager: DefaultStoresManager { onCompletion(Result.success(())) case .loadActivePaymentGatewayExtension(let onCompletion): onCompletion(paymentExtension) + case .disconnect(let onCompletion): + onCompletion(Result.success(())) default: fatalError("Not available") } diff --git a/WooCommerce/WooCommerceTests/Mocks/MockCardReader.swift b/WooCommerce/WooCommerceTests/Mocks/MockCardReader.swift index 2c6223c221e..15b9b94c131 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockCardReader.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockCardReader.swift @@ -44,4 +44,15 @@ struct MockCardReader { readerType: .wisepad3, locationId: nil) } + + static func appleBuiltIn() -> CardReader { + CardReader(serial: "APPLE-BUILT-IN-SIMULATOR-1", + vendorIdentifier: "SIMULATOR", + name: "Simulated Apple Built In Reader", + status: .init(connected: false, remembered: false), + softwareVersion: nil, + batteryLevel: nil, + readerType: .appleBuiltIn, + locationId: "st_simulated") + } } diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/CardReaderSettingsConnectedViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/BluetoothCardReaderSettingsConnectedViewModelTests.swift similarity index 76% rename from WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/CardReaderSettingsConnectedViewModelTests.swift rename to WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/BluetoothCardReaderSettingsConnectedViewModelTests.swift index 61cfe7216a9..eba2ac01329 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/CardReaderSettingsConnectedViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Dashboard/CardReaderSettings/BluetoothCardReaderSettingsConnectedViewModelTests.swift @@ -1,13 +1,14 @@ import XCTest +import TestKit @testable import Yosemite @testable import WooCommerce -final class CardReaderSettingsConnectedViewModelTests: XCTestCase { +final class BluetoothCardReaderSettingsConnectedViewModelTests: XCTestCase { private var mockStoresManager: MockCardPresentPaymentsStoresManager! private var analyticsProvider: MockAnalyticsProvider! private var analyticsTracker: CardReaderConnectionAnalyticsTracker! - private var viewModel: CardReaderSettingsConnectedViewModel! + private var viewModel: BluetoothCardReaderSettingsConnectedViewModel! override func setUpWithError() throws { mockStoresManager = MockCardPresentPaymentsStoresManager( @@ -26,10 +27,11 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { analytics: analytics) analyticsTracker.setCandidateReader(MockCardReader.wisePad3()) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: analyticsTracker, - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: analyticsTracker, + delayToShowUpdateSuccessMessage: .milliseconds(1)) } func test_did_change_should_show_returns_false_if_no_connected_readers() { @@ -41,14 +43,15 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ServiceLocator.setStores(mockStoresManager) let expectation = self.expectation(description: #function) - let _ = CardReaderSettingsConnectedViewModel(didChangeShouldShow: { shouldShow in - XCTAssertTrue(shouldShow == .isFalse) - expectation.fulfill() - }, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + let _ = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: { shouldShow in + XCTAssertTrue(shouldShow == .isFalse) + expectation.fulfill() + }, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) wait(for: [expectation], timeout: Constants.expectationTimeout) } @@ -56,23 +59,25 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { func test_did_change_should_show_returns_true_if_a_reader_is_connected() { let expectation = self.expectation(description: #function) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: { shouldShow in - XCTAssertTrue(shouldShow == .isTrue) - expectation.fulfill() - }, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: { shouldShow in + XCTAssertTrue(shouldShow == .isTrue) + expectation.fulfill() + }, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) wait(for: [expectation], timeout: Constants.expectationTimeout) } func test_view_model_correctly_formats_connected_card_reader_battery_level() { - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager)) XCTAssertEqual(viewModel.connectedReaderBatteryLevel, "50% Battery") } @@ -84,20 +89,22 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ) ServiceLocator.setStores(mockStoresManager) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) XCTAssertEqual(viewModel.connectedReaderBatteryLevel, "Unknown Battery Level") } func test_view_model_correctly_formats_connected_card_reader_software_version() { - let viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + let viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) XCTAssertEqual(viewModel.connectedReaderSoftwareVersion, "Version: 1.00.03.34-SZZZ_Generic_v45-300001") } @@ -109,11 +116,12 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ) ServiceLocator.setStores(mockStoresManager) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) XCTAssertEqual(viewModel.connectedReaderSoftwareVersion, "Unknown Software Version") } @@ -157,11 +165,12 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ) ServiceLocator.setStores(mockStoresManager) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) var updateDidBegin = false @@ -459,11 +468,12 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ) ServiceLocator.setStores(mockStoresManager) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) // Then XCTAssertEqual(viewModel.connectedReaderModel, "WISEPAD_3") @@ -478,18 +488,70 @@ final class CardReaderSettingsConnectedViewModelTests: XCTestCase { ) ServiceLocator.setStores(mockStoresManager) - viewModel = CardReaderSettingsConnectedViewModel(didChangeShouldShow: nil, - configuration: Mocks.configuration, - analyticsTracker: .init(configuration: Mocks.configuration, - stores: mockStoresManager), - delayToShowUpdateSuccessMessage: .milliseconds(1)) + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) // Then XCTAssertNil(viewModel.connectedReaderModel) } + + func test_when_connected_to_a_built_in_reader_it_isnt_displayed() { + // Given + mockStoresManager = MockCardPresentPaymentsStoresManager( + connectedReaders: [MockCardReader.appleBuiltIn()], + discoveredReaders: [], + sessionManager: SessionManager.testingInstance + ) + ServiceLocator.setStores(mockStoresManager) + + // When + let shouldShow = waitFor { promise in + self.viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: { promise($0) }, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: self.mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) + } + + // Then + assertEqual(.isFalse, shouldShow) + } + + func test_when_connected_to_a_built_in_reader_it_disconnects() { + // Given + mockStoresManager = MockCardPresentPaymentsStoresManager( + connectedReaders: [MockCardReader.appleBuiltIn()], + discoveredReaders: [], + sessionManager: SessionManager.testingInstance + ) + ServiceLocator.setStores(mockStoresManager) + + // When + viewModel = BluetoothCardReaderSettingsConnectedViewModel( + didChangeShouldShow: nil, + configuration: Mocks.configuration, + analyticsTracker: .init(configuration: Mocks.configuration, + stores: mockStoresManager), + delayToShowUpdateSuccessMessage: .milliseconds(1)) + + // Then + XCTAssertNotNil(mockStoresManager.receivedActions.first(where: { action in + switch action { + case .disconnect(_): + return true + default: + return false + } + })) + } } -private extension CardReaderSettingsConnectedViewModelTests { +private extension BluetoothCardReaderSettingsConnectedViewModelTests { enum Mocks { static let configuration = CardPresentPaymentsConfiguration(country: "US") }