Skip to content

Commit 0cb2ff5

Browse files
committed
Update tests
1 parent b1fed43 commit 0cb2ff5

File tree

7 files changed

+341
-2
lines changed

7 files changed

+341
-2
lines changed

Modules/Sources/Yosemite/Stores/ProductStore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ private extension ProductStore {
573573
return onCompletion(.success(true))
574574
} else if let productType, products.contains(where: { $0.productTypeKey == productType.rawValue}) {
575575
return onCompletion(.success(true))
576-
} else if status == nil {
576+
} else if status == nil && productType == nil {
577577
return onCompletion(.success(true))
578578
}
579579
}

Modules/Tests/YosemiteTests/Mocks/Networking/Remote/MockProductsRemote.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ extension MockProductsRemote: ProductsRemoteProtocol {
370370
pageNumber: Int,
371371
pageSize: Int,
372372
productStatus: ProductStatus?,
373+
productType: ProductType?,
373374
completion: @escaping (Result<[Int64], Error>) -> Void) {
374375
// no-op
375376
}

Modules/Tests/YosemiteTests/Stores/ProductStoreTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,6 +1898,26 @@ final class ProductStoreTests: XCTestCase {
18981898
XCTAssertFalse(hasPublishedProducts)
18991899
}
19001900

1901+
func test_checkIfStoreHasProducts_returns_expected_result_when_local_storage_has_no_product_of_given_product_type_and_remote_returns_empty_array() throws {
1902+
// Given
1903+
storageManager.insertSampleProduct(readOnlyProduct: Product.fake().copy(siteID: sampleSiteID, productTypeKey: "simple"))
1904+
let productStore = ProductStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
1905+
network.simulateResponse(requestUrlSuffix: "products", filename: "products-ids-only-empty")
1906+
1907+
// When
1908+
let result: Result<Bool, Error> = waitFor { promise in
1909+
let action = ProductAction.checkIfStoreHasProducts(siteID: self.sampleSiteID, type: .booking) { result in
1910+
promise(result)
1911+
}
1912+
productStore.onAction(action)
1913+
}
1914+
1915+
// Then
1916+
XCTAssertTrue(result.isSuccess)
1917+
let hasBookableProducts = try XCTUnwrap(result.get())
1918+
XCTAssertFalse(hasBookableProducts)
1919+
}
1920+
19011921
// MARK: - ProductAction.generateProductDescription
19021922

