-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #59 from openfort-xyz/feat/add-e2e-tests
Feat/add e2e tests
- Loading branch information
Showing
19 changed files
with
938 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
name: Playwright Tests | ||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
merge_group: | ||
branches: | ||
- main | ||
jobs: | ||
test: | ||
timeout-minutes: 60 | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Setup Node | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version-file: .nvmrc | ||
cache: 'yarn' | ||
|
||
- name: Install root dependencies | ||
run: yarn install --immutable | ||
|
||
- name: Install auth-sample dependencies | ||
run: yarn install --immutable | ||
working-directory: examples/apps/auth-sample | ||
|
||
- name: Lint | ||
run: yarn lint | ||
|
||
- name: Build | ||
run: yarn build | ||
|
||
- name: Install Playwright Browsers | ||
run: yarn playwright install --with-deps | ||
working-directory: examples/apps/auth-sample | ||
|
||
- name: Run Playwright tests | ||
env: | ||
NEXTAUTH_OPENFORT_SECRET_KEY: ${{ secrets.NEXTAUTH_OPENFORT_SECRET_KEY }} | ||
NEXTAUTH_SHIELD_ENCRYPTION_SHARE: ${{ secrets.NEXTAUTH_SHIELD_ENCRYPTION_SHARE }} | ||
NEXTAUTH_SHIELD_SECRET_KEY: ${{ secrets.NEXTAUTH_SHIELD_SECRET_KEY }} | ||
E2E_TESTS_PASSWORD: ${{ secrets.E2E_TESTS_PASSWORD }} | ||
NEXT_PUBLIC_OPENFORT_PUBLIC_KEY: ${{ vars.NEXT_PUBLIC_OPENFORT_PUBLIC_KEY }} | ||
NEXT_PUBLIC_SHIELD_API_KEY: ${{ vars.NEXT_PUBLIC_SHIELD_API_KEY }} | ||
NEXT_PUBLIC_POLICY_ID: ${{ vars.NEXT_PUBLIC_POLICY_ID }} | ||
NEXT_PUBLIC_CHAIN_ID: ${{ vars.NEXT_PUBLIC_CHAIN_ID }} | ||
NEXT_PUBLIC_CONTRACT_ID: ${{ vars.NEXT_PUBLIC_CONTRACT_ID }} | ||
NEXT_PUBLIC_REOWN_PROJECT_ID: ${{ vars.NEXT_PUBLIC_REOWN_PROJECT_ID }} | ||
NEXT_PUBLIC_COINBASE_PROJECTID: ${{ vars.NEXT_PUBLIC_COINBASE_PROJECTID }} | ||
NEXT_PUBLIC_MOONPAY_API_KEY: ${{ vars.NEXT_PUBLIC_MOONPAY_API_KEY }} | ||
E2E_TESTS_USER: ${{ vars.E2E_TESTS_USER }} | ||
run: yarn playwright test --reporter=dot --workers=5 | ||
working-directory: examples/apps/auth-sample | ||
|
||
- uses: actions/upload-artifact@v4 | ||
if: ${{ !cancelled() }} | ||
with: | ||
name: playwright-report | ||
path: examples/apps/auth-sample/playwright-report/ | ||
retention-days: 30 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { defineConfig, devices } from '@playwright/test'; | ||
|
||
import dotenv from 'dotenv'; | ||
import path from 'path'; | ||
|
||
// Alternatively, read from "../my.env" file. | ||
dotenv.config({ path: path.resolve(__dirname, '.env.local') }); | ||
|
||
/** | ||
* Read environment variables from file. | ||
* https://github.com/motdotla/dotenv | ||
*/ | ||
// import dotenv from 'dotenv'; | ||
// import path from 'path'; | ||
// dotenv.config({ path: path.resolve(__dirname, '.env') }); | ||
|
||
/** | ||
* 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: [ | ||
// Setup project | ||
{ name: 'setup', testMatch: /.*\.setup\.ts/ }, | ||
|
||
{ | ||
name: 'chromium', | ||
use: { | ||
...devices['Desktop Chrome'], | ||
// Use prepared auth state. | ||
storageState: 'playwright/.auth/user.json', | ||
}, | ||
dependencies: ['setup'], | ||
}, | ||
|
||
{ | ||
name: 'firefox', | ||
use: { | ||
...devices['Desktop Firefox'], | ||
// Use prepared auth state. | ||
storageState: 'playwright/.auth/user.json', | ||
}, | ||
dependencies: ['setup'], | ||
}, | ||
|
||
{ | ||
name: 'webkit', | ||
use: { | ||
...devices['Desktop Safari'], | ||
// Use prepared auth state. | ||
storageState: 'playwright/.auth/user.json', | ||
}, | ||
dependencies: ['setup'], | ||
}, | ||
|
||
/* 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' }, | ||
// }, | ||
], | ||
// outputDir: "playwright/.auth/", | ||
|
||
/* Run your local dev server before starting the tests */ | ||
webServer: { | ||
command: 'yarn dev', | ||
url: 'http://127.0.0.1:3000', | ||
reuseExistingServer: !process.env.CI, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { expect, Locator, Page } from "@playwright/test"; | ||
|
||
export class Logger { | ||
page: Page | ||
textArea: Locator | null = null | ||
logs: string[] = [] | ||
|
||
constructor(page: Page) { | ||
this.page = page | ||
} | ||
|
||
async init() { | ||
await this.page.waitForSelector('textarea', { timeout: 5000 }); | ||
this.textArea = this.page.locator("textarea").first() | ||
|
||
await this.textArea.textContent() | ||
|
||
await expect(this.textArea).toHaveValue(/.*> User:/, { timeout: 10000 }) | ||
|
||
this.logs.push(await this.textArea.inputValue()) | ||
} | ||
|
||
getLastLog() { | ||
return this.logs[this.logs.length - 1] | ||
} | ||
|
||
|
||
async waitForNewLogs(options: { pollInterval?: number, timeout?: number } = {}) { | ||
const { pollInterval = 1000, timeout = 30000 } = options; | ||
|
||
if (!this.textArea) { | ||
throw new Error("Logger not initialized"); | ||
} | ||
|
||
const timer = setTimeout(() => { | ||
throw new Error("Timeout waiting for new logs") | ||
}, timeout); | ||
|
||
// Store the initial value | ||
let currentValue = await this.textArea.inputValue(); | ||
|
||
// Polling loop: keep checking until the value changes | ||
while (currentValue === await this.textArea.inputValue()) { | ||
// Wait for the specified interval before checking again | ||
await new Promise(resolve => setTimeout(resolve, pollInterval)); | ||
} | ||
|
||
clearTimeout(timer); | ||
|
||
const newLogs = (await this.textArea.inputValue()).replace(currentValue, '') | ||
|
||
this.logs.push(newLogs) | ||
|
||
return newLogs; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import test, { expect } from '@playwright/test'; | ||
import { Logger } from './Logger'; | ||
import { TEST_MINT_SUCCESS_TEXT } from './constants'; | ||
|
||
test('mint NFT', async ({ page }) => { | ||
await page.goto('/') | ||
|
||
const logger = new Logger(page) | ||
await logger.init() | ||
|
||
const button = page.getByRole('button', { name: 'Mint NFT' }).first() | ||
button.click() | ||
|
||
await logger.waitForNewLogs() | ||
|
||
const lastLog = logger.getLastLog() | ||
expect(lastLog).toContain(TEST_MINT_SUCCESS_TEXT) | ||
}) | ||
|
||
test('Send batch calls', async ({ page }) => { | ||
await page.goto('/') | ||
|
||
const logger = new Logger(page) | ||
await logger.init() | ||
|
||
const button = page.getByRole('button', { name: 'Send batch calls' }).first() | ||
button.click() | ||
|
||
await logger.waitForNewLogs() | ||
|
||
const lastLog = logger.getLastLog() | ||
expect(lastLog).toContain(TEST_MINT_SUCCESS_TEXT) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { test as setup, expect } from '@playwright/test'; | ||
import path from 'path'; | ||
import { Logger } from './Logger'; | ||
|
||
const authFile = path.join(__dirname, '../playwright/.auth/user.json'); | ||
|
||
setup('authenticate', async ({ page }) => { | ||
// Perform authentication steps. Replace these actions with your own. | ||
await page.goto('/login'); | ||
|
||
// The new page should contain an h1 with "Sign in to account" | ||
await expect(page.locator('h1')).toContainText('Sign in to account') | ||
|
||
await page.getByLabel('Email address').fill(process.env.E2E_TESTS_USER || ""); | ||
await page.getByLabel('Password').fill(process.env.E2E_TESTS_PASSWORD || ""); | ||
|
||
await page.getByRole('button', { name: 'Sign in' }).click(); | ||
|
||
await page.waitForURL('/'); | ||
|
||
await expect(page.locator('h1')).toContainText('Set up your embedded signer') | ||
|
||
await page.getByRole('button', { name: 'Continue with Automatic Recovery' }).click(); | ||
|
||
await expect(page.locator('div.spinner')).toBeInViewport(); | ||
await page.locator("div.spinner").waitFor({ state: 'hidden' }); | ||
|
||
const consoleExists = await page.locator('h2').getByText('Console').count() > 0 | ||
if (!consoleExists) { | ||
// if console doesn't exists we must be at the login page, so maybe we have to log in with wallet recovery instead | ||
await expect(page.locator('h1')).toContainText('Set up your embedded signer') | ||
|
||
const passwordRecoveryInputLogin = page.locator('input[name="passwordRecovery"]') | ||
const passwordRecoveryButtonLogin = page.getByRole('button', { name: 'Continue with Password Recovery' }).first() | ||
|
||
await passwordRecoveryInputLogin.fill('password') | ||
passwordRecoveryButtonLogin.click() | ||
|
||
await expect(page.locator('div.spinner')).toBeInViewport(); | ||
await page.locator("div.spinner").waitFor({ state: 'hidden' }); | ||
|
||
// we should be logged now | ||
await expect(page.locator('h2').getByText('Console')).toBeVisible() | ||
|
||
const logger = new Logger(page) | ||
await logger.init() | ||
|
||
|
||
const automaticRecoveryButton = page.getByRole('button', { name: 'Set Automatic Recovery' }).first() | ||
const oldPasswordInput = page.locator('input[name="automatic-passwordRecovery"]') | ||
|
||
await oldPasswordInput.fill('password') | ||
automaticRecoveryButton.click() | ||
|
||
await logger.waitForNewLogs() | ||
const lastLog = logger.getLastLog() | ||
|
||
expect(lastLog).toContain("success") | ||
} | ||
|
||
await page.context().storageState({ path: authFile }); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import test, { expect } from '@playwright/test'; | ||
|
||
// remove default auth tokens | ||
test.use({ storageState: { cookies: [], origins: [] } }); | ||
|
||
// TODO: Google login | ||
test.skip('Login page', async ({ page }) => { | ||
await page.goto('/') | ||
|
||
await expect(page.locator('h1')).toContainText('Sign in to account') | ||
|
||
const button = page.locator('span').getByText('Continue with Google').first() | ||
await button.click() | ||
|
||
// ... | ||
}) |
Oops, something went wrong.