Skip to content

Commit

Permalink
Revert changes to ConfigurableBundleProductViewModelTests due to inef…
Browse files Browse the repository at this point in the history
…fectiveness
  • Loading branch information
staskus committed Jan 10, 2025
1 parent 3b53e04 commit ba142d2
Showing 1 changed file with 52 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import XCTest
import Yosemite
@testable import WooCommerce
import Combine

final class ConfigurableBundleProductViewModelTests: XCTestCase {
private var stores: MockStoresManager!
Expand All @@ -24,7 +23,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {

// MARK: - Validation

func test_validation_is_failure_when_bundle_item_is_invalid() async throws {
func test_validation_is_failure_when_bundle_item_is_invalid() throws {
// Given
// The bundle size has to be 5.
let product = Product.fake().copy(productID: 1, bundleMinSize: nil, bundleMaxSize: 5, bundledItems: [
Expand All @@ -39,7 +38,10 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
stores: self.stores,
onConfigure: { _ in })

await assertBundleItemsLoaded(on: viewModel)
// The products are loaded async before the bundle item view models are set.
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

XCTAssertTrue(viewModel.isConfigureEnabled)

Expand All @@ -58,7 +60,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
XCTAssertTrue(viewModel.isConfigureEnabled)
}

func test_validation_is_success_when_bundle_size_matches() async throws {
func test_validation_is_success_when_bundle_size_matches() throws {
// Given
// The bundle size has to be 5.
let product = Product.fake().copy(productID: 1, bundleMinSize: 5, bundleMaxSize: 5, bundledItems: [
Expand All @@ -75,7 +77,9 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

XCTAssertFalse(viewModel.isConfigureEnabled)
XCTAssertTrue(viewModel.validationState.isFailure)
Expand All @@ -93,7 +97,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
XCTAssertTrue(viewModel.validationState.isSuccess)
}

func test_validation_is_success_when_default_bundle_size_matches() async throws {
func test_validation_is_success_when_default_bundle_size_matches() throws {
// Given
// The bundle size has to be 5.
let product = Product.fake().copy(productID: 1, bundleMinSize: 5, bundleMaxSize: 5, bundledItems: [
Expand All @@ -110,13 +114,15 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

XCTAssertTrue(viewModel.isConfigureEnabled)
XCTAssertTrue(viewModel.validationState.isSuccess)
}

func test_validation_is_failure_when_bundle_size_exceeds_max() async throws {
func test_validation_is_failure_when_bundle_size_exceeds_max() throws {
// Given
let product = Product.fake().copy(productID: 1, bundleMaxSize: 5, bundledItems: [
// One optional item
Expand All @@ -132,7 +138,9 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

// Optional non-selected bundle item quantity is not counted for the bundle size.
let optionalItem = try XCTUnwrap(viewModel.bundleItemViewModels[0])
Expand All @@ -149,7 +157,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
XCTAssertTrue(viewModel.validationState.isFailure)
}

func test_validation_is_failure_when_bundle_size_smaller_than_min() async throws {
func test_validation_is_failure_when_bundle_size_smaller_than_min() throws {
// Given
let product = Product.fake().copy(productID: 1, bundleMinSize: 5, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -163,7 +171,9 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

let item = try XCTUnwrap(viewModel.bundleItemViewModels[0])
item.quantity = 4
Expand All @@ -175,7 +185,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {

// MARK: - `loadProductsErrorMessage`

func test_loadProductsErrorMessage_is_set_when_retrieveProducts_fails() async throws {
func test_loadProductsErrorMessage_is_set_when_retrieveProducts_fails() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -189,10 +199,12 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// Then
await assertProductsErrorMessage(on: viewModel, equals: "Cannot load the bundled products. Please try again.")
waitUntil {
viewModel.loadProductsErrorMessage != nil
}
}

func test_errorMessage_is_reset_when_retrieveProducts_fails_then_succeeds_after_retry() async throws {
func test_errorMessage_is_reset_when_retrieveProducts_fails_then_succeeds_after_retry() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -204,18 +216,20 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
childItems: [],
stores: stores,
onConfigure: { _ in })

await assertProductsErrorMessage(on: viewModel, equals: "Cannot load the bundled products. Please try again.")

waitUntil {
viewModel.loadProductsErrorMessage != nil
}
let productsFromRetrieval = [1, 2].map { Product.fake().copy(productID: $0) }
mockProductsRetrieval(result: .success((products: productsFromRetrieval, hasNextPage: false)))
viewModel.retry()

// Then
await assertProductsErrorMessage(on: viewModel, equals: nil)
waitUntil {
viewModel.loadProductsErrorMessage == nil
}
}

func test_configure_invokes_onConfigure_if_configuration_is_changed() async throws {
func test_configure_invokes_onConfigure_if_configuration_is_changed() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -224,32 +238,34 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
mockProductsRetrieval(result: .success((products: productsFromRetrieval, hasNextPage: false)))

var configurationsFromOnConfigure: [BundledProductConfiguration] = []
let expectation = expectation(description: "onConfigure closure invoked")
let viewModel = ConfigurableBundleProductViewModel(product: product,
childItems: [],
stores: self.stores,
onConfigure: { configurations in
configurationsFromOnConfigure = configurations
expectation.fulfill()
})

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

// When altering the bundle item
let bundleItemViewModel = try XCTUnwrap(viewModel.bundleItemViewModels.first)
bundleItemViewModel.quantity = 8

viewModel.configure()

await fulfillment(of: [expectation])
waitUntil {
configurationsFromOnConfigure.isNotEmpty
}

// Then
let configurationFromOnConfigure = try XCTUnwrap(configurationsFromOnConfigure.first)
XCTAssertEqual(configurationFromOnConfigure.quantity, 8)
}

func test_configure_does_not_invoke_onConfigure_if_configuration_is_the_same_when_bundle_is_not_new() async throws {
func test_configure_does_not_invoke_onConfigure_if_configuration_is_the_same_when_bundle_is_not_new() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -267,13 +283,15 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
})

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

// When
viewModel.configure()
}

func test_configure_invokes_onConfigure_if_configuration_is_the_same_when_bundle_is_new() async throws {
func test_configure_invokes_onConfigure_if_configuration_is_the_same_when_bundle_is_new() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2, minQuantity: 2, maxQuantity: 8, defaultQuantity: 6)
Expand All @@ -292,7 +310,9 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
})

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

// When
viewModel.configure()
Expand All @@ -302,8 +322,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
XCTAssertEqual(configurationFromOnConfigure.quantity, 6)
}

// Slowest
func test_bundleItemViewModels_have_correct_quantity_when_parent_order_item_quantity_is_more_than_one() async throws {
func test_bundleItemViewModels_have_correct_quantity_when_parent_order_item_quantity_is_more_than_one() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -322,7 +341,9 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
onConfigure: { _ in })

// The products are loaded async before the bundle item view models are set.
await assertBundleItemsLoaded(on: viewModel)
waitUntil {
viewModel.bundleItemViewModels.isNotEmpty
}

// Then
let bundleItemViewModel = try XCTUnwrap(viewModel.bundleItemViewModels.first)
Expand All @@ -331,7 +352,7 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {

// MARK: - Analytics

func test_configure_tracks_orderFormBundleProductConfigurationSaveTapped_event() async throws {
func test_configure_tracks_orderFormBundleProductConfigurationSaveTapped_event() throws {
// Given
let product = Product.fake().copy(productID: 1, bundledItems: [
.fake().copy(productID: 2)
Expand All @@ -344,7 +365,6 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
stores: stores,
analytics: analytics,
onConfigure: { _ in })
await assertBundleItemsLoaded(on: viewModel)

// When
viewModel.configure()
Expand All @@ -355,36 +375,6 @@ final class ConfigurableBundleProductViewModelTests: XCTestCase {
}

private extension ConfigurableBundleProductViewModelTests {
func assertBundleItemsLoaded(on viewModel: ConfigurableBundleProductViewModel) async {
let expectation = expectation(description: "Bundle items are set")

var subscriptions = Set<AnyCancellable>()
viewModel.$bundleItemViewModels
.sink { items in
if items.isNotEmpty {
expectation.fulfill()
}
}
.store(in: &subscriptions)

await fulfillment(of: [expectation], timeout: 5.0)
}

func assertProductsErrorMessage(on viewModel: ConfigurableBundleProductViewModel, equals: String?) async {
let expectation = expectation(description: "Error message is set")

var subscriptions = Set<AnyCancellable>()
viewModel.$loadProductsErrorMessage
.sink {
if $0 == equals {
expectation.fulfill()
}
}
.store(in: &subscriptions)

await fulfillment(of: [expectation], timeout: 5.0)
}

func mockProductsRetrieval(result: Result<(products: [Product], hasNextPage: Bool), Error>) {
stores.whenReceivingAction(ofType: ProductAction.self) { action in
switch action {
Expand Down

0 comments on commit ba142d2

Please sign in to comment.