Skip to content

Commit 6f9cd77

Browse files
committed
Add test barcode scanner setup step
1 parent b180138 commit 6f9cd77

File tree

9 files changed

+212
-0
lines changed

9 files changed

+212
-0
lines changed

WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ class PointOfSaleBarcodeScannerSetupFlow {
9494
PointOfSaleBarcodeScannerSetupStep(content: {
9595
PointOfSaleBarcodeScannerPairingView(scanner: scannerType)
9696
}),
97+
PointOfSaleBarcodeScannerSetupStep(
98+
content: {
99+
PointOfSaleBarcodeScannerTestBarcodeView(
100+
scanTester: PointOfSaleBarcodeScannerSetupScanTester(
101+
onTestPass: { [weak self] in
102+
self?.nextStep()
103+
},
104+
onTestFailure: {},
105+
barcodeDefinition: .ean13)
106+
)
107+
},
108+
buttonCustomization: PointOfSaleBarcodeScannerBackOnlyButtonCustomization()
109+
)
97110
// TODO: Add more steps for Star BSH-20B WOOMOB-696
98111
]
99112
case .tbcScanner:
@@ -120,6 +133,27 @@ class PointOfSaleBarcodeScannerSetupFlow {
120133
}
121134
}
122135

136+
@available(iOS 17.0, *)
137+
struct PointOfSaleBarcodeScannerBackOnlyButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization {
138+
func customizeButtons(for flow: PointOfSaleBarcodeScannerSetupFlow) -> PointOfSaleFlowButtonConfiguration {
139+
return PointOfSaleFlowButtonConfiguration(
140+
primaryButton: nil,
141+
secondaryButton: PointOfSaleFlowButtonConfiguration.ButtonConfig(
142+
title: Localization.backButtonTitle,
143+
action: { flow.previousStep() }
144+
)
145+
)
146+
}
147+
148+
private enum Localization {
149+
static let backButtonTitle = NSLocalizedString(
150+
"pos.barcodeScannerSetup.back.button.title",
151+
value: "Back",
152+
comment: "Title for the back button in barcode scanner setup navigation"
153+
)
154+
}
155+
}
156+
123157
// MARK: - Private Localization Extension
124158
@available(iOS 17.0, *)
125159
private extension PointOfSaleBarcodeScannerSetupFlow {

WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,22 @@ struct PointOfSaleBarcodeScannerSetupStep {
6767
self.buttonCustomization = buttonCustomization
6868
}
6969
}
70+
71+
// MARK: - Test Barcodes
72+
enum PointOfSaleBarcodeScannerTestBarcode {
73+
case ean13
74+
75+
var barcodeAsset: PointOfSaleAssets {
76+
switch self {
77+
case .ean13:
78+
return .testEan13Barcode
79+
}
80+
}
81+
82+
var expectedValue: String {
83+
switch self {
84+
case .ean13:
85+
return "1234567890128"
86+
}
87+
}
88+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Foundation
2+
3+
struct PointOfSaleBarcodeScannerSetupScanTester {
4+
private let onTestPass: () -> Void
5+
private let onTestFailure: () -> Void
6+
private let barcodeDefinition: PointOfSaleBarcodeScannerTestBarcode
7+
8+
init(onTestPass: @escaping () -> Void, onTestFailure: @escaping () -> Void, barcodeDefinition: PointOfSaleBarcodeScannerTestBarcode) {
9+
self.onTestPass = onTestPass
10+
self.onTestFailure = onTestFailure
11+
self.barcodeDefinition = barcodeDefinition
12+
}
13+
14+
var barcode: PointOfSaleAssets {
15+
barcodeDefinition.barcodeAsset
16+
}
17+
18+
func handleScan(_ scanResult: Result<String, Error>) {
19+
switch scanResult {
20+
case .success(barcodeDefinition.expectedValue):
21+
onTestPass()
22+
case .success, .failure:
23+
onTestFailure()
24+
}
25+
}
26+
}

WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,27 @@ private extension PointOfSaleBarcodeScannerPairingView {
9090
}
9191
}
9292

93+
@available(iOS 17.0, *)
94+
struct PointOfSaleBarcodeScannerTestBarcodeView: View {
95+
let scanTester: PointOfSaleBarcodeScannerSetupScanTester
96+
97+
var body: some View {
98+
PointOfSaleBarcodeScannerBarcodeView(title: Localization.title,
99+
instruction: Localization.instruction,
100+
barcode: scanTester.barcode)
101+
.barcodeScanning { result in
102+
scanTester.handleScan(result)
103+
}
104+
}
105+
}
106+
107+
@available(iOS 17.0, *)
108+
private extension PointOfSaleBarcodeScannerTestBarcodeView {
109+
enum Localization {
110+
static let title = "Test your scanner"
111+
static let instruction = "Scan the barcode to test your scanner"
112+
}
113+
}
93114

