diff options
| author | Oliver <oliver@mohlin.dev> | 2025-05-29 11:22:41 +0200 |
|---|---|---|
| committer | Oliver <oliver@mohlin.dev> | 2025-06-05 10:26:46 +0200 |
| commit | 2eb23455ebe8b169ae0dc8a8b7b3d36bf9fbb585 (patch) | |
| tree | de8504e9d33179dd18d9409ca1e93d2000caeb56 /desktop | |
| parent | f5b2cb8213bd13e0c0de6c058019821803aaf136 (diff) | |
| download | mullvadvpn-2eb23455ebe8b169ae0dc8a8b7b3d36bf9fbb585.tar.xz mullvadvpn-2eb23455ebe8b169ae0dc8a8b7b3d36bf9fbb585.zip | |
Add e2e tests for filtering by provider and ownership
Diffstat (limited to 'desktop')
| -rw-r--r-- | desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/helpers.ts | 114 | ||||
| -rw-r--r-- | desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/select-location.spec.ts | 150 |
2 files changed, 222 insertions, 42 deletions
diff --git a/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/helpers.ts b/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/helpers.ts new file mode 100644 index 0000000000..7490adc6ac --- /dev/null +++ b/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/helpers.ts @@ -0,0 +1,114 @@ +import { Page } from 'playwright'; + +import { getDefaultSettings } from '../../../../src/main/default-settings'; +import { + IRelayList, + IRelayListCity, + IRelayListCountry, + IRelayListHostname, + Ownership, +} from '../../../../src/shared/daemon-rpc-types'; +import { RoutePath } from '../../../../src/shared/routes'; +import { RoutesObjectModel } from '../../route-object-models'; +import { MockedTestUtils } from '../mocked-utils'; + +export type LocatedRelay = { + country: IRelayListCountry; + city: IRelayListCity; + relay: IRelayListHostname; +}; + +export const createHelpers = (page: Page, routes: RoutesObjectModel, utils: MockedTestUtils) => { + const areAllCheckboxesChecked = async () => { + const checkboxes = page.getByRole('checkbox'); + return checkboxes.evaluateAll((checkboxes) => + checkboxes.every((checkbox) => checkbox.getAttribute('aria-checked') === 'true'), + ); + }; + + const expandLocatedRelays = async (locatedRelays: LocatedRelay[]) => { + for (const locatedRelay of locatedRelays) { + await routes.selectLocation.toggleAccordion(locatedRelay.country.name); + await routes.selectLocation.toggleAccordion(locatedRelay.city.name); + } + }; + + const locateRelaysByProvider = (relayList: IRelayList, provider?: string): LocatedRelay[] => + relayList.countries.flatMap((country) => + country.cities.flatMap((city) => + city.relays + .filter((relay) => !provider || relay.provider === provider) + .map((relay) => ({ country, city, relay })), + ), + ); + + const locateRelaysByOwner = (relayList: IRelayList, owned?: boolean): LocatedRelay[] => + relayList.countries.flatMap((country) => + country.cities.flatMap((city) => + city.relays + .filter((relay) => relay.owned === owned) + .map((relay) => ({ country, city, relay })), + ), + ); + + const resetOwnership = async () => { + await routes.filter.expandOwnership(); + await routes.filter.selectOwnershipOption('Any'); + await routes.filter.collapseOwnership(); + }; + + const resetProviders = async () => { + await routes.filter.expandProviders(); + const allCheckboxesChecked = await areAllCheckboxesChecked(); + if (!allCheckboxesChecked) { + await routes.filter.checkAllProvidersCheckbox(); + } + await routes.filter.collapseProviders(); + }; + + const resetView = async () => { + const currentRoute = await utils.currentRoute(); + if (currentRoute === RoutePath.selectLocation) { + await routes.selectLocation.gotoFilter(); + } + }; + + const updateMockRelayFilter = async ({ + ownership, + providers, + }: { + ownership?: Ownership; + providers?: string[]; + }) => { + const settings = getDefaultSettings(); + if ('normal' in settings.relaySettings) { + if (ownership) { + settings.relaySettings.normal.ownership = ownership; + } + if (providers) { + settings.relaySettings.normal.providers = providers; + } + } + await utils.mockIpcHandle({ + channel: 'settings-setRelaySettings', + response: {}, + }); + await utils.sendMockIpcResponse({ + channel: 'settings-', + response: settings, + }); + }; + + return { + areAllCheckboxesChecked, + expandLocatedRelays, + locateRelaysByProvider, + locateRelaysByOwner, + resetOwnership, + resetProviders, + resetView, + updateMockRelayFilter, + }; +}; + +export type SelectLocationHelpers = ReturnType<typeof createHelpers>; diff --git a/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/select-location.spec.ts b/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/select-location.spec.ts index 1984213e2b..b01c5ac054 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/select-location.spec.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/mocked/select-location/select-location.spec.ts @@ -4,54 +4,16 @@ import { Page } from 'playwright'; import { getDefaultSettings } from '../../../../src/main/default-settings'; import { colorTokens } from '../../../../src/renderer/lib/foundations'; import { - IRelayList, IRelayListWithEndpointData, ISettings, IWireguardEndpointData, + Ownership, } from '../../../../src/shared/daemon-rpc-types'; import { RoutePath } from '../../../../src/shared/routes'; +import { RoutesObjectModel } from '../../route-object-models'; import { MockedTestUtils, startMockedApp } from '../mocked-utils'; - -const relayList: IRelayList = { - countries: [ - { - name: 'Sweden', - code: 'se', - cities: [ - { - name: 'Gothenburg', - code: 'got', - latitude: 58, - longitude: 12, - relays: [ - { - hostname: 'se-got-wg-101', - provider: 'mullvad', - ipv4AddrIn: '10.0.0.1', - includeInCountry: true, - active: true, - weight: 0, - owned: true, - endpointType: 'wireguard', - daita: true, - }, - { - hostname: 'se-got-wg-102', - provider: 'mullvad', - ipv4AddrIn: '10.0.0.2', - includeInCountry: true, - active: true, - weight: 0, - owned: true, - endpointType: 'wireguard', - daita: true, - }, - ], - }, - ], - }, - ], -}; +import { createHelpers, SelectLocationHelpers } from './helpers'; +import { mockData } from './mock-data'; const wireguardEndpointData: IWireguardEndpointData = { portRanges: [], @@ -60,10 +22,15 @@ const wireguardEndpointData: IWireguardEndpointData = { let page: Page; let util: MockedTestUtils; +let routes: RoutesObjectModel; +let helpers: SelectLocationHelpers; +const { relayList } = mockData; test.describe('Select location', () => { test.beforeAll(async () => { ({ page, util } = await startMockedApp()); + routes = new RoutesObjectModel(page, util); + helpers = createHelpers(page, routes, util); await util.waitForRoute(RoutePath.main); await page.getByLabel('Select location').click(); await util.waitForRoute(RoutePath.selectLocation); @@ -151,4 +118,103 @@ test.describe('Select location', () => { await expect(sweden).toBeVisible(); }); }); + + test.describe('Filter', () => { + test.beforeEach(async () => { + await helpers.resetView(); + await helpers.resetProviders(); + await helpers.resetOwnership(); + }); + + test.describe('Filter by provider', () => { + test('Should deselect all providers when clicking all providers checkbox', async () => { + await routes.filter.expandProviders(); + await routes.filter.checkAllProvidersCheckbox(); + expect(await helpers.areAllCheckboxesChecked()).toBe(false); + + await routes.filter.checkAllProvidersCheckbox(); + expect(await helpers.areAllCheckboxesChecked()).toBe(true); + }); + + test('Should apply filter when selecting provider', async () => { + await routes.filter.expandProviders(); + await routes.filter.checkAllProvidersCheckbox(); + expect(await helpers.areAllCheckboxesChecked()).toBe(false); + + // Select one provider + const provider = relayList.countries[0].cities[0].relays[0].provider; + await routes.filter.checkProviderCheckbox(provider); + + await helpers.updateMockRelayFilter({ + providers: [provider], + }); + + await routes.filter.applyFilter(); + await util.waitForRoute(RoutePath.selectLocation); + const providerFilterChip = routes.selectLocation.getFilterChip('Providers: 1'); + await expect(providerFilterChip).toBeVisible(); + + const locatedRelays = helpers.locateRelaysByProvider(relayList, provider); + const relays = locatedRelays.map((locatedRelay) => locatedRelay.relay); + const relayNames = relays.map((relay) => relay.hostname); + + // Expand all accordions + await helpers.expandLocatedRelays(locatedRelays); + + const buttons = routes.selectLocation.getRelaysMatching(relayNames); + + // Expect all filtered relays to have a button + await expect(buttons).toHaveCount(relays.length); + + // Clear filter + await providerFilterChip.click(); + + // Get all relays and expand accordions + const allLocatedRelays = helpers.locateRelaysByProvider(relayList); + await helpers.expandLocatedRelays(allLocatedRelays); + + // Should not have same length as all relays + await expect(buttons).not.toHaveCount(allLocatedRelays.length); + }); + }); + + test.describe('Filter by ownership', () => { + test('Should apply filter when selecting ownership', async () => { + // Select rented only + await routes.filter.expandOwnership(); + await routes.filter.selectOwnershipOption('Rented only'); + await helpers.updateMockRelayFilter({ + ownership: Ownership.rented, + }); + + await routes.filter.applyFilter(); + await util.waitForRoute(RoutePath.selectLocation); + + const ownerFilterChip = routes.selectLocation.getFilterChip('Rented'); + await expect(ownerFilterChip).toBeVisible(); + + const locatedRelays = helpers.locateRelaysByOwner(relayList, false); + const relays = locatedRelays.map((locatedRelay) => locatedRelay.relay); + const relayNames = relays.map((relay) => relay.hostname); + + // Expand all accordions + await helpers.expandLocatedRelays(locatedRelays); + + const buttons = routes.selectLocation.getRelaysMatching(relayNames); + + // Expect all filtered relays to have a button + await expect(buttons).toHaveCount(relays.length); + + // Clear filter + await ownerFilterChip.click(); + + // Get all relays and expand accordions + const allLocatedRelays = helpers.locateRelaysByOwner(relayList); + await helpers.expandLocatedRelays(allLocatedRelays); + + // Should not have same length as all relays + await expect(buttons).not.toHaveCount(allLocatedRelays.length); + }); + }); + }); }); |
