Skip to content

Commit

Permalink
feat(e2e): Convert db-migration test to pw (#17240)
Browse files Browse the repository at this point in the history
* feat(e2e): Convert db-migration test to pw
updates workflows and one locator renaming

* fix(e2e): Resolve confilict mistake
* fix(e2e): Fix e2e matrix conditioning
  • Loading branch information
Vere-Grey authored Feb 26, 2025
1 parent cc20a5d commit 83856e6
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 289 deletions.
50 changes: 28 additions & 22 deletions .github/workflows/test-suite-web-e2e-pw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,31 +93,38 @@ jobs:
run: |
aws s3 sync --delete ./packages/suite-web/build ${DEPLOY_PATH}/web
generate-e2e-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set matrix
id: set-matrix
run: |
matrix='[
{"TEST_GROUP": "@group=suite"},
{"TEST_GROUP": "@group=device-management"},
{"TEST_GROUP": "@group=settings"},
{"TEST_GROUP": "@group=metadata1"},
{"TEST_GROUP": "@group=metadata2"},
{"TEST_GROUP": "@group=other"},
{"TEST_GROUP": "@group=wallet"}
]'
if [ "${{ github.event_name }}" == "schedule" ]; then
matrix=$(echo $matrix | jq '. += [{"TEST_GROUP": "@group=migrations"}]')
fi
echo "matrix={\"include\":$(echo $matrix)}" >> $GITHUB_OUTPUT
e2e-test-suite-web:
if: github.repository == 'trezor/trezor-suite'
runs-on: ubuntu-latest
needs:
- build-web
- generate-e2e-matrix
strategy:
fail-fast: false
matrix:
include:
- TEST_GROUP: "@group=suite"
CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=device-management"
CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=settings"
CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=metadata1"
CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=metadata2"
CONTAINERS: "trezor-user-env-unix"
# - TEST_GROUP: "@group=passphrase"
# CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=other"
CONTAINERS: "trezor-user-env-unix"
- TEST_GROUP: "@group=wallet"
CONTAINERS: "trezor-user-env-unix bitcoin-regtest"
matrix: ${{ fromJson(needs.generate-e2e-matrix.outputs.matrix) }}

steps:
- name: Checkout
Expand All @@ -129,7 +136,7 @@ jobs:
- name: Check previous runs
id: check-previous-runs
if: github.event_name == 'pull_request' && github.run_attempt == 1
uses: './.github/actions/check-previous-test-runs'
uses: "./.github/actions/check-previous-test-runs"
with:
github_token: ${{ secrets.TREZOR_BOT_TOKEN }}
pr_branch: ${{ github.head_ref }}
Expand Down Expand Up @@ -159,7 +166,7 @@ jobs:
echo -e "\nenableHardenedMode: false" >> .yarnrc.yml
yarn workspaces focus @trezor/suite-desktop-core
npx playwright install --with-deps
docker compose pull ${{ matrix.CONTAINERS }}
docker compose pull trezor-user-env-unix
- name: Run Playwright e2e web tests
if: steps.check-previous-runs.outputs.skip_tests != 'true'
Expand All @@ -172,7 +179,7 @@ jobs:
CURRENTS_CI_BUILD_ID: pr-run-${{github.run_id}}
PASSPHRASE: ${{ secrets.E2E_TEST_PASSPHRASE }}
run: |
docker compose up -d ${{ matrix.CONTAINERS }}
docker compose up -d trezor-user-env-unix
echo "Starting Playwright Web test group ${{ matrix.TEST_GROUP }}"
yarn workspace @trezor/suite-desktop-core test:e2e:web --forbid-only --grep="(?=.*${{ matrix.TEST_GROUP }})(?=.*@webOnly)"
Expand Down Expand Up @@ -201,4 +208,3 @@ jobs:
env:
COMPOSE_FILE: ./docker/docker-compose.suite-ci-pw.yml
run: docker compose down

88 changes: 1 addition & 87 deletions .github/workflows/test-suite-web-nightly.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "[Test] nightly suite-web, migrations and canary"
name: "[Test] nightly suite-web and canary"

