Skip to content

Commit 288c42c

Browse files
committed
Remove plugin matching by name use case in ProductListViewModel with test cases on the change.
1 parent a965ae4 commit 288c42c

File tree

8 files changed

+128
-36
lines changed

8 files changed

+128
-36
lines changed

Modules/Sources/Yosemite/Tools/Plugin.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public enum Plugin: Equatable, CaseIterable {
44
case wooCommerce
55
case wooSubscriptions
66
case wooShipmentTracking
7+
case wooSquare
78

89
/// File name without extension in the plugin path.
910
/// Full plugin path is like `woocommerce/woocommerce.php`.
@@ -15,6 +16,8 @@ public enum Plugin: Equatable, CaseIterable {
1516
return "woocommerce-subscriptions"
1617
case .wooShipmentTracking:
1718
return "woocommerce-shipment-tracking"
19+
case .wooSquare:
20+
return "woocommerce-square"
1821
}
1922
}
2023
}

Modules/Sources/Yosemite/Tools/Plugins/PluginsService.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ public protocol PluginsServiceProtocol {
2121
func loadPluginInStorage(siteID: Int64, plugin: Plugin, isActive: Bool?) -> SystemPlugin?
2222
}
2323

24+
public extension PluginsServiceProtocol {
25+
func isPluginActiveInStorage(siteID: Int64, plugin: Plugin) -> Bool {
26+
let plugin = loadPluginInStorage(siteID: siteID, plugin: plugin, isActive: true)
27+
return plugin != nil && plugin?.active == true
28+
}
29+
}
30+
2431
public class PluginsService: PluginsServiceProtocol {
2532
private let storageManager: StorageManagerType
2633

WooCommerce/Classes/Extensions/SitePlugin+Woo.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ extension SitePlugin {
77
public static let WCSubscriptions = ["WooCommerce Subscriptions", "Woo Subscriptions"]
88
public static let WCProductBundles = ["WooCommerce Product Bundles", "Woo Product Bundles"]
99
public static let WCCompositeProducts = "WooCommerce Composite Products"
10-
public static let square = "WooCommerce Square"
1110
public static let WCGiftCards = ["WooCommerce Gift Cards", "Woo Gift Cards"]
1211
public static let GoogleForWooCommerce = ["Google Listings and Ads", "Google for WooCommerce"]
1312
}

WooCommerce/Classes/ViewRelated/Products/ProductsListViewModel.swift

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class ProductListViewModel: ProductsListViewModelProtocol {
1717

1818
let siteID: Int64
1919
private let stores: StoresManager
20+
private let pluginsService: PluginsServiceProtocol
2021

2122
private(set) var selectedProducts: Set<Product> = .init()
2223

@@ -32,13 +33,15 @@ final class ProductListViewModel: ProductsListViewModelProtocol {
3233
stores: StoresManager = ServiceLocator.stores,
3334
favoriteProductsUseCase: FavoriteProductsUseCase? = nil,
3435
barcodeScannerItemFinder: BarcodeScannerItemFinder = BarcodeScannerItemFinder(),
35-
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService) {
36+
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService,
37+
pluginsService: PluginsServiceProtocol = PluginsService(storageManager: ServiceLocator.storageManager)) {
3638
self.siteID = siteID
3739
self.stores = stores
3840
self.featureFlagService = featureFlagService
3941
self.wooSubscriptionProductsEligibilityChecker = WooSubscriptionProductsEligibilityChecker(siteID: siteID)
4042
self.barcodeScannerItemFinder = barcodeScannerItemFinder
4143
self.favoriteProductsUseCase = favoriteProductsUseCase ?? DefaultFavoriteProductsUseCase(siteID: siteID)
44+
self.pluginsService = pluginsService
4245

4346
Task { @MainActor [weak self] in
4447
await self?.loadFavoriteProductIDs()
@@ -199,23 +202,21 @@ final class ProductListViewModel: ProductsListViewModelProtocol {
199202
// If the plugin is active, we'll hide the inventory scanner button
200203
// More details: https://wp.me/pdfdoF-2Nq
201204
func scanToUpdateInventoryButtonShouldBeVisible(completion: @escaping (Bool) -> (Void)) {
202-
isPluginActive(SitePlugin.SupportedPlugin.square, completion: { [weak self] isPluginActive in
203-
guard let self else { return }
204-
switch isPluginActive {
205-
case true:
206-
completion(false)
207-
case false:
208-
guard self.featureFlagService.isFeatureFlagEnabled(.scanToUpdateInventory),
209-
UIImagePickerController.isSourceTypeAvailable(.camera) else {
210-
return completion(false)
211-
}
212-
// If all conditions are met, scan to update inventory should be visible:
213-
// 1. No Square plugin
214-
// 2. Feature flag
215-
// 3. Camera is available
216-
completion(true)
205+
let isPluginActive = isPluginActive(.wooSquare)
206+
switch isPluginActive {
207+
case true:
208+
completion(false)
209+
case false:
210+
guard featureFlagService.isFeatureFlagEnabled(.scanToUpdateInventory),
211+
UIImagePickerController.isSourceTypeAvailable(.camera) else {
212+
return completion(false)
217213
}
218-
})
214+
// If all conditions are met, scan to update inventory should be visible:
215+
// 1. No Square plugin
216+
// 2. Feature flag
217+
// 3. Camera is available
218+
completion(true)
219+
}
219220
}
220221

221222
/// Loads favorite product IDs
@@ -225,10 +226,7 @@ final class ProductListViewModel: ProductsListViewModelProtocol {
225226
favoriteProductIDs = await favoriteProductsUseCase.favoriteProductIDs()
226227
}
227228

228-
private func isPluginActive(_ plugin: String, completion: @escaping (Bool) -> (Void)) {
229-
let action = SystemStatusAction.fetchSystemPluginListWithNameList(siteID: siteID, systemPluginNameList: [plugin]) { plugin in
230-
completion(plugin?.active == true)
231-
}
232-
stores.dispatch(action)
229+
private func isPluginActive(_ plugin: Plugin) -> Bool {
230+
pluginsService.isPluginActiveInStorage(siteID: siteID, plugin: plugin)
233231
}
234232
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
0227958D237A51F300787C63 /* OptionsTableViewController+Styles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0227958C237A51F300787C63 /* OptionsTableViewController+Styles.swift */; };
203203
02279590237A5DC900787C63 /* AztecUnorderedListFormatBarCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0227958F237A5DC900787C63 /* AztecUnorderedListFormatBarCommandTests.swift */; };
204204
02279594237A60FD00787C63 /* AztecHeaderFormatBarCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02279593237A60FD00787C63 /* AztecHeaderFormatBarCommandTests.swift */; };
205+
0229008A2E3019040028F6D7 /* MockPluginsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022900892E3019020028F6D7 /* MockPluginsService.swift */; };
205206
02291737270BEFF200449FA0 /* ProcessConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02291736270BEFF200449FA0 /* ProcessConfiguration.swift */; };
206207
0229ED00258767BC00C336F8 /* ShippingLabelPrintingStepContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0229ECFF258767BC00C336F8 /* ShippingLabelPrintingStepContentView.swift */; };
207208
022A45EE237BADA6001417F0 /* Product+ProductFormTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 022A45ED237BADA6001417F0 /* Product+ProductFormTests.swift */; };
@@ -3380,6 +3381,7 @@
33803381
0227958C237A51F300787C63 /* OptionsTableViewController+Styles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OptionsTableViewController+Styles.swift"; sourceTree = "<group>"; };
33813382
0227958F237A5DC900787C63 /* AztecUnorderedListFormatBarCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecUnorderedListFormatBarCommandTests.swift; sourceTree = "<group>"; };
33823383
02279593237A60FD00787C63 /* AztecHeaderFormatBarCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecHeaderFormatBarCommandTests.swift; sourceTree = "<group>"; };
3384+
022900892E3019020028F6D7 /* MockPluginsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPluginsService.swift; sourceTree = "<group>"; };
33833385
02291736270BEFF200449FA0 /* ProcessConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessConfiguration.swift; sourceTree = "<group>"; };
33843386
0229ECFF258767BC00C336F8 /* ShippingLabelPrintingStepContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPrintingStepContentView.swift; sourceTree = "<group>"; };
33853387
022A45ED237BADA6001417F0 /* Product+ProductFormTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Product+ProductFormTests.swift"; sourceTree = "<group>"; };
@@ -9976,6 +9978,7 @@
99769978
746791642108D853007CF1DC /* Mocks */ = {
99779979
isa = PBXGroup;
99789980
children = (
9981+
022900892E3019020028F6D7 /* MockPluginsService.swift */,
99799982
02F36C3F2E0130E900DD8CB6 /* MockPOSEligibilityService.swift */,
99809983
02B8E41A2DFBC33C001D01FD /* MockPOSEligibilityChecker.swift */,
99819984
01F067EC2D0C5D56001C5805 /* MockLocationService.swift */,
@@ -17016,6 +17019,7 @@
1701617019
450C2CB324D0803000D570DD /* ProductSettingsRowsTests.swift in Sources */,
1701717020
EEB221A529B97F8400662A12 /* CouponInputTransformerTests.swift in Sources */,
1701817021
45AF9DAF265CFAB4001EB794 /* MockShippingLabelCarrierRate.swift in Sources */,
17022+
0229008A2E3019040028F6D7 /* MockPluginsService.swift in Sources */,
1701917023
CC593A6726EA116300EF0E04 /* ShippingLabelAddNewPackageViewModelTests.swift in Sources */,
1702017024
DE68B84326FAF17A00C86CFB /* DefaultConnectivityObserver.swift in Sources */,
1702117025
455A2FDB246B1349000CA72C /* ProductVisibilityTests.swift in Sources */,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Yosemite
2+
3+
final class MockPluginsService: PluginsServiceProtocol {
4+
var pluginToReturn: SystemPlugin = .fake()
5+
var pluginToReturnForLoadPluginInStorage: SystemPlugin?
6+
7+
func waitForPluginInStorage(siteID: Int64, pluginPath: String, isActive: Bool) async -> SystemPlugin {
8+
pluginToReturn
9+
}
10+
11+
func loadPluginInStorage(siteID: Int64, plugin: Yosemite.Plugin, isActive: Bool?) -> SystemPlugin? {
12+
pluginToReturnForLoadPluginInStorage
13+
}
14+
}

WooCommerce/WooCommerceTests/ViewRelated/Products/ProductListViewModelTests.swift

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,86 @@ final class ProductListViewModelTests: XCTestCase {
341341
XCTAssertFalse(result)
342342
}
343343

344+
func test_scanToUpdateInventoryButton_when_square_plugin_is_active_then_should_not_be_visible() {
345+
// Given
346+
let featureFlagService = MockFeatureFlagService(isScanToUpdateInventoryEnabled: true)
347+
let pluginsService = MockPluginsService()
348+
pluginsService.pluginToReturnForLoadPluginInStorage = .fake().copy(
349+
siteID: sampleSiteID,
350+
plugin: "woocommerce-square/woocommerce-square.php",
351+
active: true
352+
)
353+
354+
let viewModel = ProductListViewModel(
355+
siteID: sampleSiteID,
356+
stores: storesManager,
357+
featureFlagService: featureFlagService,
358+
pluginsService: pluginsService
359+
)
360+
361+
// When
362+
let result = waitFor { promise in
363+
viewModel.scanToUpdateInventoryButtonShouldBeVisible { result in
364+
promise(result)
365+
}
366+
}
367+
368+
// Then
369+
XCTAssertFalse(result)
370+
}
371+
372+
func test_scanToUpdateInventoryButton_when_square_plugin_is_inactive_then_should_be_visible() {
373+
// Given
374+
let featureFlagService = MockFeatureFlagService(isScanToUpdateInventoryEnabled: true)
375+
let pluginsService = MockPluginsService()
376+
pluginsService.pluginToReturnForLoadPluginInStorage = .fake().copy(
377+
siteID: sampleSiteID,
378+
plugin: "woocommerce-square/woocommerce-square.php",
379+
active: false
380+
)
381+
382+
let viewModel = ProductListViewModel(
383+
siteID: sampleSiteID,
384+
stores: storesManager,
385+
featureFlagService: featureFlagService,
386+
pluginsService: pluginsService
387+
)
388+
389+
// When
390+
let result = waitFor { promise in
391+
viewModel.scanToUpdateInventoryButtonShouldBeVisible { result in
392+
promise(result)
393+
}
394+
}
395+
396+
// Then
397+
XCTAssertTrue(result)
398+
}
399+
400+
func test_scanToUpdateInventoryButton_when_square_plugin_is_not_installed_then_should_be_visible() {
401+
// Given
402+
let featureFlagService = MockFeatureFlagService(isScanToUpdateInventoryEnabled: true)
403+
let pluginsService = MockPluginsService()
404+
pluginsService.pluginToReturnForLoadPluginInStorage = nil // Plugin not found
405+
406+
let viewModel = ProductListViewModel(
407+
siteID: sampleSiteID,
408+
stores: storesManager,
409+
featureFlagService: featureFlagService,
410+
pluginsService: pluginsService
411+
)
412+
413+
// When
414+
let result = waitFor { promise in
415+
viewModel.scanToUpdateInventoryButtonShouldBeVisible { result in
416+
promise(result)
417+
}
418+
}
419+
420+
// Then
421+
XCTAssertTrue(result)
422+
}
423+
344424
// MARK: Favorite products
345425
//
346426
func test_it_loads_favorite_products_on_init() {

WooCommerce/WooCommerceTests/ViewRelated/Settings/POS/LegacyPOSTabEligibilityCheckerTests.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -423,19 +423,6 @@ private extension LegacyPOSTabEligibilityCheckerTests {
423423
}
424424
}
425425

426-
private final class MockPluginsService: PluginsServiceProtocol {
427-
var pluginToReturn: SystemPlugin = .fake()
428-
var pluginToReturnForLoadPluginInStorage: SystemPlugin?
429-
430-
func waitForPluginInStorage(siteID: Int64, pluginPath: String, isActive: Bool) async -> SystemPlugin {
431-
pluginToReturn
432-
}
433-
434-
func loadPluginInStorage(siteID: Int64, plugin: Yosemite.Plugin, isActive: Bool?) -> SystemPlugin? {
435-
pluginToReturnForLoadPluginInStorage
436-
}
437-
}
438-
439426
private final class MockSelectedSiteSettings: SelectedSiteSettingsProtocol {
440427
var mockSettingsStream: AnyPublisher<(siteID: Int64, settings: [SiteSetting], source: SettingsUpdateSource), Never>?
441428
var siteSettings: [SiteSetting] = []

0 commit comments

Comments
 (0)