Skip to content

Commit 7a348f9

Browse files
committed
Add optional attributes text to product row
1 parent 31329a6 commit 7a348f9

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,19 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
4949
///
5050
private let manageStock: Bool
5151

52-
/// Label showing product details: stock status, price, and variations (if any).
52+
/// Product variation attributes
53+
///
54+
private let variationAttributes: [VariationAttributeViewModel]?
55+
56+
/// Label showing product details. Can include stock status or attributes, price, and variations (if any).
5357
///
5458
var productDetailsLabel: String {
55-
let stockLabel = createStockText()
59+
// When provided, the variation attributes should replace the stock status
60+
let stockOrAttributesLabel = variationAttributes != nil ? createAttributesText() : createStockText()
5661
let priceLabel = createPriceText()
5762
let variationsLabel = createVariationsText()
5863

59-
return [stockLabel, priceLabel, variationsLabel]
64+
return [stockOrAttributesLabel, priceLabel, variationsLabel]
6065
.compactMap({ $0 })
6166
.joined(separator: "")
6267
}
@@ -100,6 +105,7 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
100105
canChangeQuantity: Bool,
101106
imageURL: URL?,
102107
numberOfVariations: Int = 0,
108+
variationAttributes: [VariationAttributeViewModel]? = nil,
103109
currencyFormatter: CurrencyFormatter = CurrencyFormatter(currencySettings: ServiceLocator.currencySettings)) {
104110
self.id = id ?? productOrVariationID.description
105111
self.productOrVariationID = productOrVariationID
@@ -114,6 +120,7 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
114120
self.imageURL = imageURL
115121
self.currencyFormatter = currencyFormatter
116122
self.numberOfVariations = numberOfVariations
123+
self.variationAttributes = variationAttributes
117124
}
118125

119126
/// Initialize `ProductRowViewModel` with a `Product`
@@ -153,6 +160,7 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
153160
name: String,
154161
quantity: Decimal = 1,
155162
canChangeQuantity: Bool,
163+
attributes: [VariationAttributeViewModel]? = nil,
156164
currencyFormatter: CurrencyFormatter = CurrencyFormatter(currencySettings: ServiceLocator.currencySettings)) {
157165
let imageURL: URL?
158166
if let encodedImageURLString = productVariation.image?.src.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
@@ -172,6 +180,7 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
172180
quantity: quantity,
173181
canChangeQuantity: canChangeQuantity,
174182
imageURL: imageURL,
183+
variationAttributes: attributes,
175184
currencyFormatter: currencyFormatter)
176185
}
177186

@@ -191,6 +200,15 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
191200
}
192201
}
193202

203+
/// Create the attributes text based on the provided product variation attributes.
204+
///
205+
private func createAttributesText() -> String? {
206+
guard let attributes = variationAttributes else {
207+
return nil
208+
}
209+
return attributes.map { $0.nameOrValue }.joined(separator: ", ")
210+
}
211+
194212
/// Create the price text based on a product's price and quantity.
195213
///
196214
private func createPriceText() -> String? {

WooCommerce/WooCommerceTests/ViewRelated/Orders/Order Creation/ProductRowViewModelTests.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,37 @@ class ProductRowViewModelTests: XCTestCase {
156156
XCTAssertEqual(viewModel.productDetailsLabel, expectedProductDetailsLabel)
157157
}
158158

159+
func test_view_model_creates_expected_label_for_variation_with_provided_attributes() {
160+
// Given
161+
let variation = ProductVariation.fake().copy(attributes: [ProductVariationAttribute(id: 1, name: "Color", option: "Blue")], stockStatus: .inStock)
162+
let attributes = [VariationAttributeViewModel(name: "Color", value: "Blue"), VariationAttributeViewModel(name: "Size")]
163+
164+
// When
165+
let viewModel = ProductRowViewModel(productVariation: variation, name: "", canChangeQuantity: false, attributes: attributes)
166+
167+
// Then
168+
let expectedAttributesText = "Blue, Any Size"
169+
let unexpectedStockText = "In stock"
170+
XCTAssertTrue(viewModel.productDetailsLabel.contains(expectedAttributesText),
171+
"Expected label to contain \"\(expectedAttributesText)\" but actual label was \"\(viewModel.productDetailsLabel)\"")
172+
XCTAssertFalse(viewModel.productDetailsLabel.contains(unexpectedStockText))
173+
}
174+
175+
func test_view_model_creates_expected_label_for_variation_without_provided_attributes() {
176+
// Given
177+
let variation = ProductVariation.fake().copy(attributes: [ProductVariationAttribute(id: 1, name: "Color", option: "Blue")], stockStatus: .inStock)
178+
179+
// When
180+
let viewModel = ProductRowViewModel(productVariation: variation, name: "", canChangeQuantity: false)
181+
182+
// Then
183+
let expectedStockText = "In stock"
184+
let unexpectedAttributesText = "Blue"
185+
XCTAssertTrue(viewModel.productDetailsLabel.contains(expectedStockText),
186+
"Expected label to contain \"\(expectedStockText)\" but actual label was \"\(viewModel.productDetailsLabel)\"")
187+
XCTAssertFalse(viewModel.productDetailsLabel.contains(unexpectedAttributesText))
188+
}
189+
159190
func test_sku_label_is_formatted_correctly_for_product_with_sku() {
160191
// Given
161192
let sku = "123456"

0 commit comments

Comments
 (0)