# run all suite-web related tests every day at midnight
on:
Expand Down Expand Up @@ -92,92 +92,6 @@ jobs:
tenv-emulator-bridge-debugging.log
trezor-user-env-version.txt
e2e-test-migration-tests:
if: github.repository == 'trezor/trezor-suite'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- TEST_GROUP: "@group_migrations"
CONTAINERS: "trezor-user-env-unix"
CYPRESS_USE_TREZOR_USER_ENV_BRIDGE: "1"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- name: Extract branch name
id: extract_branch
run: |
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
- name: Extract commit message
id: extract_commit_message
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
git fetch origin +refs/pull/${{ github.event.pull_request.number }}/merge:
echo "message=$(git log --no-merges -1 --pretty=format:"%s")" >> $GITHUB_OUTPUT
else
echo "message=$(git log --no-merges -1 --pretty=format:"%s")" >> $GITHUB_OUTPUT
fi
- name: Run e2e migration tests
env:
COMPOSE_FILE: ./docker/docker-compose.suite-ci.yml
## Tells Cypress where is the index of application
CYPRESS_ASSET_PREFIX: /web
CYPRESS_baseUrl: https://dev.suite.sldev.cz/suite-web/
## should tests do snapshot testing
# cypress open todo. temporarily turned off (messaging system)
CYPRESS_SNAPSHOT: false
## reporter url
TRACK_SUITE_URL: https://track-suite-ff9ad9f5b4f6.herokuapp.com
## when debugging or developing tests it does not make sense to have retries,
## in other cases retries are useful to avoid occasional failures due to flaky tests
ALLOW_RETRY: true
TEST_GROUP: ${{ matrix.TEST_GROUP }}
CYPRESS_TEST_URLS: release/22.5 develop
CYPRESS_USE_TREZOR_USER_ENV_BRIDGE: 1
CYPRESS_updateSnapshots: false
CI_JOB_ID: ${{ github.run_id }}
CI_COMMIT_SHA: ${{ github.sha }}
CI_JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
CI_COMMIT_BRANCH: ${{ steps.extract_branch.outputs.branch }}
CI_COMMIT_MESSAGE: ${{steps.extract_commit_message.outputs.message }}
run: |
yarn install --immutable
docker compose pull
docker compose up -d ${{ matrix.CONTAINERS }}
docker compose run test-run
- name: Upload logs
run: |
docker cp docker_trezor-user-env-unix_1:/trezor-user-env/logs/debugging.log trezor-user-env-debugging.log || true
docker cp docker_trezor-user-env-unix_1:/trezor-user-env/logs/emulator_bridge.log tenv-emulator-bridge-debugging.log || true
docker cp docker_trezor-user-env-unix_1:/trezor-user-env/docker/version.txt trezor-user-env-version.txt || true
- name:
Upload artifacts
# this will run the upload artifacts even if the previous steps failed (e.g. tests failed). It wont run if the workflow was cancelled.
if: ${{ ! cancelled() }}
uses: actions/upload-artifact@v4
with:
name: test-artifacts-migration-${{ matrix.TEST_GROUP }}
path: |
./packages/suite-web/e2e/snapshots
./packages/suite-web/e2e/screenshots
./packages/suite-web/e2e/videos
download-snapshots.sh
trezor-user-env-debugging.log
tenv-emulator-bridge-debugging.log
trezor-user-env-version.txt
e2e-test-canary-fws:
if: github.repository == 'trezor/trezor-suite'
runs-on: ubuntu-latest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,15 @@ export class OnboardingActions {
}

