diff --git a/.github/workflows/test-suite-desktop-e2e.yml b/.github/workflows/test-suite-desktop-e2e.yml new file mode 100644 index 000000000000..24611a7041f4 --- /dev/null +++ b/.github/workflows/test-suite-desktop-e2e.yml @@ -0,0 +1,83 @@ +name: "[Build/Test] suite-desktop e2e" +# this action builds a desktop version of Suite and runs basic test suite for it + +# run only if there are changes in suite or related libs paths +on: + pull_request: + branches: + - develop + paths-ignore: + - "suite-native/**" + - "packages/connect*/**" + - "packages/react-native-usb/**" + # ignore unrelated github workflows config files + - ".github/workflows/connect*" + - ".github/workflows/suite-native*" + - ".github/workflows/build-desktop*" + - ".github/workflows/release*" + - ".github/workflows/template*" + +jobs: + run-desktop-tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - TEST_FILE: "spawn-bridge" + CONTAINERS: "trezor-user-env-unix" + - TEST_FILE: "suite-guide" + CONTAINERS: "trezor-user-env-unix" + - TEST_FILE: "wallet-discovery" + CONTAINERS: "trezor-user-env-unix" + # - TEST_FILE: "cardano-discovery" + # CONTAINERS: "trezor-user-env-unix" + # - TEST_FILE: "eap-modal" + # CONTAINERS: "trezor-user-env-unix" + - TEST_FILE: "electrum" + CONTAINERS: "trezor-user-env-unix electrum-regtest" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + cache: yarn + + - name: Install deps and build libs + run: | + yarn install --immutable + yarn message-system-sign-config + yarn workspace @trezor/suite-data build:lib + yarn workspace @trezor/transport-bridge build:lib + + - name: Build app.js for tests + run: | + yarn workspace @trezor/suite-desktop build:app + yarn workspace @trezor/suite-desktop build:ui + + - name: Run e2e desktop tests + env: + COMPOSE_FILE: ./docker/docker-compose.suite-desktop-ci.yml + TEST_FILE: ${{ matrix.TEST_FILE }} + run: | + docker compose pull + docker compose up -d ${{ matrix.CONTAINERS }} + docker compose run test-run + + - name: cleanup + env: + COMPOSE_FILE: ./docker/docker-compose.suite-desktop-ci.yml + run: docker compose down + + # TODO: currently only uploads trace.zip, figure out why screens are not uploaded + - name: Upload artifacts + if: ${{ ! cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: test-artifacts-${{ matrix.TEST_FILE }} + path: | + ./packages/suite-desktop-core/e2e/test-results diff --git a/ci/test.yml b/ci/test.yml index 2a3c749495c8..652674ea5c38 100644 --- a/ci/test.yml +++ b/ci/test.yml @@ -5,57 +5,6 @@ - schedules - /^release\// -# @trezor/suite-desktop -.e2e desktop: - stage: integration testing - retry: 1 - dependencies: - - install - variables: - COMPOSE_PROJECT_NAME: $CI_JOB_ID # for unique containers - COMPOSE_FILE: ./docker/docker-compose.suite-desktop-ci.yml - TEST_FILE: $TEST_FILE - before_script: - - docker login $CI_DEPENDENCY_PROXY_SERVER -u $CI_DEPENDENCY_PROXY_USER -p $CI_DEPENDENCY_PROXY_PASSWORD - script: - - yarn install --immutable - # 3 next steps could be removed if we passed packages/suite-desktop/dist and build folder as an artifact - # but since this is run only in nightly builds it can be probably built inside the job for now.. - - yarn message-system-sign-config - - yarn workspace @trezor/suite-desktop build:linux - - docker-compose pull - - docker-compose up -d ${CONTAINERS} - - docker-compose run test-run - after_script: - - docker-compose down - - docker network prune -f - artifacts: - expire_in: 7 days - when: always - paths: - - "**/test-results/**" - interruptible: true - parallel: - matrix: - - TEST_FILE: ["spawn-tor", "spawn-bridge", "suite-guide", "wallet-discovery"] - CONTAINERS: "trezor-user-env-unix" - - TEST_FILE: ["electrum"] - CONTAINERS: "trezor-user-env-unix electrum-regtest" - # commented out. coinjoin test is not adapted to current state of this feature - # - TEST_FILE: ["coinjoin"] - # CONTAINERS: "trezor-user-env-unix coinjoin-backend" - -suite desktop: - extends: .e2e desktop - only: - <<: *run_everything_rules - -suite desktop manual: - extends: .e2e desktop - except: - <<: *run_everything_rules - when: manual - .connect-popup legacy npm package base: stage: integration testing retry: 0 diff --git a/docker/docker-compose.suite-desktop-ci.yml b/docker/docker-compose.suite-desktop-ci.yml index bec403472969..499949602a48 100644 --- a/docker/docker-compose.suite-desktop-ci.yml +++ b/docker/docker-compose.suite-desktop-ci.yml @@ -25,8 +25,8 @@ services: - ../:/trezor-suite network_mode: service:trezor-user-env-unix - coinjoin-backend: - image: ghcr.io/trezor/coinjoin-backend:latest - network_mode: service:trezor-user-env-unix - volumes: - - ../:/coinjoin-backend + # coinjoin-backend: + # image: ghcr.io/trezor/coinjoin-backend:latest + # network_mode: service:trezor-user-env-unix + # volumes: + # - ../:/coinjoin-backend diff --git a/packages/suite-desktop-core/e2e/support/common.ts b/packages/suite-desktop-core/e2e/support/common.ts index 86473c10d022..daeb2ba2c62c 100644 --- a/packages/suite-desktop-core/e2e/support/common.ts +++ b/packages/suite-desktop-core/e2e/support/common.ts @@ -4,9 +4,13 @@ import { Page, _electron as electron } from '@playwright/test'; import path from 'path'; import fs from 'fs'; +import { TrezorUserEnvLink } from '@trezor/trezor-user-env-link'; + export const launchSuite = async () => { const appDir = path.join(__dirname, '../../../suite-desktop'); const desiredLogLevel = process.env.LOGLEVEL ?? 'error'; + // TODO: Find out why currently pw fails to see node-bridge so we default to legacy bridge. + await TrezorUserEnvLink.api.startBridge(); const electronApp = await electron.launch({ cwd: appDir, args: [ @@ -14,7 +18,7 @@ export const launchSuite = async () => { `--log-level=${desiredLogLevel}`, '--bridge-node-test', // uncomment to use legacy bridge - // '--bridge-legacy-test' + // '--bridge-legacy-test', ], // when testing electron, video needs to be setup like this. it works locally but not in docker // recordVideo: { dir: 'test-results' }, diff --git a/packages/suite-desktop-core/e2e/support/pageActions/settingsActions.ts b/packages/suite-desktop-core/e2e/support/pageActions/settingsActions.ts index e1842a527cfe..d422f72e5ad2 100644 --- a/packages/suite-desktop-core/e2e/support/pageActions/settingsActions.ts +++ b/packages/suite-desktop-core/e2e/support/pageActions/settingsActions.ts @@ -25,7 +25,7 @@ class SettingsActions { desiredLocationTestid = '@settings/debug/github'; break; case 'general': - desiredLocationTestid = '@settings/language'; + desiredLocationTestid = '@general-settings/language'; break; case 'device': desiredLocationTestid = '@settings/device/backup-recovery-seed'; @@ -39,7 +39,9 @@ class SettingsActions { } await window.getByTestId(`@settings/menu/${desiredLocation}`).click(); await window - .getByTestId(desiredLocationTestid) + .locator(`[data-test="${desiredLocationTestid}"]`) + // TODO: fix data-testid selectors in the app + // .getByTestId(desiredLocationTestid) .waitFor({ state: 'visible', timeout: 10_000 }); } diff --git a/packages/suite-desktop-core/e2e/tests/coinjoin.test.ts b/packages/suite-desktop-core/e2e/tests/coinjoin.test.ts index f134eff5603f..35302bc9c5a6 100644 --- a/packages/suite-desktop-core/e2e/tests/coinjoin.test.ts +++ b/packages/suite-desktop-core/e2e/tests/coinjoin.test.ts @@ -106,7 +106,7 @@ const passThroughInitialRun = async (window: Page) => { await window.waitForSelector('[data-test="@dashboard/graph"]'); }; -testPlaywright.describe('Coinjoin', () => { +testPlaywright.describe.skip('Coinjoin', () => { testPlaywright.beforeAll(async () => { testPlaywright.setTimeout(timeout * 10); diff --git a/packages/suite-desktop-core/e2e/tests/general/eap-modal.test.ts b/packages/suite-desktop-core/e2e/tests/general/eap-modal.test.ts index 60796fcefb84..bfb86b8185d9 100644 --- a/packages/suite-desktop-core/e2e/tests/general/eap-modal.test.ts +++ b/packages/suite-desktop-core/e2e/tests/general/eap-modal.test.ts @@ -1,4 +1,9 @@ -import { test as testPlaywright, ElectronApplication, Page } from '@playwright/test'; +import { + test as testPlaywright, + ElectronApplication, + Page, + expect as expectPlaywright, +} from '@playwright/test'; import { launchSuite, rmDirRecursive } from '../../support/common'; import { onTopBar } from '../../support/pageActions/topBarActions'; @@ -25,6 +30,7 @@ testPlaywright.afterAll(() => { * 4. Confrim the EAP modal * 5. Check if there is a button with `Leave` on it */ +// TODO: FIX settings cleanup: eap setting is remembered even after cache cleanup at the beginning of the test. This shouldn't affect gha run but breaks the local one. testPlaywright('Join early access button', async () => { const buttonText = 'Leave'; @@ -32,5 +38,5 @@ testPlaywright('Join early access button', async () => { await onSettingsPage.goToDesiredSettingsPlace(window, 'general'); await onSettingsPage.joinEarlyAccessProgram(window); - await expect(onSettingsPage.getEarlyAccessButtonText(window)).toContain(buttonText); + expectPlaywright(await onSettingsPage.getEarlyAccessButtonText(window)).toContain(buttonText); }); diff --git a/packages/suite-desktop-core/e2e/tests/spawn-tor.test.ts b/packages/suite-desktop-core/e2e/tests/spawn-tor.test.ts index 39ae817d540d..3516a2587b1f 100644 --- a/packages/suite-desktop-core/e2e/tests/spawn-tor.test.ts +++ b/packages/suite-desktop-core/e2e/tests/spawn-tor.test.ts @@ -31,7 +31,7 @@ const turnOnTorInSettings = async (window: Page, shouldEnableTor = true) => { await window.waitForTimeout(1000); }; -testPlaywright.describe('Tor loading screen', () => { +testPlaywright.describe.skip('Tor loading screen', () => { testPlaywright('Tor loading screen: happy path', async () => { testPlaywright.setTimeout(timeout);