From 11961ea41d7c91205f1ab7a88d30dbaf9ffbf6d1 Mon Sep 17 00:00:00 2001 From: Ondrej Hajek Date: Fri, 24 Jan 2025 11:24:54 +0100 Subject: [PATCH] feat(e2e): Migrated remembered device test --- packages/e2e-utils/src/mocks/google.ts | 13 +- .../support/pageActions/metadataActions.ts | 14 +- .../tests/metadata/metadata-lifecycle.test.ts | 1 - .../tests/metadata/output-labeling.test.ts | 2 +- .../tests/metadata/remembered-device.test.ts | 132 ++++++++++++++ .../tests/metadata/remembered-device.test.ts | 163 ------------------ 6 files changed, 146 insertions(+), 179 deletions(-) create mode 100644 packages/suite-desktop-core/e2e/tests/metadata/remembered-device.test.ts delete mode 100644 packages/suite-web/e2e/tests/metadata/remembered-device.test.ts diff --git a/packages/e2e-utils/src/mocks/google.ts b/packages/e2e-utils/src/mocks/google.ts index f63861ea8bb..18548da04f9 100644 --- a/packages/e2e-utils/src/mocks/google.ts +++ b/packages/e2e-utils/src/mocks/google.ts @@ -53,10 +53,7 @@ export class GoogleMock { if (req.method === 'OPTIONS') { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); - res.setHeader( - 'Access-Control-Allow-Headers', - 'Content-Type, Authorization, dropbox-api-arg', - ); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Allow-Credentials', 'true'); return res.status(200).end(); @@ -65,10 +62,7 @@ export class GoogleMock { // Handle normal requests res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); - res.setHeader( - 'Access-Control-Allow-Headers', - 'Content-Type, Authorization, dropbox-api-arg', - ); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); this.requests.push(req.url); if (this.nextResponse.length) { @@ -156,7 +150,7 @@ export class GoogleMock { app.get('/drive/v3/files/:id', express.json(), (req, res) => { const { id } = req.params; - console.log('[mockGoogleDrive]: get', req.params.id); + console.log('[mockGoogleDrive]: get file by id', req.params.id); const file = Object.values(this.files).find(f => f.id === id); if (file) { return res.send(file.data); @@ -171,6 +165,7 @@ export class GoogleMock { }); app.get('/drive/v3/files', express.json(), (_req, res) => { + console.log('[mockGoogleDrive]: get files'); res.json({ files: Object.values(this.files), }); diff --git a/packages/suite-desktop-core/e2e/support/pageActions/metadataActions.ts b/packages/suite-desktop-core/e2e/support/pageActions/metadataActions.ts index a9065a369aa..fd0ba501e5d 100644 --- a/packages/suite-desktop-core/e2e/support/pageActions/metadataActions.ts +++ b/packages/suite-desktop-core/e2e/support/pageActions/metadataActions.ts @@ -14,7 +14,10 @@ export class MetadataActions { private readonly metadataSubmitButton: Locator; readonly metadataCancelButton: Locator; readonly metadataInput: Locator; + readonly metadataModal: Locator; + readonly addAccountLabelButton = (accountId: string) => + this.page.getByTestId(`${this.getAccountLabelTestId(accountId)}/add-label-button`); readonly editAccountLabelButton = (accountId: string) => this.page.getByTestId(`${this.getAccountLabelTestId(accountId)}/edit-label-button`); readonly successAccountLabel = (accountId: string) => @@ -31,6 +34,8 @@ export class MetadataActions { this.page.getByTestId( `${this.getOutputLabelTestId(outputId, txNumber)}/dropdown/edit-label`, ); + readonly metadataProviderButton = (provider: MetadataProvider) => + this.page.getByTestId(`@modal/metadata-provider/${provider}-button`); constructor( private readonly page: Page, @@ -39,6 +44,7 @@ export class MetadataActions { this.metadataSubmitButton = page.getByTestId('@metadata/submit'); this.metadataCancelButton = page.getByTestId('@metadata/cancel'); this.metadataInput = page.getByTestId('@metadata/input'); + this.metadataModal = page.getByTestId('@modal/metadata-provider'); } private getAccountLabelTestId(accountId: string): string { @@ -56,13 +62,13 @@ export class MetadataActions { ) { await this.devicePrompt.confirmOnDevicePromptIsShown(); await TrezorUserEnvLink.pressYes(); - await this.page.getByTestId(`@modal/metadata-provider/${provider}-button`).click(); + await this.metadataProviderButton(provider).click(); if (options?.skipVerification) { return; } - await expect(this.page.getByTestId('@modal/metadata-provider')).not.toBeVisible({ + await expect(this.metadataModal).not.toBeVisible({ timeout: 30000, }); } @@ -77,9 +83,7 @@ export class MetadataActions { @step() async clickAddAccountLabelButton(accountId: string) { await this.accountLabel(accountId).hover(); - await this.page - .getByTestId(`${this.getAccountLabelTestId(accountId)}/add-label-button`) - .click(); + await this.addAccountLabelButton(accountId).click(); } @step() diff --git a/packages/suite-desktop-core/e2e/tests/metadata/metadata-lifecycle.test.ts b/packages/suite-desktop-core/e2e/tests/metadata/metadata-lifecycle.test.ts index dca9deb8dfd..e9b5560ef08 100644 --- a/packages/suite-desktop-core/e2e/tests/metadata/metadata-lifecycle.test.ts +++ b/packages/suite-desktop-core/e2e/tests/metadata/metadata-lifecycle.test.ts @@ -55,7 +55,6 @@ test.describe( // Add another wallet, enable labeling on the new device await page.getByTestId('@menu/switch-device').click(); - await page.pause(); await page.getByTestId('@switch-device/add-hidden-wallet-button').click(); await page.getByTestId('@passphrase/input').fill('abc'); await page.getByTestId('@passphrase/hidden/submit-button').click(); diff --git a/packages/suite-desktop-core/e2e/tests/metadata/output-labeling.test.ts b/packages/suite-desktop-core/e2e/tests/metadata/output-labeling.test.ts index c009e52fa8d..5d5dba8e61b 100644 --- a/packages/suite-desktop-core/e2e/tests/metadata/output-labeling.test.ts +++ b/packages/suite-desktop-core/e2e/tests/metadata/output-labeling.test.ts @@ -25,7 +25,7 @@ test.describe('Metadata - Output labeling', { tag: ['@group=metadata', '@webOnly // go to legacy account 6, it has txs with multiple outputs await page.getByTestId('@account-menu/legacy').click(); await page.getByTestId('@account-menu/btc/legacy/5/label').click(); - + // Try to open multiple metadata inputs await metadataPage.clickAddOutputLabelButton(OutputLabelId.BitcoinLegacy6, 0); await metadataPage.clickAddOutputLabelButton(OutputLabelId.BitcoinLegacy6, 1); diff --git a/packages/suite-desktop-core/e2e/tests/metadata/remembered-device.test.ts b/packages/suite-desktop-core/e2e/tests/metadata/remembered-device.test.ts new file mode 100644 index 00000000000..c7e2338aa15 --- /dev/null +++ b/packages/suite-desktop-core/e2e/tests/metadata/remembered-device.test.ts @@ -0,0 +1,132 @@ +import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; + +import { AccountLabelId } from '../../support/enums/accountLabelId'; +import { test, expect } from '../../support/fixtures'; +import { MetadataProvider } from '../../support/mocks/metadataProviderMock'; + +//Metadata - In settings, there is enable metadata switch. +//On enable, it initiates metadata right away (if device already has state). +//On disable, it throws away all metadata related records from memory. +test.describe('Remembered device', { tag: ['@group=metadata', '@webOnly'] }, () => { + const fileContent = { + version: '1.0.0', + accountLabel: 'already existing label', + outputLabels: {}, + addressLabels: {}, + }; + const aesKey: string = 'c785ef250807166bffc141960c525df97647fcc1bca57f6892ca3742ba86ed8d'; + + test.use({ + emulatorStartConf: { model: 'T2T1', wipe: true }, + emulatorSetupConf: { mnemonic: 'mnemonic_all' }, + }); + test.beforeEach(async ({ metadataProviderMock }) => { + await metadataProviderMock.start(MetadataProvider.GOOGLE); + await metadataProviderMock.setFileContent( + 'f7acc942eeb83921892a95085e409b3e6b5325db6400ae5d8de523a305291dca.mtdt', + fileContent, + aesKey, + ); + }); + + test('google provider', async ({ + page, + onboardingPage, + dashboardPage, + settingsPage, + metadataPage, + devicePrompt, + }) => { + await onboardingPage.completeOnboarding({ enableViewOnly: true }); + await dashboardPage.discoveryShouldFinish(); + + await page.getByTestId('@account-menu/btc/normal/0/label').click(); + + await settingsPage.navigateTo('application'); + await settingsPage.metadataSwitch.click(); + await metadataPage.passThroughInitMetadata(MetadataProvider.GOOGLE); + + // Now metadata is enabled, go to accounts and see what we got loaded from provider + await page.getByTestId('@account-menu/btc/normal/0').click(); + + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).toContainText( + 'already existing label', + ); + + // device not saved, disconnect provider + // Now go back to settings, disconnect provider and check that we don't see metadata in app + await settingsPage.navigateTo('application'); + await page.getByTestId('@settings/metadata/disconnect-provider-button').click(); + await expect(page.getByTestId('@settings/metadata/connect-provider-button')).toBeVisible(); + await page.getByTestId('@account-menu/btc/normal/0').click(); + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).not.toContainText( + 'already existing label', + ); + + // At this moment, there are no labels. But we still can see "add label" button, which inits metadata flow but without obtaining keys from device (they are saved!) + await metadataPage.clickAddAccountLabelButton(AccountLabelId.BitcoinDefault1); + await metadataPage.metadataProviderButton(MetadataProvider.GOOGLE).click(); + await expect(metadataPage.metadataModal).not.toBeVisible(); + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).toContainText( + 'already existing label', + ); + + // device not saved, disable metadata + await settingsPage.navigateTo('application'); + await page.getByTestId('@settings/metadata-switch').click(); + await page.getByTestId('@account-menu/btc/normal/0').click(); + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).not.toContainText( + 'label', + ); + await metadataPage.clickAddAccountLabelButton(AccountLabelId.BitcoinDefault1); + + // disabling metadata removed also all keys, so metadata init flow takes all steps now expect for providers, these stay connected + await devicePrompt.confirmOnDevicePromptIsShown(); + await TrezorUserEnvLink.pressYes(); + await page.waitForTimeout(1000); + + // device saved, disconnect provider + await page.getByTestId('@menu/switch-device').click(); + await page.getByTestId('@switch-device/wallet-on-index/0').click(); + + await TrezorUserEnvLink.stopEmu(); + + // Device is saved, when disconnected, user still can edit labels + await metadataPage.editAccountLabel( + AccountLabelId.BitcoinDefault1, + 'edited for remembered', + ); + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).toContainText( + 'edited for remembered', + ); + + // Now again, lets try disconnecting provider + await settingsPage.navigateTo('application'); + await page.getByTestId('@settings/metadata/disconnect-provider-button').click(); + await page.getByTestId('@account-menu/btc/normal/0').click(); + + // Disconnecting removes labels + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).toContainText('Bitcoin'); + + // Still possible to reconnect provider, we have keys still saved + await metadataPage.clickAddAccountLabelButton(AccountLabelId.BitcoinDefault1); + await metadataPage.metadataProviderButton(MetadataProvider.GOOGLE).click(); + await expect(metadataPage.metadataModal).not.toBeVisible(); + await metadataPage.fillLabelInput('mnau'); + await expect(page.getByTestId('@account-menu/btc/normal/0/label')).toContainText('mnau'); + + // device saved, disable metadata + await settingsPage.navigateTo('application'); + await page.getByTestId('@settings/metadata-switch').click(); + await page.getByTestId('@account-menu/btc/normal/0').click(); + + // Now it is not possible to add labels, keys are gone and device is not connected + await expect( + metadataPage.addAccountLabelButton(AccountLabelId.BitcoinDefault1), + ).not.toBeVisible(); + }); + + test.afterEach(async ({ metadataProviderMock }) => { + await metadataProviderMock.stop(); + }); +}); diff --git a/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts b/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts deleted file mode 100644 index 1b5599e78ff..00000000000 --- a/packages/suite-web/e2e/tests/metadata/remembered-device.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -// @group_metadata -// @retry=2 - -import { rerouteMetadataToMockProvider, stubOpen } from '../../stubs/metadata'; -import { onNavBar } from '../../support/pageObjects/topBarObject'; - -const providers = [ - { - provider: 'google', - file: 'f7acc942eeb83921892a95085e409b3e6b5325db6400ae5d8de523a305291dca.mtdt', - }, - // should be enough to test only one provider - // { - // provider: 'dropbox', - // file: '/f7acc942eeb83921892a95085e409b3e6b5325db6400ae5d8de523a305291dca.mtdt', - // }, -] as const; - -describe( - `Metadata - In settings, there is enable metadata switch. ` + - `On enable, it initiates metadata right away (if device already has state).` + - `On disable, it throws away all metadata related records from memory.`, - () => { - beforeEach(() => { - // use portrait mode monitor to prevent scrolling in settings - cy.viewport('macbook-13').resetDb(); - }); - - providers.forEach(f => { - it(f.provider, () => { - // prepare test - cy.task('stopBridge'); - cy.task('startEmu', { wipe: true }); - cy.task('setupEmu', { mnemonic: 'mnemonic_all' }); - cy.task('startBridge'); - cy.task('metadataStartProvider', f.provider); - cy.task('metadataSetFileContent', { - provider: f.provider, - file: f.file, - content: { - version: '1.0.0', - accountLabel: 'already existing label', - outputLabels: {}, - addressLabels: {}, - }, - aesKey: 'c785ef250807166bffc141960c525df97647fcc1bca57f6892ca3742ba86ed8d', - }); - - cy.prefixedVisit('/', { - onBeforeLoad: (win: Window) => { - cy.stub(win, 'open').callsFake(stubOpen(win)); - cy.stub(win, 'fetch').callsFake(rerouteMetadataToMockProvider); - }, - }); - cy.log( - 'Wait for discovery to finish. There is "add label" button, but no actual metadata appeared', - ); - cy.passThroughInitialRun(); - cy.discoveryShouldFinish(); - - cy.getTestElement('@account-menu/btc/normal/0').click(); - - cy.getTestElement('@account-menu/btc/normal/0/label').should('contain', 'Bitcoin'); - - cy.log('Go to settings and enable metadata'); - onNavBar.openSettings(); - cy.getTestElement('@settings/metadata-switch').click({ force: true }); - cy.passThroughInitMetadata(f.provider); - - cy.log( - 'Now metadata is enabled, go to accounts and see what we got loaded from provider', - ); - cy.getTestElement('@account-menu/btc/normal/0').click(); - cy.getTestElement('@account-menu/btc/normal/0/label').should( - 'contain', - 'already existing label', - ); - - // device not saved, disconnect provider - cy.log( - "Now go back to settings, disconnect provider and check that we don't see metadata in app", - ); - onNavBar.openSettings(); - cy.getTestElement('@settings/metadata/disconnect-provider-button').click(); - cy.getTestElement('@settings/metadata/connect-provider-button'); - cy.getTestElement('@account-menu/btc/normal/0').click(); - cy.getTestElement('@account-menu/btc/normal/0/label').should( - 'not.contain', - 'already existing label', - ); - - cy.log( - 'At this moment, there are no labels. But we still can see "add label" button, which inits metadata flow but without obtaining keys from device (they are saved!)', - ); - cy.hoverTestElement("@metadata/accountLabel/m/84'/0'/0'/hover-container"); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/add-label-button").click(); - cy.getTestElement(`@modal/metadata-provider/${f.provider}-button`).click(); - cy.getTestElement('@modal/metadata-provider').should('not.exist'); - cy.getTestElement('@account-menu/btc/normal/0/label').should( - 'contain', - 'already existing label', - ); - - // device not saved, disable metadata - onNavBar.openSettings(); - cy.getTestElement('@settings/metadata-switch').click({ force: true }); - cy.getTestElement('@account-menu/btc/normal/0').click(); - cy.getTestElement('@account-menu/btc/normal/0/label').should( - 'not.contain', - 'label', - ); - cy.hoverTestElement("@metadata/accountLabel/m/84'/0'/0'/hover-container"); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/add-label-button").click(); - cy.log( - 'disabling metadata removed also all keys, so metadata init flow takes all steps now expect for providers, these stay connected', - ); - cy.getConfirmActionOnDeviceModal(); - cy.task('pressYes'); - cy.wait(501); - - // device saved, disconnect provider - cy.getTestElement('@menu/switch-device').click(); - cy.getTestElement('@switch-device/wallet-on-index/0').click(); - cy.task('stopEmu'); - - cy.log('Device is saved, when disconnected, user still can edit labels'); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/edit-label-button").click({ - force: true, - }); - cy.getTestElement('@metadata/input').type(' edited for remembered{enter}'); - - cy.log('Now again, lets try disconnecting provider'); - onNavBar.openSettings(); - cy.getTestElement('@settings/metadata/disconnect-provider-button').click(); - cy.getTestElement('@account-menu/btc/normal/0').click(); - cy.log('Disconnecting removes labels'); - cy.getTestElement('@account-menu/btc/normal/0/label').should('contain', 'Bitcoin'); - - cy.log('Still possible to reconnect provider, we have keys still saved'); - // todo: sometimes modal appears and closes immediately before cypress being able to focus - // it, probably a race-condition in suite killing it with some action. adding wait :( - cy.wait(1000); - cy.hoverTestElement("@metadata/accountLabel/m/84'/0'/0'/hover-container"); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/add-label-button").click(); - - cy.getTestElement(`@modal/metadata-provider/${f.provider}-button`).click(); - cy.getTestElement('@modal/metadata-provider').should('not.exist'); - cy.getTestElement('@metadata/input').type('mnau{enter}'); - - // device saved, disable metadata - onNavBar.openSettings(); - cy.getTestElement('@settings/metadata-switch').click({ force: true }); - cy.getTestElement('@account-menu/btc/normal/0').click(); - cy.log( - 'Now it is not possible to add labels, keys are gone and device is not connected', - ); - cy.getTestElement("@metadata/accountLabel/m/84'/0'/0'/add-label-button").should( - 'not.exist', - ); - }); - }); - }, -);