Skip to content

Commit

Permalink
stateless test
Browse files Browse the repository at this point in the history
  • Loading branch information
TateB committed Feb 8, 2024
1 parent 2d372ae commit 682777b
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 57 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ NETWORK=mainnet
ARCHIVE_URL=https://storage.googleapis.com/ens-manager-build-data

TRANSACTION_WAIT_TIME=5000
STABLE_MODE=500
STABLE_MODE=500
BATCH_GATEWAY_URLS='["https://ccip-v2.ens.xyz/"]'
Binary file modified archive.tar.lz4
Binary file not shown.
129 changes: 129 additions & 0 deletions e2e/specs/stateless/importName.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { expect } from '@playwright/test'

import { test } from '../../../playwright'

test('should allow claim (owned by user)', async ({ page, login, accounts, makePageObject }) => {
const name = 'swagabc.xyz'

const homePage = makePageObject('HomePage')
const importPage = makePageObject('ImportPage')
const transactionModal = makePageObject('TransactionModal')

await homePage.goto()
await login.connect()

// should redirect to registration page
await homePage.searchInput.fill(name)
await homePage.searchInput.press('Enter')
await expect(importPage.heading).toHaveText(`Claim ${name}`)

// no type should be checked yet
await expect(importPage.offchainRadio).not.toBeChecked()
await expect(importPage.onchainRadio).not.toBeChecked()
await expect(importPage.nextButton).toBeDisabled()

await importPage.onchainRadio.click()

// option selection should enable next
await expect(importPage.nextButton).toBeEnabled({ timeout: 15000 })
await importPage.nextButton.click()

// should jump straight to transaction step
await expect(importPage.heading).toHaveText('Claim your domain')

// should show cost value above 0
await expect(importPage.getCost()).resolves.toBeGreaterThan(0)

await expect(importPage.nextButton).toHaveText('Claim')
await expect(importPage.nextButton).toBeEnabled({ timeout: 15000 })

await importPage.nextButton.click()

// should be two steps: approve and claim
await expect(transactionModal.getStepCount()).resolves.toEqual(2)

await transactionModal.confirm()
await transactionModal.complete()

// should save transaction status on refresh
await page.reload()
await expect(importPage.heading).toHaveText('Claim your domain')
await expect(importPage.nextButton).toBeEnabled({ timeout: 15000 })

// should allow finalising
await importPage.nextButton.click()

// transaction modal should still have 2 steps
await expect(transactionModal.getStepCount()).resolves.toEqual(2)

await expect(page.getByText('Open Wallet')).toBeVisible()
await transactionModal.confirm()

// should show complete step
await expect(page.getByText('Congratulations!')).toBeVisible()
await expect(page.getByText(`You are now the owner of ${name}`)).toBeVisible()

await page.getByTestId('view-name').click()
await expect(page.getByTestId('address-profile-button-eth')).toHaveText(
accounts.getAddress('user', 5),
)
})

