summaryrefslogtreecommitdiff
path: root/app/src/androidTest/java/se/leap
diff options
context:
space:
mode:
authorcyberta <cyberta@riseup.net>2026-07-03 13:23:32 +0200
committercyberta <cyberta@riseup.net>2026-07-03 17:49:31 +0200
commitbe186e4eda72f14eb3b8f6fab76fbeda9d9fb175 (patch)
tree0a35c05944b7888aecf406bfb721434e8903f318 /app/src/androidTest/java/se/leap
parent1784fb5e60414808f21f4596959adf7a8b46e675 (diff)
fix and extend instrumentation tests used for automatted screenshots
Diffstat (limited to 'app/src/androidTest/java/se/leap')
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java124
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java64
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java2
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 {
}