diff options
| author | cyberta <cyberta@riseup.net> | 2026-07-03 13:23:32 +0200 |
|---|---|---|
| committer | cyberta <cyberta@riseup.net> | 2026-07-03 17:49:31 +0200 |
| commit | be186e4eda72f14eb3b8f6fab76fbeda9d9fb175 (patch) | |
| tree | 0a35c05944b7888aecf406bfb721434e8903f318 /app/src/androidTest/java/se/leap | |
| parent | 1784fb5e60414808f21f4596959adf7a8b46e675 (diff) | |
fix and extend instrumentation tests used for automatted screenshots
Diffstat (limited to 'app/src/androidTest/java/se/leap')
3 files changed, 143 insertions, 47 deletions
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java index 1ca0980a..b984042b 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java @@ -1,7 +1,11 @@ package se.leap.bitmaskclient; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; +import static androidx.test.espresso.matcher.ViewMatchers.withId; import static org.junit.Assert.assertNotNull; +import static utils.ProviderSetupUtils.isVerboseScreenshots; import android.Manifest; import android.app.Activity; @@ -10,12 +14,12 @@ 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.contrib.RecyclerViewActions; import androidx.test.espresso.matcher.RootMatchers; import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -34,6 +38,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.StartActivity; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; @@ -66,71 +71,138 @@ public class BitmaskTest { 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), + ViewInteraction mainButton = null; + if (!VpnStatus.isVPNActive()) { + mainButton = CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button)//, + /*ViewMatchers.withTagValue(Matchers.is("button_circle_start"))*/)), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20); + // turn VPN on + mainButton.perform(ViewActions.click()); + + // resolve connecting state + CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_cancel")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 3, "attempt to resolve connecting state"); + } + + mainButton = CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button), ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), ViewAssertions.matches(ViewMatchers.isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); + 20, "attempt to resolve connected state"); + Screengrab.screenshot("01_VPN_connected"); - mainButtonStop.perform(ViewActions.click()); - Screengrab.screenshot("VPN_ask_disconnect"); + // turn VPN off + mainButton.perform(ViewActions.click()); + if (isVerboseScreenshots()) { + Screengrab.screenshot("031_VPN_ask_disconnect"); + } - Espresso.onView(ViewMatchers.withText(android.R.string.yes)) + onView(ViewMatchers.withText(android.R.string.yes)) .inRoot(RootMatchers.isDialog()) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) .perform(ViewActions.click()); - Screengrab.screenshot("VPN_disconnected"); + Screengrab.screenshot("03_VPN_disconnected"); + } + + @Test + public void test02_vpnConnectingStateTest() throws InterruptedException, UiObjectNotFoundException { + startMainActivity(); + + ViewInteraction mainButton = CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_start")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20); + // turn VPN on + mainButton.perform(ViewActions.click()); + + // resolve connecting state + CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_cancel")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 3, "attempt to resolve connecting state"); + Screengrab.screenshot("02_VPN_connecting"); + + CustomInteractions.tryResolve( + onView(Matchers.allOf( + withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20, "attempt to resolve connected state"); } @Test public void test02_SettingsFragmentScreenshots() { startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + onView(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"); + Screengrab.screenshot("05_navigationDrawer"); // Start the screen of your activity. - Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)) + onView(withId(R.id.advancedSettings)) .perform(ViewActions.click()); - Screengrab.screenshot("settingsFragment"); + Screengrab.screenshot("06_settingsFragment"); } @Test public void test03_LocationSelectionFragmentScreenshots() { startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + onView(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)) + onView(withId(R.id.manualGatewaySelection)) .perform(ViewActions.click()); - Screengrab.screenshot("GatewaySelectionFragment"); + Screengrab.screenshot("07_GatewaySelectionFragment"); } @Test - public void test04_AppExclusionFragmentScreenshots() { + public void test04_LanguageSelectionFragmentScreenshots() { startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + onView(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()); + onView(withId(R.id.language_switcher)) + .perform(ViewActions.click()); + + Screengrab.screenshot("08_LanguageSelectionFragment"); + } + + @Test + public void test05_AppExclusionFragmentScreenshots() { + startMainActivity(); + onView(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.exclude_apps)).perform(ViewActions.click()); + onView(withId(R.id.advancedSettings)).perform(ViewActions.click()); + onView(withId(R.id.exclude_apps)).perform(ViewActions.click()); CustomInteractions.tryResolve( - Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2), + onView(Matchers.allOf( + withId(R.id.list), + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE) + )).perform(RecyclerViewActions.scrollToPosition(0)), ViewAssertions.matches(ViewMatchers.isDisplayed()), - 5); + 30, "waiting until app list appears"); - Screengrab.screenshot("App_Exclusion_Fragment"); + Screengrab.screenshot("09_App_Exclusion_Fragment"); } private void startMainActivity() { @@ -146,7 +218,7 @@ public class BitmaskTest { if (setupActivity != null) { ProviderSetupUtils.runProviderSetup(device, false, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); } - Activity mainActivity = instrumentation.waitForMonitorWithTimeout(mainActivityMonitor, 1000); + Activity mainActivity = instrumentation.waitForMonitorWithTimeout(mainActivityMonitor, 1000L); 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 133b834b..e8b65d3f 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -6,24 +6,33 @@ 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.isEnabled; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; 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 static utils.ProviderSetupUtils.isVerboseScreenshots; +import android.Manifest; import android.app.Activity; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; +import android.os.Build; import androidx.test.espresso.ViewInteraction; -import androidx.test.ext.junit.rules.ActivityScenarioRule; +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.Assume; import org.junit.Before; import org.junit.ClassRule; import org.junit.FixMethodOrder; @@ -31,13 +40,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import org.junit.Assume; -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; @@ -52,9 +58,8 @@ public class ProviderSetupTest { @ClassRule public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - // @Rule - // public ActivityScenarioRule<SetupActivity> mActivityScenarioRule = - // new ActivityScenarioRule<>(SetupActivity.class); + @Rule + public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null; UiDevice device; @@ -73,39 +78,58 @@ public class ProviderSetupTest { // Assume the branding is not "custom" to skip this test when it is. Assume.assumeFalse("custom".equals(BuildConfig.FLAVOR_branding)); startSetupActivity(); - ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); + ProviderSetupUtils.runProviderSelection(true); } @Test public void test02_setupProviderCircumvention() { startSetupActivity(); - ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); + ProviderSetupUtils.runProviderSelection(false); + ProviderSetupUtils.runCircumventionSelection(isVerboseScreenshots(), true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test - public void test03_addManuallyNewProviderScreenshot() { + public void test03_addManuallyNewProviderScreenshot() throws UiObjectNotFoundException { if (!"normal".equals(BuildConfig.FLAVOR_branding)) { 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()); + Screengrab.screenshot("043_setup_custom_provider"); + Screengrab.screenshot("043_setup_custom_provider"); + + } + + @Test + public void test04_addInviteCode() throws UiObjectNotFoundException { + if (!"normal".equals(BuildConfig.FLAVOR_branding)) { + System.out.println("skipping custom provider url test"); + return; + } + startSetupActivity(); - 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()); + ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.enter_invite_code)), matches(isDisplayed())); + radioButtonSelection.perform(click()); + onView(withId(R.id.edit_customProvider)).perform(replaceText("obfsvpnintro://13.12.2.161:443/?cert=faXUc56JJAJP%2B0Gc2zHZX0I2RNXuwR0jz937PrpR%2FNopWkuJFkBQwN%2Bzm4ib%2BXvXxXxXxX&fqdn=mysecret.vpnserver.org&kcp=0&auth=_zYOreyzAh+x79j9Ab0DU3A==")); + + tryResolve(onView( + Matchers.allOf( + withId(R.id.syntax_check_result), + withText(R.string.validation_status_success)) + ), matches(isDisplayed()), 3); + tryResolve(onView( + Matchers.allOf( + withId(R.id.setup_next_button), + isEnabled()) + ), matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)), 3); + Screengrab.screenshot("044_setup_invite_code_provider"); + Screengrab.screenshot("044_setup_invite_code_provider"); - tryResolve( - onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))), - matches(isDisplayed()), - 20); - Screengrab.screenshot("setup_provider_error_dialog"); } private void startSetupActivity() { diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java index f3a8d73c..70e08cff 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java @@ -12,8 +12,8 @@ import se.leap.bitmaskclient.ProviderSetupTest; @LargeTest @RunWith(Suite.class) @Suite.SuiteClasses({ - ProviderSetupTest.class, BitmaskTest.class, + ProviderSetupTest.class, }) public class ScreenshotTest { } |