test('should allow import (not owned by user)', async ({ page, login, makePageObject }) => {
const name = 'taytems.xyz'

const homePage = makePageObject('HomePage')
const importPage = makePageObject('ImportPage')
const transactionModal = makePageObject('TransactionModal')

await homePage.goto()
await login.connect()

// should redirect to registration page
await homePage.searchInput.fill(name)
await homePage.searchInput.press('Enter')
await expect(importPage.heading).toHaveText(`Claim ${name}`)

// no type should be checked yet
await expect(importPage.offchainRadio).not.toBeChecked()
await expect(importPage.onchainRadio).not.toBeChecked()
await expect(importPage.nextButton).toBeDisabled()

await importPage.onchainRadio.click()

// option selection should enable next
await expect(importPage.nextButton).toBeEnabled({ timeout: 15000 })
await importPage.nextButton.click()

// should show verify ownership step with error message
await expect(importPage.heading).toHaveText('Verify Ownership')
await expect(
page.getByText(
'The record found does not match your connected address. You can still import this name, but you will not have ownership of it.',
),
).toBeVisible()
await expect(importPage.nextButton).toHaveText('Import without ownership')
await expect(importPage.nextButton).toHaveCSS('background-color', 'rgb(197, 47, 27)')

await importPage.nextButton.click()

// should go to transaction step
await expect(importPage.heading).toHaveText('Import this domain')

// should show cost value above 0
await expect(importPage.getCost()).resolves.toBeGreaterThan(0)

await expect(importPage.nextButton).toHaveText('Import')
await expect(importPage.nextButton).toBeEnabled({ timeout: 15000 })

await importPage.nextButton.click()

await transactionModal.attemptStep()

// should show complete step
await expect(page.getByText('Congratulations!')).toBeVisible()
await expect(page.getByText(`${name} has been imported`)).toBeVisible()

await page.getByTestId('view-name').click()
await page.waitForURL(`/${name}`)
})
8 changes: 4 additions & 4 deletions ens-test-env.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ require('dotenv').config({

process.env.ADDRESS_ETH_REGISTRAR = '0xc5a5C42992dECbae36851359345FE25997F5C42d'
process.env.ADDRESS_NAME_WRAPPER = '0x9E545E3C0baAB3E08CdfD552C960A1050f373042'
process.env.BATCH_GATEWAY_URLS = JSON.stringify([
'https://universal-offchain-unwrapper.ens-cf.workers.dev/',
])
process.env.BATCH_GATEWAY_URLS = JSON.stringify(['https://ccip-v2.ens.xyz/'])

/**
* @type {import('@ensdomains/ens-test-env').ENSTestEnvConfig}
Expand All @@ -28,7 +26,9 @@ module.exports = {
},
{
command: `pnpm wait-on http://127.0.0.1:8788 && ${
process.env.CI ? `npx playwright test --project=stateless --shard=${process.env.PLAYWRIGHT_SHARD}/${process.env.PLAYWRIGHT_TOTAL}` : 'npx playwright'
process.env.CI
? `npx playwright test --project=stateless --shard=${process.env.PLAYWRIGHT_SHARD}/${process.env.PLAYWRIGHT_TOTAL}`
: 'npx playwright'
}`,
name: 'playwright',
prefixColor: 'yellow.bold',
Expand Down
4 changes: 3 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import '@nomiclabs/hardhat-ethers'
import 'dotenv/config'
import 'hardhat-deploy'
import { HardhatUserConfig } from 'hardhat/config'

import { resolve } from 'path'

import { HardhatUserConfig } from 'hardhat/config'

const ensContractsPath = './node_modules/@ensdomains/ens-contracts'

console.log(resolve(ensContractsPath, 'artifacts'))
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"dependencies": {
"@ensdomains/address-encoder": "^1.0.0-rc.3",
"@ensdomains/content-hash": "^3.0.0-beta.5",
"@ensdomains/ens-contracts": "1.0.0",
"@ensdomains/ens-contracts": "1.2.0-beta.0",
"@ensdomains/ensjs": "3.4.2",
"@ensdomains/thorin": "0.6.44",
"@metamask/inpage-provider": "^8.1.0",
Expand Down Expand Up @@ -104,7 +104,7 @@
"@adraffy/ens-normalize": "^1.9.4",
"@cloudflare/workers-types": "^3.14.1",
"@ensdomains/buffer": "^0.1.0",
"@ensdomains/ens-test-env": "^0.3.9",
"@ensdomains/ens-test-env": "^0.4.0-beta.0",
"@ethersproject/abi": "^5.4.0",
"@ethersproject/contracts": "^5.4.0",
"@ianvs/prettier-plugin-sort-imports": "^4.1.0",
Expand Down
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
timeout: 120000, // add extra time for loading
fullyParallel: true, // required to evenly shard
workers: 1, // keep tests serial for now
reporter: [['html', { open: 'never' }]],
reporter: [['html', { open: 'always' }]],
projects: [
{
name: 'stateless',
Expand Down
32 changes: 32 additions & 0 deletions playwright/pageObjects/importPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable import/no-extraneous-dependencies */
import { expect, Locator, Page } from '@playwright/test'

export class ImportPage {
readonly page: Page

readonly nextButton: Locator

readonly onchainRadio: Locator

readonly offchainRadio: Locator

readonly heading: Locator

readonly cost: Locator

constructor(page: Page) {
this.page = page
this.nextButton = this.page.getByTestId('import-next-button')
this.onchainRadio = this.page.getByTestId('onchain-radio')
this.offchainRadio = this.page.getByTestId('offchain-radio')
this.heading = this.page.getByTestId('import-heading')
this.cost = this.page.getByTestId('import-cost')
}

async getCost() {
await expect(this.cost).not.toBeEmpty()
await expect(this.cost).not.toHaveText('0.0000 ETH')
const text = (await this.cost.textContent()) as string
return parseFloat(text)
}
}
2 changes: 2 additions & 0 deletions playwright/pageObjects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AdvancedEditorModal } from './advancedEditorModal'
import { EditRolesModal } from './editRolesModal'
import { ExtendNamesModal } from './extendNamesModal'
import { HomePage } from './homePage'
import { ImportPage } from './importPage'
import { MorePage } from './morePage'
import { OwnershipPage } from './ownershipPage'
import { PermissionsPage } from './permissionsPage'
Expand All @@ -24,6 +25,7 @@ const pageObjects = {
EditRolesModal,
ExtendNamesModal,
HomePage,
ImportPage,
MorePage,
OwnershipPage,
PermissionsPage,
Expand Down
26 changes: 21 additions & 5 deletions playwright/pageObjects/transactionModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class TransactionModal {

readonly backButton: Locator

readonly stepContainer: Locator

constructor(page: Page, wallet: Web3ProviderBackend) {
this.page = page
this.wallet = wallet
Expand All @@ -28,6 +30,7 @@ export class TransactionModal {
this.closeButton = this.page.getByTestId('close-icon')
this.transactionModal = this.page.getByTestId('transaction-modal-inner')
this.backButton = this.page.locator('body .modal').getByRole('button', { name: 'Back' })
this.stepContainer = this.page.getByTestId('step-container')
}

async authorize() {
Expand All @@ -43,15 +46,28 @@ export class TransactionModal {
await this.completeButton.click()
}

async getStepCount() {
const steps = await this.stepContainer
.locator('div')
.count()
// no step container means only 1 step is present, assuming the transaction modal is open and visible
.catch(() => 1)
return steps
}

async attemptStep() {
if (await this.introButton.isVisible()) await this.introButton.click()
if (await this.confirmButton.isVisible()) await this.confirm()
if (await this.completeButton.isVisible()) await this.complete()
await this.page.waitForTimeout(500)
}

async autoComplete() {
/* eslint-disable no-await-in-loop */

let isModalVisible = true
do {
if (await this.introButton.isVisible()) await this.introButton.click()
if (await this.confirmButton.isVisible()) await this.confirm()
if (await this.completeButton.isVisible()) await this.complete()
await this.page.waitForTimeout(500)
await this.attemptStep()
isModalVisible = await this.transactionModal.isVisible()
} while (isModalVisible)
/* eslint-enable no-await-in-loop */
Expand All @@ -60,4 +76,4 @@ export class TransactionModal {
displayItem(key: string, option = 'normal') {
return this.page.getByTestId(`display-item-${key}-${option}`).locator('> div').last()
}
}
}
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"migrate": "Migrate",
"setToSelf": "Set to self",
"editRoles": "Edit roles",
"setReminder": "Set reminder"
"setReminder": "Set reminder",
"import": "Import"
},
"unit": {
"years_one": "{{count}} year",
Expand Down Expand Up @@ -196,7 +197,9 @@
"createSubname": "Create subname",
"deleteSubname": "Delete subname",
"extendNames": "Extend names",
"importDNSSECName": "import DNSSEC name",
"approveDnsRegistrar": "Approve DNS registrar",
"claimDnsName": "Claim DNS name",
"importDnsName": "Import DNS name",
"commitName": "Start timer",
"registerName": "Register name",
"approveNameWrapper": "Approve NameWrapper",
Expand Down
Loading

0 comments on commit 682777b

Please sign in to comment.