diff --git a/.github/workflows/buildAndDeploy.yml b/.github/workflows/buildAndDeploy.yml index 94e315b..4acbc2e 100644 --- a/.github/workflows/buildAndDeploy.yml +++ b/.github/workflows/buildAndDeploy.yml @@ -12,14 +12,14 @@ jobs: concurrency: group: build-and-deploy cancel-in-progress: true - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 - name: Install dependencies run: npm ci diff --git a/.github/workflows/checkPullRequests.yml b/.github/workflows/checkPullRequests.yml index ea5cce6..f993848 100644 --- a/.github/workflows/checkPullRequests.yml +++ b/.github/workflows/checkPullRequests.yml @@ -10,14 +10,14 @@ jobs: concurrency: group: ${{ github.head_ref }} cancel-in-progress: true - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 - name: Install dependencies run: npm ci diff --git a/.github/workflows/makeArtifactWithTestScreenshots.yml b/.github/workflows/makeArtifactWithTestScreenshots.yml new file mode 100644 index 0000000..8c03fd5 --- /dev/null +++ b/.github/workflows/makeArtifactWithTestScreenshots.yml @@ -0,0 +1,32 @@ +name: "Make artifact with Test Screenshots" + +on: workflow_dispatch + +jobs: + make_artifact_with_test_screenshots: + name: Make artifact with Test Screenshots + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 20 + + - name: Install dependencies + run: npm ci + + - name: Install Playwright Browsers + run: npx playwright install --with-deps + + - name: Run e2e tests + run: PLAYWRIGHT_DEV_SERVER=1 npm run test:e2e:update-snapshots + + - name: Upload test screenshots + uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: test-screenshots + path: ./e2e/vue.spec.ts-snapshots + retention-days: 1 diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json index 239accd..ee4ba29 100644 --- a/e2e/tsconfig.json +++ b/e2e/tsconfig.json @@ -1,4 +1,4 @@ { - "extends": "@vue/tsconfig/tsconfig.node.json", + "extends": "@vue/tsconfig/tsconfig.json", "include": ["./**/*"] } diff --git a/e2e/vue.spec.ts b/e2e/vue.spec.ts index 70855d0..b4880d9 100644 --- a/e2e/vue.spec.ts +++ b/e2e/vue.spec.ts @@ -6,3 +6,138 @@ test("visits the app root url", async ({ page }) => { await page.goto("/"); await expect(page.locator("h1")).toHaveText("Get Crypto Address"); }); + +test("check menu items", async ({ page }) => { + await page.goto("/"); + const $menu = page.locator('[data-test-id="page-header-menu"]'); + const menuItems = $menu.getByRole("menuitem"); + const $$menuItems = await menuItems.all(); + await expect(menuItems).toHaveCount(4); + + await expect($$menuItems[0]).toHaveText("Home"); + await expect($$menuItems[1]).toHaveText("Create Crypto Address"); + await expect($$menuItems[2]).toHaveText("Create Paper Wallet"); + await expect($$menuItems[3]).toHaveText("Paper Wallet Editor"); +}); + +test("General flow", async ({ page, context, browserName }) => { + if (browserName === "chromium") { + await context.grantPermissions(["clipboard-read", "clipboard-write"]); + } + + await page.goto("/"); + await page.getByRole("link", { name: "Create Crypto Address" }).click(); + await page.waitForURL("/create-wallets/", { timeout: 1000 }); + + // Check the default count of addresses + { + const $counter = page.locator('[data-test-id="input-count-tokens"] input'); + const count = await $counter.inputValue(); + expect(count).toBe("20"); + } + + // Generate new addresses + await page.getByRole("button", { name: "Generate new addresses" }).click(); + + // Check the count of generated addresses + const $addresses = page.locator('[data-test-el="key-address-item"]'); + await $addresses.first().waitFor({ state: "visible", timeout: 5000 }); + expect(await $addresses.count()).toBe(20); + + /// Check the first address + const $firstAddress = $addresses.first(); + const privateKey = await $firstAddress + .locator('[data-test-el="private-key"]') + .innerText(); + const address = await $firstAddress + .locator('[data-test-el="address"]') + .innerText(); + + // Copy the first address + if (browserName !== "webkit") { + const $copyButton = $firstAddress.locator( + '[data-test-id="button-copy-wallet-to-clipboard"]', + ); + await $copyButton.click(); + const handle = await page.evaluateHandle(() => + navigator.clipboard.readText(), + ); + const clipboardContent = await handle.jsonValue(); + expect(clipboardContent).toEqual(`${privateKey}:${address}`); + } + + // Modal with the address + { + const $openModalButton = $firstAddress.locator( + '[data-test-el="button-show-qr-codes"]', + ); + await $openModalButton.click(); + const $modal = page.getByRole("dialog"); + await $modal.waitFor({ state: "visible", timeout: 1000 }); + const $modalSecret = $modal.locator( + '[data-test-id="dialog-qr-code-secret"] .n-thing-main__description', + ); + const $modalAddress = $modal.locator( + '[data-test-id="dialog-qr-code-address"] .n-thing-main__description', + ); + expect(await $modalSecret.innerText()).toBe(privateKey); + expect(await $modalAddress.innerText()).toBe(address); + const $modalMask = page.locator(".n-modal-mask"); + await page.mouse.click(1, 1); + await $modalMask.waitFor({ state: "detached", timeout: 1000 }); + } + + /// Paper wallet page + const $manualSecret = page.locator( + '[data-test-id="input-manual-secret"] textarea', + ); + const $manualAddress = page.locator( + '[data-test-id="input-manual-address"] textarea', + ); + // validate provided address and secret + { + const $printButton = $firstAddress.locator( + '[data-test-el="button-generate-paper-wallet"]', + ); + await $printButton.click(); + await page.waitForURL("/paper-wallets/"); + const $manualSecret = page.locator( + '[data-test-id="input-manual-secret"] textarea', + ); + const $manualAddress = page.locator( + '[data-test-id="input-manual-address"] textarea', + ); + await $manualSecret.waitFor({ state: "visible", timeout: 1000 }); + await $manualAddress.waitFor({ state: "visible", timeout: 1000 }); + expect(await $manualSecret.inputValue()).toBe(privateKey); + expect(await $manualAddress.inputValue()).toBe(address); + } + + // Generate paper wallet + { + await $manualSecret.fill("test-secret"); + await $manualAddress.fill("test-address"); + + const $manualGeneratePaperWalletButton = page.locator( + '[data-test-id="button-submit-manual-wallet"]', + ); + await $manualGeneratePaperWalletButton.click(); + + const $canvas = page.locator('[data-test-el="paper-wallet-canvas"]'); + const $firstCanvas = $canvas.first(); + const $secondCanvas = $canvas.nth(1); + + await $firstCanvas.waitFor({ state: "visible", timeout: 1000 }); + await expect($canvas.first()).toHaveScreenshot( + "first-test-secret-address.png", + ); + + await $secondCanvas.waitFor({ state: "visible", timeout: 1000 }); + await expect($canvas.nth(1)).toHaveScreenshot( + "second-test-secret-address.png", + ); + } + + // todo add download test + // const download = await page.waitForEvent("download", { timeout: 1000 }); +}); diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-darwin.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-darwin.png new file mode 100644 index 0000000..0bc29cd Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-linux.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-linux.png new file mode 100644 index 0000000..7e0d605 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-chromium-linux.png differ diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-darwin.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-darwin.png new file mode 100644 index 0000000..0865325 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-linux.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-linux.png new file mode 100644 index 0000000..18e2abd Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-firefox-linux.png differ diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-darwin.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-darwin.png new file mode 100644 index 0000000..ccea72a Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-linux.png b/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-linux.png new file mode 100644 index 0000000..5a3df94 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/first-test-secret-address-webkit-linux.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-darwin.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-darwin.png new file mode 100644 index 0000000..eebca22 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-linux.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-linux.png new file mode 100644 index 0000000..15f8842 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-chromium-linux.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-darwin.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-darwin.png new file mode 100644 index 0000000..635499b Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-linux.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-linux.png new file mode 100644 index 0000000..c836f06 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-firefox-linux.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-darwin.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-darwin.png new file mode 100644 index 0000000..9dcbf9d Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-darwin.png differ diff --git a/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-linux.png b/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-linux.png new file mode 100644 index 0000000..970dc02 Binary files /dev/null and b/e2e/vue.spec.ts-snapshots/second-test-secret-address-webkit-linux.png differ diff --git a/package.json b/package.json index 6ada810..8169f82 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "preview": "vite preview", "test:unit": "vitest", "test:e2e": "playwright test --reporter=list", + "test:e2e:update-snapshots": "playwright test --update-snapshots", + "test:e2e:ui": " playwright test --ui", "build-only": "vite build", "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", diff --git a/src/entities/CryptoWallets/ui/CreateWalletsForm/CreateWalletsForm.vue b/src/entities/CryptoWallets/ui/CreateWalletsForm/CreateWalletsForm.vue index 2d88a56..ced5d78 100644 --- a/src/entities/CryptoWallets/ui/CreateWalletsForm/CreateWalletsForm.vue +++ b/src/entities/CryptoWallets/ui/CreateWalletsForm/CreateWalletsForm.vue @@ -99,6 +99,7 @@ :min="10" />