Skip to content

Commit b26626e

Browse files
committed
Toggle cellular for full sync on catalog endpoint
1 parent 29fc16b commit b26626e

File tree

7 files changed

+146
-39
lines changed

7 files changed

+146
-39
lines changed

Modules/Sources/Networking/Remote/POSCatalogSyncRemote.swift

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ public protocol POSCatalogSyncRemoteProtocol {
3939
/// - Parameters:
4040
/// - siteID: Site ID to download catalog for.
4141
/// - downloadURL: Download URL of the catalog file.
42+
/// - allowCellular: Should cellular data be used if required.
4243
/// - Returns: List of products and variations in the POS catalog.
43-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
44-
func downloadCatalog(for siteID: Int64, downloadURL: String) async throws -> POSCatalogResponse
44+
func downloadCatalog(for siteID: Int64,
45+
downloadURL: String,
46+
allowCellular: Bool) async throws -> POSCatalogResponse
4547

4648
/// Loads POS products for full sync.
4749
///
@@ -87,7 +89,6 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
8789
/// - pageNumber: Page number for pagination.
8890
/// - Returns: Paginated list of POS products.
8991
///
90-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
9192
public func loadProducts(modifiedAfter: Date, siteID: Int64, pageNumber: Int)
9293
async throws -> PagedItems<POSProduct> {
9394
let path = Path.products
@@ -120,7 +121,6 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
120121
/// - pageNumber: Page number for pagination.
121122
/// - Returns: Paginated list of POS product variations.
122123
///
123-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
124124
public func loadProductVariations(modifiedAfter: Date, siteID: Int64, pageNumber: Int) async throws -> PagedItems<POSProductVariation> {
125125
let path = Path.variations
126126
let parameters = [
@@ -153,7 +153,6 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
153153
/// - siteID: Site ID to generate catalog for.
154154
/// - Returns: Catalog job response with job ID.
155155
///
156-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
157156
public func requestCatalogGeneration(for siteID: Int64, forceGeneration: Bool) async throws -> POSCatalogRequestResponse {
158157
let path = "products/catalog"
159158
let parameters: [String: Any] = [
@@ -176,14 +175,17 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
176175
/// - Parameters:
177176
/// - siteID: Site ID to download catalog for.
178177
/// - downloadURL: Download URL of the catalog file.
178+
/// - allowCellular: Should cellular data be used if required.
179179
/// - Returns: List of products and variations in the POS catalog.
180-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
181-
public func downloadCatalog(for siteID: Int64, downloadURL: String) async throws -> POSCatalogResponse {
180+
public func downloadCatalog(for siteID: Int64,
181+
downloadURL: String,
182+
allowCellular: Bool) async throws -> POSCatalogResponse {
182183
// TODO: WOOMOB-1173 - move download task to the background using `URLSessionConfiguration.background`
183184
guard let url = URL(string: downloadURL) else {
184185
throw NetworkError.invalidURL
185186
}
186-
let request = URLRequest(url: url)
187+
var request = URLRequest(url: url)
188+
request.allowsCellularAccess = allowCellular
187189
let mapper = ListMapper<POSProduct>(siteID: siteID)
188190
let items = try await enqueue(request, mapper: mapper)
189191
let variationProductTypeKey = "variation"
@@ -200,7 +202,6 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
200202
/// - pageNumber: Page number for pagination.
201203
/// - Returns: Paginated list of POS products.
202204
///
203-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
204205
public func loadProducts(siteID: Int64, pageNumber: Int) async throws -> PagedItems<POSProduct> {
205206
let path = Path.products
206207
let parameters = [
@@ -230,7 +231,6 @@ public class POSCatalogSyncRemote: Remote, POSCatalogSyncRemoteProtocol {
230231
/// - pageNumber: Page number for pagination.
231232
/// - Returns: Paginated list of POS product variations.
232233
///
233-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
234234
public func loadProductVariations(siteID: Int64, pageNumber: Int) async throws -> PagedItems<POSProductVariation> {
235235
let path = Path.variations
236236
let parameters = [
@@ -331,7 +331,6 @@ private extension POSCatalogSyncRemote {
331331
// MARK: - Response Models
332332

333333
/// Response from catalog generation request.
334-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
335334
public struct POSCatalogRequestResponse: Decodable {
336335
/// Current status of the catalog generation job.
337336
public let status: POSCatalogStatus
@@ -353,7 +352,6 @@ public enum POSCatalogStatus: String, Decodable {
353352
}
354353

355354
/// POS catalog from download.
356-
// periphery:ignore - TODO - remove this periphery ignore comment when this endpoint is integrated with catalog sync
357355
public struct POSCatalogResponse {
358356
public let products: [POSProduct]
359357
public let variations: [POSProductVariation]

Modules/Sources/Yosemite/Tools/POS/POSCatalogFullSyncService.swift

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ public protocol POSCatalogFullSyncServiceProtocol {
1414
/// - Parameters:
1515
/// - siteID: The site ID to sync catalog for
1616
/// - regenerateCatalog: Whether to force the catalog generation
17+
/// - allowCellular: Should cellular data be used if required.
1718
/// - Returns: The synced catalog containing products and variations
18-
func startFullSync(for siteID: Int64, regenerateCatalog: Bool) async throws -> POSCatalog
19+
func startFullSync(for siteID: Int64, regenerateCatalog: Bool, allowCellular: Bool) async throws -> POSCatalog
1920
}
2021

2122
/// POS catalog from full sync.
@@ -68,14 +69,20 @@ public final class POSCatalogFullSyncService: POSCatalogFullSyncServiceProtocol
6869

6970
// MARK: - Protocol Conformance
7071

71-
public func startFullSync(for siteID: Int64, regenerateCatalog: Bool = false) async throws -> POSCatalog {
72-
DDLogInfo("🔄 Starting full catalog sync for site ID: \(siteID) with regenerateCatalog: \(regenerateCatalog)")
72+
public func startFullSync(for siteID: Int64,
73+
regenerateCatalog: Bool = false,
74+
allowCellular: Bool) async throws -> POSCatalog {
75+
DDLogInfo("🔄 Starting full catalog sync for site ID: \(siteID) with regenerateCatalog: \(regenerateCatalog) " +
76+
"and allowCellular: \(allowCellular)")
7377

7478
do {
7579
// Sync from network
7680
let catalog: POSCatalog
7781
if usesCatalogAPI {
78-
catalog = try await loadCatalogFromCatalogAPI(for: siteID, syncRemote: syncRemote, regenerateCatalog: regenerateCatalog)
82+
catalog = try await loadCatalogFromCatalogAPI(for: siteID,
83+
syncRemote: syncRemote,
84+
regenerateCatalog: regenerateCatalog,
85+
allowCellular: allowCellular)
7986
} else {
8087
catalog = try await loadCatalog(for: siteID, syncRemote: syncRemote)
8188
}
@@ -114,9 +121,15 @@ private extension POSCatalogFullSyncService {
114121
return POSCatalog(products: products, variations: variations, syncDate: syncStartDate)
115122
}
116123

117-
func loadCatalogFromCatalogAPI(for siteID: Int64, syncRemote: POSCatalogSyncRemoteProtocol, regenerateCatalog: Bool) async throws -> POSCatalog {
124+
func loadCatalogFromCatalogAPI(for siteID: Int64,
125+
syncRemote: POSCatalogSyncRemoteProtocol,
126+
regenerateCatalog: Bool,
127+
allowCellular: Bool) async throws -> POSCatalog {
118128
let downloadStartTime = CFAbsoluteTimeGetCurrent()
119-
let catalog = try await downloadCatalog(for: siteID, syncRemote: syncRemote, regenerateCatalog: regenerateCatalog)
129+
let catalog = try await downloadCatalog(for: siteID,
130+
syncRemote: syncRemote,
131+
regenerateCatalog: regenerateCatalog,
132+
allowCellular: allowCellular)
120133
let downloadTime = CFAbsoluteTimeGetCurrent() - downloadStartTime
121134
DDLogInfo("🟣 Catalog download completed - Time: \(String(format: "%.2f", downloadTime))s")
122135

@@ -125,7 +138,10 @@ private extension POSCatalogFullSyncService {
125138
}
126139

127140
private extension POSCatalogFullSyncService {
128-
func downloadCatalog(for siteID: Int64, syncRemote: POSCatalogSyncRemoteProtocol, regenerateCatalog: Bool) async throws -> POSCatalogResponse {
141+
func downloadCatalog(for siteID: Int64,
142+
syncRemote: POSCatalogSyncRemoteProtocol,
143+
regenerateCatalog: Bool,
144+
allowCellular: Bool) async throws -> POSCatalogResponse {
129145
DDLogInfo("🟣 Starting catalog request...")
130146

131147
// 1. Requests catalog until download URL is available.
@@ -143,7 +159,7 @@ private extension POSCatalogFullSyncService {
143159
throw POSCatalogSyncError.invalidData
144160
}
145161
DDLogInfo("🟣 Catalog ready for download: \(downloadURL)")
146-
return try await syncRemote.downloadCatalog(for: siteID, downloadURL: downloadURL)
162+
return try await syncRemote.downloadCatalog(for: siteID, downloadURL: downloadURL, allowCellular: allowCellular)
147163
}
148164

149165
func pollForCatalogCompletion(siteID: Int64, syncRemote: POSCatalogSyncRemoteProtocol) async throws -> String {

Modules/Sources/Yosemite/Tools/POS/POSCatalogSyncCoordinator.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,13 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
117117

118118
emitSyncState(isFirstSync ? .initialSyncStarted(siteID: siteID) : .syncStarted(siteID: siteID))
119119

120+
let allowCellular = isFirstSync || siteSettings.getPOSLocalCatalogCellularDataAllowed(siteID: siteID)
120121
DDLogInfo("🔄 POSCatalogSyncCoordinator starting full sync for site \(siteID)")
121122

122123
do {
123-
_ = try await fullSyncService.startFullSync(for: siteID, regenerateCatalog: regenerateCatalog)
124+
_ = try await fullSyncService.startFullSync(for: siteID,
125+
regenerateCatalog: regenerateCatalog,
126+
allowCellular: allowCellular)
124127
emitSyncState(.syncCompleted(siteID: siteID))
125128
} catch AFError.explicitlyCancelled, is CancellationError {
126129
if isFirstSync {

Modules/Tests/NetworkingTests/Remote/POSCatalogSyncRemoteTests.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ struct POSCatalogSyncRemoteTests {
638638

639639
// When
640640
network.simulateResponse(requestUrlSuffix: "", filename: "pos-catalog-download-mixed")
641-
let catalog = try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL)
641+
let catalog = try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL, allowCellular: true)
642642

643643
// Then
644644
#expect(catalog.products.count == 2)
@@ -700,7 +700,7 @@ struct POSCatalogSyncRemoteTests {
700700

701701
// When
702702
network.simulateResponse(requestUrlSuffix: "", filename: "empty-data-array")
703-
let catalog = try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL)
703+
let catalog = try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL, allowCellular: true)
704704

705705
// Then
706706
#expect(catalog.products.count == 0)
@@ -714,7 +714,7 @@ struct POSCatalogSyncRemoteTests {
714714

715715
// When/Then
716716
await #expect(throws: NetworkError.invalidURL) {
717-
try await remote.downloadCatalog(for: sampleSiteID, downloadURL: emptyURL)
717+
try await remote.downloadCatalog(for: sampleSiteID, downloadURL: emptyURL, allowCellular: true)
718718
}
719719
}
720720

@@ -725,7 +725,22 @@ struct POSCatalogSyncRemoteTests {
725725

726726
// When/Then
727727
await #expect(throws: NetworkError.notFound()) {
728-
try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL)
728+
try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL, allowCellular: true)
729729
}
730730
}
731+
732+
@Test(arguments: [true, false])
733+
func downloadCatalog_sets_allowsCellularAccess_on_request(allowCellular: Bool) async throws {
734+
// Given
735+
let remote = POSCatalogSyncRemote(network: network)
736+
let downloadURL = "https://example.com/catalog.json"
737+
network.simulateResponse(requestUrlSuffix: "", filename: "empty-data-array")
738+
739+
// When
740+
_ = try await remote.downloadCatalog(for: sampleSiteID, downloadURL: downloadURL, allowCellular: allowCellular)
741+
742+
// Then
743+
let urlRequest = try #require(network.requestsForResponseData.last as? URLRequest)
744+
#expect(urlRequest.allowsCellularAccess == allowCellular)
745+
}
731746
}

Modules/Tests/YosemiteTests/Mocks/MockPOSCatalogSyncRemote.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ final class MockPOSCatalogSyncRemote: POSCatalogSyncRemoteProtocol {
1919
private(set) var lastIncrementalProductsModifiedAfter: Date?
2020
private(set) var lastIncrementalVariationsModifiedAfter: Date?
2121
private(set) var lastCatalogRequestForceGeneration: Bool?
22+
private(set) var lastCatalogDownloadAllowCellular: Bool?
2223

2324
// Fallback result when no specific page result is configured
2425
private let fallbackResult = PagedItems(items: [] as [POSProduct], hasMorePages: false, totalItems: 0)
@@ -142,7 +143,8 @@ final class MockPOSCatalogSyncRemote: POSCatalogSyncRemoteProtocol {
142143
}
143144
}
144145

145-
func downloadCatalog(for siteID: Int64, downloadURL: String) async throws -> POSCatalogResponse {
146+
func downloadCatalog(for siteID: Int64, downloadURL: String, allowCellular: Bool) async throws -> POSCatalogResponse {
147+
lastCatalogDownloadAllowCellular = allowCellular
146148
switch catalogDownloadResult {
147149
case .success(let response):
148150
return response

Modules/Tests/YosemiteTests/Tools/POS/POSCatalogFullSyncServiceTests.swift

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct POSCatalogFullSyncServiceTests {
2828
mockSyncRemote.setVariationResult(pageNumber: 1, result: .success(PagedItems(items: expectedVariations, hasMorePages: false, totalItems: 0)))
2929

3030
// When
31-
let result = try await sut.startFullSync(for: sampleSiteID)
31+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
3232

3333
// Then
3434
#expect(result.products.count == expectedProducts.count)
@@ -50,7 +50,7 @@ struct POSCatalogFullSyncServiceTests {
5050
])
5151

5252
// When
53-
let result = try await sut.startFullSync(for: sampleSiteID)
53+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
5454

5555
// Then
5656
#expect(result.products.count == 3)
@@ -71,7 +71,7 @@ struct POSCatalogFullSyncServiceTests {
7171
])
7272

7373
// When
74-
let result = try await sut.startFullSync(for: sampleSiteID)
74+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
7575

7676
// Then
7777
#expect(result.variations.count == 4)
@@ -91,7 +91,7 @@ struct POSCatalogFullSyncServiceTests {
9191
mockSyncRemote.setVariationResult(pageNumber: 1, result: .success(PagedItems(items: [], hasMorePages: false, totalItems: 0)))
9292

9393
// When
94-
let result = try await sut.startFullSync(for: sampleSiteID)
94+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
9595

9696
// Then - Should stop after empty page
9797
#expect(result.products.count == 1)
@@ -112,7 +112,7 @@ struct POSCatalogFullSyncServiceTests {
112112
mockSyncRemote.setVariationResult(pageNumber: 1, result: .success(PagedItems(items: [], hasMorePages: false, totalItems: 0)))
113113

114114
// When
115-
let result = try await sut.startFullSync(for: sampleSiteID)
115+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
116116

117117
// Then
118118
#expect(result.products.count == 5)
@@ -127,7 +127,7 @@ struct POSCatalogFullSyncServiceTests {
127127

128128
// When/Then
129129
await #expect(throws: expectedError) {
130-
_ = try await sut.startFullSync(for: sampleSiteID)
130+
_ = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
131131
}
132132
}
133133

@@ -174,7 +174,7 @@ struct POSCatalogFullSyncServiceTests {
174174
let service = POSCatalogFullSyncService(syncRemote: mockSyncRemote,
175175
batchSize: customBatchSize,
176176
persistenceService: mockPersistenceService)
177-
_ = try await service.startFullSync(for: sampleSiteID)
177+
_ = try await service.startFullSync(for: sampleSiteID, allowCellular: true)
178178

179179
// Then
180180
#expect(await mockSyncRemote.loadProductsCallCount.value == 5)
@@ -199,7 +199,7 @@ struct POSCatalogFullSyncServiceTests {
199199
)
200200

201201
// When
202-
let result = try await sut.startFullSync(for: sampleSiteID)
202+
let result = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
203203

204204
// Then
205205
#expect(result.products.count == 1)
@@ -223,7 +223,7 @@ struct POSCatalogFullSyncServiceTests {
223223

224224
// When/Then
225225
await #expect(throws: expectedError) {
226-
_ = try await sut.startFullSync(for: sampleSiteID)
226+
_ = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
227227
}
228228
}
229229

@@ -242,7 +242,7 @@ struct POSCatalogFullSyncServiceTests {
242242

243243
// When/Then
244244
await #expect(throws: expectedError) {
245-
_ = try await sut.startFullSync(for: sampleSiteID)
245+
_ = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
246246
}
247247
}
248248

@@ -262,7 +262,7 @@ struct POSCatalogFullSyncServiceTests {
262262

263263
// When/Then
264264
await #expect(throws: expectedError) {
265-
_ = try await sut.startFullSync(for: sampleSiteID)
265+
_ = try await sut.startFullSync(for: sampleSiteID, allowCellular: true)
266266
}
267267
}
268268

@@ -280,9 +280,29 @@ struct POSCatalogFullSyncServiceTests {
280280
)
281281

282282
// When
283-
_ = try await sut.startFullSync(for: sampleSiteID, regenerateCatalog: regenerateCatalog)
283+
_ = try await sut.startFullSync(for: sampleSiteID, regenerateCatalog: regenerateCatalog, allowCellular: true)
284284

285285
// Then
286286
#expect(mockSyncRemote.lastCatalogRequestForceGeneration == regenerateCatalog)
287287
}
288+
289+
@Test(arguments: [true, false])
290+
func startFullSync_with_catalog_API_passes_allowCellular_to_downloadCatalog(allowCellular: Bool) async throws {
291+
// Given
292+
mockSyncRemote.catalogRequestResult = .success(.init(status: .complete, downloadURL: "https://example.com/catalog.json"))
293+
mockSyncRemote.catalogDownloadResult = .success(.init(products: [], variations: []))
294+
295+
let sut = POSCatalogFullSyncService(
296+
syncRemote: mockSyncRemote,
297+
batchSize: 2,
298+
persistenceService: mockPersistenceService,
299+
usesCatalogAPI: true
300+
)
301+
302+
// When
303+
_ = try await sut.startFullSync(for: sampleSiteID, regenerateCatalog: false, allowCellular: allowCellular)
304+
305+
// Then
306+
#expect(mockSyncRemote.lastCatalogDownloadAllowCellular == allowCellular)
307+
}
288308
}

0 commit comments

Comments
 (0)