Skip to content

Commit

Permalink
Initialize view model with order items instead of entire order
Browse files Browse the repository at this point in the history
  • Loading branch information
rachelmcr committed Sep 13, 2024
1 parent bc5fde5 commit cfb9cc7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WooFoundation
/// Provides view data for `WooShippingItems`.
///
final class WooShippingItemsViewModel: ObservableObject {
private let order: Order
private let orderItems: [OrderItem]
private let currencyFormatter: CurrencyFormatter

/// Label with the total number of items to ship.
Expand All @@ -17,9 +17,9 @@ final class WooShippingItemsViewModel: ObservableObject {
/// View models for rows of items to ship.
@Published var itemRows: [WooShippingItemRowViewModel] = []

init(order: Order,
init(orderItems: [OrderItem],
currencySettings: CurrencySettings = ServiceLocator.currencySettings) {
self.order = order
self.orderItems = orderItems
self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings)

configureSectionHeader()
Expand All @@ -44,9 +44,7 @@ private extension WooShippingItemsViewModel {
/// Generates a label with the total number of items to ship.
///
func generateItemsCountLabel() -> String {
let itemsCount = order.items
.map { $0.quantity }
.reduce(0, +)
let itemsCount = orderItems.map(\.quantity).reduce(0, +)
return Localization.itemsCount(itemsCount)
}

Expand All @@ -55,21 +53,22 @@ private extension WooShippingItemsViewModel {
///
func generateItemsDetailLabel() -> String {
let formattedWeight = "1 kg" // TODO-13550: Get the total weight (each product/variation * item quantity) and weight unit
let formattedPrice = currencyFormatter.formatAmount(order.total) ?? order.total
let itemsTotal = orderItems.map { $0.price.decimalValue * $0.quantity }.reduce(0, +)
let formattedPrice = currencyFormatter.formatAmount(itemsTotal) ?? itemsTotal.description

return "\(formattedWeight)\(formattedPrice)"
}

/// Generates an item row view model for each order item.
///
func generateItemRows() -> [WooShippingItemRowViewModel] {
order.items.map { item in
return WooShippingItemRowViewModel(imageUrl: nil, // TODO-13550: Get the product/variation imageURL
quantityLabel: item.quantity.description,
name: item.name,
detailsLabel: generateItemRowDetailsLabel(for: item),
weightLabel: "", // TODO-13550: Get the product/variation weight
priceLabel: currencyFormatter.formatAmount(item.total) ?? item.total)
orderItems.map { item in
WooShippingItemRowViewModel(imageUrl: nil, // TODO-13550: Get the product/variation imageURL
quantityLabel: item.quantity.description,
name: item.name,
detailsLabel: generateItemRowDetailsLabel(for: item),
weightLabel: "", // TODO-13550: Get the product/variation weight
priceLabel: currencyFormatter.formatAmount(item.price.decimalValue) ?? item.price.description)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ import Yosemite
/// Provides view data for `WooShippingCreateLabelsView`.
///
final class WooShippingCreateLabelsViewModel: ObservableObject {
private let order: Order

/// View model for the items to ship.
@Published private(set) var items: WooShippingItemsViewModel

init(order: Order) {
self.order = order
self.items = WooShippingItemsViewModel(order: order)
self.items = WooShippingItemsViewModel(orderItems: order.items)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,58 @@ final class WooShippingItemsViewModelTests: XCTestCase {

func test_inits_with_expected_values_from_order_items() throws {
// Given
let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt",
quantity: 1,
total: "20",
attributes: [OrderItemAttribute.fake().copy(value: "Red")]),
OrderItem.fake().copy(quantity: 1)])
let orderItems = [OrderItem.fake().copy(name: "Shirt",
quantity: 1,
price: 10,
attributes: [OrderItemAttribute.fake().copy(value: "Red")]),
OrderItem.fake().copy(quantity: 1, price: 2.5)]

// When
let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings)
let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings)

// Then
// Section header labels have expected values
assertEqual("2 items", viewModel.itemsCountLabel)
assertEqual("1 kg • $22.50", viewModel.itemsDetailLabel)
assertEqual("1 kg • $12.50", viewModel.itemsDetailLabel)

// Section rows have expected values
assertEqual(2, viewModel.itemRows.count)
let firstItem = try XCTUnwrap(viewModel.itemRows.first)
assertEqual("Shirt", firstItem.name)
assertEqual("1", firstItem.quantityLabel)
assertEqual("$20.00", firstItem.priceLabel)
assertEqual("$10.00", firstItem.priceLabel)
assertEqual("Red", firstItem.detailsLabel)
}

func test_total_items_count_handles_items_with_quantity_greater_than_one() {
// Given
let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt", quantity: 2, total: "20"), OrderItem.fake().copy(quantity: 1)])
let orderItems = [OrderItem.fake().copy(quantity: 2), OrderItem.fake().copy(quantity: 1)]

// When
let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings)
let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings)

// Then
assertEqual("3 items", viewModel.itemsCountLabel)
}

func test_total_items_details_handles_total_price_for_items_with_quantity_greater_than_one() {
// Given
let orderItems = [OrderItem.fake().copy(quantity: 2, price: 10), OrderItem.fake().copy(quantity: 1, price: 2.5)]

// When
let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings)

// Then
assertEqual("1 kg • $22.50", viewModel.itemsDetailLabel)
}

func test_item_row_details_label_handles_items_with_multiple_attributes() throws {
// Given
let order = Order.fake().copy(total: "22.5", items: [OrderItem.fake().copy(name: "Shirt",
quantity: 2,
total: "20",
attributes: [OrderItemAttribute.fake().copy(value: "Red"),
OrderItemAttribute.fake().copy(value: "Small")])])
let orderItems = [OrderItem.fake().copy(attributes: [OrderItemAttribute.fake().copy(value: "Red"),
OrderItemAttribute.fake().copy(value: "Small")])]

// When
let viewModel = WooShippingItemsViewModel(order: order, currencySettings: currencySettings)
let viewModel = WooShippingItemsViewModel(orderItems: orderItems, currencySettings: currencySettings)

// Then
let firstItem = try XCTUnwrap(viewModel.itemRows.first)
Expand Down

0 comments on commit cfb9cc7

Please sign in to comment.