Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

e2e:
name: E2E Tests
name: E2E Tests (${{ matrix.shard }}/${{ strategy.job-total }})
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3]

steps:
- name: Clone repository
Expand All @@ -54,6 +58,17 @@ jobs:
- name: Setup pnpm
run: corepack enable pnpm

- name: Get pnpm store directory
id: pnpm-cache
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Cache pnpm dependencies
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ runner.os }}-

- name: Install dependencies
run: pnpm install

Expand All @@ -77,12 +92,12 @@ jobs:
run: pnpm exec playwright install-deps chromium

- name: Run Playwright tests
run: pnpm run test:e2e
run: pnpm run test:e2e --shard=${{ matrix.shard }}/3

- name: Upload test results
uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
name: playwright-report-${{ matrix.shard }}
path: playwright-report/
retention-days: 15
10 changes: 9 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
},
"files": {
"ignoreUnknown": false,
"includes": ["**", "!dist", "!node_modules", "!specs/lib", "!src/snippets/unformatted"]
"includes": [
"**",
"!dist",
"!node_modules",
"!playwright-report",
"!specs/lib",
"!src/snippets/unformatted",
"!test-results"
]
}
}
60 changes: 60 additions & 0 deletions e2e/create-a-stablecoin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { expect, test } from '@playwright/test'

test('create a stablecoin', async ({ page }) => {
test.setTimeout(120000)

// Set up virtual authenticator via CDP
const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/issuance/create-a-stablecoin')

// Step 1: Sign up with passkey
const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

// Wait for sign out button (indicates successful sign up)
await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

// Step 2: Add funds
const addFundsButton = page.getByRole('button', { name: 'Add funds' }).first()
await expect(addFundsButton).toBeVisible()
await addFundsButton.click()

// Wait for "Add more funds" button (indicates funds were added)
await expect(page.getByRole('button', { name: 'Add more funds' }).first()).toBeVisible({
timeout: 90000,
})

// Step 3: Fill in token details and deploy
// Use label-based selectors to ensure we're filling the right inputs in the demo form
const nameInput = page.getByLabel('Token name').first()
await expect(nameInput).toBeVisible()
await nameInput.fill('TestUSD')

const symbolInput = page.getByLabel('Token symbol').first()
await expect(symbolInput).toBeVisible()
await symbolInput.fill('TEST')

const deployButton = page.getByRole('button', { name: 'Deploy' }).first()
await expect(deployButton).toBeVisible()
await deployButton.click()

// Wait for success - View receipt link
await expect(page.getByRole('link', { name: 'View receipt' })).toBeVisible({ timeout: 90000 })

// Clean up
await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
110 changes: 110 additions & 0 deletions e2e/distribute-rewards.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { expect, test } from '@playwright/test'

test('distribute rewards', async ({ page }) => {
test.setTimeout(240000)

// Set up virtual authenticator via CDP
const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/issuance/distribute-rewards')

// Step 1: Sign up with passkey
const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

// Step 2: Add funds
const addFundsButton = page.getByRole('button', { name: 'Add funds' }).first()
await expect(addFundsButton).toBeVisible()
await addFundsButton.click()

await expect(page.getByRole('button', { name: 'Add more funds' }).first()).toBeVisible({
timeout: 90000,
})

// Step 3: Create a token
// Use label-based selectors to ensure we're filling the right inputs in the demo form
const nameInput = page.getByLabel('Token name').first()
await expect(nameInput).toBeVisible()
await nameInput.fill('RewardTestUSD')

const symbolInput = page.getByLabel('Token symbol').first()
await expect(symbolInput).toBeVisible()
await symbolInput.fill('REWARD')

const deployButton = page.getByRole('button', { name: 'Deploy' }).first()
await expect(deployButton).toBeVisible()
await deployButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).first()).toBeVisible({
timeout: 90000,
})

// Step 4: Grant issuer role
const grantEnterDetails = page.getByRole('button', { name: 'Enter details' }).first()
await expect(grantEnterDetails).toBeVisible()
await grantEnterDetails.click()

const grantButton = page.getByRole('button', { name: 'Grant' }).first()
await grantButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(1)).toBeVisible({
timeout: 90000,
})

// Step 5: Mint tokens (after grant completes, Enter details button is the first visible one)
const mintEnterDetails = page.getByRole('button', { name: 'Enter details' }).first()
await expect(mintEnterDetails).toBeVisible()
await mintEnterDetails.click()

const mintButton = page.getByRole('button', { name: 'Mint' }).first()
await mintButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(2)).toBeVisible({
timeout: 90000,
})

// Step 6: Opt in to rewards
const optInButton = page.getByRole('button', { name: 'Opt In' }).first()
await expect(optInButton).toBeVisible()
await optInButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(3)).toBeVisible({
timeout: 90000,
})

