From d4470a47b356ac53eb3d43134bf470387854c850 Mon Sep 17 00:00:00 2001 From: Jonathan Conn Date: Mon, 17 Jul 2023 16:53:00 -0400 Subject: [PATCH 01/23] chore: skeleton e2e structure --- laboratory/.github/workflows/playwright.yml | 27 ++++++++++ laboratory/.gitignore | 7 +++ laboratory/package.json | 8 ++- laboratory/playwright.config.ts | 52 +++++++++++++++++++ laboratory/src/pages/index.tsx | 7 +++ .../component-validators/w3-modal-backcard.ts | 5 ++ laboratory/tests/v2-tests.spec.ts | 41 +++++++++++++++ 7 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 laboratory/.github/workflows/playwright.yml create mode 100644 laboratory/.gitignore create mode 100644 laboratory/playwright.config.ts create mode 100644 laboratory/tests/shared/component-validators/w3-modal-backcard.ts create mode 100644 laboratory/tests/v2-tests.spec.ts diff --git a/laboratory/.github/workflows/playwright.yml b/laboratory/.github/workflows/playwright.yml new file mode 100644 index 0000000000..90b6b700d4 --- /dev/null +++ b/laboratory/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/laboratory/.gitignore b/laboratory/.gitignore new file mode 100644 index 0000000000..6d284fa687 --- /dev/null +++ b/laboratory/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +/test-results/ +/playwright-report/ +/playwright/.cache/ +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/laboratory/package.json b/laboratory/package.json index c00d3dcda1..ce931e3fd7 100644 --- a/laboratory/package.json +++ b/laboratory/package.json @@ -4,7 +4,10 @@ "private": true, "scripts": { "dev": "rm -rf .next; next dev", - "build": "next build" + "build": "next build", + "playwright:install": "playwright install --with-deps", + "playwright:test": "playwright test", + "playwright:debug": "playwright test --debug" }, "dependencies": { "@nextui-org/react": "1.0.0-beta.13", @@ -20,5 +23,8 @@ "valtio": "1.10.6", "viem": "1.2.5", "wagmi": "1.3.3" + }, + "devDependencies": { + "@playwright/test": "^1.36.1" } } diff --git a/laboratory/playwright.config.ts b/laboratory/playwright.config.ts new file mode 100644 index 0000000000..2b927e6b80 --- /dev/null +++ b/laboratory/playwright.config.ts @@ -0,0 +1,52 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + /* Retry on CI only */ + retries: process.env.CI ? 2 : 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', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry' + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] } + } + + /* + *{ + * name: 'firefox', + * use: { ...devices['Desktop Firefox'] } + *}, + * + *{ + * name: 'webkit', + * use: { ...devices['Desktop Safari'] } + *} + */ + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI + } +}) diff --git a/laboratory/src/pages/index.tsx b/laboratory/src/pages/index.tsx index 5ae956b8fd..6f3613dc71 100644 --- a/laboratory/src/pages/index.tsx +++ b/laboratory/src/pages/index.tsx @@ -14,6 +14,13 @@ const reactCards = [ link: '/with-wagmi/react-themed', color: 'secondary', libraries: ['@web3modal/react', '@web3modal/ethereum', 'wagmi', 'viem'] + }, + { + title: 'With Ethers Wagmi', + description: 'Wagmi playground using older deps with Ethers', + link: '/with-wagmi/react-ethers', + color: 'secondary', + libraries: ['@web3modal/react', '@web3modal/ethereum', 'wagmi', 'ethers'] } ] as const diff --git a/laboratory/tests/shared/component-validators/w3-modal-backcard.ts b/laboratory/tests/shared/component-validators/w3-modal-backcard.ts new file mode 100644 index 0000000000..9cc2b43041 --- /dev/null +++ b/laboratory/tests/shared/component-validators/w3-modal-backcard.ts @@ -0,0 +1,5 @@ +import { expect, test } from '@playwright/test' + +test('should load all components', async ({ page }) => { + await expect(page.getByTestId('component-modal-backcard')).toBeVisible() +}) diff --git a/laboratory/tests/v2-tests.spec.ts b/laboratory/tests/v2-tests.spec.ts new file mode 100644 index 0000000000..f00ff38a4d --- /dev/null +++ b/laboratory/tests/v2-tests.spec.ts @@ -0,0 +1,41 @@ +import { expect, test } from '@playwright/test' + +/* + * Test pref injected providers + * Url param: ?w3mPreferInjected=true + */ + +/* + * Validate network images load correctly + * + */ + +/* Open web3 modal page */ +test.beforeEach(async ({ page }) => { + await page.goto('./with-wagmi/react') + await expect(page.getByText('Connect your wallet')).not.toBeVisible() + await page.getByTestId('partial-core-connect-button').click() + await expect(page.getByText('Connect your wallet')).toBeVisible() +}) + +test.afterEach(async ({ page }) => { + await expect(page).not.toHaveTitle('Error') +}) + +test('should open explorer view', async ({ page }) => { + await page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() +}) + +test('should load qr code', async ({ page }) => { + const content = page.getByTestId('partial-desktop-wallet-selection-content') + await expect(content).toBeVisible() + await expect(content.getByTestId('partial-qr-spinner')).not.toBeVisible() + await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() +}) + +// Test('should create valid uri', async ({ page }) => { +// Const header = page.getByTestId('partial-desktop-wallet-selection-header') +// Const uri = header.getByTestId('component-header-action-button').click() +// /* expect(uri).toContain('wc:') */ +// }) From 0d6fb9381ec55db8d7b6946ca41039079f7079b5 Mon Sep 17 00:00:00 2001 From: Jonathan Conn Date: Tue, 18 Jul 2023 17:26:46 -0400 Subject: [PATCH 02/23] feat: explorer tests --- laboratory/tests/v2-tests.spec.ts | 78 ++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/laboratory/tests/v2-tests.spec.ts b/laboratory/tests/v2-tests.spec.ts index f00ff38a4d..ed21370e8d 100644 --- a/laboratory/tests/v2-tests.spec.ts +++ b/laboratory/tests/v2-tests.spec.ts @@ -12,9 +12,9 @@ import { expect, test } from '@playwright/test' /* Open web3 modal page */ test.beforeEach(async ({ page }) => { - await page.goto('./with-wagmi/react') + page.goto('./with-wagmi/react') await expect(page.getByText('Connect your wallet')).not.toBeVisible() - await page.getByTestId('partial-core-connect-button').click() + page.getByTestId('partial-core-connect-button').click() await expect(page.getByText('Connect your wallet')).toBeVisible() }) @@ -22,11 +22,6 @@ test.afterEach(async ({ page }) => { await expect(page).not.toHaveTitle('Error') }) -test('should open explorer view', async ({ page }) => { - await page.getByTestId('partial-all-wallets-button').click() - await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() -}) - test('should load qr code', async ({ page }) => { const content = page.getByTestId('partial-desktop-wallet-selection-content') await expect(content).toBeVisible() @@ -34,8 +29,67 @@ test('should load qr code', async ({ page }) => { await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() }) -// Test('should create valid uri', async ({ page }) => { -// Const header = page.getByTestId('partial-desktop-wallet-selection-header') -// Const uri = header.getByTestId('component-header-action-button').click() -// /* expect(uri).toContain('wc:') */ -// }) +test('should open explorer view', async ({ page }) => { + await page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() +}) + +test('should search explorer view', async ({ page }) => { + page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() + await page.getByTestId('component-search-input').type('metamask') + await expect(page.getByTestId('component-wallet-button-metamask')).toBeVisible() + await expect(page.locator('w3m-wallet-button')).toHaveCount(1) +}) + +/* + * TODO: update E2E api with sign-client for this test + * test('should create valid uri', async ({ page }) => { + * const header = page.getByTestId('partial-desktop-wallet-selection-header') + * const uri = header.getByTestId('component-header-action-button').click() + * }) + */ + +test.only('should search explorer view and then open wallet', async ({ page, context }) => { + // open explorer page + await page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() + await expect(page.locator('w3m-wallet-button')).not.toHaveCount(0) + await expect(page.locator('w3m-wallet-button')).not.toHaveCount(1) + + // search for wallet + await page.getByTestId('component-search-input').type('metamask') + await expect(page.getByTestId('component-search-input')).toHaveValue('metamask') + const walletButton = page.getByTestId('component-wallet-button-metamask') + + await expect(walletButton).toBeVisible() + await expect(page.locator('w3m-wallet-button')).toHaveCount(1) + + // "open" wallet (extension not installed) + await walletButton.click() + + // ensure components loaded + await expect(page.getByText(/MetaMask/)).toBeVisible() + await expect(page.getByTestId('component-qrcode-svg')).toBeVisible() + await expect(page.getByTestId('view-mobile-qr-connecting-footer')).toBeVisible() + + // attempt to open extension (should fail since not installed) + const browserButton = page.locator('w3m-button', { hasText: 'Browser' }) + await expect(browserButton).toBeVisible() + await browserButton.click() + + await expect(page.getByText(/Not Detected/)).toBeVisible() + + const downloadButton = page.getByTestId('view-install-wallet-download-button') + await expect(downloadButton).toBeVisible() + + // open wallet download page + const pagePromise = context.waitForEvent('page') + await downloadButton.click() + const newPage = await pagePromise + await newPage.waitForLoadState() + + expect(page.url()).not.toBe(newPage.url()) + await expect(newPage).toHaveURL(/metamask/) + await expect(page).not.toHaveURL('error') +}) From be42dcca44aca504c1baf6bacf932ace3db5205f Mon Sep 17 00:00:00 2001 From: Jonathan Conn Date: Wed, 19 Jul 2023 16:15:28 -0400 Subject: [PATCH 03/23] feat: made wallet tests in explorer view modular to write wallet tests quicker in the future --- laboratory/tests/v2-explorer.spec.ts | 162 +++++++++++++++++++++++++++ laboratory/tests/v2-home.spec.ts | 36 ++++++ laboratory/tests/v2-tests.spec.ts | 95 ---------------- 3 files changed, 198 insertions(+), 95 deletions(-) create mode 100644 laboratory/tests/v2-explorer.spec.ts create mode 100644 laboratory/tests/v2-home.spec.ts delete mode 100644 laboratory/tests/v2-tests.spec.ts diff --git a/laboratory/tests/v2-explorer.spec.ts b/laboratory/tests/v2-explorer.spec.ts new file mode 100644 index 0000000000..a9c6f0805e --- /dev/null +++ b/laboratory/tests/v2-explorer.spec.ts @@ -0,0 +1,162 @@ +import { expect, test } from '@playwright/test' +import type { Page, BrowserContext } from '@playwright/test' + +// eslint-disable-next-line @typescript-eslint/require-await +test.describe('Explorer view', async () => { + /* Open explorer view */ + test.beforeEach(async ({ page }) => { + await page.goto('./with-wagmi/react') + await page.getByTestId('partial-core-connect-button').click() + await page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-content')).toBeVisible() + }) + + test.afterEach(async ({ page }) => { + await expect(page).not.toHaveTitle('Error') + }) + + /* Helpers */ + + /* Return to previous page */ + async function testBack(page: Page) { + await page.getByTestId('component-header-back-button').click() + await expect(page.getByTestId('view-install-wallet-content')).not.toBeVisible() + } + + async function testBrowserButton(page: Page) { + const browserButton = page.locator('w3m-button', { hasText: 'Browser' }) + if (await browserButton.isVisible()) { + await expect(browserButton).toBeVisible() + await browserButton.click() + } + } + + async function testWebButton(page: Page, context: BrowserContext) { + const webButton = page.locator('w3m-button', { hasText: 'Web' }) + if (await webButton.isVisible()) { + await expect(webButton).toBeVisible() + + /* Open wallet web page */ + const pagePromise = context.waitForEvent('page') + await webButton.click() + const newPage = await pagePromise + await newPage.waitForLoadState() + + expect(page.url()).not.toBe(newPage.url()) + await expect(page).not.toHaveURL('error') + } + } + + async function testDownloadButton(page: Page, context: BrowserContext) { + const downloadButton = page.getByTestId('view-install-wallet-download-button') + if (await downloadButton.isVisible()) { + await expect(downloadButton).toBeVisible() + + /* Open wallet download page */ + const pagePromise = context.waitForEvent('page') + await downloadButton.click() + const newPage = await pagePromise + await newPage.waitForLoadState() + + expect(page.url()).not.toBe(newPage.url()) + await expect(page).not.toHaveURL('error') + } + } + + /** + * Used to open a wallet from the explorer view + * @param walletName - name of wallet to open + * @param page - playwright page + */ + async function openWalletFromExplorer(walletName: string, page: Page) { + await page.getByTestId('component-search-input').type(walletName) + await expect(page.getByTestId('component-search-input')).toHaveValue(walletName) + + const walletButton = page.getByTestId(`component-wallet-button-${walletName.toLowerCase()}`) + await expect(walletButton).toBeVisible() + await expect(page.locator('w3m-wallet-button')).toHaveCount(1) + await walletButton.click() + } + + /** + * Used to check that the UI elements of the mobile view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + */ + async function testWalletMobileView(walletName: string, page: Page) { + /* Ensure components loaded correctly in header */ + const header = page.getByTestId('view-mobile-qr-connecting-header') + await expect(header).toBeVisible() + + const headerTitle = header.locator('w3m-text') + expect(headerTitle).toBeVisible() + + const headerText = (await headerTitle.innerText()).toLowerCase() + expect(headerText).toBe(walletName.toLowerCase()) + + /* Ensure componented loaded correctly in content */ + const qrCode = page.getByTestId('partial-qr-code') + await expect(qrCode).toBeVisible() + await expect(qrCode.locator('w3m-wallet-image')).toBeVisible() + + /* Ensure components loaded correctly in footer */ + await expect(page.getByTestId('view-mobile-qr-connecting-footer')).toBeVisible() + + /* Return to previous page */ + await testBack(page) + } + + /** + * Used to check that the UI elements of the install view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + * @param context - playwright context + */ + async function testWalletInstallView(walletName: string, page: Page, context: BrowserContext) { + await testBrowserButton(page) + + await expect(page.getByTestId('view-install-wallet-content')).toBeVisible() + await testDownloadButton(page, context) + + /* Return to previous page */ + await testBack(page) + } + + /** + * Used to check that the UI elements of the desktop view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + */ + async function testWalletDesktopView(walletName: string, page: Page, context: BrowserContext) { + const mobileButton = page.locator('w3m-button', { hasText: 'Mobile' }) + await expect(mobileButton).toBeVisible() + await mobileButton.click() + + /* Test web button */ + const webPage = await context.newPage() + await testWebButton(webPage, context) + + /* Ensure mobile view loads correctly */ + await page.getByTestId('view-mobile-qr-connecting-content').isVisible() + await testWalletMobileView(walletName, page) + } + + test('MetaMask explorer view', async ({ page, context }) => { + const walletName = 'MetaMask' + await openWalletFromExplorer(walletName, page) + + /* Ensure Mobile view loads correctly */ + await testWalletMobileView(walletName, page) + + /* Attempt to open extension (should fail since not installed) */ + await testWalletInstallView(walletName, page, context) + }) + + test('Zerion explorer view', async ({ page, context }) => { + const walletName = 'Zerion' + await openWalletFromExplorer(walletName, page) + + /* Ensure desktop view loads correctly */ + await testWalletDesktopView(walletName, page, context) + }) +}) diff --git a/laboratory/tests/v2-home.spec.ts b/laboratory/tests/v2-home.spec.ts new file mode 100644 index 0000000000..d0a4028c2b --- /dev/null +++ b/laboratory/tests/v2-home.spec.ts @@ -0,0 +1,36 @@ +import { expect, test } from '@playwright/test' +/* + * Test pref injected providers + * Url param: ?w3mPreferInjected=true + */ + +/* + * Validate network images load correctly + * + */ + +/* Open web3 modal page */ +test.beforeEach(async ({ page }) => { + page.goto('./with-wagmi/react') + await expect(page.getByText('Connect your wallet')).not.toBeVisible() + page.getByTestId('partial-core-connect-button').click() + await expect(page.getByText('Connect your wallet')).toBeVisible() +}) + +test.afterEach(async ({ page }) => { + await expect(page).not.toHaveTitle('Error') +}) + +test('should load qr code', async ({ page }) => { + const content = page.getByTestId('partial-desktop-wallet-selection-content') + await expect(content).toBeVisible() + await expect(content.getByTestId('partial-qr-spinner')).not.toBeVisible() + await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() +}) +/* + * TODO: update E2E api with sign-client for this test + * test('should create valid uri', async ({ page }) => { + * const header = page.getByTestId('partial-desktop-wallet-selection-header') + * const uri = header.getByTestId('component-header-action-button').click() + * }) + */ diff --git a/laboratory/tests/v2-tests.spec.ts b/laboratory/tests/v2-tests.spec.ts deleted file mode 100644 index ed21370e8d..0000000000 --- a/laboratory/tests/v2-tests.spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { expect, test } from '@playwright/test' - -/* - * Test pref injected providers - * Url param: ?w3mPreferInjected=true - */ - -/* - * Validate network images load correctly - * - */ - -/* Open web3 modal page */ -test.beforeEach(async ({ page }) => { - page.goto('./with-wagmi/react') - await expect(page.getByText('Connect your wallet')).not.toBeVisible() - page.getByTestId('partial-core-connect-button').click() - await expect(page.getByText('Connect your wallet')).toBeVisible() -}) - -test.afterEach(async ({ page }) => { - await expect(page).not.toHaveTitle('Error') -}) - -test('should load qr code', async ({ page }) => { - const content = page.getByTestId('partial-desktop-wallet-selection-content') - await expect(content).toBeVisible() - await expect(content.getByTestId('partial-qr-spinner')).not.toBeVisible() - await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() -}) - -test('should open explorer view', async ({ page }) => { - await page.getByTestId('partial-all-wallets-button').click() - await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() -}) - -test('should search explorer view', async ({ page }) => { - page.getByTestId('partial-all-wallets-button').click() - await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() - await page.getByTestId('component-search-input').type('metamask') - await expect(page.getByTestId('component-wallet-button-metamask')).toBeVisible() - await expect(page.locator('w3m-wallet-button')).toHaveCount(1) -}) - -/* - * TODO: update E2E api with sign-client for this test - * test('should create valid uri', async ({ page }) => { - * const header = page.getByTestId('partial-desktop-wallet-selection-header') - * const uri = header.getByTestId('component-header-action-button').click() - * }) - */ - -test.only('should search explorer view and then open wallet', async ({ page, context }) => { - // open explorer page - await page.getByTestId('partial-all-wallets-button').click() - await expect(page.getByTestId('view-wallet-explorer-header')).toBeVisible() - await expect(page.locator('w3m-wallet-button')).not.toHaveCount(0) - await expect(page.locator('w3m-wallet-button')).not.toHaveCount(1) - - // search for wallet - await page.getByTestId('component-search-input').type('metamask') - await expect(page.getByTestId('component-search-input')).toHaveValue('metamask') - const walletButton = page.getByTestId('component-wallet-button-metamask') - - await expect(walletButton).toBeVisible() - await expect(page.locator('w3m-wallet-button')).toHaveCount(1) - - // "open" wallet (extension not installed) - await walletButton.click() - - // ensure components loaded - await expect(page.getByText(/MetaMask/)).toBeVisible() - await expect(page.getByTestId('component-qrcode-svg')).toBeVisible() - await expect(page.getByTestId('view-mobile-qr-connecting-footer')).toBeVisible() - - // attempt to open extension (should fail since not installed) - const browserButton = page.locator('w3m-button', { hasText: 'Browser' }) - await expect(browserButton).toBeVisible() - await browserButton.click() - - await expect(page.getByText(/Not Detected/)).toBeVisible() - - const downloadButton = page.getByTestId('view-install-wallet-download-button') - await expect(downloadButton).toBeVisible() - - // open wallet download page - const pagePromise = context.waitForEvent('page') - await downloadButton.click() - const newPage = await pagePromise - await newPage.waitForLoadState() - - expect(page.url()).not.toBe(newPage.url()) - await expect(newPage).toHaveURL(/metamask/) - await expect(page).not.toHaveURL('error') -}) From 07e9095b1ea0620f874d583f8054eed13dbce9cf Mon Sep 17 00:00:00 2001 From: Jonathan Conn Date: Sun, 23 Jul 2023 14:32:43 -0400 Subject: [PATCH 04/23] feat: tested web3modal using lab against our web3wallet example, added more explorer page testing, started creating fixtures for cleanup, added skeleton for injected wallets --- laboratory/.gitignore | 2 + laboratory/playwright.config.ts | 67 ++++++-- .../src/components/NotificationModal.tsx | 5 +- .../src/components/WagmiWeb3ModalWidget.tsx | 8 +- laboratory/tests/basic-tests.spec.ts | 23 +++ laboratory/tests/explorer-page.spec.ts | 41 +++++ laboratory/tests/injected-wallet.spec.ts | 31 ++++ laboratory/tests/shared/fixtures/ModalPage.ts | 15 ++ .../tests/shared/fixtures/WalletPage.ts | 13 ++ .../tests/shared/fixtures/extensions.ts | 34 ++++ laboratory/tests/shared/fixtures/fixture.ts | 24 +++ laboratory/tests/shared/util/explorer.ts | 134 +++++++++++++++ laboratory/tests/shared/util/web-examples.ts | 98 +++++++++++ laboratory/tests/v2-explorer.spec.ts | 162 ------------------ laboratory/tests/v2-home.spec.ts | 36 ---- laboratory/tests/web-examples.spec.ts | 72 ++++++++ 16 files changed, 553 insertions(+), 212 deletions(-) create mode 100644 laboratory/tests/basic-tests.spec.ts create mode 100644 laboratory/tests/explorer-page.spec.ts create mode 100644 laboratory/tests/injected-wallet.spec.ts create mode 100644 laboratory/tests/shared/fixtures/ModalPage.ts create mode 100644 laboratory/tests/shared/fixtures/WalletPage.ts create mode 100644 laboratory/tests/shared/fixtures/extensions.ts create mode 100644 laboratory/tests/shared/fixtures/fixture.ts create mode 100644 laboratory/tests/shared/util/explorer.ts create mode 100644 laboratory/tests/shared/util/web-examples.ts delete mode 100644 laboratory/tests/v2-explorer.spec.ts delete mode 100644 laboratory/tests/v2-home.spec.ts create mode 100644 laboratory/tests/web-examples.spec.ts diff --git a/laboratory/.gitignore b/laboratory/.gitignore index 6d284fa687..4269e15b42 100644 --- a/laboratory/.gitignore +++ b/laboratory/.gitignore @@ -5,3 +5,5 @@ node_modules/ /test-results/ /playwright-report/ /playwright/.cache/ +/tests/shared/data/ +!/tests/shared/data/extension.txt diff --git a/laboratory/playwright.config.ts b/laboratory/playwright.config.ts index 2b927e6b80..45605e5e52 100644 --- a/laboratory/playwright.config.ts +++ b/laboratory/playwright.config.ts @@ -6,7 +6,7 @@ import { defineConfig, devices } from '@playwright/test' export default defineConfig({ testDir: './tests', /* Run tests in files in parallel */ - fullyParallel: true, + fullyParallel: false, /* Fail the build on CI if you accidentally left test.only in the source code. */ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, @@ -14,32 +14,77 @@ export default defineConfig({ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html', + + /* Increase timeout time for slower browsers */ + timeout: 60 * 1000, /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://127.0.0.1:3000', + baseURL: 'https://lab.web3modal.com', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry' + trace: 'on-first-retry', + + video: 'on-first-retry' }, /* Configure projects for major browsers */ projects: [ + /** + * Run tests in Chromium. { + * name: 'Google Chrome', + * use: { ...devices['Desktop Chrome'], channel: 'chrome' } + * } + */ { name: 'chromium', use: { ...devices['Desktop Chrome'] } + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] } + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] } } + /* Test against other browsers. */ /* - *{ - * name: 'firefox', - * use: { ...devices['Desktop Firefox'] } - *}, + * { + * name: 'firefox', + * use: { ...devices['Desktop Firefox'] } + * }, * - *{ - * name: 'webkit', - * use: { ...devices['Desktop Safari'] } - *} + * { + * name: 'webkit', + * use: { ...devices['Desktop Safari'] } + * } + */ + /* Test against mobile viewports. */ + /* + * { + * name: 'Mobile Chrome', + * use: { ...devices['Pixel 5'] }, + * }, + * { + * name: 'Mobile Safari', + * use: { ...devices['iPhone 12'] }, + * }, + */ + + /* Test against branded browsers. */ + /* + * { + * name: 'Microsoft Edge', + * use: { ...devices['Desktop Edge'], channel: 'msedge' }, + * }, + * { + * name: 'Google Chrome', + * use: { ..devices['Desktop Chrome'], channel: 'chrome' }, + * }, */ ], diff --git a/laboratory/src/components/NotificationModal.tsx b/laboratory/src/components/NotificationModal.tsx index 786140d9e1..7cc937b3ec 100644 --- a/laboratory/src/components/NotificationModal.tsx +++ b/laboratory/src/components/NotificationModal.tsx @@ -15,7 +15,9 @@ export function NotificationModal() { css={{ maxWidth: 900, margin: '0 auto' }} > - {title} + + {title} +
{body}
diff --git a/laboratory/src/components/WagmiWeb3ModalWidget.tsx b/laboratory/src/components/WagmiWeb3ModalWidget.tsx index 89079803c3..7999159c3b 100644 --- a/laboratory/src/components/WagmiWeb3ModalWidget.tsx +++ b/laboratory/src/components/WagmiWeb3ModalWidget.tsx @@ -64,9 +64,13 @@ export default function WagmiWeb3ModalWidget() { {isConnected ? ( <> - + - + ) : ( <> diff --git a/laboratory/tests/basic-tests.spec.ts b/laboratory/tests/basic-tests.spec.ts new file mode 100644 index 0000000000..8b1014c100 --- /dev/null +++ b/laboratory/tests/basic-tests.spec.ts @@ -0,0 +1,23 @@ +import { expect, test } from '@playwright/test' + +// eslint-disable-next-line @typescript-eslint/require-await +test.describe('Basic tests', async () => { + /* Open web3 modal page */ + test.beforeEach(async ({ page }) => { + page.goto('./with-wagmi/react') + await expect(page.getByText('Connect your wallet')).not.toBeVisible() + page.getByTestId('partial-core-connect-button').click() + await expect(page.getByText('Connect your wallet')).toBeVisible() + }) + + test.afterEach(async ({ page }) => { + await expect(page).not.toHaveTitle('Error') + }) + + test('should load qr code', async ({ page }) => { + const content = page.getByTestId('partial-desktop-wallet-selection-content') + await expect(content).toBeVisible() + await expect(content.getByTestId('partial-qr-spinner')).not.toBeVisible() + await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() + }) +}) diff --git a/laboratory/tests/explorer-page.spec.ts b/laboratory/tests/explorer-page.spec.ts new file mode 100644 index 0000000000..b3a0263cf3 --- /dev/null +++ b/laboratory/tests/explorer-page.spec.ts @@ -0,0 +1,41 @@ +import { expect, test } from '@playwright/test' +import { + openWalletFromExplorer, + testWalletMobileView, + testWalletDesktopView, + testWalletInstallView +} from './shared/util/explorer' + +// eslint-disable-next-line @typescript-eslint/require-await +test.describe('Explorer view', async () => { + /* Open explorer view */ + test.beforeEach(async ({ page }) => { + await page.goto('./with-wagmi/react') + await page.getByTestId('partial-core-connect-button').click() + await page.getByTestId('partial-all-wallets-button').click() + await expect(page.getByTestId('view-wallet-explorer-content')).toBeVisible() + }) + + test.afterEach(async ({ page }) => { + await expect(page).not.toHaveTitle('Error') + }) + + test('MetaMask explorer view', async ({ page, context }) => { + const walletName = 'MetaMask' + await openWalletFromExplorer(walletName, page) + + /* Ensure Mobile view loads correctly */ + await testWalletMobileView(walletName, page) + + /* Attempt to open extension (should fail since not installed) */ + await testWalletInstallView(walletName, page, context) + }) + + test('Zerion explorer view', async ({ page, context }) => { + const walletName = 'Zerion' + await openWalletFromExplorer(walletName, page) + + /* Ensure desktop view loads correctly */ + await testWalletDesktopView(walletName, page, context) + }) +}) diff --git a/laboratory/tests/injected-wallet.spec.ts b/laboratory/tests/injected-wallet.spec.ts new file mode 100644 index 0000000000..83981bd50f --- /dev/null +++ b/laboratory/tests/injected-wallet.spec.ts @@ -0,0 +1,31 @@ +import { testWithMM } from './shared/fixtures/extensions' +import { expect } from '@playwright/test' + +/** + * R&D testing for inject wallets, WIP + */ +testWithMM('open extension', async ({ page, context }) => { + const mmPageEvent = context.waitForEvent('page') + const mmPage = await mmPageEvent + await mmPage.getByTestId('unlock-password').fill('3e1b0433a44e4c2c9a34e3b105eb6564') + await mmPage.getByTestId('unlock-submit').click() + + // eslint-disable-next-line no-promise-executor-return + await new Promise(resolve => setTimeout(resolve, 10000000)) + await page.goto('https://example.com') +}) + +/* You can use this mock test + playwright debug to open/modify the mm extension*/ +testWithMM('configure extension', async ({ page }) => { + await page.goto('https://example.com') + + // eslint-disable-next-line no-promise-executor-return + await new Promise(resolve => setTimeout(resolve, 10000000)) + await page.goto('./with-wagmi/react?w3mPreferInjected=true') + await page.getByTestId('partial-core-connect-button').click() + await page.pause() + await page.goto(`chrome-extension://deciejoknbkjgpaljdhgfcpnmipdnbnk/home.html#unlock`) + await page.getByTestId('unlock-password').fill('3e1b0433a44e4c2c9a34e3b105eb6564') + await page.getByTestId('unlock-submit').click() + expect(true).toBe(true) +}) diff --git a/laboratory/tests/shared/fixtures/ModalPage.ts b/laboratory/tests/shared/fixtures/ModalPage.ts new file mode 100644 index 0000000000..2e228b935f --- /dev/null +++ b/laboratory/tests/shared/fixtures/ModalPage.ts @@ -0,0 +1,15 @@ +import type { Page } from '@playwright/test' + +export class ModalPage { + constructor(public readonly page: Page) {} + + async goto() { + await this.page.goto('http://localhost:3000') + } + + async getUri() { + await this.page.goto('./with-wagmi/react') + await this.page.getByTestId('partial-core-connect-button').click() + await this.page.getByTestId('component-header-action-button').click() + } +} diff --git a/laboratory/tests/shared/fixtures/WalletPage.ts b/laboratory/tests/shared/fixtures/WalletPage.ts new file mode 100644 index 0000000000..0795878edb --- /dev/null +++ b/laboratory/tests/shared/fixtures/WalletPage.ts @@ -0,0 +1,13 @@ +import type { Page } from '@playwright/test' + +export class WalletPage { + constructor(public readonly page: Page) {} + + async goto() { + await this.page.goto('http://localhost:3001') + } + + async connect() { + await this.page.getByTestId('wc-connect').click() + } +} diff --git a/laboratory/tests/shared/fixtures/extensions.ts b/laboratory/tests/shared/fixtures/extensions.ts new file mode 100644 index 0000000000..16efdc9c10 --- /dev/null +++ b/laboratory/tests/shared/fixtures/extensions.ts @@ -0,0 +1,34 @@ +/* eslint-disable prefer-destructuring */ +/* eslint-disable no-empty-pattern */ +import { test as base, chromium, type BrowserContext } from '@playwright/test' +import path from 'path' + +export const testWithMM = base.extend<{ + context: BrowserContext + extensionId: string +}>({ + context: async ({}, use) => { + const pathToExtension = path.join(__dirname, '../data/chrome') + const pathToStorage = path.join(__dirname, '../data/mm-storage') + + const context = await chromium.launchPersistentContext(pathToStorage, { + headless: false, + args: [ + // `--headless=new`, + `--disable-extensions-except=${pathToExtension}`, + `--load-extension=${pathToExtension}` + ] + }) + await use(context) + await context.close() + }, + extensionId: async ({ context }, use) => { + let [background] = context.serviceWorkers() + if (!background) { + background = await context.waitForEvent('serviceworker') + } + + const extensionId = background.url().split('/')[2] + await use(extensionId) + } +}) diff --git a/laboratory/tests/shared/fixtures/fixture.ts b/laboratory/tests/shared/fixtures/fixture.ts new file mode 100644 index 0000000000..7229b2ca5d --- /dev/null +++ b/laboratory/tests/shared/fixtures/fixture.ts @@ -0,0 +1,24 @@ +import { test as base } from '@playwright/test' +import { WalletPage } from './WalletPage' +import { ModalPage } from './ModalPage' + +// Declare the types of fixtures to use +interface ModalWalletFixture { + walletPage: WalletPage + modalPage: ModalPage +} + +export const test = base.extend({ + walletPage: async ({ page }) => { + // Set up the fixture. + const walletPage = new WalletPage(page) + await walletPage.goto() + }, + + modalPage: async ({ page }) => { + // Set up the fixture. + const modalPage = new ModalPage(page) + await modalPage.goto() + } +}) +export { expect } from '@playwright/test' diff --git a/laboratory/tests/shared/util/explorer.ts b/laboratory/tests/shared/util/explorer.ts new file mode 100644 index 0000000000..342e59ab19 --- /dev/null +++ b/laboratory/tests/shared/util/explorer.ts @@ -0,0 +1,134 @@ +import { expect } from '@playwright/test' +import type { Page, BrowserContext } from '@playwright/test' + +/* Return to previous page */ +async function testBack(page: Page) { + await page.getByTestId('component-header-back-button').click() + await expect(page.getByTestId('view-install-wallet-content')).not.toBeVisible() +} + +async function testBrowserButton(page: Page) { + const browserButton = page.locator('w3m-button', { hasText: 'Browser' }) + if (await browserButton.isVisible()) { + await expect(browserButton).toBeVisible() + await browserButton.click() + } +} + +async function testWebButton(page: Page, context: BrowserContext) { + const webButton = page.locator('w3m-button', { hasText: 'Web' }) + if (await webButton.isVisible()) { + await expect(webButton).toBeVisible() + + /* Open wallet web page */ + const pagePromise = context.waitForEvent('page') + await webButton.click() + const newPage = await pagePromise + await newPage.waitForLoadState() + + expect(page.url()).not.toBe(newPage.url()) + await expect(page).not.toHaveURL('error') + } +} + +async function testDownloadButton(page: Page, context: BrowserContext) { + const downloadButton = page.getByTestId('view-install-wallet-download-button') + if (await downloadButton.isVisible()) { + await expect(downloadButton).toBeVisible() + + /* Open wallet download page */ + const pagePromise = context.waitForEvent('page') + await downloadButton.click() + const newPage = await pagePromise + await newPage.waitForLoadState() + + expect(page.url()).not.toBe(newPage.url()) + await expect(page).not.toHaveURL('error') + } +} + +/** + * Used to open a wallet from the explorer view + * @param walletName - name of wallet to open + * @param page - playwright page + */ +export async function openWalletFromExplorer(walletName: string, page: Page) { + await page.getByTestId('component-search-input').type(walletName) + await expect(page.getByTestId('component-search-input')).toHaveValue(walletName) + + const walletButton = page.getByTestId(`component-wallet-button-${walletName.toLowerCase()}`) + await expect(walletButton).toBeVisible() + await expect(page.locator('w3m-wallet-button')).toHaveCount(1) + await walletButton.click() +} + +/** + * Used to check that the UI elements of the mobile view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + */ +export async function testWalletMobileView(walletName: string, page: Page) { + /* Ensure components loaded correctly in header */ + const header = page.getByTestId('view-mobile-qr-connecting-header') + await expect(header).toBeVisible() + + const headerTitle = header.locator('w3m-text') + expect(headerTitle).toBeVisible() + + const headerText = (await headerTitle.innerText()).toLowerCase() + expect(headerText).toBe(walletName.toLowerCase()) + + /* Ensure componented loaded correctly in content */ + const qrCode = page.getByTestId('partial-qr-code') + await expect(qrCode).toBeVisible() + await expect(qrCode.locator('w3m-wallet-image')).toBeVisible() + + /* Ensure components loaded correctly in footer */ + await expect(page.getByTestId('view-mobile-qr-connecting-footer')).toBeVisible() + + /* Return to previous page */ + await testBack(page) +} + +/** + * Used to check that the UI elements of the install view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + * @param context - playwright context + */ +export async function testWalletInstallView( + walletName: string, + page: Page, + context: BrowserContext +) { + await testBrowserButton(page) + + await expect(page.getByTestId('view-install-wallet-content')).toBeVisible() + await testDownloadButton(page, context) + + /* Return to previous page */ + await testBack(page) +} + +/** + * Used to check that the UI elements of the desktop view are correct + * @param walletName - name of wallet to open + * @param page - playwright page + */ +export async function testWalletDesktopView( + walletName: string, + page: Page, + context: BrowserContext +) { + const mobileButton = page.locator('w3m-button', { hasText: 'Mobile' }) + await expect(mobileButton).toBeVisible() + await mobileButton.click() + + /* Test web button */ + const webPage = await context.newPage() + await testWebButton(webPage, context) + + /* Ensure mobile view loads correctly */ + await page.getByTestId('view-mobile-qr-connecting-content').isVisible() + await testWalletMobileView(walletName, page) +} diff --git a/laboratory/tests/shared/util/web-examples.ts b/laboratory/tests/shared/util/web-examples.ts new file mode 100644 index 0000000000..816facce22 --- /dev/null +++ b/laboratory/tests/shared/util/web-examples.ts @@ -0,0 +1,98 @@ +import { expect } from '@playwright/test' +import type { Page, BrowserContext } from '@playwright/test' + +const WALLET_URL = 'http://localhost:3001' + +export async function connectToWallet(page: Page, context: BrowserContext, browserName: string) { + if (browserName === 'chromium') { + await context.grantPermissions(['clipboard-read', 'clipboard-write']) + } + + await page.goto('./with-wagmi/react') + await page.getByTestId('partial-core-connect-button').click() + await page.getByTestId('component-header-action-button').click() + + const walletPage = await context.newPage() + walletPage.goto(WALLET_URL) + await walletPage.waitForLoadState() + + await walletPage.getByTestId('wc-connect').click() + + const uriField = walletPage.getByTestId('uri-input') + await expect(uriField).toBeVisible() + + const uriFieldButton = walletPage.getByTestId('uri-connect-button') + await expect(uriFieldButton).toBeDisabled() + + await uriField.focus() + await expect(uriField).toBeFocused() + + const isMac = process.platform === 'darwin' + const modifier = isMac ? 'Meta' : 'Control' + await walletPage.keyboard.press(`${modifier}+KeyV`) + + await expect(uriFieldButton).toBeVisible() + await uriFieldButton.click() + + const approveButton = walletPage.getByTestId('session-approve-button') + await expect(approveButton).toBeVisible() + await expect(approveButton).toBeDisabled() + + /* Cannot select buttons because of next/ui */ + const account1Buttons = await walletPage + .locator('[role=button]') + .filter({ hasText: 'Account 1' }) + .all() + await Promise.all(account1Buttons.map(async button => button.click())) + + await expect(approveButton).toHaveAttribute('data-state', 'ready') + await expect(approveButton).toBeEnabled() + + /* Click does not work on this button due to next/ui */ + await approveButton.focus() + await walletPage.keyboard.press('Space') + + await expect(page.getByText('0 ETH')).toBeVisible() + + return walletPage +} + +export async function disconnectUsingModal(page: Page, walletPage: Page) { + // Ensure that the wallet is connected + await walletPage.getByTestId('sessions').click() + const sessionCard = walletPage.getByTestId('session-card').first() + await expect(sessionCard).toBeVisible() + + // Disconnect using web3modal + await page.getByTestId('partial-account-address').click() + await page.getByTestId('view-account-disconnect-button').click() + + // Ensure web3modal disconnects + await expect(page.getByTestId('partial-connect-button')).toBeVisible() + + // Force wallet page to refresh + await walletPage.reload() + + // Ensure that the wallet is disconnected + await expect(sessionCard).not.toBeVisible() +} + +export async function disconnectUsingWallet(page: Page, walletPage: Page) { + // Ensure that the wallet is connected + await walletPage.getByTestId('sessions').click() + const sessionCard = walletPage.getByTestId('session-card').first() + await expect(sessionCard).toBeVisible() + + // Disconnect using wallet + await sessionCard.getByTestId('session-icon').click() + await walletPage.getByTestId('session-delete-button').click() + + // Ensure web3modal disconnects + await expect(page.getByTestId('partial-connect-button')).toBeVisible() + + // Force wallet page to refresh + await walletPage.reload() + + // Ensure that the wallet is disconnected + await expect(sessionCard).not.toBeVisible() +} diff --git a/laboratory/tests/v2-explorer.spec.ts b/laboratory/tests/v2-explorer.spec.ts deleted file mode 100644 index a9c6f0805e..0000000000 --- a/laboratory/tests/v2-explorer.spec.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { expect, test } from '@playwright/test' -import type { Page, BrowserContext } from '@playwright/test' - -// eslint-disable-next-line @typescript-eslint/require-await -test.describe('Explorer view', async () => { - /* Open explorer view */ - test.beforeEach(async ({ page }) => { - await page.goto('./with-wagmi/react') - await page.getByTestId('partial-core-connect-button').click() - await page.getByTestId('partial-all-wallets-button').click() - await expect(page.getByTestId('view-wallet-explorer-content')).toBeVisible() - }) - - test.afterEach(async ({ page }) => { - await expect(page).not.toHaveTitle('Error') - }) - - /* Helpers */ - - /* Return to previous page */ - async function testBack(page: Page) { - await page.getByTestId('component-header-back-button').click() - await expect(page.getByTestId('view-install-wallet-content')).not.toBeVisible() - } - - async function testBrowserButton(page: Page) { - const browserButton = page.locator('w3m-button', { hasText: 'Browser' }) - if (await browserButton.isVisible()) { - await expect(browserButton).toBeVisible() - await browserButton.click() - } - } - - async function testWebButton(page: Page, context: BrowserContext) { - const webButton = page.locator('w3m-button', { hasText: 'Web' }) - if (await webButton.isVisible()) { - await expect(webButton).toBeVisible() - - /* Open wallet web page */ - const pagePromise = context.waitForEvent('page') - await webButton.click() - const newPage = await pagePromise - await newPage.waitForLoadState() - - expect(page.url()).not.toBe(newPage.url()) - await expect(page).not.toHaveURL('error') - } - } - - async function testDownloadButton(page: Page, context: BrowserContext) { - const downloadButton = page.getByTestId('view-install-wallet-download-button') - if (await downloadButton.isVisible()) { - await expect(downloadButton).toBeVisible() - - /* Open wallet download page */ - const pagePromise = context.waitForEvent('page') - await downloadButton.click() - const newPage = await pagePromise - await newPage.waitForLoadState() - - expect(page.url()).not.toBe(newPage.url()) - await expect(page).not.toHaveURL('error') - } - } - - /** - * Used to open a wallet from the explorer view - * @param walletName - name of wallet to open - * @param page - playwright page - */ - async function openWalletFromExplorer(walletName: string, page: Page) { - await page.getByTestId('component-search-input').type(walletName) - await expect(page.getByTestId('component-search-input')).toHaveValue(walletName) - - const walletButton = page.getByTestId(`component-wallet-button-${walletName.toLowerCase()}`) - await expect(walletButton).toBeVisible() - await expect(page.locator('w3m-wallet-button')).toHaveCount(1) - await walletButton.click() - } - - /** - * Used to check that the UI elements of the mobile view are correct - * @param walletName - name of wallet to open - * @param page - playwright page - */ - async function testWalletMobileView(walletName: string, page: Page) { - /* Ensure components loaded correctly in header */ - const header = page.getByTestId('view-mobile-qr-connecting-header') - await expect(header).toBeVisible() - - const headerTitle = header.locator('w3m-text') - expect(headerTitle).toBeVisible() - - const headerText = (await headerTitle.innerText()).toLowerCase() - expect(headerText).toBe(walletName.toLowerCase()) - - /* Ensure componented loaded correctly in content */ - const qrCode = page.getByTestId('partial-qr-code') - await expect(qrCode).toBeVisible() - await expect(qrCode.locator('w3m-wallet-image')).toBeVisible() - - /* Ensure components loaded correctly in footer */ - await expect(page.getByTestId('view-mobile-qr-connecting-footer')).toBeVisible() - - /* Return to previous page */ - await testBack(page) - } - - /** - * Used to check that the UI elements of the install view are correct - * @param walletName - name of wallet to open - * @param page - playwright page - * @param context - playwright context - */ - async function testWalletInstallView(walletName: string, page: Page, context: BrowserContext) { - await testBrowserButton(page) - - await expect(page.getByTestId('view-install-wallet-content')).toBeVisible() - await testDownloadButton(page, context) - - /* Return to previous page */ - await testBack(page) - } - - /** - * Used to check that the UI elements of the desktop view are correct - * @param walletName - name of wallet to open - * @param page - playwright page - */ - async function testWalletDesktopView(walletName: string, page: Page, context: BrowserContext) { - const mobileButton = page.locator('w3m-button', { hasText: 'Mobile' }) - await expect(mobileButton).toBeVisible() - await mobileButton.click() - - /* Test web button */ - const webPage = await context.newPage() - await testWebButton(webPage, context) - - /* Ensure mobile view loads correctly */ - await page.getByTestId('view-mobile-qr-connecting-content').isVisible() - await testWalletMobileView(walletName, page) - } - - test('MetaMask explorer view', async ({ page, context }) => { - const walletName = 'MetaMask' - await openWalletFromExplorer(walletName, page) - - /* Ensure Mobile view loads correctly */ - await testWalletMobileView(walletName, page) - - /* Attempt to open extension (should fail since not installed) */ - await testWalletInstallView(walletName, page, context) - }) - - test('Zerion explorer view', async ({ page, context }) => { - const walletName = 'Zerion' - await openWalletFromExplorer(walletName, page) - - /* Ensure desktop view loads correctly */ - await testWalletDesktopView(walletName, page, context) - }) -}) diff --git a/laboratory/tests/v2-home.spec.ts b/laboratory/tests/v2-home.spec.ts deleted file mode 100644 index d0a4028c2b..0000000000 --- a/laboratory/tests/v2-home.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { expect, test } from '@playwright/test' -/* - * Test pref injected providers - * Url param: ?w3mPreferInjected=true - */ - -/* - * Validate network images load correctly - * - */ - -/* Open web3 modal page */ -test.beforeEach(async ({ page }) => { - page.goto('./with-wagmi/react') - await expect(page.getByText('Connect your wallet')).not.toBeVisible() - page.getByTestId('partial-core-connect-button').click() - await expect(page.getByText('Connect your wallet')).toBeVisible() -}) - -test.afterEach(async ({ page }) => { - await expect(page).not.toHaveTitle('Error') -}) - -test('should load qr code', async ({ page }) => { - const content = page.getByTestId('partial-desktop-wallet-selection-content') - await expect(content).toBeVisible() - await expect(content.getByTestId('partial-qr-spinner')).not.toBeVisible() - await expect(content.getByTestId('component-qrcode-svg')).toBeVisible() -}) -/* - * TODO: update E2E api with sign-client for this test - * test('should create valid uri', async ({ page }) => { - * const header = page.getByTestId('partial-desktop-wallet-selection-header') - * const uri = header.getByTestId('component-header-action-button').click() - * }) - */ diff --git a/laboratory/tests/web-examples.spec.ts b/laboratory/tests/web-examples.spec.ts new file mode 100644 index 0000000000..a1e3516f50 --- /dev/null +++ b/laboratory/tests/web-examples.spec.ts @@ -0,0 +1,72 @@ +import { test, expect } from '@playwright/test' +import { + connectToWallet, + disconnectUsingModal, + disconnectUsingWallet +} from './shared/util/web-examples' + +// eslint-disable-next-line @typescript-eslint/require-await +test.describe('Functional tests', async () => { + test.beforeEach(async ({ page, context, browserName }) => { + await connectToWallet(page, context, browserName) + + return '' + }) + test('should be able to connect to wallet', async ({ page, context, browserName }) => { + await connectToWallet(page, context, browserName) + }) + + test('should send disconnect to wallet', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await disconnectUsingModal(page, walletPage) + }) + + test('should recieve disconnect from wallet', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await disconnectUsingWallet(page, walletPage) + }) + + test('should sign a message', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await page.getByTestId('lab-sign').click() + + await expect(walletPage.getByText('Sign Message')).toBeVisible() + await walletPage.getByTestId('request-button-approve').click() + + await expect(page.getByText('Sign Message')).toBeVisible() + await expect(page.getByText('0x')).toBeVisible() + }) + + test('should handle rejected sign', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await page.getByTestId('lab-sign').click() + + await expect(walletPage.getByText('Sign Message')).toBeVisible() + await walletPage.getByTestId('request-button-reject').click() + + await expect(page.getByText('Sign Message')).toBeVisible() + await expect(page.getByText(/User rejected/u)).toBeVisible() + }) + + test('should sign typed data', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await page.getByTestId('lab-sign-typed').click() + + await expect(walletPage.getByText('Sign Typed Data')).toBeVisible() + await walletPage.getByTestId('request-button-approve').click() + + await expect(page.getByText('Sign Typed Data')).toBeVisible() + await expect(page.getByText('0x')).toBeVisible() + }) + + test('should handle rejected sign typed data', async ({ page, context, browserName }) => { + const walletPage = await connectToWallet(page, context, browserName) + await page.getByTestId('lab-sign-typed').click() + + await expect(walletPage.getByText('Sign Typed Data')).toBeVisible() + await walletPage.getByTestId('request-button-reject').click() + + await expect(page.getByText('Sign Typed Data')).toBeVisible() + await expect(page.getByText(/User rejected/u)).toBeVisible() + }) +}) From 21fe637a640648d8d1bd6d1ac3f42d6279b63005 Mon Sep 17 00:00:00 2001 From: Jonathan Conn Date: Sun, 23 Jul 2023 17:27:44 -0400 Subject: [PATCH 05/23] fix: minor cleanup, added tags to ui, added a test for chain switching --- .github/docs/dom-selectors.md | 4 +++- laboratory/playwright.config.ts | 2 +- laboratory/tests/basic-tests.spec.ts | 3 +-- laboratory/tests/explorer-page.spec.ts | 3 +-- laboratory/tests/web-examples.spec.ts | 21 ++++++++++++------- .../components/w3m-modal-backcard/index.ts | 6 ++++-- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.github/docs/dom-selectors.md b/.github/docs/dom-selectors.md index 661e4f6387..a694c998d1 100644 --- a/.github/docs/dom-selectors.md +++ b/.github/docs/dom-selectors.md @@ -161,4 +161,6 @@ | w3m-text | `component-text` | W3M Text | `` | | w3m-modal-content | `component-modal-content` | W3M Content | `
` | | w3m-modal-footer | `component-modal-footer` | W3M Footer | `