Skip to content

Commit add1b67

Browse files
committed
Use ProductVariationFormatter instead of extension for variation helpers
1 parent f1cde90 commit add1b67

File tree

7 files changed

+92
-38
lines changed

7 files changed

+92
-38
lines changed

WooCommerce/Classes/Model/ProductVariation+Woo.swift

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Foundation
2+
import Yosemite
3+
4+
/// Helper to format product variation details, such as variation name or attributes.
5+
///
6+
struct ProductVariationFormatter {
7+
8+
/// Generates a name for the product variation, given a list of the parent product attributes, e.g. "Blue - Any Size"
9+
/// - Parameters:
10+
/// - variation: The product variation whose name is being generated
11+
/// - allAttributes: A list of attributes from the parent `Product`
12+
///
13+
func generateName(for variation: ProductVariation, from allAttributes: [ProductAttribute]) -> String {
14+
let variationAttributes = generateAttributes(for: variation, from: allAttributes)
15+
return variationAttributes.map { $0.nameOrValue }.joined(separator: " - ")
16+
}
17+
18+
/// Generates the variation attributes, given a list of the parent product attributes.
19+
/// - Parameters:
20+
/// - variation: The product variation whose attributes are being generated
21+
/// - allAttributes: A list of attributes from the parent `Product`
22+
///
23+
func generateAttributes(for variation: ProductVariation, from allAttributes: [ProductAttribute]) -> [VariationAttributeViewModel] {
24+
return allAttributes
25+
.sorted(by: { (lhs, rhs) -> Bool in
26+
lhs.position < rhs.position
27+
})
28+
.map { attribute -> VariationAttributeViewModel in
29+
guard let variationAttribute = variation.attributes.first(where: { $0.id == attribute.attributeID && $0.name == attribute.name }) else {
30+
return VariationAttributeViewModel(name: attribute.name)
31+
}
32+
return VariationAttributeViewModel(productVariationAttribute: variationAttribute)
33+
}
34+
}
35+
}

WooCommerce/Classes/ViewRelated/Orders/Order Creation/NewOrderViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ final class NewOrderViewModel: ObservableObject {
188188
name: product.name,
189189
quantity: item.quantity,
190190
canChangeQuantity: canChangeQuantity,
191-
attributes: variation.generateVariationAttributes(from: product.attributes))
191+
attributes: ProductVariationFormatter().generateAttributes(for: variation, from: product.attributes))
192192
} else {
193193
return ProductRowViewModel(id: item.id, product: product, quantity: item.quantity, canChangeQuantity: canChangeQuantity)
194194
}

WooCommerce/Classes/ViewRelated/Orders/Order Creation/ProductsSection/AddProductVariationToOrderViewModel.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ final class AddProductVariationToOrderViewModel: ObservableObject {
4444
/// View models for each product variation row
4545
///
4646
var productVariationRows: [ProductRowViewModel] {
47-
productVariations.map { .init(productVariation: $0, name: $0.generateVariationName(from: productAttributes), canChangeQuantity: false) }
47+
return productVariations.map {
48+
.init(productVariation: $0, name: ProductVariationFormatter().generateName(for: $0, from: productAttributes), canChangeQuantity: false)
49+
}
4850
}
4951

5052
/// Closure to be invoked when a product variation is selected

WooCommerce/Classes/ViewRelated/Products/Edit Product/EditableProductVariationModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extension EditableProductVariationModel: ProductFormDataModel, TaxClassRequestab
2727
}
2828

2929
var name: String {
30-
productVariation.generateVariationName(from: allAttributes)
30+
ProductVariationFormatter().generateName(for: productVariation, from: allAttributes)
3131
}
3232