94115
// MARK: - Button Customizations
95116
@available(iOS 17.0, *)

WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ enum PointOfSaleAssets: CaseIterable {
1414
case shoppingBags
1515
case successCheck
1616
case coupons
17+
//TODO: WOOMOB-793 Update the imagesets for these barcodes to vector/dark mode friendly images
1718
case starBsh20SetupBarcode
19+
case testEan13Barcode
1820

1921
var imageName: String {
2022
switch self {
@@ -46,6 +48,8 @@ enum PointOfSaleAssets: CaseIterable {
4648
"coupons"
4749
case .starBsh20SetupBarcode:
4850
"star-bsh20-setup-barcode"
51+
case .testEan13Barcode:
52+
"test-ean13-barcode"
4953
}
5054
}
5155
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "barcode-1-2.png",
5+
"idiom" : "universal"
6+
}
7+
],
8+
"info" : {
9+
"author" : "xcode",
10+
"version" : 1
11+
}
12+
}
3.57 KB
Loading

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,8 @@
871871
207823E32C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E22C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift */; };
872872
207823E52C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E42C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift */; };
873873
207823E92C5D3A1700025A59 /* POSErrorExclamationMark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E82C5D3A1700025A59 /* POSErrorExclamationMark.swift */; };
874+
207CEA852E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */; };
875+
207CEA882E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */; };
874876
207D2D232CFDCCBF00F79204 /* MockPOSOrderableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207D2D222CFDCCBF00F79204 /* MockPOSOrderableItem.swift */; };
875877
207E71CB2C60F765008540FC /* MockPOSOrderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207E71CA2C60F765008540FC /* MockPOSOrderService.swift */; };
876878
2084B7A22C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2084B7A12C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift */; };
@@ -4043,6 +4045,8 @@
40434045
207823E22C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift; sourceTree = "<group>"; };
40444046
207823E42C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift; sourceTree = "<group>"; };
40454047
207823E82C5D3A1700025A59 /* POSErrorExclamationMark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSErrorExclamationMark.swift; sourceTree = "<group>"; };
4048+
207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerSetupScanTester.swift; sourceTree = "<group>"; };
4049+
207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerSetupScanTesterTests.swift; sourceTree = "<group>"; };
40464050
207D2D222CFDCCBF00F79204 /* MockPOSOrderableItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MockPOSOrderableItem.swift; path = ../Modules/Tests/YosemiteTests/Mocks/MockPOSOrderableItem.swift; sourceTree = SOURCE_ROOT; };
40474051
207E71CA2C60F765008540FC /* MockPOSOrderService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPOSOrderService.swift; sourceTree = "<group>"; };
40484052
2084B7A12C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentPaymentsModalButtonViewModelTests.swift; sourceTree = "<group>"; };
@@ -7229,6 +7233,7 @@
72297233
026A502D2D2F8087002C42C2 /* Presentation */ = {
72307234
isa = PBXGroup;
72317235
children = (
7236+
207CEA862E1FD6D80023EC35 /* Barcode Scanner Setup */,
72327237
20D5575E2DFAE3D500D9EC8B /* Barcode Scanning */,
72337238
01AB2D132DDC7CD000AA67FD /* POSItemActionHandlerFactoryTests.swift */,
72347239
01AB2D112DDC7AD100AA67FD /* PointOfSaleItemListAnalyticsTrackerTests.swift */,
@@ -8234,6 +8239,14 @@
82348239
path = "Reader Messages";
82358240
sourceTree = "<group>";
82368241
};
8242+
207CEA862E1FD6D80023EC35 /* Barcode Scanner Setup */ = {
8243+
isa = PBXGroup;
8244+
children = (
8245+
207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */,
8246+
);
8247+
path = "Barcode Scanner Setup";
8248+
sourceTree = "<group>";
8249+
};
82378250
2084B7A02C7768E200EFBD2E /* Connection Alerts */ = {
82388251
isa = PBXGroup;
82398252
children = (
@@ -8313,6 +8326,7 @@
83138326
20C3DB202E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupModels.swift */,
83148327
20C3DB212E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupViews.swift */,
83158328
208C0F092E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift */,
8329+
207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */,
83168330
20C3DB282E1E6FBA00CF7D3B /* PointOfSaleFlowButtonsView.swift */,
83178331
);
83188332
path = "Barcode Scanner Setup";
@@ -15457,6 +15471,7 @@
1545715471
CE22E3F72170E23C005A6BEF /* PrivacySettingsViewController.swift in Sources */,
1545815472
02222BD02D5AFE4F00FB97D2 /* POSButtonProgressViewStyle.swift in Sources */,
1545915473
021125482577CC650075AD2A /* ShippingLabelDetailsViewModel.swift in Sources */,
15474+
207CEA852E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift in Sources */,
1546015475
2004E2D82C08E56300D62521 /* CardPresentPaymentOnboardingPresentationEvent.swift in Sources */,
1546115476
68D1BEDD2900E4180074A29E /* CustomerSearchUICommand.swift in Sources */,
1546215477
316837DA25CCA90C00E36B2F /* OrderStatusListDataSource.swift in Sources */,
@@ -17598,6 +17613,7 @@
1759817613
B9CB14E02A42E246005912C2 /* BarcodeScannerErrorNoticeFactoryTests.swift in Sources */,
1759917614
6856D49DB7DCF4D87745C0B1 /* MockPushNotificationsManager.swift in Sources */,
1760017615
4569D3C925DC065B00CDC3E2 /* SiteAddressTests.swift in Sources */,
17616+
207CEA882E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift in Sources */,
1760117617
EE289AFE2C9D9CF0004AB1A6 /* ProductCreationAIEligibilityCheckerTests.swift in Sources */,
1760217618
CC4D1E7925EE415D00B6E4E7 /* RenameAttributesViewModelTests.swift in Sources */,
1760317619
458BAC702C57E38F009440EA /* ProductPasswordEligibilityUseCaseTests.swift in Sources */,
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import Testing
2+
@testable import WooCommerce
3+
4+
struct PointOfSaleBarcodeScannerSetupScanTesterTests {
5+
6+
@Test func test_scanTester_calls_onTestPass_when_scan_received_for_expected_barcode() {
7+
// Given a test EAN13 barcode
8+
let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13
9+
var onTestPassCalled = false
10+
var onTestFailureCalled = false
11+
12+
let sut = PointOfSaleBarcodeScannerSetupScanTester(
13+
onTestPass: { onTestPassCalled = true },
14+
onTestFailure: { onTestFailureCalled = true },
15+
barcodeDefinition: expectedBarcode)
16+
17+
// When the barcode is scanned
18+
sut.handleScan(.success(expectedBarcode.expectedValue))
19+
20+
// Then it calls the pass closure
21+
#expect(onTestPassCalled == true)
22+
#expect(onTestFailureCalled == false)
23+
}
24+
25+
@Test func test_scanTester_calls_onTestFailure_when_scan_received_for_unexpected_barcode() {
26+
// Given a test EAN13 barcode
27+
let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13
28+
var onTestPassCalled = false
29+
var onTestFailureCalled = false
30+
31+
let sut = PointOfSaleBarcodeScannerSetupScanTester(
32+
onTestPass: { onTestPassCalled = true },
33+
onTestFailure: { onTestFailureCalled = true },
34+
barcodeDefinition: expectedBarcode)
35+
36+
// When an unexpected barcode is scanned
37+
sut.handleScan(.success("9999999999999"))
38+
39+
// Then it calls the failure closure
40+
#expect(onTestPassCalled == false)
41+
#expect(onTestFailureCalled == true)
42+
}
43+
44+
@Test func test_scanTester_calls_onTestFailure_when_scan_fails() {
45+
// Given a test EAN13 barcode
46+
let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13
47+
var onTestPassCalled = false
48+
var onTestFailureCalled = false
49+
50+
let sut = PointOfSaleBarcodeScannerSetupScanTester(
51+
onTestPass: { onTestPassCalled = true },
52+
onTestFailure: { onTestFailureCalled = true },
53+
barcodeDefinition: expectedBarcode)
54+
55+
// When the scan fails
56+
sut.handleScan(.failure(TestError.scanFailed))
57+
58+
// Then it calls the failure closure
59+
#expect(onTestPassCalled == false)
60+
#expect(onTestFailureCalled == true)
61+
}
62+
63+
private enum TestError: Error {
64+
case scanFailed
65+
}
66+
67+
@Test func test_scanTester_provides_correct_barcode_asset() {
68+
// Given a test EAN13 barcode
69+
let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13
70+
71+
let sut = PointOfSaleBarcodeScannerSetupScanTester(
72+
onTestPass: {},
73+
onTestFailure: {},
74+
barcodeDefinition: expectedBarcode)
75+
76+
// Then it provides the correct barcode asset
77+
#expect(sut.barcode == .testEan13Barcode)
78+
}
79+
80+
}

0 commit comments

Comments
 (0)