-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Setup E2E testing with Playwright (#401)
* Setup Playwright * Add test for signup success flow * Upgrade playwright to v1.46.0 * Extract webauthn emulator logic as class * Rename test script to e2e * Extract keychain connection logic * Describe e2e test script in readme
- Loading branch information
1 parent
2c64486
commit b18a085
Showing
14 changed files
with
253 additions
and
46 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,27 @@ | ||
# name: End-to-End tests | ||
# on: | ||
# push: | ||
# branches: [main] | ||
# pull_request: | ||
# branches: [main] | ||
# jobs: | ||
# test: | ||
# timeout-minutes: 60 | ||
# runs-on: ubuntu-latest | ||
# steps: | ||
# - uses: actions/checkout@v4 | ||
# - uses: actions/setup-node@v4 | ||
# with: | ||
# node-version: lts/* | ||
# - name: Install dependencies | ||
# run: npm install -g pnpm && pnpm install | ||
# - name: Install Playwright Browsers | ||
# run: pnpm exec playwright install --with-deps | ||
# - name: Run Playwright tests | ||
# run: pnpm exec playwright test | ||
# - uses: actions/upload-artifact@v4 | ||
# if: always() | ||
# with: | ||
# name: playwright-report | ||
# path: 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules/ | ||
/test-results/ | ||
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ |
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 |
---|---|---|
@@ -1,45 +1,27 @@ | ||
This is an example showing how to use StarkNet React with Next.js | ||
## Controller Example (Next.js) | ||
|
||
## Getting Started | ||
### Development | ||
|
||
First, run the development server: | ||
|
||
```bash | ||
pnpm example:next dev | ||
``` | ||
pnpm i | ||
pnpm dev | ||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the | ||
result. | ||
|
||
You can start editing the page by modifying `pages/index.tsx`. The page | ||
auto-updates as you edit the file. | ||
|
||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on | ||
[http://localhost:3000/api/hello](http://localhost:3000/api/hello). This | ||
endpoint can be edited in `pages/api/hello.ts`. | ||
|
||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are | ||
treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead | ||
of React pages. | ||
|
||
## Learn More | ||
|
||
To learn more about Next.js, take a look at the following resources: | ||
# Example page: localhost:3002 | ||
# Keychain: localhost:3001 | ||
``` | ||
|
||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js | ||
features and API. | ||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | ||
### E2E test | ||
|
||
You can check out | ||
[the Next.js GitHub repository](https://github.com/vercel/next.js/) - your | ||
feedback and contributions are welcome! | ||
```sh | ||
# Start api server locally | ||
bin/apidev | ||
|
||
## Deploy on Vercel | ||
# Start example page and keychain | ||
pnpm dev | ||
|
||
The easiest way to deploy your Next.js app is to use the | ||
[Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) | ||
from the creators of Next.js. | ||
# Run test | ||
pnpm example:next e2e | ||
|
||
Check out our | ||
[Next.js deployment documentation](https://nextjs.org/docs/deployment) for more | ||
details. | ||
# or Run test with Playwright UI | ||
pnpm example:next e2e:ui | ||
``` |
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,36 @@ | ||
import { defineConfig, devices } from "@playwright/test"; | ||
|
||
export default defineConfig({ | ||
testDir: "./tests", | ||
fullyParallel: true, | ||
forbidOnly: !!process.env.CI, | ||
retries: process.env.CI ? 2 : 0, | ||
workers: process.env.CI ? 1 : undefined, | ||
reporter: "html", | ||
use: { | ||
baseURL: "http://localhost:3002", | ||
trace: "on-first-retry", | ||
}, | ||
projects: [ | ||
{ | ||
name: "chromium", | ||
use: { ...devices["Desktop Chrome"] }, | ||
}, | ||
// { | ||
// name: "firefox", | ||
// use: { ...devices["Desktop Firefox"] }, | ||
// }, | ||
// { | ||
// name: "webkit", | ||
// use: { ...devices["Desktop Safari"] }, | ||
// }, | ||
], | ||
webServer: { | ||
command: "pnpm dev", | ||
cwd: "../..", | ||
port: 3002, | ||
reuseExistingServer: !process.env.CI, | ||
stdout: "pipe", | ||
stderr: "pipe", | ||
}, | ||
}); |
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,24 @@ | ||
import { test, expect } from "@playwright/test"; | ||
import { WebauthnEmulator } from "./webauthn"; | ||
import { Keychain } from "./keychain"; | ||
|
||
test.beforeEach(async ({ page }) => { | ||
await page.goto("/"); | ||
|
||
const client = await page.context().newCDPSession(page); | ||
const webauthn = new WebauthnEmulator({ client }); | ||
|
||
await webauthn.enable(); | ||
await webauthn.addVirtualAuthenticator(); | ||
}); | ||
|
||
test("Sign up -> Disconnect -> Log in", async ({ page }) => { | ||
const keychain = new Keychain({ page }); | ||
|
||
await keychain.signup(); | ||
await keychain.session(); | ||
await keychain.disconnect(); | ||
await keychain.login(); | ||
|
||
await expect(page.getByText(`Username: ${keychain.username}`)).toBeVisible(); | ||
}); |
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,43 @@ | ||
import { FrameLocator } from "@playwright/test"; | ||
import { Page } from "@playwright/test"; | ||
|
||
export class Keychain { | ||
private page: Page; | ||
private modal: FrameLocator; | ||
public username: string; | ||
|
||
constructor({ page, username }: { page: Page; username?: string }) { | ||
this.page = page; | ||
this.modal = page.frameLocator("#cartridge-modal"); | ||
this.username = username ?? this.randomUsername(); | ||
} | ||
|
||
async signup() { | ||
await this.connect(); | ||
await this.modal.getByPlaceholder("Username").fill(this.username); | ||
await this.modal.getByText("SIGN UP").click(); | ||
} | ||
|
||
async session() { | ||
await this.modal.getByRole("button", { name: "CREATE SESSION" }).click(); | ||
} | ||
|
||
async login() { | ||
await this.connect(); | ||
await this.modal.getByText("Log In").click(); | ||
await this.modal.getByPlaceholder("Username").fill(this.username); | ||
await this.modal.getByText("LOG IN").click(); | ||
} | ||
|
||
disconnect() { | ||
return this.page.getByText("Disconnect").click(); | ||
} | ||
|
||
private connect() { | ||
return this.page.getByText("Connect").click(); | ||
} | ||
|
||
private randomUsername() { | ||
return `test-${Math.random().toString().slice(2, -1)}`; | ||
} | ||
} |
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,9 @@ | ||
import { test, expect } from "@playwright/test"; | ||
|
||
test.beforeEach(async ({ page }) => { | ||
await page.goto("/"); | ||
}); | ||
|
||
test("Page Title", async ({ page }) => { | ||
await expect(page).toHaveTitle(/StarkNet ❤️ React/); | ||
}); |
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,42 @@ | ||
import { CDPSession } from "@playwright/test"; | ||
|
||
export class WebauthnEmulator { | ||
private client: CDPSession; | ||
public authenticatorId?: string; | ||
|
||
constructor({ client }: { client: CDPSession }) { | ||
this.client = client; | ||
} | ||
|
||
async enable() { | ||
await this.client.send("WebAuthn.enable"); | ||
} | ||
|
||
async addVirtualAuthenticator() { | ||
const { authenticatorId } = await this.client.send( | ||
"WebAuthn.addVirtualAuthenticator", | ||
{ | ||
options: { | ||
protocol: "ctap2", | ||
transport: "ble", | ||
hasResidentKey: true, | ||
hasUserVerification: true, | ||
isUserVerified: true, | ||
automaticPresenceSimulation: true, | ||
}, | ||
}, | ||
); | ||
|
||
this.authenticatorId = authenticatorId; | ||
} | ||
|
||
async removeVirtualAuthenticator() { | ||
if (!this.authenticatorId) { | ||
throw new Error("No virtual authnticator found"); | ||
} | ||
|
||
await this.client.send("WebAuthn.removeVirtualAuthenticator", { | ||
authenticatorId: this.authenticatorId, | ||
}); | ||
} | ||
} |
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
Oops, something went wrong.