@step()
async disableFirmwareHashCheck() {
async disableFirmwareHashCheck(options?: { skipSuiteLoadedCheck?: boolean }) {
// Desktop starts with already disabled firmware hash check. Web needs to disable it.
if (!isWebProject(this.testInfo)) {
return;
}

await this.verifySuiteIsLoaded();
if (!options?.skipSuiteLoadedCheck) {
await this.verifySuiteIsLoaded();
}
// eslint-disable-next-line @typescript-eslint/no-shadow
await this.page.evaluate(SuiteActions => {
window.store.dispatch({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class WalletActions {
readonly accountDetails: Locator;
readonly showPublicKeyButton: Locator;
readonly copyPublicKeyButton: Locator;
readonly sendButton: Locator;
readonly openSendFormButton: Locator;
readonly sendForm: Locator;
readonly receiveButton: Locator;
readonly revealAddressButton: Locator;
Expand Down Expand Up @@ -57,7 +57,7 @@ export class WalletActions {
this.accountDetails = this.page.getByTestId('@wallet/account-details');
this.showPublicKeyButton = this.page.getByTestId('@wallets/details/show-xpub-button');
this.copyPublicKeyButton = this.page.getByTestId('@metadata/copy-xpub-button');
this.sendButton = this.page.getByTestId('@wallet/menu/wallet-send');
this.openSendFormButton = this.page.getByTestId('@wallet/menu/wallet-send');
this.sendForm = this.page.getByTestId('@wallet/send/outputs-and-options');
this.receiveButton = this.page.getByTestId('@wallet/menu/wallet-receive');
this.revealAddressButton = this.page.getByTestId('@wallet/receive/reveal-address-button');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ test.describe('Metadata - wallet labeling', { tag: ['@group=metadata2', '@webOnl
await devicePrompt.confirmOnDevicePromptIsShown();
await trezorUserEnvLink.pressNo();
await dashboardPage.openDeviceSwitcher();
await dashboardPage.openDevice(standardWalletIndex);
await dashboardPage.walletAtIndex(standardWalletIndex).click();

// Enable labeling for wallet C
await dashboardPage.openDeviceSwitcher();
Expand Down
133 changes: 133 additions & 0 deletions packages/suite-desktop-core/e2e/tests/suite/db-migration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { expect, test } from '../../support/fixtures';

const migrateFromVersion = 'release/22.5/web';
const migrateToVersion = 'develop/web';
const walletPassphrase = 'doggo je dobros';
const btcAddress = 'bc1qkmdl2z9u503r6r5s6kyrczje60e2ye7ne7q53e';
const suiteDevInstance = 'https://dev.suite.sldev.cz/suite-web';
const workaroundBtcAddressInputSelector = 'outputs.0.address';

test.describe('Database migration', { tag: ['@group=migrations', '@webOnly'] }, () => {
test.use({ emulatorSetupConf: { passphrase_protection: true, mnemonic: 'mnemonic_all' } });

test(`Db migration between: ${migrateFromVersion} => ${migrateToVersion}`, async ({
page,
onboardingPage,
dashboardPage,
walletPage,
trezorUserEnvLink,
}) => {
const discoveryBar = page.locator('[data-test="\\@wallet\\/discovery-progress-bar"] div');

await test.step(`Load suite in old version ${migrateFromVersion}`, async () => {
await page.goto(`${suiteDevInstance}/${migrateFromVersion}`);
await page.locator('[data-test="@onboarding/continue-button"]').click();
await page.locator('[data-test="@onboarding/exit-app-button"]').click();
await expect(page.locator('[data-test="@suite/loading"]')).not.toBeVisible();
await page.locator('[data-test="@passphrase-type/standard"]').click();
await discoveryBar.waitFor({ state: 'visible', timeout: 45000 });
await discoveryBar.waitFor({ state: 'hidden', timeout: 45000 });
});

await test.step('Change Theme to dark', async () => {
await page.locator('[data-test="@suite/menu/settings"]').click();
await page.locator('[data-test="@theme/color-scheme-select/input"]').click();
await page.locator('[data-test="@theme/color-scheme-select/option/dark"]').click();
await expect(
page.locator('[data-test="@theme/color-scheme-select/input"]'),
).toContainText('Dark');
});

await test.step('Add passphrase wallet', async () => {
await page.locator('[data-test="@menu/switch-device"]').click();
await expect(page.locator('[data-test="@modal"]')).toBeVisible();
await page.locator('[data-test="@switch-device/add-hidden-wallet-button"]').click();
await page.locator('[data-test="@passphrase/input"]').fill(walletPassphrase);
await page.locator('[data-test="@passphrase/hidden/submit-button"]').click();
await page.waitForTimeout(500);
await trezorUserEnvLink.pressYes();
await trezorUserEnvLink.pressYes();
await discoveryBar.waitFor({ state: 'visible', timeout: 45000 });
await discoveryBar.waitFor({ state: 'hidden', timeout: 45000 });
await page.locator('[data-test="@suite/menu/wallet-index"]').click();
});

await test.step('Fill in send form', async () => {
await page.locator('[data-test="@wallet/menu/wallet-send"]').click();
await page.locator('[data-test="outputs[0].address"]').fill(btcAddress);
await page.waitForTimeout(500); // wait has to be for a state save to happen
await page.locator('[data-test="@wallet/menu/close-button"]').last().click();
});

const originalTxLabel = await test.step('Get address of first transaction', async () => {
const metadataOutputLabel = page
.locator('[data-test^="@metadata/outputLabel"] > span')
.first();
await metadataOutputLabel.scrollIntoViewIfNeeded();
await expect(metadataOutputLabel).toBeVisible();

return metadataOutputLabel.textContent();
});

await test.step('Remember the wallet and stop Emulator', async () => {
await page.locator('[data-test="@menu/switch-device"]').click();
const firstHiddenWallet = page
.locator('[data-test^="@switch-device/wallet-on-index"]')
.filter({ hasText: 'Hidden wallet #1' });
await firstHiddenWallet.locator('[data-test*="toggle-remember-switch"]').click();
await expect(firstHiddenWallet.locator('input')).toBeChecked();
await trezorUserEnvLink.stopEmu();
});

await test.step(`Navigate to new version ${migrateToVersion} and check wallet status`, async () => {
await page.goto(`${suiteDevInstance}/${migrateToVersion}`);
await expect(dashboardPage.graph).toBeVisible({ timeout: 30_000 });
await page.getByTestId('@account-menu/normal').click();
await walletPage.accountButton({ symbol: 'btc' }).click();
await dashboardPage.openDeviceSwitcher();
await expect(
page.getByTestId('@menu/switch-device').getByTestId('@deviceStatus-disconnected'),
).toBeVisible();
await expect(dashboardPage.walletAtIndex(0)).toContainText('Passphrase wallet #1');
});

await test.step('Compare the address of the first transaction', async () => {
await dashboardPage.deviceSwitchingCloseButton.click();
const firstTxLabel = page.getByTestId('@wallet/transaction/target-address').first();
await expect(firstTxLabel).toBeVisible();
const afterMigrationTxLabel = await firstTxLabel.textContent();
expect(afterMigrationTxLabel).toBe(originalTxLabel);
});

// go to receive tab, trigger show address to make sure passphrase is properly cached
// -> no passphrase prompt should be displayed
await test.step('Reveal receive address and see warning "device not connected"', async () => {
await walletPage.receiveButton.click();
await walletPage.revealAddressButton.click();
await expect(page.getByTestId('@modal')).toBeVisible();
await page.getByTestId('@modal/close-button').click();
await expect(page.getByTestId('@modal')).not.toBeVisible();
});

await test.step('Reconnect Emulator', async () => {
await trezorUserEnvLink.startEmu();
await onboardingPage.disableFirmwareHashCheck({ skipSuiteLoadedCheck: true });
await dashboardPage.openDeviceSwitcher();
await expect(page.getByTestId('@deviceStatus-connected')).toBeVisible();
await dashboardPage.deviceSwitchingCloseButton.click();
await page.getByTestId('@account-subpage/back').last().click();
});

await test.step('Verify send form has still the original address filled in', async () => {
await walletPage.openSendFormButton.click();
await expect(page.getByTestId(workaroundBtcAddressInputSelector)).toHaveValue(
btcAddress,
);
await page.getByTestId('@account-subpage/back').last().click();
});

await test.step('Verify theme is still dark', async () => {
await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(23, 23, 23)');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test.describe('Cardano', { tag: ['@group=wallet', '@snapshot'] }, () => {
});

await test.step('Verify Cardano send form', async () => {
await walletPage.sendButton.click();
await walletPage.openSendFormButton.click();
// await expect(walletPage.sendForm).toHaveScreenshot('cardano-send.png');
await page.getByTestId('@account-subpage/back').click();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.describe('Import a BTC csv file', { tag: ['@group=wallet', '@webOnly'] }, (
await metadataPage.account.clickAddLabelButton(AccountLabelId.BitcoinDefault1);
await metadataPage.passThroughInitMetadata(MetadataProvider.DROPBOX);

await walletPage.sendButton.click();
await walletPage.openSendFormButton.click();

await page.getByTestId('@send/header-dropdown').click();
await page.getByTestId('@send/header-dropdown/import').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test.describe('Use regtest to test pending transactions', { tag: ['@group=wallet

// create 2 transactions (one self, one fund another account of mine)
for (const [index, transaction] of [accounts.account1, accounts.account2].entries()) {
await walletPage.sendButton.click();
await walletPage.openSendFormButton.click();
await marketPage.sendAmountInput.fill('0.3');
await marketPage.sendAddressInput.fill(transaction.address);
await page.getByTestId('add-output').click();
Expand Down
Loading

0 comments on commit 83856e6

Please sign in to comment.