summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2025-08-28 16:55:22 +0200
committerOskar <oskar@mullvad.net>2025-08-29 07:38:40 +0200
commit2e986bb30274889869871ed050043155f21cf466 (patch)
tree93bed5f5c395f1ce9239b23e48f052b88ee19bb6
parenta2fd2e3fabac41053c08bdddb34b3beecf5d6a7d (diff)
downloadmullvadvpn-2e986bb30274889869871ed050043155f21cf466.tar.xz
mullvadvpn-2e986bb30274889869871ed050043155f21cf466.zip
Add tests of warnings when clearing account history
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/mocked/login.spec.ts103
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/index.ts2
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/login-route-object-model.ts56
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/selectors.ts15
-rw-r--r--desktop/packages/mullvad-vpn/test/e2e/route-object-models/routes-object-model.ts3
5 files changed, 179 insertions, 0 deletions
diff --git a/desktop/packages/mullvad-vpn/test/e2e/mocked/login.spec.ts b/desktop/packages/mullvad-vpn/test/e2e/mocked/login.spec.ts
new file mode 100644
index 0000000000..46f2dcd6a0
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/test/e2e/mocked/login.spec.ts
@@ -0,0 +1,103 @@
+import { expect, test } from '@playwright/test';
+import { Page } from 'playwright';
+
+import { DeviceEvent } from '../../../src/shared/daemon-rpc-types';
+import { RoutesObjectModel } from '../route-object-models';
+import { MockedTestUtils, startMockedApp } from './mocked-utils';
+
+let page: Page;
+let util: MockedTestUtils;
+let routes: RoutesObjectModel;
+
+test.describe.configure({ mode: 'parallel' });
+
+test.describe('Clear account history warnings', () => {
+ const startup = async () => {
+ ({ page, util } = await startMockedApp());
+ routes = new RoutesObjectModel(page, util);
+ };
+
+ const logout = async () => {
+ await util.sendMockIpcResponse<DeviceEvent>({
+ channel: util.ipcEvents.account.device,
+ response: { type: 'logged out', deviceState: { type: 'logged out' } },
+ });
+
+ await routes.login.waitForRoute();
+ };
+
+ test.beforeAll(async () => {
+ await startup();
+ await routes.main.waitForRoute();
+ });
+
+ test.beforeEach(async () => {
+ await logout();
+ });
+
+ test.afterAll(async () => {
+ await page.close();
+ });
+
+ const setAccountHistory = async () => {
+ await util.sendMockIpcResponse({
+ channel: util.ipcEvents.accountHistory[''],
+ response: '1234123412341234',
+ });
+ };
+
+ test('Should not warn about creating an account', async () => {
+ const accountHistoryItemButton = routes.login.getAccountHistoryItemButton();
+ await expect(accountHistoryItemButton).not.toBeVisible();
+
+ await Promise.all([
+ util.expectIpcCall(util.ipcEvents.account.create),
+ routes.login.createNewAccount(),
+ ]);
+ });
+
+ test('Should warn about creating an account', async () => {
+ await setAccountHistory();
+
+ const confirmationMessage = routes.login.getCreateNewAccountConfirmationMessage();
+ await expect(confirmationMessage).not.toBeVisible();
+ await routes.login.createNewAccount();
+ await expect(confirmationMessage).toBeVisible();
+ await routes.login.cancelCreateNewAccount();
+ await expect(confirmationMessage).not.toBeVisible();
+
+ await routes.login.createNewAccount();
+
+ await Promise.all([
+ util.expectIpcCall(util.ipcEvents.account.create),
+ routes.login.confirmCreateNewAccount(),
+ ]);
+ });
+
+ test('Should warn about clearing account history', async () => {
+ await setAccountHistory();
+
+ const accountHistoryItemButton = routes.login.getAccountHistoryItemButton();
+ await expect(accountHistoryItemButton).toBeVisible();
+
+ const confirmationMessage = routes.login.getClearAccountHistoryConfirmationMessage();
+ await expect(confirmationMessage).not.toBeVisible();
+ await routes.login.clearAccountHistory();
+ await expect(confirmationMessage).toBeVisible();
+ await routes.login.cancelClearAccountHistory();
+ await expect(confirmationMessage).not.toBeVisible();
+ await expect(accountHistoryItemButton).toBeVisible();
+
+ await routes.login.clearAccountHistory();
+ await Promise.all([
+ util.expectIpcCall(util.ipcEvents.accountHistory.clear),
+ routes.login.confirmClearAccountHistory(),
+ ]);
+
+ await util.sendMockIpcResponse({
+ channel: util.ipcEvents.accountHistory[''],
+ response: undefined,
+ });
+ await expect(accountHistoryItemButton).not.toBeVisible();
+ });
+});
diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/index.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/index.ts
new file mode 100644
index 0000000000..2bee8b20be
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/index.ts
@@ -0,0 +1,2 @@
+export * from './login-route-object-model';
+export * from './selectors';
diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/login-route-object-model.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/login-route-object-model.ts
new file mode 100644
index 0000000000..4dfe73a2a8
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/login-route-object-model.ts
@@ -0,0 +1,56 @@
+import { Page } from 'playwright';
+
+import { RoutePath } from '../../../../src/shared/routes';
+import { TestUtils } from '../../utils';
+import { createSelectors } from './selectors';
+
+export class LoginRouteObjectModel {
+ readonly selectors: ReturnType<typeof createSelectors>;
+
+ constructor(
+ private readonly page: Page,
+ private readonly utils: TestUtils,
+ ) {
+ this.selectors = createSelectors(this.page);
+ }
+
+ async waitForRoute() {
+ await this.utils.waitForRoute(RoutePath.login);
+ }
+
+ async createNewAccount() {
+ await this.selectors.createNewAccountButton().click();
+ }
+
+ getCreateNewAccountConfirmationMessage() {
+ return this.selectors.createNewAccountMessage();
+ }
+
+ async confirmCreateNewAccount() {
+ await this.selectors.confirmCreateNewAccountButton().click();
+ }
+
+ async cancelCreateNewAccount() {
+ await this.selectors.cancelDialogButton().click();
+ }
+
+ async clearAccountHistory() {
+ await this.selectors.clearAccountHistory().click();
+ }
+
+ getAccountHistoryItemButton() {
+ return this.selectors.accountHistoryItemButton();
+ }
+
+ getClearAccountHistoryConfirmationMessage() {
+ return this.selectors.clearAccountHistoryMessage();
+ }
+
+ async confirmClearAccountHistory() {
+ await this.selectors.confirmClearAccountHistoryButton().click();
+ }
+
+ async cancelClearAccountHistory() {
+ await this.selectors.cancelDialogButton().click();
+ }
+}
diff --git a/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/selectors.ts b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/selectors.ts
new file mode 100644
index 0000000000..c49df8ce87
--- /dev/null
+++ b/desktop/packages/mullvad-vpn/test/e2e/route-object-models/login/selectors.ts
@@ -0,0 +1,15 @@
+import { Page } from 'playwright';
+
+export const createSelectors = (page: Page) => ({
+ createNewAccountButton: () => page.getByRole('button', { name: 'Create account' }),
+ createNewAccountMessage: () => page.getByText('Do you want to create a new account?'),
+ confirmCreateNewAccountButton: () => page.getByRole('button', { name: 'Create new account' }),
+
+ accountHistoryItemButton: () => page.getByRole('button', { name: 'Login with account number' }),
+ clearAccountHistory: () => page.getByRole('button', { name: 'Forget account number' }),
+ clearAccountHistoryMessage: () =>
+ page.getByText('Do you want to remove the saved account number?'),
+ confirmClearAccountHistoryButton: () => page.getByRole('button', { name: 'Remove' }),
+
+ cancelDialogButton: () => page.getByRole('button', { name: 'Cancel' }),
+});
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 2de9fa7d64..ec58260dd3 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
@@ -4,6 +4,7 @@ import { TestUtils } from '../utils';
import { DaitaSettingsRouteObjectModel } from './daita-settings';
import { FilterRouteObjectModel } from './filter';
import { LaunchRouteObjectModel } from './launch';
+import { LoginRouteObjectModel } from './login';
import { MainRouteObjectModel } from './main';
import { MultihopSettingsRouteObjectModel } from './multihop-settings';
import { SelectLanguageRouteObjectModel } from './select-language';
@@ -17,6 +18,7 @@ import { WireguardSettingsRouteObjectModel } from './wireguard-settings';
export class RoutesObjectModel {
readonly main: MainRouteObjectModel;
readonly launch: LaunchRouteObjectModel;
+ readonly login: LoginRouteObjectModel;
readonly settings: SettingsRouteObjectModel;
readonly userInterfaceSettings: UserInterfaceSettingsRouteObjectModel;
readonly selectLanguage: SelectLanguageRouteObjectModel;
@@ -32,6 +34,7 @@ export class RoutesObjectModel {
this.selectLanguage = new SelectLanguageRouteObjectModel(page, utils);
this.main = new MainRouteObjectModel(page, utils);
this.launch = new LaunchRouteObjectModel(page, utils);
+ this.login = new LoginRouteObjectModel(page, utils);
this.settings = new SettingsRouteObjectModel(page, utils);
this.userInterfaceSettings = new UserInterfaceSettingsRouteObjectModel(page, utils);
this.filter = new FilterRouteObjectModel(page, utils);