19031923
func test_generateProductDescription_returns_text_on_success() throws {

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,6 +2862,7 @@
28622862
DEDA8DBE2B19952B0076BF0F /* ThemeSettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDA8DBD2B19952B0076BF0F /* ThemeSettingViewModel.swift */; };
28632863
DEDA8DC02B19CDC50076BF0F /* ThemeSettingViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDA8DBF2B19CDC50076BF0F /* ThemeSettingViewModelTests.swift */; };
28642864
DEDB2D262845D31900CE7D35 /* CouponAllowedEmailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDB2D252845D31900CE7D35 /* CouponAllowedEmailsViewModel.swift */; };
2865+
DEDB5D392E7AC0670022E5A1 /* BookingsTabEligibilityCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDB5D372E7AC0670022E5A1 /* BookingsTabEligibilityCheckerTests.swift */; };
28652866
DEDB886B26E8531E00981595 /* ShippingLabelPackageAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDB886A26E8531E00981595 /* ShippingLabelPackageAttributes.swift */; };
28662867
DEDC5F5E2D9E7CD5005E38BD /* WooShippingShipmentDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDC5F5D2D9E7CD5005E38BD /* WooShippingShipmentDetailsView.swift */; };
28672868
DEDC5F602D9E7CEA005E38BD /* WooShippingShipmentDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEDC5F5F2D9E7CDD005E38BD /* WooShippingShipmentDetailsViewModel.swift */; };
@@ -6099,6 +6100,7 @@
60996100
DEDA8DBD2B19952B0076BF0F /* ThemeSettingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeSettingViewModel.swift; sourceTree = "<group>"; };
61006101
DEDA8DBF2B19CDC50076BF0F /* ThemeSettingViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeSettingViewModelTests.swift; sourceTree = "<group>"; };
61016102
DEDB2D252845D31900CE7D35 /* CouponAllowedEmailsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CouponAllowedEmailsViewModel.swift; sourceTree = "<group>"; };
6103+
DEDB5D372E7AC0670022E5A1 /* BookingsTabEligibilityCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookingsTabEligibilityCheckerTests.swift; sourceTree = "<group>"; };
61026104
DEDB886A26E8531E00981595 /* ShippingLabelPackageAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPackageAttributes.swift; sourceTree = "<group>"; };
61036105
DEDC5F5D2D9E7CD5005E38BD /* WooShippingShipmentDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingShipmentDetailsView.swift; sourceTree = "<group>"; };
61046106
DEDC5F5F2D9E7CDD005E38BD /* WooShippingShipmentDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingShipmentDetailsViewModel.swift; sourceTree = "<group>"; };
@@ -10846,6 +10848,7 @@
1084610848
B958A7CF28B527FB00823EEF /* Universal Links */,
1084710849
D8F01DD125DEDC0100CE70BE /* Stripe Integration Tests */,
1084810850
5791FB4024EC833200117FD6 /* ViewModels */,
10851+
DEDB5D382E7AC0670022E5A1 /* Bookings */,
1084910852
57C2F6E324C27B0C00131012 /* Authentication */,
1085010853
CCDC49F1240060F3003166BA /* UnitTests.xctestplan */,
1085110854
D816DDBA22265D8000903E59 /* ViewRelated */,
@@ -13757,6 +13760,14 @@
1375713760
path = Themes;
1375813761
sourceTree = "<group>";
1375913762
};
13763+
DEDB5D382E7AC0670022E5A1 /* Bookings */ = {
13764+
isa = PBXGroup;
13765+
children = (
13766+
DEDB5D372E7AC0670022E5A1 /* BookingsTabEligibilityCheckerTests.swift */,
13767+
);
13768+
path = Bookings;
13769+
sourceTree = "<group>";
13770+
};
1376013771
DEDC5F5C2D9E7CB8005E38BD /* ShipmentDetails */ = {
1376113772
isa = PBXGroup;
1376213773
children = (
@@ -17738,6 +17749,7 @@
1773817749
EE57C121297E76E000BC31E7 /* TrackEventRequestNotificationHandlerTests.swift in Sources */,
1773917750
D8A8C4F32268288F001C72BF /* AddManualCustomTrackingViewModelTests.swift in Sources */,
1774017751
269B46642A16D6ED00ADA872 /* UpdateAnalyticsSettingsUseCaseTests.swift in Sources */,
17752+
DEDB5D392E7AC0670022E5A1 /* BookingsTabEligibilityCheckerTests.swift in Sources */,
1774117753
AEFF77A829786A2900667F7A /* PriceInputViewControllerTests.swift in Sources */,
1774217754
02C2756F24F5F5EE00286C04 /* ProductShippingSettingsViewModel+ProductVariationTests.swift in Sources */,
1774317755
EEBB9B402D8FE5B6008D6CE5 /* WooShippingSplitShipmentsViewModelTests.swift in Sources */,
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import Combine
2+
import Foundation
3+
import Testing
4+
import WooFoundation
5+
import Yosemite
6+
@testable import WooCommerce
7+
8+
@MainActor
9+
struct BookingsTabEligibilityCheckerTests {
10+
private var stores: MockStoresManager!
11+
private var site: Site!
12+
private var featureFlagService: MockFeatureFlagService!
13+
private var ciabEligibilityChecker: MockCIABEligibilityChecker!
14+
private let siteID: Int64 = 123
15+
16+
init() {
17+
stores = MockStoresManager(sessionManager: .makeForTesting(authenticated: true))
18+
stores.updateDefaultStore(storeID: siteID)
19+
site = Site.fake().copy(siteID: siteID)
20+
featureFlagService = MockFeatureFlagService()
21+
ciabEligibilityChecker = MockCIABEligibilityChecker(mockedIsCurrentSiteCIAB: true, mockedCIABSites: [site])
22+
}
23+
24+
// MARK: - `checkInitialVisibility` Tests
25+
26+
@Test func checkInitialVisibility_returns_true_when_cached_tab_visibility_is_enabled() async throws {
27+
// Given
28+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
29+
userDefaults[.ciabBookingsTabAvailable] = [siteID.description: true]
30+
let checker = BookingsTabEligibilityChecker(site: site,
31+
stores: stores,
32+
featureFlagService: featureFlagService,
33+
ciabEligibilityChecker: ciabEligibilityChecker,
34+
userDefaults: userDefaults)
35+
36+
// When
37+
let result = checker.checkInitialVisibility()
38+
39+
// Then
40+
#expect(result == true)
41+
}
42+
43+
@Test func checkInitialVisibility_returns_false_when_cached_tab_visibility_is_disabled() async throws {
44+
// Given
45+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
46+
userDefaults[.ciabBookingsTabAvailable] = [siteID.description: false]
47+
let checker = BookingsTabEligibilityChecker(site: site,
48+
stores: stores,
49+
featureFlagService: featureFlagService,
50+
ciabEligibilityChecker: ciabEligibilityChecker,
51+
userDefaults: userDefaults)
52+
53+
// When
54+
let result = checker.checkInitialVisibility()
55+
56+
// Then
57+
#expect(result == false)
58+
}
59+
60+
@Test func checkInitialVisibility_returns_false_when_cached_tab_visibility_is_unavailable() async throws {
61+
// Given
62+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
63+
let checker = BookingsTabEligibilityChecker(site: site,
64+
stores: stores,
65+
featureFlagService: featureFlagService,
66+
ciabEligibilityChecker: ciabEligibilityChecker,
67+
userDefaults: userDefaults)
68+
69+
// When
70+
let result = checker.checkInitialVisibility()
71+
72+
// Then
73+
#expect(result == false)
74+
}
75+
76+
// MARK: - `checkVisibility` Tests
77+
78+
@Test func checkVisibility_returns_false_when_feature_flag_is_disabled() async throws {
79+
// Given
80+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
81+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: false)
82+
let checker = BookingsTabEligibilityChecker(site: site,
83+
stores: stores,
84+
featureFlagService: featureFlagService,
85+
ciabEligibilityChecker: ciabEligibilityChecker,
86+
userDefaults: userDefaults)
87+
88+
// When
89+
let result = await checker.checkVisibility()
90+
91+
// Then
92+
#expect(result == false)
93+
}
94+
95+
@Test func checkVisibility_returns_false_when_site_is_not_CIAB() async throws {
96+
// Given
97+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
98+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
99+
let ciabEligibilityChecker = MockCIABEligibilityChecker(mockedIsCurrentSiteCIAB: false)
100+
setupStoreHasBookableProducts(hasProducts: true)
101+
let checker = BookingsTabEligibilityChecker(site: site,
102+
stores: stores,
103+
featureFlagService: featureFlagService,
104+
ciabEligibilityChecker: ciabEligibilityChecker,
105+
userDefaults: userDefaults)
106+
107+
// When
108+
let result = await checker.checkVisibility()
109+
110+
// Then
111+
#expect(result == false)
112+
}
113+
114+
@Test func checkVisibility_returns_false_when_store_has_no_bookable_products() async throws {
115+
// Given
116+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
117+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
118+
setupStoreHasBookableProducts(hasProducts: false)
119+
let checker = BookingsTabEligibilityChecker(site: site,
120+
stores: stores,
121+
featureFlagService: featureFlagService,
122+
ciabEligibilityChecker: ciabEligibilityChecker,
123+
userDefaults: userDefaults)
124+
125+
// When
126+
let result = await checker.checkVisibility()
127+
128+
// Then
129+
#expect(result == false)
130+
}
131+
132+
@Test func checkVisibility_returns_true_when_all_conditions_are_satisfied() async throws {
133+
// Given
134+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
135+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
136+
setupStoreHasBookableProducts(hasProducts: true)
137+
let checker = BookingsTabEligibilityChecker(site: site,
138+
stores: stores,
139+
featureFlagService: featureFlagService,
140+
ciabEligibilityChecker: ciabEligibilityChecker,
141+
userDefaults: userDefaults)
142+
143+
// When
144+
let result = await checker.checkVisibility()
145+
146+
// Then
147+
#expect(result == true)
148+
}
149+
150+
@Test func checkVisibility_caches_result_when_visible() async throws {
151+
// Given
152+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
153+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
154+
setupStoreHasBookableProducts(hasProducts: true)
155+
let checker = BookingsTabEligibilityChecker(site: site,
156+
stores: stores,
157+
featureFlagService: featureFlagService,
158+
ciabEligibilityChecker: ciabEligibilityChecker,
159+
userDefaults: userDefaults)
160+
161+
// When
162+
let result = await checker.checkVisibility()
163+
164+
// Then
165+
#expect(result == true)
166+
#expect(userDefaults.loadCachedBookingsTabVisibility(siteID: siteID) == true)
167+
}
168+
169+
@Test func checkVisibility_caches_result_when_not_visible() async throws {
170+
// Given
171+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
172+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
173+
setupStoreHasBookableProducts(hasProducts: false)
174+
let checker = BookingsTabEligibilityChecker(site: site,
175+
stores: stores,
176+
featureFlagService: featureFlagService,
177+
ciabEligibilityChecker: ciabEligibilityChecker,
178+
userDefaults: userDefaults)
179+
180+
// When
181+
let result = await checker.checkVisibility()
182+
183+
// Then
184+
#expect(result == false)
185+
#expect(userDefaults.loadCachedBookingsTabVisibility(siteID: siteID) == false)
186+
}
187+
188+
@Test func checkVisibility_handles_store_check_failure_gracefully() async throws {
189+
// Given
190+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
191+
let featureFlagService = MockFeatureFlagService(isCIABBookingsEnabled: true)
192+
setupStoreHasBookableProducts(hasProducts: false, shouldFail: true)
193+
let checker = BookingsTabEligibilityChecker(site: site,
194+
stores: stores,
195+
featureFlagService: featureFlagService,
196+
ciabEligibilityChecker: ciabEligibilityChecker,
197+
userDefaults: userDefaults)
198+
199+
// When
200+
let result = await checker.checkVisibility()
201+
202+
// Then
203+
#expect(result == false)
204+
}
205+
206+
// MARK: - UserDefaults Extension Tests
207+
208+
@Test func userDefaults_loadCachedBookingsTabVisibility_returns_false_when_no_cache() async throws {
209+
// Given
210+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
211+
212+
// When
213+
let result = userDefaults.loadCachedBookingsTabVisibility(siteID: siteID)
214+
215+
// Then
216+
#expect(result == false)
217+
}
218+
219+
@Test func userDefaults_loadCachedBookingsTabVisibility_returns_cached_value() async throws {
220+
// Given
221+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
222+
userDefaults[.ciabBookingsTabAvailable] = [siteID.description: true]
223+
224+
// When
225+
let result = userDefaults.loadCachedBookingsTabVisibility(siteID: siteID)
226+
227+
// Then
228+
#expect(result == true)
229+
}
230+
231+
@Test func userDefaults_cacheBookingsTabVisibility_stores_value_correctly() async throws {
232+
// Given
233+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
234+
235+
// When
236+
userDefaults.cacheBookingsTabVisibility(siteID: siteID, isVisible: true)
237+
238+
// Then
239+
#expect(userDefaults[.ciabBookingsTabAvailable] == [siteID.description: true])
240+
}
241+
242+
@Test func userDefaults_handles_multiple_sites() async throws {
243+
// Given
244+
let siteID2: Int64 = 456
245+
let userDefaults = UserDefaults(suiteName: UUID().uuidString)!
246+
247+
// When
248+
userDefaults[.ciabBookingsTabAvailable] = [
249+
siteID.description: true,
250+
siteID2.description: false
251+
]
252+
253+
// Then
254+
#expect(userDefaults.loadCachedBookingsTabVisibility(siteID: siteID) == true)
255+
#expect(userDefaults.loadCachedBookingsTabVisibility(siteID: siteID2) == false)
256+
}
257+
}
258+
259+
// MARK: - Private Helpers
260+
261+
private extension BookingsTabEligibilityCheckerTests {
262+
263+
func setupStoreHasBookableProducts(hasProducts: Bool, shouldFail: Bool = false) {
264+
stores.whenReceivingAction(ofType: ProductAction.self) { action in
265+
switch action {
266+
case .checkIfStoreHasProducts(_, _, let type, let completion):
267+
if type == .booking {
268+
if shouldFail {
269+
completion(.failure(NSError(domain: "test", code: 500)))
270+
} else {
271+
completion(.success(hasProducts))
272+
}
273+
}
274+
default:
275+
break
276+
}
277+
}
278+
}
279+
}

0 commit comments

Comments
 (0)