Skip to content

Commit cbccd3f

Browse files
Add unit tests
1 parent 5384012 commit cbccd3f

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

WooCommerce/src/test/kotlin/com/woocommerce/android/ui/products/details/ProductDetailViewModelTest.kt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.woocommerce.android.AppPrefsWrapper
55
import com.woocommerce.android.R
66
import com.woocommerce.android.analytics.AnalyticsEvent
77
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
8+
import com.woocommerce.android.ciab.CIABSiteGateKeeper
89
import com.woocommerce.android.extensions.takeIfNotEqualTo
910
import com.woocommerce.android.media.MediaFilesRepository
1011
import com.woocommerce.android.media.ProductImagesServiceWrapper
@@ -35,6 +36,7 @@ import com.woocommerce.android.ui.products.variations.domain.GenerateVariationCa
3536
import com.woocommerce.android.util.CurrencyFormatter
3637
import com.woocommerce.android.util.IsWindowClassLargeThanCompact
3738
import com.woocommerce.android.util.ProductUtils
39+
import com.woocommerce.android.util.captureValues
3840
import com.woocommerce.android.util.getOrAwaitValue
3941
import com.woocommerce.android.util.runAndCaptureValues
4042
import com.woocommerce.android.viewmodel.BaseUnitTest
@@ -1515,4 +1517,60 @@ class ProductDetailViewModelTest : BaseUnitTest() {
15151517
// THEN: once the product is stored, trash option should be visible
15161518
Assertions.assertThat(menuButtonsStates.last().trashOption).isTrue()
15171519
}
1520+
1521+
@Test
1522+
fun `given CIAB site and bookable product, when product detail is opened, then show WebView`() = testBlocking {
1523+
// GIVEN
1524+
whenever(selectedSite.get()).thenReturn(
1525+
SiteModel().apply {
1526+
setIsGardenSite(true)
1527+
gardenName = CIABSiteGateKeeper.CIAB_GARDEN_NAME
1528+
}
1529+
)
1530+
savedState = ProductDetailFragmentArgs(ProductDetailFragment.Mode.ShowProduct(PRODUCT_REMOTE_ID))
1531+
.toSavedStateHandle()
1532+
val testProductAggregate = productAggregate.copy(
1533+
product = productAggregate.product.copy(type = ProductType.BOOKING.value)
1534+
)
1535+
doReturn(testProductAggregate).whenever(productRepository).fetchAndGetProductAggregate(any())
1536+
doReturn(testProductAggregate).whenever(productRepository).getProductAggregate(any())
1537+
1538+
setup()
1539+
viewModel.start()
1540+
1541+
// WHEN
1542+
val event = viewModel.event.getOrAwaitValue()
1543+
1544+
// THEN
1545+
Assertions.assertThat(event).isEqualTo(
1546+
ProductDetailViewModel.OpenProductInWebView(testProductAggregate.product.remoteId)
1547+
)
1548+
}
1549+
1550+
@Test
1551+
fun `given CIAB site and non-bookable product, when product detail is opened, then don't show WebView`() = testBlocking {
1552+
// GIVEN
1553+
whenever(selectedSite.get()).thenReturn(
1554+
SiteModel().apply {
1555+
setIsGardenSite(true)
1556+
gardenName = CIABSiteGateKeeper.CIAB_GARDEN_NAME
1557+
}
1558+
)
1559+
savedState = ProductDetailFragmentArgs(ProductDetailFragment.Mode.ShowProduct(PRODUCT_REMOTE_ID))
1560+
.toSavedStateHandle()
1561+
val testProductAggregate = productAggregate.copy(
1562+
product = productAggregate.product.copy(type = ProductType.SIMPLE.value)
1563+
)
1564+
doReturn(testProductAggregate).whenever(productRepository).fetchAndGetProductAggregate(any())
1565+
doReturn(testProductAggregate).whenever(productRepository).getProductAggregate(any())
1566+
1567+
setup()
1568+
viewModel.start()
1569+
1570+
// WHEN
1571+
val events = viewModel.event.captureValues()
1572+
1573+
// THEN
1574+
Assertions.assertThat(events).noneMatch { it is ProductDetailViewModel.OpenProductInWebView }
1575+
}
15181576
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.woocommerce.android.ui.products.details.webview
2+
3+
import androidx.lifecycle.SavedStateHandle
4+
import com.woocommerce.android.tools.SelectedSite
5+
import com.woocommerce.android.ui.common.webview.WebViewAuthenticator
6+
import com.woocommerce.android.ui.products.ProductTestUtils
7+
import com.woocommerce.android.ui.products.details.ProductDetailRepository
8+
import com.woocommerce.android.util.captureValues
9+
import com.woocommerce.android.util.getOrAwaitValue
10+
import com.woocommerce.android.util.runAndCaptureValues
11+
import com.woocommerce.android.viewmodel.BaseUnitTest
12+
import com.woocommerce.android.viewmodel.MultiLiveEvent
13+
import kotlinx.coroutines.ExperimentalCoroutinesApi
14+
import org.assertj.core.api.Assertions.assertThat
15+
import org.junit.Before
16+
import org.junit.Test
17+
import org.mockito.kotlin.doReturn
18+
import org.mockito.kotlin.mock
19+
import org.mockito.kotlin.whenever
20+
import org.wordpress.android.fluxc.model.SiteModel
21+
import org.wordpress.android.fluxc.network.UserAgent
22+
23+
@ExperimentalCoroutinesApi
24+
class ProductDetailWebViewViewModelTest : BaseUnitTest() {
25+
26+
private val productDetailRepository: ProductDetailRepository = mock()
27+
private val selectedSite: SelectedSite = mock()
28+
private val webViewAuthenticator: WebViewAuthenticator = mock()
29+
private val userAgent: UserAgent = mock()
30+
31+
private lateinit var viewModel: ProductDetailWebViewViewModel
32+
private lateinit var savedStateHandle: SavedStateHandle
33+
34+
private val testProduct = ProductTestUtils.generateProduct(
35+
productId = 456L,
36+
productName = "Test Product"
37+
)
38+
39+
private val testSite = SiteModel().apply {
40+
adminUrl = "https://example.com/wp-admin/"
41+
}
42+
43+
@Before
44+
fun setup() {
45+
whenever(selectedSite.get()).doReturn(testSite)
46+
}
47+
48+
private suspend fun setupViewModel(
49+
remoteProductId: Long = testProduct.remoteId,
50+
setupMocks: suspend () -> Unit = {}
51+
) {
52+
setupMocks()
53+
54+
savedStateHandle = SavedStateHandle().apply {
55+
set("remoteProductId", remoteProductId)
56+
}
57+
58+
viewModel = ProductDetailWebViewViewModel(
59+
savedStateHandle = savedStateHandle,
60+
productDetailRepository = productDetailRepository,
61+
selectedSite = selectedSite,
62+
webViewAuthenticator = webViewAuthenticator,
63+
userAgent = userAgent
64+
)
65+
}
66+
67+
@Test
68+
fun `given valid product, when viewState is observed, then correct ViewState is emitted`() = testBlocking {
69+
// GIVEN
70+
setupViewModel {
71+
whenever(productDetailRepository.getProductAsync(testProduct.remoteId))
72+
.doReturn(testProduct)
73+
}
74+
75+
// WHEN
76+
val viewState = viewModel.viewState.getOrAwaitValue()
77+
78+
// THEN
79+
assertThat(viewState.title).isEqualTo(testProduct.name)
80+
assertThat(viewState.urlToLoad).isEqualTo(
81+
"https://example.com/wp-admin/?page=next-admin&p=/woocommerce/products/edit/${testProduct.remoteId}"
82+
)
83+
}
84+
85+
@Test
86+
fun `given product not found, when viewState is observed, then navigation back event is triggered`() = testBlocking {
87+
// GIVEN
88+
setupViewModel {
89+
whenever(productDetailRepository.getProductAsync(testProduct.remoteId))
90+
.doReturn(null)
91+
}
92+
93+
// WHEN
94+
val event = viewModel.event.runAndCaptureValues {
95+
// Trigger viewState observation
96+
viewModel.viewState.captureValues()
97+
}.last()
98+
99+
// THEN
100+
assertThat(event).isEqualTo(MultiLiveEvent.Event.Exit)
101+
}
102+
}

0 commit comments

Comments
 (0)