3333
var description: String? {

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,7 @@
11621162
CC254F3426C4113B005F3C82 /* ShippingLabelPackageSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC254F3326C4113B005F3C82 /* ShippingLabelPackageSelection.swift */; };
11631163
CC254F3626C437AB005F3C82 /* ShippingLabelCustomPackageForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC254F3526C437AB005F3C82 /* ShippingLabelCustomPackageForm.swift */; };
11641164
CC254F3826C43B52005F3C82 /* ShippingLabelCustomPackageFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC254F3726C43B52005F3C82 /* ShippingLabelCustomPackageFormViewModel.swift */; };
1165+
CC2E72F727B6BFB800A62872 /* ProductVariationFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC2E72F627B6BFB800A62872 /* ProductVariationFormatterTests.swift */; };
11651166
CC440E1E2770C6AF0074C264 /* ProductInOrderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC440E1D2770C6AF0074C264 /* ProductInOrderViewModel.swift */; };
11661167
CC4A4E962655273D00B75DCD /* ShippingLabelPaymentMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4A4E952655273D00B75DCD /* ShippingLabelPaymentMethods.swift */; };
11671168
CC4A4ED82655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC4A4ED72655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift */; };
@@ -1194,7 +1195,7 @@
11941195
CCDC49ED24000533003166BA /* TestCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDC49EC24000533003166BA /* TestCredentials.swift */; };
11951196
CCE4CD172667EBB100E09FD4 /* ShippingLabelPaymentMethodsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE4CD162667EBB100E09FD4 /* ShippingLabelPaymentMethodsViewModelTests.swift */; };
11961197
CCE4CD282669324300E09FD4 /* ShippingLabelPaymentMethodsTopBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE4CD272669324300E09FD4 /* ShippingLabelPaymentMethodsTopBanner.swift */; };
1197-
CCEC256A27B581E800EF9FA3 /* ProductVariation+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCEC256927B581E800EF9FA3 /* ProductVariation+Woo.swift */; };
1198+
CCEC256A27B581E800EF9FA3 /* ProductVariationFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCEC256927B581E800EF9FA3 /* ProductVariationFormatter.swift */; };
11981199
CCF87BBE279047BC00461C43 /* InfiniteScrollList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF87BBD279047BC00461C43 /* InfiniteScrollList.swift */; };
11991200
CCF87BC02790582500461C43 /* AddProductVariationToOrder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF87BBF2790582400461C43 /* AddProductVariationToOrder.swift */; };
12001201
CCFC00B523E9BD1500157A78 /* ScreenshotCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCFC00B423E9BD1500157A78 /* ScreenshotCredentials.swift */; };
@@ -2781,6 +2782,7 @@
27812782
CC254F3326C4113B005F3C82 /* ShippingLabelPackageSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPackageSelection.swift; sourceTree = "<group>"; };
27822783
CC254F3526C437AB005F3C82 /* ShippingLabelCustomPackageForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelCustomPackageForm.swift; sourceTree = "<group>"; };
27832784
CC254F3726C43B52005F3C82 /* ShippingLabelCustomPackageFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelCustomPackageFormViewModel.swift; sourceTree = "<group>"; };
2785+
CC2E72F627B6BFB800A62872 /* ProductVariationFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductVariationFormatterTests.swift; sourceTree = "<group>"; };
27842786
CC440E1D2770C6AF0074C264 /* ProductInOrderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductInOrderViewModel.swift; sourceTree = "<group>"; };
27852787
CC4A4E952655273D00B75DCD /* ShippingLabelPaymentMethods.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethods.swift; sourceTree = "<group>"; };
27862788
CC4A4ED72655478D00B75DCD /* ShippingLabelPaymentMethodsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethodsViewModel.swift; sourceTree = "<group>"; };
@@ -2815,7 +2817,7 @@
28152817
CCDC49F224006130003166BA /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = UITests.xctestplan; path = WooCommerceUITests/UITests.xctestplan; sourceTree = SOURCE_ROOT; };
28162818
CCE4CD162667EBB100E09FD4 /* ShippingLabelPaymentMethodsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethodsViewModelTests.swift; sourceTree = "<group>"; };
28172819
CCE4CD272669324300E09FD4 /* ShippingLabelPaymentMethodsTopBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaymentMethodsTopBanner.swift; sourceTree = "<group>"; };
2818-
CCEC256927B581E800EF9FA3 /* ProductVariation+Woo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductVariation+Woo.swift"; sourceTree = "<group>"; };
2820+
CCEC256927B581E800EF9FA3 /* ProductVariationFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductVariationFormatter.swift; sourceTree = "<group>"; };
28192821
CCF87BBD279047BC00461C43 /* InfiniteScrollList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfiniteScrollList.swift; sourceTree = "<group>"; };
28202822
CCF87BBF2790582400461C43 /* AddProductVariationToOrder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProductVariationToOrder.swift; sourceTree = "<group>"; };
28212823
CCFC00B423E9BD1500157A78 /* ScreenshotCredentials.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenshotCredentials.swift; sourceTree = "<group>"; };
@@ -5147,6 +5149,7 @@
51475149
D41C9F2F26D9A41F00993558 /* WhatsNew */,
51485150
D8025469265517F9001B2CC1 /* CardPresentPayments */,
51495151
5791FB4124EC834300117FD6 /* MainTabViewModelTests.swift */,
5152+
CC2E72F627B6BFB800A62872 /* ProductVariationFormatterTests.swift */,
51505153
);
51515154
path = ViewModels;
51525155
sourceTree = "<group>";
@@ -5943,7 +5946,6 @@
59435946
CECC759423D6057E00486676 /* OrderItem+Woo.swift */,
59445947
CECC759623D607C900486676 /* OrderItemRefund+Woo.swift */,
59455948
7435E58D21C0151B00216F0F /* OrderNote+Woo.swift */,
5946-
CCEC256927B581E800EF9FA3 /* ProductVariation+Woo.swift */,
59475949
45E3C8F225E7D30300102E84 /* ShippingLabelAddress+Woo.swift */,
59485950
D8C2A28723190B2300F503E9 /* StorageProductReview+Woo.swift */,
59495951
B59D1EE92190AE96009D1978 /* StorageNote+Woo.swift */,
@@ -6786,6 +6788,7 @@
67866788
D8815AE526383FC200EDAD62 /* CardPresentPayments */,
67876789
D817585C22BB5E6900289CFE /* Order Details */,
67886790
D843D5D82248EE90001BFA55 /* ManualTrackingViewModel.swift */,
6791+
CCEC256927B581E800EF9FA3 /* ProductVariationFormatter.swift */,
67896792
CECC758B23D2227000486676 /* ProductDetailsCellViewModel.swift */,
67906793
D843D5D622485B19001BFA55 /* ShippingProvidersViewModel.swift */,
67916794
D8736B5922F07D7100A14A29 /* MainTabViewModel.swift */,
@@ -8573,7 +8576,7 @@
85738576
45DB70662614CE3F0064A6CF /* Decimal+Helpers.swift in Sources */,
85748577
02E8B17C23E2C78A00A43403 /* ProductImageStatus.swift in Sources */,
85758578
0259D5FF2581F3FA003B1CD6 /* ShippingLabelPaperSizeOptionsViewController.swift in Sources */,
8576-
CCEC256A27B581E800EF9FA3 /* ProductVariation+Woo.swift in Sources */,
8579+
CCEC256A27B581E800EF9FA3 /* ProductVariationFormatter.swift in Sources */,
85778580
02EA6BFA2435E92600FFF90A /* KingfisherImageDownloader+ImageDownloadable.swift in Sources */,
85788581
7E7C5F8F2719BA7300315B61 /* ProductCategoryCellViewModel.swift in Sources */,
85798582
DEC2962326BD4E6E005A056B /* ShippingLabelCustomsFormInput.swift in Sources */,
@@ -9261,6 +9264,7 @@
92619264
9379E1A6225537D0006A6BE4 /* TestingAppDelegate.swift in Sources */,
92629265
453904F323BB88B5007C4956 /* ProductTaxStatusListSelectorCommandTests.swift in Sources */,
92639266
02BAB02124D0235F00F8B06E /* ProductPriceSettingsViewModel+ProductVariationTests.swift in Sources */,
9267+
CC2E72F727B6BFB800A62872 /* ProductVariationFormatterTests.swift in Sources */,
92649268
D802547826551DB8001B2CC1 /* CardPresentModalDisplayMessageTests.swift in Sources */,
92659269
02503C632538301400FD235D /* ProductVariationFormActionsFactory+ReadonlyVariationTests.swift in Sources */,
92669270
DE67D46926BAA82600EFE8DB /* Publisher+WithLatestFromTests.swift in Sources */,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import XCTest
2+
import Yosemite
3+
@testable import WooCommerce
4+
5+
final class ProductVariationFormatterTests: XCTestCase {
6+
7+
func test_generateName_returns_expected_name_from_single_attribute() {
8+
// Given
9+
let productAttributes = [ProductAttribute.fake().copy(attributeID: 1, name: "Color")]
10+
let variation = ProductVariation.fake().copy(attributes: [ProductVariationAttribute(id: 1, name: "Color", option: "Blue")])
11+
12+
// When
13+
let name = ProductVariationFormatter().generateName(for: variation, from: productAttributes)
14+
15+
// Then
16+
XCTAssertEqual(name, "Blue")
17+
}
18+
19+
func test_generateName_returns_expected_name_from_multiple_attributes() {
20+
// Given
21+
let productAttributes = [ProductAttribute.fake().copy(attributeID: 1, name: "Color"), ProductAttribute.fake().copy(attributeID: 2, name: "Size")]
22+
let variation = ProductVariation.fake().copy(attributes: [ProductVariationAttribute(id: 1, name: "Color", option: "Blue")])
23+
24+
// When
25+
let name = ProductVariationFormatter().generateName(for: variation, from: productAttributes)
26+
27+
// Then
28+
XCTAssertEqual(name, "Blue - Any Size")
29+
}
30+
31+
func test_generateAttributes_returns_expected_attributes() {
32+
// Given
33+
let productAttributes = [ProductAttribute.fake().copy(attributeID: 1, name: "Color"), ProductAttribute.fake().copy(attributeID: 2, name: "Size")]
34+
let variation = ProductVariation.fake().copy(attributes: [ProductVariationAttribute(id: 1, name: "Color", option: "Blue")])
35+
36+
// When
37+
let attributes = ProductVariationFormatter().generateAttributes(for: variation, from: productAttributes)
38+
39+
// Then
40+
let expectedColorAttribute = VariationAttributeViewModel(name: "Color", value: "Blue")
41+
let expectedSizeAttribute = VariationAttributeViewModel(name: "Size")
42+
XCTAssertEqual(attributes, [expectedColorAttribute, expectedSizeAttribute])
43+
}
44+
}

0 commit comments

Comments
 (0)