Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📦️ chore: Add example project #1028

Merged
merged 1 commit into from
Dec 3, 2023
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
2 changes: 2 additions & 0 deletions examples/new-dawn/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SEED_PHRASE="test test test test test test test test test test test junk"
WALLET_PASSWORD="SynpressIsAwesomeNow!!!"
63 changes: 63 additions & 0 deletions examples/new-dawn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<h1 align="center">
Synpress: New Dawn
<br>
<small>⭐ Example Project ⭐</small>
</h1>

# 📖 Intro

The New Dawn version of Synpress differs in one major way from all previous versions and all other similar Web3 tools:
- We set up the browser only once, and we cache it. Thanks to this, tests not only run faster, but it also allows to use **ALL FEATURES** of [Playwright](https://playwright.dev/), such as parallel testing 🚀

You can define how a browser should be set up yourself. You can find setup file examples [here](./test/wallet-setup). All setup files must have the following naming structure: `*.setup.{js,ts}`.

Once you define a setup file, you can build a cache with our CLI. By default, the cache is built in a headed mode and utilizes the setup files from `test/wallet-setup` directory.
Try running it with the `--help` flag to see all available configuration options.

Here's how to use it:
```bash
# Build cache in a headed mode:
synpress

# Build cache in a headless mode:
synpress --headless
```

# 🧑‍💻 Usage

1. Install dependencies:
```bash
pnpm install
```

2. Build cache with our CLI by using a script:
```bash
# You can either build cache in a headed mode:
pnpm run build:cache

# Or in a headless mode:
pnpm run build:cache:headless
```

3. Run Playwright tests as you would normally do:
```bash
# Use one of our scripts:
pnpm run test:e2e:headful
pnpm run test:e2e:headless
pnpm run test:e2e:headless:ui

# Or use Playwright directly:
playwright test
HEADLESS=true playwright test
HEADLESS=true playwright test --ui
```

### ⚠️ Important note ⚠️

Currently, tests are triggered in a headed mode by default. Add `HEADLESS=true` to run them in a headless mode.

This behavior will change soon! 🫡

# 🤔 Still want more?

If you need more than this example project, check out our tests for MetaMask [here](../../wallets/metamask/test/e2e).
10 changes: 10 additions & 0 deletions examples/new-dawn/environment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
SEED_PHRASE: string
WALLET_PASSWORD: string
}
}
}

export {}
25 changes: 25 additions & 0 deletions examples/new-dawn/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "example-new-dawn",
"private": true,
"type": "module",
"scripts": {
"build:cache": "synpress",
"build:cache:force": "synpress --force",
"build:cache:headless": "synpress --headless",
"serve:test-dapp": "serve node_modules/@metamask/test-dapp/dist -p 12345",
"test:e2e:headful": "playwright test",
"test:e2e:headless": "HEADLESS=true playwright test",
"test:e2e:headless:ui": "HEADLESS=true playwright test --ui"
},
"dependencies": {
"@playwright/test": "1.40.0",
"@synthetixio/synpress": "workspace:*",
"dotenv": "16.3.1"
},
"devDependencies": {
"@metamask/test-dapp": "8.0.0",
"@types/node": "20.10.2",
"serve": "14.2.1",
"typescript": "5.3.2"
}
}
35 changes: 35 additions & 0 deletions examples/new-dawn/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { defineConfig, devices } from '@playwright/test'

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
// Look for test files in the "test/e2e" directory, relative to this configuration file.
testDir: './test/e2e',

// Run all tests in parallel.
fullyParallel: true,

// Use half of the number of logical CPU cores for running tests in parallel.
workers: undefined,

use: {
// We are using locally deployed MetaMask Test Dapp.
baseURL: 'http://localhost:12345'
},

// Synpress currently only supports Chromium, however, this will change in the future.
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
}
],

