From 85e5ed816451b6e78574a40980f6b30876836e4d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 21 Nov 2023 15:05:38 +0100 Subject: fixing Screenshot tests for Bitmask, provider setup screenshot tests are also fixed for custom flavored builds. --- .../se/leap/bitmaskclient/ProviderSetupTest.java | 92 ++++++++++++ .../leap/bitmaskclient/base/ProviderBaseTest.java | 167 --------------------- .../androidTest/java/utils/ProviderSetupUtils.java | 93 ++++++++++++ 3 files changed, 185 insertions(+), 167 deletions(-) create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java delete mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java create mode 100644 app/src/androidTest/java/utils/ProviderSetupUtils.java (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java new file mode 100644 index 00000000..a878951a --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -0,0 +1,92 @@ +package se.leap.bitmaskclient; + + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static utils.CustomInteractions.tryResolve; + +import android.app.Instrumentation; +import android.content.Context; + +import androidx.test.espresso.ViewInteraction; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.manipulation.Ordering; + +import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.providersetup.activities.SetupActivity; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; +import tools.fastlane.screengrab.locale.LocaleTestRule; +import utils.ProviderSetupUtils; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class ProviderSetupTest { + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @Rule + public ActivityScenarioRule mActivityScenarioRule = + new ActivityScenarioRule<>(SetupActivity.class); + + UiDevice device; + + @Before + public void setup() { + Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); + //PreferenceHelper.clear(); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + device = UiDevice.getInstance(instrumentation); + } + + @Test + public void test01_setupProviderDefault() { + ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + + @Test + public void test01_setupProviderCircumvention() { + ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + + @Test + public void testaddManuallyNewProviderScreenshot() { + if (!"normal".equals(BuildConfig.FLAVOR_branding)) { + System.out.println("skipping custom provider url test"); + return; + } + ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); + radioButtonSelection.perform(click()); + + onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); + Screengrab.screenshot("setup_custom_provider"); + onView(withId(R.id.setup_next_button)).perform(click()); + onView(withId(R.id.setup_next_button)).perform(click()); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + tryResolve( + onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))), + matches(isDisplayed()), + 20); + Screengrab.screenshot("setup_provider_error_dialog"); + } +} diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java deleted file mode 100644 index 68676bee..00000000 --- a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package se.leap.bitmaskclient.base; - -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.contrib.DrawerMatchers.isClosed; -import static androidx.test.espresso.matcher.RootMatchers.isDialog; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anything; -import static org.hamcrest.Matchers.is; -import static utils.CustomInteractions.tryResolve; - -import android.app.Instrumentation; -import android.content.SharedPreferences; -import android.net.VpnService; -import android.view.Gravity; - -import androidx.test.espresso.ViewInteraction; -import androidx.test.espresso.contrib.DrawerActions; -import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiObjectNotFoundException; -import androidx.test.uiautomator.UiSelector; - -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; -import tools.fastlane.screengrab.locale.LocaleTestRule; - -@LargeTest -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public abstract class ProviderBaseTest { - - @ClassRule - public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - - @Rule - public ActivityScenarioRule mActivityScenarioRule = - new ActivityScenarioRule<>(StartActivity.class); - - UiDevice device; - @Before - public void setup() { - Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); - SharedPreferences preferences = PreferenceHelper.getSharedPreferences(getApplicationContext()); - preferences.edit().clear().commit(); - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(instrumentation); - } - - @Test - public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { - boolean configurationNeeded = configureProviderIfNeeded(); - - ViewInteraction mainButtonStop; - if (!configurationNeeded) { - // click on Main on/off button and start VPN - ViewInteraction mainButton = tryResolve( - onView(withId(R.id.main_button)), - matches(isDisplayed()) - ); - - mainButton.perform(click()); - Thread.sleep(50); - Screengrab.screenshot("VPN_connecting"); - - mainButtonStop = tryResolve( - onView(allOf( - withId(R.id.button), - withTagValue(is("button_circle_stop")))), - matches(isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); - } else { - // handle VPN permission dialog - if (VpnService.prepare(getApplicationContext()) != null) { - UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); - okButton.click(); - } - // on new configurations the VPN is automatically started - Screengrab.screenshot("VPN_connecting"); - mainButtonStop = tryResolve( - onView(allOf( - withId(R.id.button), - withTagValue(is("button_circle_stop")))), - matches(isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); - } - - mainButtonStop.perform(click()); - Screengrab.screenshot("VPN_ask_disconnect"); - - onView(withText(android.R.string.yes)) - .inRoot(isDialog()) - .check(matches(isDisplayed())) - .perform(click()); - Screengrab.screenshot("VPN_disconnected"); - } - - @Test - public void test02_SettingsFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - Screengrab.screenshot("navigationDrawer"); - - // Start the screen of your activity. - onView(withId(R.id.advancedSettings)) - .perform(click()); - - Screengrab.screenshot("settingsFragment"); - } - - @Test - public void test03_LocationSelectionFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - onView(withId(R.id.manualGatewaySelection)) - .perform(click()); - - Screengrab.screenshot("GatewaySelectionFragment"); - } - - @Test - public void test04_AppExclusionFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - onView(withId(R.id.advancedSettings)).perform(click()); - - onView(withId(R.id.exclude_apps)).perform(click()); - - tryResolve( - onData(anything()).inAdapterView(withId(android.R.id.list)).atPosition(2), - matches(isDisplayed()), - 5); - - Screengrab.screenshot("App_Exclusion_Fragment"); - } - - public abstract boolean configureProviderIfNeeded(); -} diff --git a/app/src/androidTest/java/utils/ProviderSetupUtils.java b/app/src/androidTest/java/utils/ProviderSetupUtils.java new file mode 100644 index 00000000..10e0b950 --- /dev/null +++ b/app/src/androidTest/java/utils/ProviderSetupUtils.java @@ -0,0 +1,93 @@ +package utils; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static utils.CustomInteractions.tryResolve; + +import android.content.Context; +import android.net.VpnService; + +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; + +import org.hamcrest.Matchers; + +import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.R; +import tools.fastlane.screengrab.Screengrab; + +public class ProviderSetupUtils { + + public static void runProviderSetup(UiDevice device, boolean takeConfigurationScreenshots, boolean useCircumvention, Context targetContext) { + try { + // ------- PROVIDER SELECTION -------------- + if ("normal".equals(BuildConfig.FLAVOR_branding)) { + System.out.println("next: provider selection"); + ViewInteraction radioButtonSelection = tryResolve(onView(withText("Riseup")), matches(isDisplayed())); + if (takeConfigurationScreenshots) Screengrab.screenshot("provider_selection"); + radioButtonSelection.perform(click()); + // next button click + onView(withText(R.string.next)).perform(click()); + } + + // ------- CIRCUMVENTION SELECTION -------------- + System.out.println("next: standard/circumvention selection"); + if (useCircumvention) { + onView(withText(targetContext.getString(R.string.use_circumvention_tech))).perform(click()); + } else { + onView(withText(targetContext.getString(R.string.use_standard_vpn, targetContext.getString(R.string.app_name)))).perform(click()); + } + if (takeConfigurationScreenshots) Screengrab.screenshot("circumvention_selection"); + + // ------- CONFIGURATION PROGRESS -------------- + System.out.println("next: configuring"); + onView(withText(R.string.next)).perform(click()); + tryResolve( + onView( + Matchers.allOf( + withText(R.string.configuring_provider), + withId(R.id.tv_title) + ) + ), + matches(isDisplayed()) + ); + if (takeConfigurationScreenshots) Screengrab.screenshot("configuring_provider"); + + // ------- VPN PERMISSON DIALOG -------------- + boolean showPermissionDialog = false; + if (VpnService.prepare(getApplicationContext()) != null) { + showPermissionDialog = true; + tryResolve(onView(withText(R.string.upcoming_connection_request_description)), matches(isDisplayed()), useCircumvention ? 180 : 20); + System.out.println("next: next permission request"); + onView(withText(R.string.next)).perform(click()); + UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); + okButton.waitForExists(30000); + okButton.click(); + device.waitForWindowUpdate("com.android.vpndialogs", 1000); + } + + // ------- START VPN -------------- + System.out.println("next: perform click on VPN button"); + ViewInteraction interaction = tryResolve(onView(withTagValue(Matchers.is("button_setup_circle_custom"))), matches(isDisplayed()), useCircumvention && !showPermissionDialog ? 180 : 20); + Screengrab.screenshot("all_set_start_vpn"); + interaction.perform(click()); + } catch (NoMatchingViewException e) { + // it might be that the provider was already configured, so we print the stack + // trace here and try to continue + e.printStackTrace(); + } catch (UiObjectNotFoundException | NullPointerException e) { + e.printStackTrace(); + } + } +} -- cgit v1.2.3 From e2eccdcf5c49daf9236f782dcdf8ba9924cf7147 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 10:41:39 +0100 Subject: improve screenhsot tests, fix them for custom flavored builds --- .../java/se/leap/bitmaskclient/BitmaskTest.java | 152 +++++++++++++++++++++ .../se/leap/bitmaskclient/ProviderSetupTest.java | 20 +-- .../leap/bitmaskclient/suite/ScreenshotTest.java | 19 +++ 3 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java new file mode 100644 index 00000000..1ca0980a --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java @@ -0,0 +1,152 @@ +package se.leap.bitmaskclient; + + +import static org.junit.Assert.assertNotNull; + +import android.Manifest; +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.os.Build; +import android.view.Gravity; + +import androidx.test.espresso.Espresso; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.contrib.DrawerActions; +import androidx.test.espresso.contrib.DrawerMatchers; +import androidx.test.espresso.matcher.RootMatchers; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.StartActivity; +import se.leap.bitmaskclient.providersetup.activities.SetupActivity; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; +import tools.fastlane.screengrab.locale.LocaleTestRule; +import utils.CustomInteractions; +import utils.ProviderSetupUtils; + +@LargeTest +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class BitmaskTest { + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @Rule + public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null; + + UiDevice device; + @Before + public void setup() { + Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + device = UiDevice.getInstance(instrumentation); + } + + @Test + public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { + startMainActivity(); + + Screengrab.screenshot("VPN_connecting"); + ViewInteraction mainButtonStop = CustomInteractions.tryResolve( + Espresso.onView(Matchers.allOf( + ViewMatchers.withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20); + Screengrab.screenshot("VPN_connected"); + + mainButtonStop.perform(ViewActions.click()); + Screengrab.screenshot("VPN_ask_disconnect"); + + Espresso.onView(ViewMatchers.withText(android.R.string.yes)) + .inRoot(RootMatchers.isDialog()) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .perform(ViewActions.click()); + Screengrab.screenshot("VPN_disconnected"); + } + + @Test + public void test02_SettingsFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Screengrab.screenshot("navigationDrawer"); + + // Start the screen of your activity. + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)) + .perform(ViewActions.click()); + + Screengrab.screenshot("settingsFragment"); + } + + @Test + public void test03_LocationSelectionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.manualGatewaySelection)) + .perform(ViewActions.click()); + + Screengrab.screenshot("GatewaySelectionFragment"); + } + + @Test + public void test04_AppExclusionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)).perform(ViewActions.click()); + + Espresso.onView(ViewMatchers.withId(R.id.exclude_apps)).perform(ViewActions.click()); + + CustomInteractions.tryResolve( + Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 5); + + Screengrab.screenshot("App_Exclusion_Fragment"); + } + + private void startMainActivity() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false); + Instrumentation.ActivityMonitor mainActivityMonitor = new Instrumentation.ActivityMonitor(MainActivity.class.getName(), null, false); + instrumentation.addMonitor(setupActivityMonitor); + instrumentation.addMonitor(mainActivityMonitor); + Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.startActivitySync(intent); + Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L); + if (setupActivity != null) { + ProviderSetupUtils.runProviderSetup(device, false, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + Activity mainActivity = instrumentation.waitForMonitorWithTimeout(mainActivityMonitor, 1000); + assertNotNull(mainActivity); + } +} diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java index a878951a..b9da0dff 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -7,7 +7,6 @@ import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static utils.CustomInteractions.tryResolve; @@ -20,18 +19,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObjectNotFoundException; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.ClassRule; +import org.junit.FixMethodOrder; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runner.manipulation.Ordering; +import org.junit.runners.MethodSorters; -import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; import tools.fastlane.screengrab.Screengrab; import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; @@ -40,6 +36,7 @@ import utils.ProviderSetupUtils; @LargeTest @RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ProviderSetupTest { @ClassRule @@ -65,24 +62,27 @@ public class ProviderSetupTest { } @Test - public void test01_setupProviderCircumvention() { + public void test02_setupProviderCircumvention() { ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test - public void testaddManuallyNewProviderScreenshot() { + public void test03_addManuallyNewProviderScreenshot() { if (!"normal".equals(BuildConfig.FLAVOR_branding)) { System.out.println("skipping custom provider url test"); return; } + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); radioButtonSelection.perform(click()); - onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); Screengrab.screenshot("setup_custom_provider"); onView(withId(R.id.setup_next_button)).perform(click()); + + onView(withText(context.getString(R.string.use_standard_vpn, context.getString(R.string.app_name)))).perform(click()); onView(withId(R.id.setup_next_button)).perform(click()); - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + tryResolve( onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))), matches(isDisplayed()), diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java new file mode 100644 index 00000000..f3a8d73c --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java @@ -0,0 +1,19 @@ +package se.leap.bitmaskclient.suite; + + +import androidx.test.filters.LargeTest; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import se.leap.bitmaskclient.BitmaskTest; +import se.leap.bitmaskclient.ProviderSetupTest; + +@LargeTest +@RunWith(Suite.class) +@Suite.SuiteClasses({ + ProviderSetupTest.class, + BitmaskTest.class, +}) +public class ScreenshotTest { +} -- cgit v1.2.3 From fdcc7ac00be21c22e1bd94df06c304f6a7a765be Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:45:02 +0100 Subject: ensure ProviderSetupTest doesn't fail with fastlane which runs the same test class multuple times with different locales --- .../se/leap/bitmaskclient/ProviderSetupTest.java | 32 ++++++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java index b9da0dff..dedb40d7 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -8,10 +8,14 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.junit.Assert.assertNotNull; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_ENCRYPTED_PREFERENCES; import static utils.CustomInteractions.tryResolve; +import android.app.Activity; import android.app.Instrumentation; import android.content.Context; +import android.content.Intent; import androidx.test.espresso.ViewInteraction; import androidx.test.ext.junit.rules.ActivityScenarioRule; @@ -28,6 +32,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.StartActivity; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; import tools.fastlane.screengrab.Screengrab; import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; @@ -42,9 +51,9 @@ public class ProviderSetupTest { @ClassRule public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - @Rule - public ActivityScenarioRule mActivityScenarioRule = - new ActivityScenarioRule<>(SetupActivity.class); + // @Rule + // public ActivityScenarioRule mActivityScenarioRule = + // new ActivityScenarioRule<>(SetupActivity.class); UiDevice device; @@ -54,15 +63,19 @@ public class ProviderSetupTest { //PreferenceHelper.clear(); Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); device = UiDevice.getInstance(instrumentation); + instrumentation.getTargetContext().deleteSharedPreferences(SHARED_ENCRYPTED_PREFERENCES); + ProviderObservable.getInstance().updateProvider(new Provider()); } @Test public void test01_setupProviderDefault() { + startSetupActivity(); ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test public void test02_setupProviderCircumvention() { + startSetupActivity(); ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @@ -72,11 +85,13 @@ public class ProviderSetupTest { System.out.println("skipping custom provider url test"); return; } + startSetupActivity(); Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); radioButtonSelection.perform(click()); onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); + tryResolve(onView(withId(R.id.edit_customProvider)), matches(withText("https://leapvpn.myserver.org"))); Screengrab.screenshot("setup_custom_provider"); onView(withId(R.id.setup_next_button)).perform(click()); @@ -89,4 +104,15 @@ public class ProviderSetupTest { 20); Screengrab.screenshot("setup_provider_error_dialog"); } + + private void startSetupActivity() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false); + instrumentation.addMonitor(setupActivityMonitor); + Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.startActivitySync(intent); + Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L); + assertNotNull(setupActivity); + } } -- cgit v1.2.3 From 9da7c99730c09e9b9164dec2f8cfbd2e4c337a69 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:45:30 +0100 Subject: less verbose output for tryResolve() --- app/src/androidTest/java/utils/CustomInteractions.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/utils/CustomInteractions.java b/app/src/androidTest/java/utils/CustomInteractions.java index 9e3a8f9d..4890c20c 100644 --- a/app/src/androidTest/java/utils/CustomInteractions.java +++ b/app/src/androidTest/java/utils/CustomInteractions.java @@ -30,8 +30,7 @@ public class CustomInteractions { } hasFound = true; } catch (NoMatchingViewException exception) { - System.out.println("NoMatchingViewException attempt: " + attempt); - exception.printStackTrace(); + System.out.println("NoMatchingViewException - attempt: " + attempt + ". " + exception.getLocalizedMessage()); attempt++; if (attempt == maxTries) { throw exception; -- cgit v1.2.3 From d80e8606039f498f34fb4e7e4f8184c68b541e6f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:46:59 +0100 Subject: only click on the VPN start button after a successful provider setup if we actually want to test the following activities --- app/src/androidTest/java/utils/ProviderSetupUtils.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/utils/ProviderSetupUtils.java b/app/src/androidTest/java/utils/ProviderSetupUtils.java index 10e0b950..9b76ffbd 100644 --- a/app/src/androidTest/java/utils/ProviderSetupUtils.java +++ b/app/src/androidTest/java/utils/ProviderSetupUtils.java @@ -70,6 +70,7 @@ public class ProviderSetupUtils { showPermissionDialog = true; tryResolve(onView(withText(R.string.upcoming_connection_request_description)), matches(isDisplayed()), useCircumvention ? 180 : 20); System.out.println("next: next permission request"); + if (takeConfigurationScreenshots) Screengrab.screenshot("vpn_permission_rationale"); onView(withText(R.string.next)).perform(click()); UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); okButton.waitForExists(30000); @@ -80,8 +81,12 @@ public class ProviderSetupUtils { // ------- START VPN -------------- System.out.println("next: perform click on VPN button"); ViewInteraction interaction = tryResolve(onView(withTagValue(Matchers.is("button_setup_circle_custom"))), matches(isDisplayed()), useCircumvention && !showPermissionDialog ? 180 : 20); - Screengrab.screenshot("all_set_start_vpn"); - interaction.perform(click()); + if (takeConfigurationScreenshots) { + Screengrab.screenshot("all_set_start_vpn"); + } else { + // we only want to start the VPN in case we're not running the ProviderSetupTest + interaction.perform(click()); + } } catch (NoMatchingViewException e) { // it might be that the provider was already configured, so we print the stack // trace here and try to continue -- cgit v1.2.3