From 7a963fab7c0f83f9fe5ec17f28292d0b0c74198e Mon Sep 17 00:00:00 2001 From: blech Date: Mon, 29 Apr 2024 16:30:30 +0200 Subject: [PATCH] issuer node automation --- ui/.gitignore | 4 ++ ui/package.json | 4 ++ ui/playwright.config.ts | 78 +++++++++++++++++++++++++++++++++++++++ ui/tests/example.spec.ts | 80 ++++++++++++++++++++++++++++++++++++++++ ui/tests/fixtures.ts | 80 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 246 insertions(+) create mode 100644 ui/playwright.config.ts create mode 100644 ui/tests/example.spec.ts create mode 100644 ui/tests/fixtures.ts diff --git a/ui/.gitignore b/ui/.gitignore index 6de792c7e..18e65bdba 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -20,3 +20,7 @@ # package managers npm-debug.log* +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/ui/package.json b/ui/package.json index e090d3d58..204056605 100644 --- a/ui/package.json +++ b/ui/package.json @@ -21,12 +21,16 @@ }, "devDependencies": { "@iden3/eslint-config-react-ts": "^2.0.0", + "@playwright/test": "^1.41.0", + "@synthetixio/synpress": "^3.7.2-beta.9", + "@types/dotenv": "^8.2.0", "@types/node": "^20.9.0", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@types/react-syntax-highlighter": "^15.5.10", "@types/validator": "^13.11.6", "@vitejs/plugin-react": "^4.1.1", + "dotenv": "^16.3.1", "eslint": "^8.53.0", "husky": "^8.0.3", "lint-staged": "^15.0.2", diff --git a/ui/playwright.config.ts b/ui/playwright.config.ts new file mode 100644 index 000000000..af771db2b --- /dev/null +++ b/ui/playwright.config.ts @@ -0,0 +1,78 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * 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: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* 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' }, + // }, + ], + timeout: 60000, + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/ui/tests/example.spec.ts b/ui/tests/example.spec.ts new file mode 100644 index 000000000..eb54f607d --- /dev/null +++ b/ui/tests/example.spec.ts @@ -0,0 +1,80 @@ +import * as dotenv from 'dotenv'; +import { test, expect } from './fixtures'; +import * as metamask from "@synthetixio/synpress/commands/metamask"; +import { formatDate } from '../src/utils/forms' + + +test.beforeEach(async ({ page }) => { + // baseUrl is set in playwright.config.ts + await page.goto("https://schema-builder-dev.polygonid.me"); +}); + +test('Import schema to issuer node', async ({ page }) => { + var currentDate = formatDate(new Date(), 'date-time'); + await page.goto('https://schema-builder-dev.polygonid.me'); + await page.bringToFront(); + await page.getByRole('menuitem', { name: 'Schema Builder' }).click(); + await page.getByRole('button', { name: 'Accept' }).click(); + await page.getByText("Connect wallet").click(); + await metamask.acceptAccess({signInSignature: true}); + await page.getByPlaceholder('Enter a title').fill(`TestTitle ${currentDate}`); + await page.getByPlaceholder('Enter type').fill(`TestSchemaType`); + await page.locator('#version').fill(`Version ${currentDate}`); + await page.getByLabel('Description').fill('Description'); + await page.getByRole('button', { name: 'Define attributes' }).click(); + await page.getByRole('button', { name: 'Add' }).click(); + await page.getByPlaceholder('Enter name').fill('String'); + await page.getByPlaceholder('Enter title').fill('String'); + await page.getByLabel('Description').fill('Desc'); + await page.getByText('credentialSubject', { exact: true }).click(); + await page.getByRole('button', { name: 'Add' }).click(); + await page.getByPlaceholder('Enter name').fill('Int'); + await page.getByPlaceholder('Enter title').fill('Int'); + await page.locator('.ant-select-selection-item').last().click(); + await page.getByTitle('integer').locator('div').click(); + await page.getByLabel('Description').fill('Desc'); + await page.getByText('credentialSubject', { exact: true }).click(); + await page.getByRole('button', { name: 'Add' }).click(); + await page.getByPlaceholder('Enter name').fill('Numb'); + await page.getByPlaceholder('Enter title').fill('Numb'); + await page.locator('.ant-select-selection-item').last().click(); + await page.getByTitle('number').locator('div').click(); + await page.getByLabel('Description').fill('Desc'); + await page.getByText('credentialSubject', { exact: true }).click(); + await page.getByRole('button', { name: 'Add' }).click(); + await page.getByPlaceholder('Enter name').fill('Bool'); + await page.getByPlaceholder('Enter title').fill('Bool'); + await page.locator('.ant-select-selection-item').last().click(); + await page.getByTitle('boolean').locator('div').click(); + await page.getByLabel('Description').fill('Desc'); + await page.getByRole('button', { name: 'Publish on IPFS' }).click(); + await page.locator('.ant-modal-body .ant-form-item-control-input').click(); + await page.getByText('Age').click(); + await page.getByRole('button', { name: 'Publish on IPFS' }).last().click(); + await expect(page.locator('h2.ant-typography').first()).toHaveText(`TestTitle ${currentDate}`); + var jsonLd = await page.locator('a').nth(4).getAttribute('href'); + var json = await page.locator('a').nth(3).getAttribute('href'); + + dotenv.config({path: "../.env-ui"}); + await page.goto(`https://${process.env.ISSUER_UI_AUTH_USERNAME}:${process.env.ISSUER_UI_AUTH_PASSWORD}@issuer-ui-testing-testnet.polygonid.me/`); + + await page.getByRole('button', { name: 'Import schema' }).click(); + if (json != null) { + await page.getByPlaceholder('Enter URL').fill(json); + } else { + expect(true).toBeFalsy(); + } + await page.getByRole('button', { name: 'Fetch' }).click(); + await expect(page.locator("anticon-spin")).toHaveCount(0, {timeout: 300000}); + await page.getByRole('button', { name: 'Preview import' }).click(); + await page.getByRole('button', { name: 'Import' }).click(); + await expect(page.getByText(`Version ${currentDate}`, { exact: true })).toBeVisible(); + await page.locator('a').nth(6).click(); + await page.locator('.ant-radio').nth(1).click(); + await page.getByRole('button', { name: 'Next step' }).click(); + await page.getByPlaceholder('Type string').fill('String'); + await page.getByPlaceholder('Type integer').fill('2'); + await page.getByPlaceholder('Type number').fill('4'); + await page.getByRole('button', { name: 'Create credential link' }).click(); + console.log("STOP") +}); \ No newline at end of file diff --git a/ui/tests/fixtures.ts b/ui/tests/fixtures.ts new file mode 100644 index 000000000..bd37dea8a --- /dev/null +++ b/ui/tests/fixtures.ts @@ -0,0 +1,80 @@ +import { test as base, chromium, type BrowserContext } from "@playwright/test"; +import { initialSetup } from "@synthetixio/synpress/commands/metamask"; +import { setExpectInstance } from "@synthetixio/synpress/commands/playwright"; +import { resetState } from "@synthetixio/synpress/commands/synpress"; +import { prepareMetamask } from "@synthetixio/synpress/helpers"; +import dotenv from 'dotenv'; +import path from 'path'; + +export const test = base.extend<{ + context: BrowserContext; +}>({ + context: async ({}, use) => { + dotenv.config({path: path.resolve("../.env-ui")}); + // required for synpress as it shares same expect instance as playwright + await setExpectInstance(expect); + + // download metamask + const metamaskPath = await prepareMetamask( + process.env.METAMASK_VERSION || "10.25.0" + ); + + // prepare browser args + const browserArgs = [ + `--disable-extensions-except=${metamaskPath}`, + `--load-extension=${metamaskPath}`, + "--remote-debugging-port=9222", + ]; + + if (process.env.CI) { + browserArgs.push("--disable-gpu"); + } + + if (process.env.HEADLESS_MODE) { + browserArgs.push("--headless=new"); + } + + // launch browser + const context = await chromium.launchPersistentContext("", { + headless: false, + args: browserArgs, + }); + + // wait for metamask + await context.pages()[0].waitForTimeout(3000); + + // setup metamask + await initialSetup(chromium, { + enableExperimentalSettings: true, + secretWordsOrPrivateKey: + "fill", + network: { + id: 80002, + network: "Polygon", + name: "Amoy Testnet", + nativeCurrency: { name: 'Matic', symbol: 'MATIC', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://rpc-amoy.polygon.technology/'], + } + }, + blockExplorers: { + etherscan: { + name: 'Amoy', + url: 'https://www.oklink.com/amoy', + }, + } + }, + password: "Tester@1234", + enableAdvancedSettings: true, + }); + + await use(context); + + await context.close(); + + await resetState(); + }, +}); + +export const expect = test.expect; \ No newline at end of file