// Serve MetaMask Test Dapp locally before starting the tests.
webServer: {
command: 'pnpm run serve:test-dapp',
url: 'http://localhost:12345',
reuseExistingServer: true
}
})
39 changes: 39 additions & 0 deletions examples/new-dawn/test/advancedFixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { test as base } from './simpleFixture'

/**
* This fixture is further built upon the `simpleFixture`.
* It will serve as a foundation for the tests in the `03_advanced.spec.ts` file.
*
* You can read more about Playwright fixtures here: https://playwright.dev/docs/test-fixtures
*/
export const test = base.extend<{
deployToken: () => Promise<void>
deployPiggyBank: () => Promise<void>
}>({
deployToken: async ({ page, metamask }, use) => {
await use(async () => {
// We want to make sure we are connected to the local Anvil node.
await expect(page.locator('#network')).toHaveText('0x53a')

await expect(page.locator('#tokenAddresses')).toBeEmpty()
await page.locator('#createToken').click()

await metamask.confirmTransaction()
})
},
deployPiggyBank: async ({ page, metamask }, use) => {
await use(async () => {
// We want to make sure we are connected to the local Anvil node.
await expect(page.locator('#network')).toHaveText('0x53a')

await expect(page.locator('#contractStatus')).toHaveText('Not clicked')

await page.locator('#deployButton').click()
await metamask.confirmTransaction()

await expect(page.locator('#contractStatus')).toHaveText('Deployed')
})
}
})

export const { expect, describe } = test
19 changes: 19 additions & 0 deletions examples/new-dawn/test/e2e/01_basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MetaMask, testWithSynpress, unlockForFixture } from '@synthetixio/synpress'
import BasicSetup from '../wallet-setup/basic.setup'

const test = testWithSynpress(BasicSetup, unlockForFixture)

const { expect } = test

