Skip to content

Commit

Permalink
Add dAppwright testing
Browse files Browse the repository at this point in the history
  • Loading branch information
aefhm committed Dec 3, 2024
1 parent 0a77e5a commit 5a80bbd
Show file tree
Hide file tree
Showing 9 changed files with 4,836 additions and 3,626 deletions.
85 changes: 85 additions & 0 deletions .github/workflows/ci-playwright.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: playwright-test
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
playwright-test:
runs-on: ubuntu-latest
services:
sapphire-localnet-ci:
image: ghcr.io/oasisprotocol/sapphire-localnet
ports:
- 8545:8545
- 8546:8546
env:
OASIS_DEPOSIT_BINARY: /oasis-deposit -test-mnemonic -n 5
options: >-
--rm
--health-cmd="test -f /CONTAINER_READY"
--health-start-period=90s
env:
SAPPHIRE_LOCALNET_HTTP_PROXY_PORT: 3001
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 18

- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install
with:
version: 8
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
working-directory: backend
run: pnpm install

- name: Build backend
working-directory: backend
run: pnpm build

- name: Deploy backend
working-directory: backend
run: pnpm hardhat deploy --network sapphire-localnet

- name: Install dependencies
working-directory: frontend
run: pnpm install

- name: Install Playwright dependencies
run: pnpm test:setup
working-directory: frontend

- name: Run playwright tests (with xvfb-run to support headed extension test)
working-directory: frontend
run: xvfb-run pnpm test

- name: Upload playwright test-results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: playwright-test-results
path: frontend/test-results
retention-days: 5
11 changes: 6 additions & 5 deletions frontend/.env.development
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# VITE_NETWORK=0x5afd
# VITE_WEB3_GATEWAY=http://localhost:8545
VITE_NETWORK=0x5aff
VITE_WEB3_GATEWAY=https://testnet.sapphire.oasis.dev
VITE_MESSAGE_BOX_ADDR=0x2dE080e97B0caE9825375D31f5D0eD5751fDf16D
VITE_NETWORK=0x5afd
VITE_WEB3_GATEWAY=http://localhost:8545
VITE_MESSAGE_BOX_ADDR=0x5FbDB2315678afecb367f032d93F642f64180aa3
# VITE_NETWORK=0x5aff
# VITE_WEB3_GATEWAY=https://testnet.sapphire.oasis.dev
# VITE_MESSAGE_BOX_ADDR=0x2dE080e97B0caE9825375D31f5D0eD5751fDf16D
4 changes: 2 additions & 2 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dist-ssr
coverage
*.local

/cypress/videos/
/cypress/screenshots/
playwright-report
test-results

# Editor directories and files
.vscode/*
Expand Down
6 changes: 5 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
"lint": "npm-run-all lint:**",
"format:eslint": "eslint --fix . --ext .vue,.ts --ignore-path .gitignore",
"format:prettier": "prettier --write --cache '**/*.{vue,js,ts,json}'",
"format": "npm-run-all format:**"
"format": "npm-run-all format:**",
"test": "playwright test",
"test:setup": "playwright install --with-deps"
},
"dependencies": {
"@metamask/detect-provider": "^2.0.0",
"@metamask/jazzicon": "^2.0.0",
"@oasisprotocol/demo-starter-backend": "workspace:^",
"@oasisprotocol/sapphire-paratime": "^1.3.2",
"@playwright/test": "^1.49.0",
"@tenkeylabs/dappwright": "^2.8.6",
"ethers": "^6.10.0",
"pinia": "^2.0.28",
"vue": "^3.2.45",
Expand Down
46 changes: 46 additions & 0 deletions frontend/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { defineConfig, devices } from "@playwright/test";

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
timeout: 2 * 60 * 1000,
testDir: "./test/",
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 1 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [["html"], ["list", { printSteps: true }]],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL: process.env.FRONTEND_URL || "http://localhost:5173/",
trace: "on-first-retry",
headless: false,
screenshot: {
mode: "only-on-failure",
fullPage: true,
},
},
/* Configure projects for major browsers */
projects: [
{
name: 'main',
testDir: './test/',
use: {
...devices['Desktop Chrome'],
},
},
],
/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm dev',
url: process.env.FRONTEND_URL || "http://localhost:5173/",
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
stderr: 'pipe',
},
});
2 changes: 1 addition & 1 deletion frontend/src/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ onMounted(async () => {

<div class="message p-6 mb-6 rounded-xl border-2 border-gray-300" v-if="!isLoading">
<div class="flex items-center justify-between">
<h2 class="text-lg lg:text-lg m-0">{{ message }}</h2>
<h2 class="text-lg lg:text-lg m-0" data-testid="message">{{ message }}</h2>
<div class="flex items-center flex-shrink-0">
<JazzIcon class="mr-2" :size="20" :address="author" />
<abbr :title="author" class="font-mono block no-underline">{{ abbrAddr(author) }}</abbr>
Expand Down
71 changes: 71 additions & 0 deletions frontend/test/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { BrowserContext, expect, test as baseTest } from "@playwright/test";
import dappwright, { Dappwright, MetaMaskWallet } from "@tenkeylabs/dappwright";

export const test = baseTest.extend<{
context: BrowserContext;
wallet: Dappwright;
}>({
context: async ({}, use) => {
// Launch context with extension
const [wallet, _, context] = await dappwright.bootstrap("", {
wallet: "metamask",
version: MetaMaskWallet.recommendedVersion,
seed: "test test test test test test test test test test test junk", // Hardhat's default https://hardhat.org/hardhat-network/docs/reference#accounts
headless: false,
});

// Add Sapphire Localnet as a custom network
await wallet.addNetwork({
networkName: "Sapphire Localnet",
rpc: "http://localhost:8545",
chainId: 23293,
symbol: "ROSE",
});

await use(context);
},

wallet: async ({ context }, use) => {
const metamask = await dappwright.getWallet("metamask", context);

await use(metamask);
},
});

test.beforeEach(async ({ wallet, page }) => {
// Use first account from seed. dAppwright adds two accounts by default.
await wallet.switchAccount(1); // Selector queries as a string
await page.bringToFront();
});

// TODO: improve test without reloading wallet page
test("set and view message", async ({ wallet, page }) => {
await page.goto("http://localhost:5173");

// load
await page.getByRole('button', { name: 'Connect Wallet', exact: true }).click();
await wallet.page.reload();
await wallet.page.getByRole('button', { name: 'Next' }).click();

// confirm
await wallet.page.getByRole('button', { name: 'Confirm' }).click();

// sign twice
await wallet.page.getByTestId('signature-request-scroll-button').click();
await wallet.page.getByRole('button', { name: 'Sign' }).click();
await wallet.page.waitForLoadState();
await wallet.page.goBack();
await wallet.page.reload();
await wallet.page.getByTestId('signature-request-scroll-button').click();
await wallet.page.getByRole('button', { name: 'Sign' }).click();

// Set a message
await page.fill('text=New Message:', 'hola amigos');
await page.getByRole('button', { name: 'Set Message' }).click();

await wallet.page.reload();
await wallet.page.getByRole('button', { name: 'Confirm' }).click();

// Assert message has been set
await expect(page.getByTestId('message')).toHaveText('hola amigos');
});
2 changes: 1 addition & 1 deletion frontend/tsconfig.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "@vue/tsconfig/tsconfig.node.json",
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
"include": ["vite.config.*", "vitest.config.*", "playwright.config.*"],
"compilerOptions": {
"composite": true,
"types": ["node"]
Expand Down
Loading

0 comments on commit 5a80bbd

Please sign in to comment.