diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 000000000..aec86a076 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,35 @@ +name: Playwright Tests + +on: + push: + branches: + - main + - development + - noah/playwright + pull_request: + branches: + - main + - development + - noah/playwright + +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: yarn + - run: yarn install + - name: Install Playwright browsers + run: yarn playwright install --with-deps + - name: Run Playwright tests + run: yarn test:e2e + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 0aa576f5d..75db95d1f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ out/ \#*\# .turbo + +# playwright +test-results/ +playwright-report/ +blob-report/ +playwright/.cache/ diff --git a/apps/dapp/package.json b/apps/dapp/package.json index 8811f51ff..caaec6870 100644 --- a/apps/dapp/package.json +++ b/apps/dapp/package.json @@ -52,10 +52,12 @@ "devDependencies": { "@dao-dao/config": "2.4.0-rc.8", "@next/bundle-analyzer": "^14.1.0", + "@playwright/test": "^1.44.1", "@sentry/cli": "^2.21.3", "@solana/web3.js": "^1.75.0", "@types/cors": "^2.8.13", "@types/lodash.clonedeep": "^4.5.0", + "@types/node": "^20.14.2", "@types/react": "^17.0.37", "autoprefixer": "^9.8.6", "eslint": "^8.23.1", diff --git a/apps/dapp/playwright.config.ts b/apps/dapp/playwright.config.ts new file mode 100644 index 000000000..cfa564036 --- /dev/null +++ b/apps/dapp/playwright.config.ts @@ -0,0 +1,86 @@ +// GNU AFFERO GENERAL PUBLIC LICENSE Version 3. Copyright (C) 2022 DAO DAO Contributors. +// See the "LICENSE" file in the root directory of this package for more copyright information. +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * 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. */ + forbidOnly: !!process.env.CI, + /* 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'] }, + }, + + /* 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' }, + // }, + ], + + /* Build and run server before starting the tests */ + webServer: { + command: 'cp .env.testnet .env.local && yarn build && yarn start', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + // allow 10 minutes for the server to build + timeout: 10 * 60 * 1000, + }, + + expect: { + // Default expect timeout to 20 seconds. + timeout: 20 * 1000, + }, +}) diff --git a/apps/dapp/tests/dao.spec.ts b/apps/dapp/tests/dao.spec.ts new file mode 100644 index 000000000..b0fe8e0bb --- /dev/null +++ b/apps/dapp/tests/dao.spec.ts @@ -0,0 +1,13 @@ +// GNU AFFERO GENERAL PUBLIC LICENSE Version 3. Copyright (C) 2022 DAO DAO Contributors. +// See the "LICENSE" file in the root directory of this package for more copyright information. + +import { expect, test } from '@playwright/test' + +test('DAO home renders', async ({ page }) => { + await page.goto( + '/dao/juno1vh0xndu9pj8g0lat6k3500mxusfduh804sf9hj7jpt4kgj0gmreq3jmqj4' + ) + + // Expect description to exist. + await expect(page.getByText('Worship the moon.')).toBeVisible() +}) diff --git a/apps/dapp/tests/home.spec.ts b/apps/dapp/tests/home.spec.ts new file mode 100644 index 000000000..479105f47 --- /dev/null +++ b/apps/dapp/tests/home.spec.ts @@ -0,0 +1,34 @@ +// GNU AFFERO GENERAL PUBLIC LICENSE Version 3. Copyright (C) 2022 DAO DAO Contributors. +// See the "LICENSE" file in the root directory of this package for more copyright information. + +import { expect, test } from '@playwright/test' + +test('home page renders', async ({ page }) => { + await page.goto('/') + + // Expect "Log in" button to exist. + await expect(page.getByRole('button', { name: 'Log in' })).toBeVisible() + + // Expect "Chain governance" title to exist. + await expect( + page.getByText('Chain governance', { exact: true }) + ).toBeVisible() + + // Expect "Featured DAOs" title to exist. + await expect(page.getByText('Featured DAOs', { exact: true })).toBeVisible() +}) + +test('chain-specific home page renders', async ({ page }) => { + await page.goto('/juno') + + // Expect "Log in" button to exist. + await expect(page.getByRole('button', { name: 'Log in' })).toBeVisible() + + // Expect "Chain governance" title to exist. + await expect( + page.getByText('Chain governance', { exact: true }) + ).toBeVisible() + + // Expect "Featured DAOs" title to exist. + await expect(page.getByText('Featured DAOs', { exact: true })).toBeVisible() +}) diff --git a/package.json b/package.json index 192520cc4..a36db3ccb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "format": "prettier --write \"**/*.{css,json,md}\" && turbo run format --continue --parallel", "lint": "prettier --check \"**/*.{css,json,md}\" && turbo run lint --continue --parallel", "test": "jest", + "test:e2e": "yarn dapp playwright test", "dapp": "yarn workspace @dao-dao/dapp", "sda": "yarn workspace @dao-dao/sda", "i18n": "yarn workspace @dao-dao/i18n", diff --git a/yarn.lock b/yarn.lock index 7d8ec1575..a8f402a3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6042,6 +6042,13 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@playwright/test@^1.44.1": + version "1.44.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.44.1.tgz#cc874ec31342479ad99838040e99b5f604299bcb" + integrity sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q== + dependencies: + playwright "1.44.1" + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.7" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2" @@ -8313,6 +8320,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.36.tgz#c414052cb9d43fab67d679d5f3c641be911f5835" integrity sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ== +"@types/node@^20.14.2": + version "20.14.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" + integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== + dependencies: + undici-types "~5.26.4" + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -14441,6 +14455,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@2.3.2, fsevents@^2.1.2, fsevents@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fsevents@^1.2.7: version "1.2.13" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" @@ -14449,11 +14468,6 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fsevents@^2.1.2, fsevents@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -20319,6 +20333,20 @@ pkg-types@^1.1.0: mlly "^1.6.1" pathe "^1.1.2" +playwright-core@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.44.1.tgz#53ec975503b763af6fc1a7aa995f34bc09ff447c" + integrity sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA== + +playwright@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.44.1.tgz#5634369d777111c1eea9180430b7a184028e7892" + integrity sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg== + dependencies: + playwright-core "1.44.1" + optionalDependencies: + fsevents "2.3.2" + plur@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a"