Skip to content

[WOO POS] UI tests for Simple products banner in Products screen #12428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 28 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5788341
Mock blaze GET request so that our UI tests will run fine.
AnirudhBhat Aug 20, 2024
0433bad
Add POSModeScreen
AnirudhBhat Aug 20, 2024
71c04c0
Add function to open POS mode in more menu UI screen
AnirudhBhat Aug 20, 2024
4316da2
Trigger POS event when clicked on payments settings - This is tempora…
AnirudhBhat Aug 20, 2024
eded8b3
Add ID to WooPosActivity so that it can be references in the UI screens
AnirudhBhat Aug 20, 2024
1a7a0b7
Add test tag for WooPosBanner so that we can reference this in UI test
AnirudhBhat Aug 20, 2024
acf27ac
Add test tag in WooPosProductsScreen
AnirudhBhat Aug 20, 2024
c2c6cf0
Add test to verify simple products only banner is displayed when prod…
AnirudhBhat Aug 20, 2024
d0ba4b2
Add UI test to verify that simple products banner title is displayed …
AnirudhBhat Aug 21, 2024
644a87f
Add UI test to verify that simple products banner message is displaye…
AnirudhBhat Aug 21, 2024
54b81f4
Add UI test to verify that simple products banner opens simple produc…
AnirudhBhat Aug 21, 2024
7a75fd7
Add UI test to verify that simple products banner is dismissed when c…
AnirudhBhat Aug 21, 2024
0c2e310
Add test tag for Simple products info dialog so that we can reference…
AnirudhBhat Aug 21, 2024
9a5034a
Combine testing simple products banner's message and title into one t…
AnirudhBhat Aug 21, 2024
8a37125
Fix detekt errors
AnirudhBhat Aug 21, 2024
71f491a
Remove unused imports
AnirudhBhat Aug 21, 2024
d064a29
Merge branch 'refs/heads/trunk' into issue/12377-ui-tests-for-simple-…
AnirudhBhat Aug 28, 2024
9719332
Merge branch 'refs/heads/trunk' into issue/12377-ui-tests-for-simple-…
AnirudhBhat Jan 8, 2025
623678f
Fix merge conflicts
AnirudhBhat Jan 8, 2025
b921716
Move WooPosBannerTest under POS package
AnirudhBhat Jan 8, 2025
99de33a
Add configuration to run tests under POS package only on tablet device
AnirudhBhat Jan 8, 2025
4b9d804
Add configuration to run tests under POS package only on tablet devic…
AnirudhBhat Jan 8, 2025
d0908e6
Remove unused imports
AnirudhBhat Jan 8, 2025
1ea704d
Remove unnecessary configuration
AnirudhBhat Jan 8, 2025
e8b2e58
Replace with supported tablet model
AnirudhBhat Jan 8, 2025
19390b9
modify fladle configuration logic to run all the UI tests
AnirudhBhat Jan 8, 2025
7035847
modify fladle configuration
AnirudhBhat Jan 9, 2025
cd1d8a6
trying different solution
AnirudhBhat Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions WooCommerce/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,23 @@ plugins {
fladle {
variant = "vanillaDebug"
serviceAccountCredentials = rootProject.file(".configure-files/firebase.secrets.json")
testTargets = [
"notPackage com.woocommerce.android.e2e.tests.screenshot"
]
devices = [
[ "model": "Pixel2.arm", "version": "30" ]
]
localResultsDir = "$rootDir/build/instrumented-tests"

maxTestShards = 50
shardTime = 120
smartFlankGcsPath = "gs://fladle/woocommerce-android/smart-flank/JUnitReport.xml"
smartFlankGcsPath = "gs://fladle/woocommerce-android/smart-flank/tablet/JUnitReport.xml"
configs {
tabletTests {
testTargets.set([
"package com.woocommerce.android.e2e.tests.ui.pos"
])
devices.set([
[ "model": "Nexus9", "version": "30" ]
])
}
}
}


sentry {
includeSourceContext = true
autoUploadSourceContext = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"request": {
"method": "GET",
"urlPathPattern": "/rest/v1.1/jetpack-blogs/161477129/rest-api/",
"queryParameters": {
"path": {
"equalTo": "/wc/gla/ads/campaigns/&_method=get"
},
"json": {
"equalTo": "true"
},
"locale": {
"matches": "(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"total_items": 0,
"campaigns": [],
"total_pages": 0,
"page": 1
},
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.ui.test.performScrollTo
import com.woocommerce.android.R
import com.woocommerce.android.e2e.helpers.util.Screen
import com.woocommerce.android.e2e.screens.mystore.settings.SettingsScreen
import com.woocommerce.android.e2e.screens.pos.POSModeScreen
import com.woocommerce.android.e2e.screens.reviews.ReviewsListScreen

class MoreMenuScreen : Screen(R.id.more_menu_compose_view) {
Expand All @@ -22,6 +23,15 @@ class MoreMenuScreen : Screen(R.id.more_menu_compose_view) {
return ReviewsListScreen()
}

fun openPOSScreen(composeTestRule: ComposeTestRule): POSModeScreen {
composeTestRule.onNodeWithText(
getTranslatedString(R.string.more_menu_button_payments)
)
.performScrollTo()
.performClick()
return POSModeScreen()
}

fun openSettings(composeTestRule: ComposeTestRule): SettingsScreen {
// Tests are failing randomly here depending on how fast this screen is displayed after tapping on the More button
// Adding this retry to wait for the settings icon to be displayed, retrying up to a max time
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.woocommerce.android.e2e.screens.pos

import com.woocommerce.android.R
import com.woocommerce.android.e2e.helpers.util.Screen

class POSModeScreen : Screen(R.id.pos_mode_compose_view)
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
@file:Suppress("DEPRECATION")

package com.woocommerce.android.e2e.tests.ui.pos

import androidx.activity.ComponentActivity
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.woocommerce.android.BuildConfig
import com.woocommerce.android.R
import com.woocommerce.android.e2e.helpers.InitializationRule
import com.woocommerce.android.e2e.helpers.TestBase
import com.woocommerce.android.e2e.rules.RetryTestRule
import com.woocommerce.android.e2e.screens.TabNavComponent
import com.woocommerce.android.e2e.screens.login.WelcomeScreen
import com.woocommerce.android.ui.login.LoginActivity
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import javax.inject.Inject

@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class WooPosBannerTest : TestBase() {
@get:Rule(order = 1)
val rule = HiltAndroidRule(this)

@get:Rule(order = 2)
val composeTestRule = createAndroidComposeRule<ComponentActivity>()

@get:Rule(order = 3)
val initRule = InitializationRule()

@get:Rule(order = 4)
var activityRule = ActivityTestRule(LoginActivity::class.java)

@get:Rule(order = 5)
var retryTestRule = RetryTestRule()

@Inject
lateinit var dataStore: DataStore<Preferences>

@Before
fun setUp() = runTest {
rule.inject()
WelcomeScreen
.skipCarouselIfNeeded()
.selectLogin()
.proceedWith(BuildConfig.SCREENSHOTS_URL)
.proceedWith(BuildConfig.SCREENSHOTS_USERNAME)
.proceedWith(BuildConfig.SCREENSHOTS_PASSWORD)

TabNavComponent()
.gotoMoreMenuScreen()
.openPOSScreen(composeTestRule)
dataStore.edit { it.clear() }
}

@Test
fun testWooPosSimpleProductsOnlyBannerIsDisplayedOnProductsScreen() = runTest {
composeTestRule.waitUntil(5000) {
try {
composeTestRule.onNodeWithTag("products_list")
.assertExists()
.assertIsDisplayed()
true
} catch (e: AssertionError) {
e.printStackTrace()
false
}
}

composeTestRule.onNodeWithTag(
"woo_pos_simple_products_banner"
).assertIsDisplayed()
}

@Test
fun testWooPosSimpleProductsOnlyBannerTitleAndMessageIsDisplayedOnBanner() = runTest {
composeTestRule.waitUntil(5000) {
try {
composeTestRule.onNodeWithTag("products_list")
.assertExists()
.assertIsDisplayed()
true
} catch (e: AssertionError) {
e.printStackTrace()
false
}
}

composeTestRule.onNodeWithText(
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_only_title)
).assertIsDisplayed()

composeTestRule.onNodeWithText(
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_only_message) +
" " +
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_only_message_learn_more)
).assertIsDisplayed()
}

@Test
fun testWooPosSimpleProductsOnlyBannerOpensProductInfoDialogWhenClickedOnLearnMore() = runTest {
composeTestRule.waitUntil(5000) {
try {
composeTestRule.onNodeWithTag("products_list")
.assertExists()
.assertIsDisplayed()
true
} catch (e: AssertionError) {
e.printStackTrace()
false
}
}

composeTestRule.onNodeWithText(
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_only_message) +
" " +
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_only_message_learn_more)
).performClick()

composeTestRule.onNodeWithTag("woo_pos_product_info_dialog")
.assertIsDisplayed()
}

@Test
fun testWooPosSimpleProductsOnlyBannerIsDismissedWhenClosed() = runTest {
composeTestRule.waitUntil(5000) {
try {
composeTestRule.onNodeWithTag("products_list")
.assertExists()
.assertIsDisplayed()
true
} catch (e: AssertionError) {
e.printStackTrace()
false
}
}

composeTestRule.onNodeWithContentDescription(
composeTestRule.activity.getString(R.string.woopos_banner_simple_products_close_content_description)
).performClick()

composeTestRule.onNodeWithTag(
"woo_pos_simple_products_banner"
).assertIsNotDisplayed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,8 @@ class MoreMenuViewModel @Inject constructor(
mapOf(VALUE_MORE_MENU_PAYMENTS_BADGE_VISIBLE to isPaymentBadgeVisible().toString())
)
moreMenuNewFeatureHandler.markPaymentsIconAsClicked()
triggerEvent(MoreMenuEvent.ViewPayments)
// triggerEvent(MoreMenuEvent.ViewPayments)
triggerEvent(MoreMenuEvent.NavigateToWooPosEvent)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was made solely to run UI tests and needs to be reverted. The reason for the change is that the store used for UI testing doesn't pass IPP onboarding, which causes the POS setting to not appear in the settings.

}

private fun onPromoteProductsWithGoogle() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ fun WooPosPaginationErrorScreenPreview() {
WooPosItemList(
state = itemsState,
listState = rememberLazyListState(),
testTagName = "products_list",
onItemClicked = {},
onEndOfProductsListReached = {}
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
Expand Down Expand Up @@ -54,7 +55,8 @@ fun WooPosProductInfoDialog(
.padding(40.dp.toAdaptivePadding())
.semantics(mergeDescendants = true) {
contentDescription = dialogContentDescription
},
}
.testTag("woo_pos_product_info_dialog"),
contentAlignment = Alignment.Center
) {
ConstraintLayout(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
Expand Down Expand Up @@ -56,6 +57,7 @@ fun WooPosBanner(
contentDescription = bannerContentDescription
}
.focusable()
.testTag("woo_pos_simple_products_banner")
) {
WooPosCard(
shape = RoundedCornerShape(8.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
Expand All @@ -56,11 +57,13 @@ import kotlinx.coroutines.flow.filter
fun WooPosItemList(
state: ContentViewState,
listState: LazyListState,
testTagName: String,
onItemClicked: (item: WooPosItem) -> Unit,
onEndOfProductsListReached: () -> Unit,
onErrorWhilePaginating: @Composable () -> Unit,
) {
WooPosLazyColumn(
modifier = Modifier.testTag(testTagName),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(2.dp),
state = listState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private fun MainItemsList(
WooPosItemList(
itemsState,
listState,
"products_list",
onItemClicked,
onEndOfItemListReached,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ private fun WooPosVariationsScreens(
WooPosItemList(
state = itemsState,
listState = listState,
testTagName = "variations_list",
onItemClicked = {
onItemClicked(
(it as WooPosItem.Variation).productId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
Expand Down Expand Up @@ -36,7 +37,13 @@ class WooPosActivity : AppCompatActivity() {
lifecycle.addObserver(wooPosCardReaderFacade)
lifecycle.addObserver(wooPosGetSupportFacade)

setContent {
val composeView = ComposeView(this).apply {
id = com.woocommerce.android.R.id.pos_mode_compose_view
}

setContentView(composeView)

composeView.setContent {
WooPosTheme {
SystemBars()

Expand Down
1 change: 1 addition & 0 deletions WooCommerce/src/main/res/values/ids.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<item type="id" name="stats_tab_layout" />
<item type="id" name="more_menu_compose_view" />
<item type="id" name="product_selector_compose_view" />
<item type="id" name="pos_mode_compose_view" />
<item type="id" name="product_configuration_view" />
<item type="id" name="analytics_hub_settings_view" />
</resources>
Loading