diff options
| author | Oskar <oskar@mullvad.net> | 2025-09-30 12:12:00 +0200 |
|---|---|---|
| committer | Oskar <oskar@mullvad.net> | 2025-09-30 12:12:00 +0200 |
| commit | c7feb62a4e74c6f5f58c267ea76ee56c40a55fea (patch) | |
| tree | 8099d01800c7e5947dade2b2c287b7a29c9ae12d | |
| parent | e58b5ee1a8db4d5cf68826301daa8380ed1249bf (diff) | |
| parent | 1be072d3168e1799224d7d3930943df9853d5987 (diff) | |
| download | mullvadvpn-c7feb62a4e74c6f5f58c267ea76ee56c40a55fea.tar.xz mullvadvpn-c7feb62a4e74c6f5f58c267ea76ee56c40a55fea.zip | |
Merge branch 'quick-access-feature-setting-state-e2e-tests'
12 files changed, 97 insertions, 58 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/wireguard-settings/components/obfuscation-settings/ObfuscationSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/wireguard-settings/components/obfuscation-settings/ObfuscationSettings.tsx index 0ac893db9e..aa9b1e7835 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/views/wireguard-settings/components/obfuscation-settings/ObfuscationSettings.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/wireguard-settings/components/obfuscation-settings/ObfuscationSettings.tsx @@ -83,7 +83,7 @@ export function ObfuscationSettings() { </SettingsListbox.SplitOption.Item> <SettingsListbox.SplitOption.NavigateButton to={RoutePath.shadowsocks} - aria-description={messages.pgettext('accessibility', 'Shadowsocks settings')} + aria-label={messages.pgettext('accessibility', 'Shadowsocks settings')} /> </SettingsListbox.SplitOption> <SettingsListbox.SplitOption value={ObfuscationType.udp2tcp}> @@ -101,7 +101,7 @@ export function ObfuscationSettings() { </SettingsListbox.SplitOption.Item> <SettingsListbox.SplitOption.NavigateButton to={RoutePath.udpOverTcp} - aria-description={messages.pgettext('accessibility', 'UDP-over-TCP settings')} + aria-label={messages.pgettext('accessibility', 'UDP-over-TCP settings')} /> </SettingsListbox.SplitOption> <SettingsListbox.BaseOption value={ObfuscationType.quic}> diff --git a/desktop/packages/mullvad-vpn/test/e2e/installed/state-dependent/obfuscation.spec.ts b/desktop/packages/mullvad-vpn/test/e2e/installed/state-dependent/obfuscation.spec.ts index 9c2f3c3348..b0d81a7f54 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/installed/state-dependent/obfuscation.spec.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/installed/state-dependent/obfuscation.spec.ts @@ -2,8 +2,8 @@ import { expect, test } from '@playwright/test'; import { execSync } from 'child_process'; import { Page } from 'playwright'; -import { colorTokens } from '../../../../src/renderer/lib/foundations'; import { RoutePath } from '../../../../src/shared/routes'; +import { RoutesObjectModel } from '../../route-object-models'; import { TestUtils } from '../../utils'; import { startInstalledApp } from '../installed-utils'; @@ -15,10 +15,15 @@ const UDPOVERTCP_PORT = '80'; let page: Page; let util: TestUtils; +let routes: RoutesObjectModel; test.beforeAll(async () => { ({ page, util } = await startInstalledApp()); + routes = new RoutesObjectModel(page, util); await util.expectRoute(RoutePath.main); + await routes.main.gotoSettings(); + await routes.settings.gotoVpnSettings(); + await routes.vpnSettings.gotoWireguardSettings(); }); test.afterAll(async () => { @@ -26,22 +31,10 @@ test.afterAll(async () => { }); test('App should have automatic obfuscation', async () => { - await page.click('button[aria-label="Settings"]'); - await util.expectRoute(RoutePath.settings); + const automaticObfuscationOption = + routes.wireguardSettings.selectors.automaticObfuscationOption(); - await page.getByText('VPN settings').click(); - await util.expectRoute(RoutePath.vpnSettings); - - await page.getByText('WireGuard settings').click(); - await util.expectRoute(RoutePath.wireguardSettings); - - const obfuscationListbox = page.getByRole('listbox', { name: 'Obfuscation' }); - await obfuscationListbox.highlight(); - const automaticOption = obfuscationListbox.getByRole('option', { - name: 'Automatic', - exact: true, - }); - await expect(automaticOption).toHaveAttribute('aria-selected', 'true'); + await expect(automaticObfuscationOption).toHaveAttribute('aria-selected', 'true'); const cliObfuscation = execSync('mullvad obfuscation get').toString().split('\n'); expect(cliObfuscation[0]).toEqual('Obfuscation mode: auto'); @@ -50,61 +43,52 @@ test('App should have automatic obfuscation', async () => { }); test('App should set obfuscation to shadowsocks with custom port', async () => { - await page.click('button[aria-label="Shadowsocks settings"]'); - await util.expectRoute(RoutePath.shadowsocks); + await routes.wireguardSettings.gotoShadowSocksSettings(); + const automaticOption = routes.shadowsocksSettings.selectors.automaticPortOption(); - const automatic = page.locator('button', { hasText: 'Automatic' }); - await expect(automatic).toHaveCSS('background-color', colorTokens.green); + await expect(automaticOption).toHaveAttribute('aria-selected', 'true'); - const customInput = page.locator('input[type="text"]'); - await customInput.click(); - await customInput.fill(`${SHADOWSOCKS_PORT}`); - await customInput.blur(); + await routes.shadowsocksSettings.fillPortInput(SHADOWSOCKS_PORT); - const customItem = page.locator('div[role="option"]', { hasText: 'Custom' }); - await expect(customItem).toHaveCSS('background-color', colorTokens.green); + const customPortOption = routes.shadowsocksSettings.selectors.customPortOption(); + await expect(customPortOption).toHaveAttribute('aria-selected', 'true'); - await page.click('button[aria-label="Back"]'); - await util.expectRoute(RoutePath.wireguardSettings); + await routes.shadowsocksSettings.goBack(); - const shadowsocksItem = page.locator('button', { hasText: 'Shadowsocks' }); - await shadowsocksItem.click(); - await expect(shadowsocksItem).toHaveCSS('background-color', colorTokens.green); - await expect(shadowsocksItem).toContainText(`Port: ${SHADOWSOCKS_PORT}`); + const shadowsocksOption = routes.wireguardSettings.selectors.shadowsocksOption(); + await expect(shadowsocksOption).toContainText(`Port: ${SHADOWSOCKS_PORT}`); + + await routes.wireguardSettings.selectShadowsocks(); + await expect(shadowsocksOption).toHaveAttribute('aria-selected', 'true'); const cliObfuscation = execSync('mullvad obfuscation get').toString().split('\n')[2]; expect(cliObfuscation).toEqual(`Shadowsocks settings: port ${SHADOWSOCKS_PORT}`); }); test('App should still have shadowsocks custom port', async () => { - await page.click('button[aria-label="Shadowsocks settings"]'); - await util.expectRoute(RoutePath.shadowsocks); + await routes.wireguardSettings.gotoShadowSocksSettings(); - const customItem = page.locator('div[role="option"]', { hasText: 'Custom' }); - await expect(customItem).toHaveCSS('background-color', colorTokens.green); + const customPortOption = routes.shadowsocksSettings.selectors.customPortOption(); + await expect(customPortOption).toHaveAttribute('aria-selected', 'true'); - await page.click('button[aria-label="Back"]'); - await util.expectRoute(RoutePath.wireguardSettings); + await routes.shadowsocksSettings.goBack(); }); test('App should set obfuscation to UDP-over-TCP with port', async () => { - await page.click('button[aria-label="UDP-over-TCP settings"]'); - await util.expectRoute(RoutePath.udpOverTcp); - - const automatic = page.locator('button', { hasText: 'Automatic' }); - await expect(automatic).toHaveCSS('background-color', colorTokens.green); + await routes.wireguardSettings.gotoUdpOverTcpSettings(); - const portButton = page.locator('button', { hasText: UDPOVERTCP_PORT }); - await portButton.click(); + const automaticOption = routes.udpOverTcpSettings.selectors.automaticPortOption(); + await expect(automaticOption).toHaveAttribute('aria-selected', 'true'); - await expect(portButton).toHaveCSS('background-color', colorTokens.green); + await routes.udpOverTcpSettings.selectPort(parseInt(UDPOVERTCP_PORT)); + const portButton = routes.udpOverTcpSettings.selectors.portNumber(parseInt(UDPOVERTCP_PORT)); + await expect(portButton).toHaveAttribute('aria-selected', 'true'); - await page.click('button[aria-label="Back"]'); - await util.expectRoute(RoutePath.wireguardSettings); + await routes.udpOverTcpSettings.goBack(); - const udpOverTcpItem = page.locator('button', { hasText: 'UDP-over-TCP' }); - await udpOverTcpItem.click(); - await expect(udpOverTcpItem).toHaveCSS('background-color', colorTokens.green); + const udpOverTcpItem = routes.wireguardSettings.selectors.udpOverTcpOption(); + await routes.wireguardSettings.selectUdpOverTcp(); + await expect(udpOverTcpItem).toHaveAttribute('aria-selected', 'true'); await expect(udpOverTcpItem).toContainText(`Port: ${UDPOVERTCP_PORT}`); const cliObfuscation = execSync('mullvad obfuscation get').toString().split('\n')[1]; diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/daita-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/daita-settings/selectors.ts index 4c8f8c51bd..ece73c4c72 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/daita-settings/selectors.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/daita-settings/selectors.ts @@ -1,5 +1,5 @@ import { Page } from 'playwright'; export const createSelectors = (page: Page) => ({ - enableDaitaSwitch: () => page.getByLabel('Enable'), + enableDaitaSwitch: () => page.getByRole('switch', { name: 'Enable' }), }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/multihop-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/multihop-settings/selectors.ts index 217ed920a2..333a436574 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/multihop-settings/selectors.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/multihop-settings/selectors.ts @@ -1,5 +1,5 @@ import { Page } from 'playwright'; export const createSelectors = (page: Page) => ({ - enableMultihopSwitch: () => page.getByRole('checkbox', { name: 'Enable' }), + enableMultihopSwitch: () => page.getByRole('switch', { name: 'Enable' }), }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/routes-object-model.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/routes-object-model.ts index 9cf32e5caf..997247d2fa 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/routes-object-model.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/routes-object-model.ts @@ -10,6 +10,7 @@ import { MultihopSettingsRouteObjectModel } from './multihop-settings'; import { SelectLanguageRouteObjectModel } from './select-language'; import { SelectLocationRouteObjectModel } from './select-location'; import { SettingsRouteObjectModel } from './settings/settings-route-object-model'; +import { ShadowsocksSettingsRouteObjectModel } from './shadowsocks-settings'; import { SplitTunnelingSettingsRouteObjectModel } from './split-tunneling-settings'; import { UdpOverTcpSettingsRouteObjectModel } from './udp-over-tcp-settings'; import { UserInterfaceSettingsRouteObjectModel } from './user-interface-settings'; @@ -31,6 +32,7 @@ export class RoutesObjectModel { readonly multihopSettings: MultihopSettingsRouteObjectModel; readonly daitaSettings: DaitaSettingsRouteObjectModel; readonly splitTunnelingSettings: SplitTunnelingSettingsRouteObjectModel; + readonly shadowsocksSettings: ShadowsocksSettingsRouteObjectModel; constructor(page: Page, utils: TestUtils) { this.selectLanguage = new SelectLanguageRouteObjectModel(page, utils); @@ -47,5 +49,6 @@ export class RoutesObjectModel { this.multihopSettings = new MultihopSettingsRouteObjectModel(page, utils); this.daitaSettings = new DaitaSettingsRouteObjectModel(page, utils); this.splitTunnelingSettings = new SplitTunnelingSettingsRouteObjectModel(page, utils); + this.shadowsocksSettings = new ShadowsocksSettingsRouteObjectModel(page, utils); } } diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/index.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/index.ts new file mode 100644 index 0000000000..ee8499fbda --- /dev/null +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/index.ts @@ -0,0 +1,2 @@ +export * from './shadowsocks-settings-route-object-model'; +export * from './selectors'; diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/selectors.ts new file mode 100644 index 0000000000..6d7844396d --- /dev/null +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/selectors.ts @@ -0,0 +1,13 @@ +import { Page } from 'playwright'; + +export const createSelectors = (page: Page) => ({ + automaticPortOption: () => + page + .getByRole('listbox', { name: 'Port' }) + .getByRole('option', { name: 'Automatic', exact: true }), + customPortOption: () => + page + .getByRole('listbox', { name: 'Port' }) + .getByRole('option', { name: 'Custom', exact: true }), + portInput: () => page.getByPlaceholder('Port'), +}); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/shadowsocks-settings-route-object-model.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/shadowsocks-settings-route-object-model.ts new file mode 100644 index 0000000000..3c56fa5bc0 --- /dev/null +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/shadowsocks-settings/shadowsocks-settings-route-object-model.ts @@ -0,0 +1,22 @@ +import { Page } from 'playwright'; + +import { TestUtils } from '../../utils'; +import { NavigationObjectModel } from '../navigation'; +import { createSelectors } from './selectors'; + +export class ShadowsocksSettingsRouteObjectModel extends NavigationObjectModel { + readonly selectors: ReturnType<typeof createSelectors>; + + constructor(page: Page, utils: TestUtils) { + super(page, utils); + + this.selectors = createSelectors(page); + } + + async fillPortInput(port: number) { + const input = this.selectors.portInput(); + await input.click(); + await input.fill(`${port}`); + await input.press('Enter'); + } +} diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/udp-over-tcp-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/udp-over-tcp-settings/selectors.ts index f993e501ca..ca2e4ad402 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/udp-over-tcp-settings/selectors.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/udp-over-tcp-settings/selectors.ts @@ -2,4 +2,8 @@ import { Page } from 'playwright'; export const createSelectors = (page: Page) => ({ portNumber: (port: number) => page.getByRole('option', { name: `${port}` }), + automaticPortOption: () => + page + .getByRole('listbox', { name: 'Port' }) + .getByRole('option', { name: 'Automatic', exact: true }), }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/vpn-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/vpn-settings/selectors.ts index 607756d76f..29e32ff9b6 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/vpn-settings/selectors.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/vpn-settings/selectors.ts @@ -2,8 +2,8 @@ import { Page } from 'playwright'; export const createSelectors = (page: Page) => ({ heading: () => page.getByRole('heading', { name: 'VPN settings' }), - launchAppOnStartupSwitch: () => page.getByLabel('Launch app on start-up'), - autoConnectSwitch: () => page.getByLabel('Auto-connect'), - lanSwitch: () => page.getByLabel('Local network sharing'), + launchAppOnStartupSwitch: () => page.getByRole('switch', { name: 'Launch app on start-up' }), + autoConnectSwitch: () => page.getByRole('switch', { name: 'Auto-connect' }), + lanSwitch: () => page.getByRole('switch', { name: 'Local network sharing' }), wireguardSettingsButton: () => page.getByRole('button', { name: 'WireGuard settings' }), }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/selectors.ts index ff7621e637..d7b3ed004c 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/selectors.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/selectors.ts @@ -7,4 +7,6 @@ export const createSelectors = (page: Page) => ({ page .getByRole('listbox', { name: 'Obfuscation' }) .getByRole('option', { name: 'Automatic', exact: true }), + shadowsocksSettingsButton: () => page.getByRole('button', { name: 'Shadowsocks settings' }), + shadowsocksOption: () => page.getByRole('option', { name: 'Shadowsocks' }), }); diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/wireguard-settings-route-object-model.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/wireguard-settings-route-object-model.ts index fa568fd9cc..cfaae197d3 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/wireguard-settings-route-object-model.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/wireguard-settings/wireguard-settings-route-object-model.ts @@ -34,4 +34,13 @@ export class WireguardSettingsRouteObjectModel extends NavigationObjectModel { async selectUdpOverTcp() { await this.getUdpOverTcpOption().click(); } + + async selectShadowsocks() { + await this.selectors.shadowsocksOption().click(); + } + + async gotoShadowSocksSettings() { + await this.selectors.shadowsocksSettingsButton().click(); + await this.utils.expectRoute(RoutePath.shadowsocks); + } } |