test('should connect wallet to the MetaMask Test Dapp', async ({ context, page, extensionId }) => {
const metamask = new MetaMask(context, page, BasicSetup.walletPassword, extensionId)

await page.goto('/')

await page.locator('#connectButton').click()
await metamask.connectToDapp()
await expect(page.locator('#accounts')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266')

await page.locator('#getAccounts').click()
await expect(page.locator('#getAccountsResult')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266')
})
42 changes: 42 additions & 0 deletions examples/new-dawn/test/e2e/02_simple.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { expect, test } from '../simpleFixture'

test('should confirm contract deployment', async ({ page, metamask, connectToAnvil }) => {
await connectToAnvil()

await expect(page.locator('#tokenAddresses')).toBeEmpty()
await page.locator('#createToken').click()

await metamask.confirmTransaction()

await expect(page.locator('#tokenAddresses')).toHaveText('0x5FbDB2315678afecb367f032d93F642f64180aa3')
})

test('should confirm legacy transaction', async ({ page, metamask, connectToAnvil }) => {
await connectToAnvil()

await page.locator('#sendButton').click()

await metamask.confirmTransaction()
})

test('should confirm EIP-1559 transaction', async ({ page, metamask, connectToAnvil }) => {
await connectToAnvil()

await page.locator('#sendEIP1559Button').click()

await metamask.confirmTransaction()
})

test('should sign and verify EIP-712 message', async ({ page, metamask }) => {
await page.locator('#signTypedDataV4').click()

await metamask.confirmSignature()

await expect(page.locator('#signTypedDataV4Result')).toHaveText(
'0x1cf422c4a319c19ecb89c960e7c296810278fa2bef256c7e9419b285c8216c547b3371fa1ec3987ce08561d3ed779845393d8d3e4311376d0bc0846f37d1b2821c'
)

await page.locator('#signTypedDataV4Verify').click()

await expect(page.locator('#signTypedDataV4VerifyResult')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266')
})
41 changes: 41 additions & 0 deletions examples/new-dawn/test/e2e/03_advanced.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, expect, test } from '../advancedFixture'

describe('Token', () => {
test('should confirm tokens transfer', async ({ page, metamask, connectToAnvil, deployToken }) => {
await connectToAnvil()
await deployToken()

await page.locator('#transferTokens').click()
await metamask.confirmTransaction()
})

test('should approve tokens', async ({ page, metamask, connectToAnvil, deployToken }) => {
await connectToAnvil()
await deployToken()

await page.locator('#approveTokens').click()
await metamask.approvePermission()
})
})

describe('Piggy Bank', () => {
test('should deposit and then withdraw ETH from the contract', async ({
page,
metamask,
connectToAnvil,
deployPiggyBank
}) => {
await connectToAnvil()
await deployPiggyBank()

await page.locator('#depositButton').click()
await metamask.confirmTransaction()

await expect(page.locator('#contractStatus')).toHaveText('Deposit completed')

await page.locator('#withdrawButton').click()
await metamask.confirmTransaction()

await expect(page.locator('#contractStatus')).toHaveText('Withdrawn')
})
})
44 changes: 44 additions & 0 deletions examples/new-dawn/test/simpleFixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { MetaMask, testWithSynpress, unlockForFixture } from '@synthetixio/synpress'
import ConnectedSetup from './wallet-setup/connected.setup'

/**
* We're creating a fixture that will serve as a foundation for tests in the `02_simple.spec.ts` file.
*
* You can read more about Playwright fixtures here: https://playwright.dev/docs/test-fixtures
*/
export const test = testWithSynpress(ConnectedSetup, unlockForFixture).extend<{
metamask: MetaMask
connectToAnvil: () => Promise<void>
}>({
metamask: async ({ context, metamaskPage, extensionId }, use) => {
const metamask = new MetaMask(context, metamaskPage, ConnectedSetup.walletPassword, extensionId)

await use(metamask)
},
page: async ({ page }, use) => {
/**
* Refers to the home page of the locally hosted MetaMask Test Dapp.
*
* See: https://playwright.dev/docs/api/class-testoptions#test-options-base-url
*/
await page.goto('/')

await use(page)
},
connectToAnvil: async ({ metamask, createAnvilNode }, use) => {
await use(async () => {
const { rpcUrl, chainId } = await createAnvilNode({
chainId: 1338
})

await metamask.addNetwork({
name: 'Local Anvil Network',
rpcUrl,
chainId,
symbol: 'ETH'
})
})
}
})

export const { expect } = test
10 changes: 10 additions & 0 deletions examples/new-dawn/test/wallet-setup/basic.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { MetaMask, defineWalletSetup } from '@synthetixio/synpress'

const SEED_PHRASE = 'test test test test test test test test test test test junk'
const PASSWORD = 'SynpressIsAwesomeNow!!!'

export default defineWalletSetup(PASSWORD, async (context, walletPage) => {
const metamask = new MetaMask(context, walletPage, PASSWORD)

await metamask.importWallet(SEED_PHRASE)
})
24 changes: 24 additions & 0 deletions examples/new-dawn/test/wallet-setup/connected.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MetaMask, defineWalletSetup, getExtensionId } from '@synthetixio/synpress'
import 'dotenv/config'

const SEED_PHRASE = process.env.SEED_PHRASE
const PASSWORD = process.env.WALLET_PASSWORD

export default defineWalletSetup(PASSWORD, async (context, walletPage) => {
// This is a workaround for the fact that the MetaMask extension ID changes.
// This workaround won't be needed in the near future! 😁
const extensionId = await getExtensionId(context, 'MetaMask')

const metamask = new MetaMask(context, walletPage, PASSWORD, extensionId)

await metamask.importWallet(SEED_PHRASE)

const page = await context.newPage()

// Go to a locally hosted MetaMask Test Dapp.
await page.goto('http://localhost:12345')

await page.locator('#connectButton').click()

await metamask.connectToDapp()
})
14 changes: 14 additions & 0 deletions examples/new-dawn/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"rootDir": "test",
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["test"],
"files": ["environment.d.ts"]
}
Loading