diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2024-05-22 12:29:13 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2024-05-28 15:41:20 +0200 |
| commit | 58556c0da8a4f3abc441d18c9dd0c026b1986dfb (patch) | |
| tree | 0d53951c8d6939526d41173269cba9d57e58b611 /gui/test | |
| parent | 973a31567940c383e2234c50182a5c95907a22ec (diff) | |
| download | mullvadvpn-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.ts | 162 |
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)); +} |
