diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt new file mode 100644 index 000000000000..ada96b9c90c6 --- /dev/null +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt @@ -0,0 +1,62 @@ +package org.wordpress.android.e2e + +import androidx.test.espresso.Espresso +import androidx.test.espresso.matcher.ViewMatchers +import dagger.hilt.android.testing.HiltAndroidTest +import org.junit.After +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.Test +import org.wordpress.android.BuildConfig +import org.wordpress.android.R +import org.wordpress.android.e2e.pages.MySitesPage +import org.wordpress.android.support.BaseTest +import org.wordpress.android.support.ComposeEspressoLink +import org.wordpress.android.support.WPSupportUtils +import org.wordpress.android.util.StatsKeyValueData +import org.wordpress.android.util.StatsMocksReader +import org.wordpress.android.util.StatsVisitsData + +@HiltAndroidTest +class StatsGranularTabsTest : BaseTest() { + @Before + fun setUp() { + assumeTrue(BuildConfig.IS_JETPACK_APP) + ComposeEspressoLink().unregister() + logoutIfNecessary() + wpLogin() + } + + @After + fun tearDown() { + // "tabLayout" is a Tab switcher for stats. + // We need to leave stats at the end of test. + if (WPSupportUtils.isElementDisplayed(Espresso.onView(ViewMatchers.withId(R.id.tabLayout)))) { + Espresso.pressBack() + } + } + + @Test + fun e2eAllDayStatsLoad() { + val todayVisits = StatsVisitsData("97", "28", "14", "11") + val postsList: List = StatsMocksReader().readDayTopPostsToList() + val referrersList: List = StatsMocksReader().readDayTopReferrersToList() + val clicksList: List = StatsMocksReader().readDayClicksToList() + val authorsList: List = StatsMocksReader().readDayAuthorsToList() + val countriesList: List = StatsMocksReader().readDayCountriesToList() + val videosList: List = StatsMocksReader().readDayVideoPlaysToList() + val downloadsList: List = StatsMocksReader().readDayFileDownloadsToList() + MySitesPage() + .go() + .goToStats() + .openDayStats() + .assertVisits(todayVisits) + .scrollToPosts().assertPosts(postsList) + .scrollToReferrers().assertReferrers(referrersList) + .scrollToClicks().assertClicks(clicksList) + .scrollToAuthors().assertAuthors(authorsList) + .scrollToCountries().assertCountries(countriesList) + .scrollToVideos().assertVideos(videosList) + .scrollToFileDownloads().assertDownloads(downloadsList) + } +} diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsTests.kt b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsTests.kt index 1e9495f14b3e..77a26a4175b3 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsTests.kt +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsTests.kt @@ -4,7 +4,7 @@ import androidx.test.espresso.Espresso import androidx.test.espresso.matcher.ViewMatchers import dagger.hilt.android.testing.HiltAndroidTest import org.junit.After -import org.junit.Assume.assumeTrue +import org.junit.Assume import org.junit.Before import org.junit.Test import org.wordpress.android.BuildConfig @@ -13,15 +13,14 @@ import org.wordpress.android.e2e.pages.MySitesPage import org.wordpress.android.support.BaseTest import org.wordpress.android.support.ComposeEspressoLink import org.wordpress.android.support.WPSupportUtils -import org.wordpress.android.util.StatsKeyValueData -import org.wordpress.android.util.StatsMocksReader -import org.wordpress.android.util.StatsVisitsData +import org.wordpress.android.wiremock.WireMockStub +import org.wordpress.android.wiremock.WireMockUrlPath @HiltAndroidTest -class StatsTests : BaseTest() { +class StatsTests : BaseTest(listOf(WireMockStub(urlPath = WireMockUrlPath.FEATURE_RESPONSE, fileName = "new-stats-feature-response.json"))) { @Before fun setUp() { - assumeTrue(BuildConfig.IS_JETPACK_APP) + Assume.assumeTrue(BuildConfig.IS_JETPACK_APP) ComposeEspressoLink().unregister() logoutIfNecessary() wpLogin() @@ -35,28 +34,12 @@ class StatsTests : BaseTest() { Espresso.pressBack() } } - + @Test fun e2eAllDayStatsLoad() { - val todayVisits = StatsVisitsData("97", "28", "14", "11") - val postsList: List = StatsMocksReader().readDayTopPostsToList() - val referrersList: List = StatsMocksReader().readDayTopReferrersToList() - val clicksList: List = StatsMocksReader().readDayClicksToList() - val authorsList: List = StatsMocksReader().readDayAuthorsToList() - val countriesList: List = StatsMocksReader().readDayCountriesToList() - val videosList: List = StatsMocksReader().readDayVideoPlaysToList() - val downloadsList: List = StatsMocksReader().readDayFileDownloadsToList() MySitesPage() .go() .goToStats() - .openDayStats() - .assertVisits(todayVisits) - .scrollToPosts().assertPosts(postsList) - .scrollToReferrers().assertReferrers(referrersList) - .scrollToClicks().assertClicks(clicksList) - .scrollToAuthors().assertAuthors(authorsList) - .scrollToCountries().assertCountries(countriesList) - .scrollToVideos().assertVideos(videosList) - .scrollToFileDownloads().assertDownloads(downloadsList) + .hasNewStatTabs() } } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/pages/StatsPage.kt b/WordPress/src/androidTest/java/org/wordpress/android/e2e/pages/StatsPage.kt index 76c2c4d8a054..6096099be7ee 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/pages/StatsPage.kt +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/pages/StatsPage.kt @@ -14,6 +14,24 @@ import org.wordpress.android.util.StatsKeyValueData import org.wordpress.android.util.StatsVisitsData class StatsPage { + /** + * Matcher to check that the right tabs exist. + */ + fun hasNewStatTabs(): StatsPage { + Espresso.onView( + Matchers.allOf( + ViewMatchers.isDescendantOfA(ViewMatchers.withId(R.id.tabLayout)), + ViewMatchers.withText("Traffic") + ) + ).check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + Espresso.onView( + Matchers.allOf( + ViewMatchers.isDescendantOfA(ViewMatchers.withId(R.id.tabLayout)), + ViewMatchers.withText("Insights") + ) + ).check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + return this + } fun openDayStats(): StatsPage { val daysStatsTab = Espresso.onView( Matchers.allOf( diff --git a/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java b/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java index e1c967f4029b..95322a95a7ff 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java @@ -1,7 +1,9 @@ package org.wordpress.android.support; import android.app.Instrumentation; +import android.util.Log; +import androidx.annotation.Nullable; import androidx.compose.ui.test.junit4.ComposeTestRule; import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.ext.junit.rules.ActivityScenarioRule; @@ -10,6 +12,7 @@ import com.fasterxml.jackson.databind.util.ISO8601Utils; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; +import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer; import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.DateOffset; import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.HandlebarsHelper; @@ -28,14 +31,17 @@ import org.wordpress.android.e2e.flows.LoginFlow; import org.wordpress.android.e2e.pages.MePage; import org.wordpress.android.e2e.pages.MySitesPage; +import org.wordpress.android.editor.Utils; import org.wordpress.android.mocks.AndroidNotifier; import org.wordpress.android.mocks.AssetFileSource; import org.wordpress.android.ui.WPLaunchActivity; +import org.wordpress.android.wiremock.WireMockStub; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.TimeZone; @@ -52,6 +58,7 @@ import dagger.hilt.android.testing.HiltAndroidRule; public class BaseTest { + static final String TAG = BaseTest.class.getSimpleName(); public static final int WIREMOCK_PORT = 8080; @Rule(order = 0) @@ -70,18 +77,45 @@ public class BaseTest { @Rule(order = 4) public WireMockRule wireMockRule; - { - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + public BaseTest() { + this(null); + } + /** + * Constructor + * + * @param wireMockStubs the wiremock stubs to use for this specific test. + */ + public BaseTest(@Nullable final List wireMockStubs) { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); wireMockRule = new WireMockRule( options().port(WIREMOCK_PORT) - .fileSource(new AssetFileSource(instrumentation.getContext().getAssets())) + .fileSource( + new AssetFileSource(instrumentation.getContext().getAssets()) + ) + .extensions(new ResponseTemplateTransformer(true, new HashMap() { { put("fnow", new UnlocalizedDateHelper()); } })) .notifier(new AndroidNotifier())); + if (wireMockStubs != null && !wireMockStubs.isEmpty()) { + for (WireMockStub wireMockStub : wireMockStubs) { + try { + final String result = Utils.getStringFromInputStream( + instrumentation.getContext().getClassLoader().getResourceAsStream( + wireMockStub.getFileName() + ) + ); + // This is where we can stub out + wireMockRule.stubFor(WireMock.get(WireMock.urlPathMatching(wireMockStub.getUrlPath().getPath())) + .willReturn(WireMock.aResponse().withBody(result))); + } catch (final Exception exception) { + Log.e(TAG, "Problem stubbing endpoint", exception); + } + } + } } @Before diff --git a/WordPress/src/androidTest/java/org/wordpress/android/wiremock/WireMockStub.kt b/WordPress/src/androidTest/java/org/wordpress/android/wiremock/WireMockStub.kt new file mode 100644 index 000000000000..516d915f0ef5 --- /dev/null +++ b/WordPress/src/androidTest/java/org/wordpress/android/wiremock/WireMockStub.kt @@ -0,0 +1,18 @@ +package org.wordpress.android.wiremock + +/** + * Represents a WireMock#stubFor call on a WireMockServer. + * @property apiPathUrl The API path we are matching against. + * @property fileName The filename used to return as the body stored in the androidTest resources sub directory. + */ +data class WireMockStub( + val urlPath: WireMockUrlPath, + val fileName: String, +) + +/** + * Enum used to represent supported URLs we can stub. + */ +enum class WireMockUrlPath(val path: String) { + FEATURE_RESPONSE("/wpcom/v2/mobile/feature-flags/") +} diff --git a/WordPress/src/androidTest/resources/new-stats-feature-response.json b/WordPress/src/androidTest/resources/new-stats-feature-response.json new file mode 100644 index 000000000000..6caeb0a839bd --- /dev/null +++ b/WordPress/src/androidTest/resources/new-stats-feature-response.json @@ -0,0 +1,3 @@ +{ + "stats_traffic_tab": true +}