// Step 7: Start reward
const startButton = page.getByRole('button', { name: 'Start Reward' }).first()
await expect(startButton).toBeVisible()
await startButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(4)).toBeVisible({
timeout: 90000,
})

// Step 8: Claim reward
const claimButton = page.getByRole('button', { name: 'Claim' }).first()
await expect(claimButton).toBeVisible()
await claimButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(5)).toBeVisible({
timeout: 90000,
})

// Clean up
await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
49 changes: 49 additions & 0 deletions e2e/executing-swaps.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { expect, test } from '@playwright/test'

test('executing swaps', async ({ page }) => {
test.setTimeout(180000)

// Set up virtual authenticator via CDP
const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/stablecoin-dex/executing-swaps')

// Step 1: Sign up with passkey
const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

// Step 2: Add funds
const addFundsButton = page.getByRole('button', { name: 'Add funds' }).first()
await expect(addFundsButton).toBeVisible()
await addFundsButton.click()

await expect(page.getByRole('button', { name: 'Add more funds' }).first()).toBeVisible({
timeout: 90000,
})

// Step 3: Execute a swap (Buy AlphaUSD with BetaUSD)
const buyButton = page.getByRole('button', { name: 'Buy' }).first()
await expect(buyButton).toBeVisible()
await buyButton.click()

// Wait for swap receipt
await expect(page.getByRole('link', { name: 'View receipt' })).toBeVisible({ timeout: 90000 })

// Clean up
await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
8 changes: 6 additions & 2 deletions e2e/faucet.spec.ts → e2e/faucet.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { expect, test } from '@playwright/test'

test('fund an address via faucet', async ({ page }) => {
test.setTimeout(120000)

await page.goto('/quickstart/faucet')

// Switch to "Fund an address" tab
await page.getByRole('tab', { name: 'Fund an address' }).click()
const tab = page.getByRole('tab', { name: 'Fund an address' })
await expect(tab).toBeVisible({ timeout: 90000 })
await tab.click()

// Enter an address
const addressInput = page.getByPlaceholder('0x...')
Expand All @@ -14,5 +18,5 @@ test('fund an address via faucet', async ({ page }) => {
await page.getByRole('button', { name: 'Add funds' }).click()

// Confirm "View receipt" link is visible
await expect(page.getByRole('link', { name: 'View receipt' })).toBeVisible({ timeout: 30000 })
await expect(page.getByRole('link', { name: 'View receipt' })).toBeVisible({ timeout: 90000 })
})
86 changes: 86 additions & 0 deletions e2e/manage-stablecoin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { expect, test } from '@playwright/test'

test('manage stablecoin - grant and revoke roles', async ({ page }) => {
test.setTimeout(180000)

// Set up virtual authenticator via CDP
const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/issuance/manage-stablecoin')

// Step 1: Sign up with passkey
const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

// Step 2: Add funds
const addFundsButton = page.getByRole('button', { name: 'Add funds' }).first()
await expect(addFundsButton).toBeVisible()
await addFundsButton.click()

await expect(page.getByRole('button', { name: 'Add more funds' }).first()).toBeVisible({
timeout: 90000,
})

// Step 3: Create a token
// Use label-based selectors to ensure we're filling the right inputs in the demo form
const nameInput = page.getByLabel('Token name').first()
await expect(nameInput).toBeVisible()
await nameInput.fill('ManageTestUSD')

const symbolInput = page.getByLabel('Token symbol').first()
await expect(symbolInput).toBeVisible()
await symbolInput.fill('MANAGE')

const deployButton = page.getByRole('button', { name: 'Deploy' }).first()
await expect(deployButton).toBeVisible()
await deployButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).first()).toBeVisible({
timeout: 90000,
})

// Step 4: Grant issuer role
const grantEnterDetails = page.getByRole('button', { name: 'Enter details' }).first()
await expect(grantEnterDetails).toBeVisible()
await grantEnterDetails.click()

const grantButton = page.getByRole('button', { name: 'Grant' }).first()
await expect(grantButton).toBeVisible()
await grantButton.click()

await expect(page.getByRole('link', { name: 'View receipt' }).nth(1)).toBeVisible({
timeout: 90000,
})

// Step 5: Revoke issuer role (now the first visible Enter details)
const revokeEnterDetails = page.getByRole('button', { name: 'Enter details' }).first()
await expect(revokeEnterDetails).toBeVisible()
await revokeEnterDetails.click()

const revokeButton = page.getByRole('button', { name: 'Revoke' }).first()
await expect(revokeButton).toBeVisible()
await revokeButton.click()

// Wait for revoke receipt
await expect(page.getByRole('link', { name: 'View receipt' }).nth(2)).toBeVisible({
timeout: 90000,
})

// Clean up
await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
Loading