summaryrefslogtreecommitdiffhomepage
path: root/gui/test
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2024-05-22 12:29:13 +0200
committerOskar Nyberg <oskar@mullvad.net>2024-05-28 15:41:20 +0200
commit58556c0da8a4f3abc441d18c9dd0c026b1986dfb (patch)
tree0d53951c8d6939526d41173269cba9d57e58b611 /gui/test
parent973a31567940c383e2234c50182a5c95907a22ec (diff)
downloadmullvadvpn-58556c0da8a4f3abc441d18c9dd0c026b1986dfb.tar.xz
mullvadvpn-58556c0da8a4f3abc441d18c9dd0c026b1986dfb.zip
Add macos split tunneling test
Diffstat (limited to 'gui/test')
-rw-r--r--gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts162
1 files changed, 162 insertions, 0 deletions
diff --git a/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts b/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts
new file mode 100644
index 0000000000..0f1680bf44
--- /dev/null
+++ b/gui/test/e2e/installed/state-dependent/macos-split-tunneling.spec.ts
@@ -0,0 +1,162 @@
+import { Locator, expect, test } from '@playwright/test';
+import { Page } from 'playwright';
+import { execSync } from 'child_process';
+
+import { startInstalledApp } from '../installed-utils';
+import { TestUtils } from '../../utils';
+import { RoutePath } from '../../../../src/renderer/lib/routes';
+
+// macOS only. This test expects the daemon to be logged in and for split tunneling to be off and
+// have no split applications.
+
+let page: Page;
+let util: TestUtils;
+
+test.beforeAll(async () => {
+ ({ page, util } = await startInstalledApp());
+});
+
+test.afterAll(async () => {
+ await page.close();
+});
+
+async function navigateToSplitTunneling() {
+ await util.waitForNavigation(async () => await page.click('button[aria-label="Settings"]'));
+
+ expect(
+ await util.waitForNavigation(async () => await page.getByText('Split tunneling').click())
+ ).toEqual(RoutePath.splitTunneling);
+
+ const title = page.locator('h1')
+ await expect(title).toHaveText('Split tunneling');
+}
+
+test('App should enable split tunneling', async () => {
+ await navigateToSplitTunneling();
+
+ const toggle = page.getByRole('checkbox');
+ await expect(toggle).not.toBeChecked();
+
+ const splitList = page.getByTestId('split-applications');
+ const nonSplitList = page.getByTestId('non-split-applications');
+
+ await expect(splitList).not.toBeVisible();
+ await expect(nonSplitList).not.toBeVisible();
+
+ const launchPadApp = page.getByText('launchpad');
+ await expect(launchPadApp).not.toBeVisible();
+
+ toggle.click();
+ await expect(toggle).toBeChecked();
+ await expect(splitList).not.toBeVisible();
+ await expect(nonSplitList).toBeVisible();
+ await expect(launchPadApp).toBeVisible();
+ expect(await numberOfApplicationsInList('split-applications')).toBe(0);
+ expect(getDaemonSplitTunnelingApplications()).toHaveLength(0);
+});
+
+test('App should split launchpad', async () => {
+ const splitList = page.getByTestId('split-applications');
+ const nonSplitList = page.getByTestId('non-split-applications');
+
+ const splitLaunchPadApp = splitList.getByText('launchpad');
+ const nonSplitLaunchPadApp = nonSplitList.getByText('launchpad');
+
+ await expect(splitLaunchPadApp).not.toBeVisible();
+ await expect(nonSplitLaunchPadApp).toBeVisible();
+
+ await toggleApplication(nonSplitLaunchPadApp);
+
+ await expect(splitLaunchPadApp).toBeVisible();
+ await expect(nonSplitLaunchPadApp).not.toBeVisible();
+ expect(await numberOfApplicationsInList('split-applications')).toBe(1);
+
+ const daemonSplitTunnelingApplications = getDaemonSplitTunnelingApplications();
+ expect(daemonSplitTunnelingApplications).toHaveLength(1);
+ expect(isSplitInDaemon('launchpad')).toBeTruthy();
+});
+
+test('App should split clock', async () => {
+ const splitList = page.getByTestId('split-applications');
+ const nonSplitList = page.getByTestId('non-split-applications');
+
+ const splitClockApp = splitList.getByText('clock');
+ const nonSplitClockApp = nonSplitList.getByText('clock');
+
+ await expect(splitClockApp).not.toBeVisible();
+ await expect(nonSplitClockApp).toBeVisible();
+
+ await toggleApplication(nonSplitClockApp);
+
+ await expect(splitClockApp).toBeVisible();
+ await expect(nonSplitClockApp).not.toBeVisible();
+ expect(await numberOfApplicationsInList('split-applications')).toBe(2);
+
+ const daemonSplitTunnelingApplications = getDaemonSplitTunnelingApplications();
+ expect(daemonSplitTunnelingApplications).toHaveLength(2);
+ expect(isSplitInDaemon('launchpad')).toBeTruthy();
+ expect(isSplitInDaemon('clock')).toBeTruthy();
+});
+
+test('App should unsplit launchpad', async () => {
+ const splitList = page.getByTestId('split-applications');
+ const nonSplitList = page.getByTestId('non-split-applications');
+
+ const splitLaunchPadApp = splitList.getByText('launchpad');
+ const nonSplitLaunchPadApp = nonSplitList.getByText('launchpad');
+
+ await expect(splitLaunchPadApp).toBeVisible();
+ await expect(nonSplitLaunchPadApp).not.toBeVisible();
+
+ await toggleApplication(splitLaunchPadApp);
+
+ await expect(splitLaunchPadApp).not.toBeVisible();
+ await expect(nonSplitLaunchPadApp).toBeVisible();
+ expect(await numberOfApplicationsInList('split-applications')).toBe(1);
+
+ const daemonSplitTunnelingApplications = getDaemonSplitTunnelingApplications();
+ expect(daemonSplitTunnelingApplications).toHaveLength(1);
+ expect(isSplitInDaemon('launchpad')).toBeFalsy();
+ expect(isSplitInDaemon('clock')).toBeTruthy();
+});
+
+test('App should disable split tunneling', async () => {
+ const toggle = page.getByRole('checkbox');
+ await expect(toggle).toBeChecked();
+
+ const splitList = page.getByTestId('split-applications');
+ const nonSplitList = page.getByTestId('non-split-applications');
+
+ await expect(splitList).toBeVisible();
+ await expect(nonSplitList).toBeVisible();
+
+ const launchPadApp = page.getByText('launchpad');
+ await expect(launchPadApp).toBeVisible();
+
+ toggle.click();
+ await expect(toggle).not.toBeChecked();
+});
+
+async function toggleApplication(applicationLocator: Locator) {
+ await applicationLocator.locator('~ div').click();
+}
+
+async function numberOfApplicationsInList(listTestid: string) {
+ const list = page.getByTestId(listTestid);
+ const listHidden = await list.isHidden();
+ if (listHidden) {
+ return 0;
+ }
+
+ return await list.locator('button').count();
+}
+
+function getDaemonSplitTunnelingApplications() {
+ const output = execSync('mullvad split-tunnel get').toString().trim().split('\n');
+ return output.slice(output.indexOf('Excluded applications:') + 1);
+}
+
+function isSplitInDaemon(app: string): boolean {
+ return !!getDaemonSplitTunnelingApplications()
+ .find((splitApp) => splitApp.toLowerCase().includes(app));
+}