From 2f6b1a6036d0078329fdb4f3a43a55d8052bc011 Mon Sep 17 00:00:00 2001 From: Stephen Kilbourn Date: Thu, 29 Feb 2024 13:08:32 -0700 Subject: [PATCH] Revert "move tests into ui submodule" This reverts commit 258e7fcba7004d6852a4763b5c6eef34f8a4ff4e. --- e2e/README.md | 19 +- e2e/generateTestData.js | 10 +- e2e/pages/aboutPage.ts | 11 ++ e2e/pages/analysisPage.ts | 55 ++++++ e2e/pages/analysisResultsPage.ts | 13 ++ e2e/pages/basePage.ts | 52 +++++ e2e/pages/catalogPage.ts | 14 ++ e2e/pages/datasetPage.ts | 18 ++ e2e/pages/footerComponent.ts | 13 ++ e2e/pages/headerComponent.ts | 23 +++ e2e/pages/homePage.ts | 14 ++ e2e/pages/storyPage.ts | 14 ++ e2e/tests/analysis.spec.ts | 44 +++++ e2e/tests/catalog.spec.ts | 27 +++ e2e/tests/catalogRouting.spec.ts | 35 ++++ e2e/tests/stories.spec.ts | 30 +++ e2e/tests/storiesRouting.spec.ts | 30 +++ package.json | 7 +- playwright.config.ts | 58 ++++++ yarn.lock | 326 +++---------------------------- 20 files changed, 500 insertions(+), 313 deletions(-) create mode 100644 e2e/pages/aboutPage.ts create mode 100644 e2e/pages/analysisPage.ts create mode 100644 e2e/pages/analysisResultsPage.ts create mode 100644 e2e/pages/basePage.ts create mode 100644 e2e/pages/catalogPage.ts create mode 100644 e2e/pages/datasetPage.ts create mode 100644 e2e/pages/footerComponent.ts create mode 100644 e2e/pages/headerComponent.ts create mode 100644 e2e/pages/homePage.ts create mode 100644 e2e/pages/storyPage.ts create mode 100644 e2e/tests/analysis.spec.ts create mode 100644 e2e/tests/catalog.spec.ts create mode 100644 e2e/tests/catalogRouting.spec.ts create mode 100644 e2e/tests/stories.spec.ts create mode 100644 e2e/tests/storiesRouting.spec.ts create mode 100644 playwright.config.ts diff --git a/e2e/README.md b/e2e/README.md index 85ca19755..075171b81 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,6 +1,6 @@ # Playwright E2E Testing -The veda-config can be tested end-to-end to by leveraging a suite of Playwright tests located in the veda-ui git submodule. It works by serving a local version of the site using yarn serve and performing UI checks against that locally hosted site. The suite is designed to generate a `playwrightTestData.json` that contains the list of all Catalog and Story names. This is done by parsing the `name` field in the `*.mdx` files of the `/datasets` and `/stories` directories of the config repo. +This testing suite is for End to End testing the VEDA website via the UI using Playwright. It works by serving a local version of the site using yarn serve and performing UI checks against that locally hosted site. The suite is designed to generate a `playwrightTestData.json` that contains the list of all Catalog and Story names. This is done by parsing the `name` field in the `*.mdx` files of the `/datasets` and `/stories` directories. ## Running the test suite @@ -11,12 +11,25 @@ The test suite can be run via the `yarn test:e2e` script. There is a `prtest:e2e The end to end tests are organized in the `/e2e` directory. The tests have been written following a [Page Object Model](https://martinfowler.com/bliki/PageObject.html) pattern. Supporting files within the repo are in the following structure: +```text +/e2e + │ + │─── README.md + │─── playwright.config.ts - imports our global setup, defines preferred browsers, & number of retries + │─── generateTestData.js - parses mdx files and creates a json based on their metadata + └─── /pages + │ └─── basePage.ts - imports all seeded data and PageObjects into our `test` object. + │ │ + │ └─── [PAGENAME]Page.ts - The page objects. UI elements interacted with on a page are defined once to keep tests DRY and minimize test changes if layout changes. + └─── tests - our actual tests +``` + ## Updating Tests -If the layout of a page changes, then the tests may no longer be able to interact with locators. These locators are defined in the Page Objects defined in `/e2e/pages`. The Playwright framework provides multiple ways to choose elements to interact with. The recommended ones are defined in the [Playwright documentation](https://playwright.dev/docs/locators#quick-guide). +If the layout of a page changes, then the tests may no longer be able to interact with locators. These locators are defined in the Page Objects defined in `/e2e/pages`. The Playwright framework provides multiple ways to choose elements to interact with. The recomended ones are defined in the [Playwright documentation](https://playwright.dev/docs/locators#quick-guide). Any new pages will need to have new page objects created and then imported into the `basePage.ts` file following th format of existing pages. This allows all tests to reference the page. ## Output -Playwright will generate an html report with test results. This report will show all tests that were run, and will allow a user to view the results of any failed tests. This report can be viewed with the script `yarn report` from the config repo. +Playwright will generate an html report with test results. This report will show all tests that were run, and will allow a user to view the results of any failed tests. diff --git a/e2e/generateTestData.js b/e2e/generateTestData.js index 1b0477117..89c83ca9a 100644 --- a/e2e/generateTestData.js +++ b/e2e/generateTestData.js @@ -6,14 +6,11 @@ const fg = require('fast-glob'); const catalogPaths = fg.globSync('**/datasets/*.mdx'); const storyPaths = fg.globSync('**/stories/*.mdx'); const catalogNames = []; -const datasetIds = []; const storyNames = []; for (const catalog of catalogPaths) { const catalogData = matter.read(catalog).data; catalogNames.push(catalogData['name']); - datasetIds.push(catalogData['id']); - } for (const story of storyPaths) { @@ -22,12 +19,11 @@ for (const story of storyPaths) { } const testDataJson = { - catalogs: catalogNames, - datasetIds: datasetIds, - stories: storyNames + "catalogs": catalogNames, + "stories": storyNames } -fs.writeFile(path.join(__dirname, '../.veda/ui/e2e/playwrightTestData.json'), JSON.stringify(testDataJson), err => { +fs.writeFile(path.join(__dirname, 'playwrightTestData.json'), JSON.stringify(testDataJson), err => { if (err) { console.error(err); } else { diff --git a/e2e/pages/aboutPage.ts b/e2e/pages/aboutPage.ts new file mode 100644 index 000000000..a9e84eac3 --- /dev/null +++ b/e2e/pages/aboutPage.ts @@ -0,0 +1,11 @@ +import { Locator, Page } from '@playwright/test'; + +export default class AboutPage { + readonly page: Page; + readonly mainContent: Locator; + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + } +} \ No newline at end of file diff --git a/e2e/pages/analysisPage.ts b/e2e/pages/analysisPage.ts new file mode 100644 index 000000000..36f267a1e --- /dev/null +++ b/e2e/pages/analysisPage.ts @@ -0,0 +1,55 @@ +import { Locator, Page, test } from '@playwright/test'; + +export default class AnalysisPage { + readonly page: Page; + readonly mainContent: Locator; + readonly header: Locator; + readonly mapboxCanvas: Locator; + readonly generateAnalysisButton: Locator; + readonly datasetOptions: Locator; + readonly datasetCheckbox: Locator; + + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + this.header = this.mainContent.getByRole('heading', {level: 1, name: /analysis/i }); + this.mapboxCanvas = this.page.getByLabel('Map', { exact: true }); + this.generateAnalysisButton = this.page.getByRole('link', { name: /Generate analysis/i }); + this.datasetOptions = this.page.getByTestId('datasetOptions'); + this.datasetCheckbox = this.datasetOptions.getByRole('checkbox'); + } + + async drawPolygon (polygonCorners: number[][]) { + await test.step('draw polygon on mapbox canvas box', async () => { + if(polygonCorners.length < 3) { + throw new Error('polygon in drawPolygon must have >=3 corners') + } + // mutating corners array to have all but the final corner + const finalCorner = polygonCorners.pop()|| []; + + // single click each remaining corner + for (const corner of polygonCorners) { + await this.mapboxCanvas.click({ + position: { + x: corner[0], + y: corner[1] + } + }); + } + // double click on final corner + await this.mapboxCanvas.dblclick({ + position: { + x: finalCorner[0], + y: finalCorner[1] + } + }); + }) + } + + async clickDatasetOption (index: number) { + test.step(`clicking dataset number ${index}`, async () => { + this.datasetCheckbox.nth(index).locator('..').click(); + }) + } +} \ No newline at end of file diff --git a/e2e/pages/analysisResultsPage.ts b/e2e/pages/analysisResultsPage.ts new file mode 100644 index 000000000..b018735d7 --- /dev/null +++ b/e2e/pages/analysisResultsPage.ts @@ -0,0 +1,13 @@ +import { Locator, Page } from '@playwright/test'; + +export default class AnalysisResultsPage { + readonly page: Page; + readonly analysisCards: Locator; + + + constructor(page: Page) { + this.page = page; + this.analysisCards = this.page.getByTestId('analysisCards'); + } + +} \ No newline at end of file diff --git a/e2e/pages/basePage.ts b/e2e/pages/basePage.ts new file mode 100644 index 000000000..b2dde30a1 --- /dev/null +++ b/e2e/pages/basePage.ts @@ -0,0 +1,52 @@ +import { test as base } from '@playwright/test'; +import AboutPage from './aboutPage'; +import AnalysisPage from './analysisPage'; +import AnalysisResultsPage from './analysisResultsPage'; +import HomePage from './homePage'; +import FooterComponent from './footerComponent'; +import HeaderComponent from './headerComponent'; +import CatalogPage from './catalogPage'; +import DatasetPage from './datasetPage'; +import StoryPage from './storyPage'; + +export const test = base.extend<{ + aboutPage: AboutPage; + analysisPage: AnalysisPage; + analysisResultsPage: AnalysisResultsPage; + footerComponent: FooterComponent; + headerComponent: HeaderComponent; + homePage: HomePage; + catalogPage: CatalogPage; + datasetPage: DatasetPage; + storyPage: StoryPage +}> ({ + aboutPage: async ({page}, use) => { + await use(new AboutPage(page)); + }, + analysisPage: async ({page}, use) => { + await use(new AnalysisPage(page)); + }, + analysisResultsPage: async ({page}, use) => { + await use(new AnalysisResultsPage(page)); + }, + catalogPage: async ({page}, use) => { + await use(new CatalogPage(page)); + }, + datasetPage: async ({page}, use) => { + await use(new DatasetPage(page)); + }, + homePage: async ({page}, use) => { + await use(new HomePage(page)); + }, + storyPage: async ({page}, use) => { + await use(new StoryPage(page)); + }, + headerComponent: async ({page}, use) => { + await use(new HeaderComponent(page)); + }, + footerComponent: async ({page}, use) => { + await use(new FooterComponent(page)); + }, +}); + +export const expect = test.expect; \ No newline at end of file diff --git a/e2e/pages/catalogPage.ts b/e2e/pages/catalogPage.ts new file mode 100644 index 000000000..64025f5df --- /dev/null +++ b/e2e/pages/catalogPage.ts @@ -0,0 +1,14 @@ +import { Locator, Page } from '@playwright/test'; + +export default class CatalogPage { + readonly page: Page; + readonly mainContent: Locator; + readonly header: Locator; + + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + this.header = this.mainContent.getByRole('heading', {level: 1}) + } +} \ No newline at end of file diff --git a/e2e/pages/datasetPage.ts b/e2e/pages/datasetPage.ts new file mode 100644 index 000000000..75386bca9 --- /dev/null +++ b/e2e/pages/datasetPage.ts @@ -0,0 +1,18 @@ +import { Locator, Page } from '@playwright/test'; + +export default class DatasetPage { + readonly page: Page; + readonly mainContent: Locator; + readonly header: Locator; + readonly exploreDataButton: Locator; + readonly analyzeDataButton: Locator; + + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + this.header = this.mainContent.getByRole('heading', { level: 1 }) + this.exploreDataButton = this.page.getByRole('link', {name: /explore data/i} ); + this.analyzeDataButton = this.page.getByRole('button', {name: /analyze data/i} ); + } +} \ No newline at end of file diff --git a/e2e/pages/footerComponent.ts b/e2e/pages/footerComponent.ts new file mode 100644 index 000000000..90d5bdf8d --- /dev/null +++ b/e2e/pages/footerComponent.ts @@ -0,0 +1,13 @@ +import { Locator, Page } from '@playwright/test'; + +export default class FooterComponent { + readonly page: Page; + readonly footer: Locator; + readonly partners: Locator; + + constructor(page: Page) { + this.page = page; + this.footer = this.page.locator('footer'); + this.partners = this.footer.locator('div'); + } +} \ No newline at end of file diff --git a/e2e/pages/headerComponent.ts b/e2e/pages/headerComponent.ts new file mode 100644 index 000000000..96808702a --- /dev/null +++ b/e2e/pages/headerComponent.ts @@ -0,0 +1,23 @@ +import { Locator, Page } from '@playwright/test'; + +export default class HeaderComponent { + readonly page: Page; + readonly header: Locator; + readonly welcomeLink: Locator; + readonly dataCatalogLink: Locator; + readonly analysisLink: Locator; + readonly dataInsightsLink: Locator; + readonly aboutLink: Locator; + readonly feedbackLink: Locator; + + constructor(page: Page) { + this.page = page; + this.header = this.page.getByRole('navigation'); + this.welcomeLink = this.header.getByRole('link', {name: /welcome/i}); + this.dataCatalogLink = this.header.getByRole('link', {name: / data catalog/i}); + this.analysisLink = this.header.getByRole('link', {name: /analysis/i}); + this.dataInsightsLink = this.header.getByRole('link', {name: /data insights/i}); + this.aboutLink = this.header.getByRole('link', {name: /about/i}); + this.feedbackLink = this.header.getByRole('link', {name: /feedback/i}); + } +} \ No newline at end of file diff --git a/e2e/pages/homePage.ts b/e2e/pages/homePage.ts new file mode 100644 index 000000000..5fa13895e --- /dev/null +++ b/e2e/pages/homePage.ts @@ -0,0 +1,14 @@ +import { Locator, Page } from '@playwright/test'; + +export default class HomePage { + readonly page: Page; + readonly mainContent: Locator; + readonly headingContainer: Locator; + + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + this.headingContainer = this.mainContent.locator('div').filter({ hasText: 'U.S. Greenhouse Gas CenterUniting Data and Technology to Empower Tomorrow\'s' }).nth(2) + } +} \ No newline at end of file diff --git a/e2e/pages/storyPage.ts b/e2e/pages/storyPage.ts new file mode 100644 index 000000000..358b2caa2 --- /dev/null +++ b/e2e/pages/storyPage.ts @@ -0,0 +1,14 @@ +import { Locator, Page } from '@playwright/test'; + +export default class StoryPage { + readonly page: Page; + readonly mainContent: Locator; + readonly header: Locator; + + + constructor(page: Page) { + this.page = page; + this.mainContent = this.page.getByRole('main'); + this.header = this.mainContent.getByRole('heading', {level: 1}) + } +} \ No newline at end of file diff --git a/e2e/tests/analysis.spec.ts b/e2e/tests/analysis.spec.ts new file mode 100644 index 000000000..988c646fe --- /dev/null +++ b/e2e/tests/analysis.spec.ts @@ -0,0 +1,44 @@ +import { test, expect } from '../pages/basePage'; + +test('load /analysis route', async ({ + page, + analysisPage, + analysisResultsPage, + }) => { + let pageErrorCalled = false; + // Log all uncaught errors to the terminal + page.on('pageerror', exception => { + console.log(`Uncaught exception: "${exception}"`); + pageErrorCalled = true; + }); + + const mapboxResponsePromise = page.waitForResponse(/api\.mapbox.com\/v4\/mapbox\.mapbox-streets-v8/i); + await page.goto('/analysis'); + await expect(analysisPage.header, `analysis page should load`).toBeVisible(); + const mapboxResponse = await mapboxResponsePromise; + expect(mapboxResponse.ok(), 'mapbox request should be successful').toBeTruthy(); + await expect(analysisPage.mapboxCanvas, 'mapbox canvas should be visible').toBeVisible(); + + const box = await analysisPage.mapboxCanvas.boundingBox(); + + // using Non-null Assertion because we know the mapbox is visible, therefore box is not null + const firstCorner = [box!.width / 4, box!.height / 4]; + const secondCorner = [box!.width / 3, box!.height / 4]; + const thirdCorner = [box!.width / 4, box!.height / 3]; + + await analysisPage.mapboxCanvas.click(); + + await analysisPage.drawPolygon([firstCorner, secondCorner, thirdCorner]) + + await analysisPage.clickDatasetOption(1); + + const searchResponsePromise = page.waitForResponse(/\/search/i); + await analysisPage.generateAnalysisButton.click({force: true }); + + + const searchResponse = await searchResponsePromise; + expect(searchResponse.ok(), 'request to GET /search should be successful').toBeTruthy(); + + await expect(analysisResultsPage.analysisCards.first(), 'at least one analysis results is visible' ).toBeVisible(); + +}); \ No newline at end of file diff --git a/e2e/tests/catalog.spec.ts b/e2e/tests/catalog.spec.ts new file mode 100644 index 000000000..c9e7c4b33 --- /dev/null +++ b/e2e/tests/catalog.spec.ts @@ -0,0 +1,27 @@ +import { test, expect } from '../pages/basePage'; + +const catalogs = JSON.parse(require('fs').readFileSync('e2e/playwrightTestData.json', 'utf8'))['catalogs']; + +test('load catalogs on /data-catalog route', async ({ + page, + catalogPage, + }) => { + let pageErrorCalled = false; + // Log all uncaught errors to the terminal + page.on('pageerror', exception => { + console.log(`Uncaught exception: "${exception}"`); + pageErrorCalled = true; + }); + + await page.goto('/data-catalog'); + await expect(catalogPage.header, `catalog page should load`).toHaveText(/data catalog/i); + + for (const item of catalogs) { + const catalogCard = catalogPage.mainContent.getByRole('article').getByRole('heading', { level: 3, name: item, exact: true}).last(); + await catalogCard.scrollIntoViewIfNeeded(); + await expect(catalogCard, `${item} catalog card should load`).toBeVisible(); + }; + + expect(pageErrorCalled, 'no javascript exceptions thrown on page').toBe(false) + +}); \ No newline at end of file diff --git a/e2e/tests/catalogRouting.spec.ts b/e2e/tests/catalogRouting.spec.ts new file mode 100644 index 000000000..8161311d5 --- /dev/null +++ b/e2e/tests/catalogRouting.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from '../pages/basePage'; + +const catalogs = JSON.parse(require('fs').readFileSync('e2e/playwrightTestData.json', 'utf8'))['catalogs']; + +test.describe('catalog card routing', () => { + for (const item of catalogs) { + test(`${item} routes to dataset details page`, async({ + page, + catalogPage, + datasetPage, + }) => { + let pageErrorCalled = false; + // Log all uncaught errors to the terminal + page.on('pageerror', exception => { + console.log(`Uncaught exception: "${exception}"`); + pageErrorCalled = true; + }); + + await page.goto('/data-catalog'); + await expect(catalogPage.header, `catalog page should load`).toHaveText(/data catalog/i); + + const catalogCard = catalogPage.mainContent.getByRole('article').getByRole('heading', { level: 3, name: item, exact: true}).first(); + await catalogCard.scrollIntoViewIfNeeded(); + await catalogCard.click({force: true}); + + await expect(datasetPage.header.filter({ hasText: item}), `${item} page should load`).toBeVisible(); + + // scroll page to bottom + await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); + + expect(pageErrorCalled, 'no javascript exceptions thrown on page').toBe(false) + }) + } + +}); \ No newline at end of file diff --git a/e2e/tests/stories.spec.ts b/e2e/tests/stories.spec.ts new file mode 100644 index 000000000..4b3adb0fe --- /dev/null +++ b/e2e/tests/stories.spec.ts @@ -0,0 +1,30 @@ +import { test, expect } from '../pages/basePage'; + +const stories = JSON.parse(require('fs').readFileSync('e2e/playwrightTestData.json', 'utf8'))['stories']; + +test('load stories on /stories route', async ({ + page, + storyPage, + }) => { + + + + let pageErrorCalled = false; + // Log all uncaught errors to the terminal + page.on('pageerror', exception => { + console.log(`Uncaught exception: "${exception}"`); + pageErrorCalled = true; + }); + + await page.goto('/stories'); + await expect(storyPage.header, `data stories page should load`).toHaveText(/data stories/i); + + for (const item of stories) { + const storiesCard = storyPage.mainContent.getByRole('article').getByRole('heading', { level: 3, name: item, exact: true}).first(); + await storiesCard.scrollIntoViewIfNeeded(); + await expect(storiesCard, `${item} story card should load`).toBeVisible(); + }; + + expect(pageErrorCalled, 'no javascript exceptions thrown on page').toBe(false) + +}); \ No newline at end of file diff --git a/e2e/tests/storiesRouting.spec.ts b/e2e/tests/storiesRouting.spec.ts new file mode 100644 index 000000000..8336f16cf --- /dev/null +++ b/e2e/tests/storiesRouting.spec.ts @@ -0,0 +1,30 @@ +import { test, expect } from '../pages/basePage'; + +const stories = JSON.parse(require('fs').readFileSync('e2e/playwrightTestData.json', 'utf8'))['stories']; + +test.describe('stories card routing', () => { + for (const item of stories) { + test(`${item} routes to dataset details page`, async({ + page, + storyPage, + datasetPage, + }) => { + let pageErrorCalled = false; + // Log all uncaught errors to the terminal + page.on('pageerror', exception => { + console.log(`Uncaught exception: "${exception}"`); + pageErrorCalled = true; + }); + + await page.goto('/stories'); + await expect(storyPage.header, `stories page should load`).toHaveText(/data stories/i); + + const storyCard = storyPage.mainContent.getByRole('article').getByRole('heading', { level: 3, name: item, exact: true}).last(); + await storyCard.scrollIntoViewIfNeeded(); + await storyCard.click({force: true}); + await expect(datasetPage.header.filter({ hasText: item}), `${item} page should load`).toBeVisible(); + expect(pageErrorCalled, 'no javascript exceptions thrown on page').toBe(false) + }) + } + +}); \ No newline at end of file diff --git a/package.json b/package.json index 15291e0ae..83e01e6ba 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "local-cms": "npx netlify-cms-proxy-server", "test": "NODE_ENV=test .veda/veda test", "pretest:e2e": "node e2e/generateTestData.js", - "test:e2e": "start-server-and-test 'yarn serve' http://127.0.0.1:9000/ 'cd .veda/ui && yarn playwright test'", - "report": "cd .veda/ui && yarn playwright show-report" + "test:e2e": "yarn playwright test" }, "browserslist": "> 0.5%, last 2 versions, not dead", "engines": { @@ -23,12 +22,12 @@ "devDependencies": { "@parcel/packager-raw-url": "2.7.0", "@parcel/transformer-webmanifest": "2.7.0", + "@playwright/test": "^1.41.1", "@types/node": "^20.11.6", "dotenv": "^10.0.0", "fast-glob": "^3.3.2", "gray-matter": "^4.0.3", - "netlify-cms-proxy-server": "^1.3.24", - "start-server-and-test": "^2.0.3" + "netlify-cms-proxy-server": "^1.3.24" }, "alias": { "react": "./.veda/ui/node_modules/react", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 000000000..08dd56875 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,58 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* 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, + // Global single test timeout + timeout: 300000, + // For expect calls + expect: { + timeout: 180000, + }, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : 3, + /* 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://localhost:9000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'retain-on-failure', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + // uncomment to also run tests in Firefox and webkit + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'] }, + // }, + + // { + // name: 'webkit', + // use: { ...devices['Desktop Safari'] }, + // }, + + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'yarn serve', + url: 'http://localhost:9000', + reuseExistingServer: !process.env.CI, + }, +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 44b5fb96c..6ec4d6e7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,7 +28,7 @@ resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": +"@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== @@ -49,7 +49,7 @@ resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== -"@hapi/topo@^5.0.0", "@hapi/topo@^5.1.0": +"@hapi/topo@^5.0.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== @@ -334,22 +334,12 @@ chrome-trace-event "^1.0.2" nullthrows "^1.1.1" -"@sideway/address@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" - integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== +"@playwright/test@^1.41.1": + version "1.41.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.41.1.tgz#6954139ed4a67999f1b17460aa3d184f4b334f18" + integrity sha512-9g8EWTjiQ9yFBXc6HjCWe41msLpxEX0KhmfmPl9RPLJdfzL4F0lg2BdJ91O9azFdl11y1pmpwdjBiSxvqc+btw== dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + playwright "1.41.1" "@types/node@^20.11.6": version "20.11.6" @@ -373,11 +363,6 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -arg@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" - integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -402,20 +387,6 @@ async@^3.2.3: resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -axios@^1.6.1: - version "1.6.7" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" - integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== - dependencies: - follow-redirects "^1.15.4" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - basic-auth@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" @@ -423,11 +394,6 @@ basic-auth@~2.0.1: dependencies: safe-buffer "5.1.2" -bluebird@3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -474,11 +440,6 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -check-more-types@2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" - integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== - chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -532,13 +493,6 @@ colorspace@1.1.x: color "^3.1.3" text-hex "1.0.x" -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -569,15 +523,6 @@ cors@^2.8.5: object-assign "^4" vary "^1" -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -585,18 +530,13 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4.3.4, debug@^4.1.1, debug@^4.3.4: +debug@^4.1.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - depd@2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -617,11 +557,6 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -duplexer@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -652,34 +587,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -event-stream@=3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -execa@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - express@^4.17.1: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -772,20 +679,6 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.4: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -796,10 +689,10 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" @@ -815,11 +708,6 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.3" -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -865,11 +753,6 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -919,22 +802,6 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -joi@^17.11.0: - version "17.12.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.1.tgz#3347ecf4cd3301962d42191c021b165eef1f395b" - integrity sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -958,11 +825,6 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== -lazy-ass@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" - integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== - lmdb@2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.5.2.tgz#37e28a9fb43405f4dc48c44cec0e13a14c4a6ff1" @@ -981,11 +843,6 @@ lmdb@2.5.2: "@lmdb/lmdb-linux-x64" "2.5.2" "@lmdb/lmdb-win32-x64" "2.5.2" -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - logform@^2.3.2, logform@^2.4.0: version "2.4.2" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.2.tgz#a617983ac0334d0c3b942c34945380062795b47c" @@ -997,11 +854,6 @@ logform@^2.3.2, logform@^2.4.0: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1012,11 +864,6 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1040,7 +887,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -1052,16 +899,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimist@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - morgan@^1.9.1: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" @@ -1154,13 +991,6 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" @@ -1202,13 +1032,6 @@ one-time@^1.0.0: dependencies: fn.name "1.x.x" -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - ordered-binary@^1.2.4: version "1.4.0" resolved "https://registry.yarnpkg.com/ordered-binary/-/ordered-binary-1.4.0.tgz#6bb53d44925f3b8afc33d1eed0fa15693b211389" @@ -1219,28 +1042,30 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== - dependencies: - through "~2.3" - picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +playwright-core@1.41.1: + version "1.41.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.41.1.tgz#9c152670010d9d6f970f34b68e3e935d3c487431" + integrity sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg== + +playwright@1.41.1: + version "1.41.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.41.1.tgz#83325f34165840d019355c2a78a50f21ed9b9c85" + integrity sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ== + dependencies: + playwright-core "1.41.1" + optionalDependencies: + fsevents "2.3.2" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -1249,18 +1074,6 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -ps-tree@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" - integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== - dependencies: - event-stream "=3.3.4" - qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -1309,13 +1122,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.8.1: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - safe-buffer@5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -1383,18 +1189,6 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -1404,11 +1198,6 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - simple-git@^3.0.0: version "3.15.1" resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-3.15.1.tgz#57f595682cb0c2475d5056da078a05c8715a25ef" @@ -1425,13 +1214,6 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== - dependencies: - through "2" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -1442,32 +1224,11 @@ stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== -start-server-and-test@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-2.0.3.tgz#15c53c85e23cba7698b498b8a2598cab95f3f802" - integrity sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg== - dependencies: - arg "^5.0.2" - bluebird "3.7.2" - check-more-types "2.24.0" - debug "4.3.4" - execa "5.1.1" - lazy-ass "1.6.0" - ps-tree "1.2.0" - wait-on "7.2.0" - statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== - dependencies: - duplexer "~0.1.1" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -1480,11 +1241,6 @@ strip-bom-string@^1.0.0: resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -1497,11 +1253,6 @@ text-hex@1.0.x: resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== -through@2, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -1519,11 +1270,6 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -tslib@^2.1.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - tslib@^2.3.1: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" @@ -1567,17 +1313,6 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -wait-on@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.2.0.tgz#d76b20ed3fc1e2bebc051fae5c1ff93be7892928" - integrity sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ== - dependencies: - axios "^1.6.1" - joi "^17.11.0" - lodash "^4.17.21" - minimist "^1.2.8" - rxjs "^7.8.1" - weak-lru-cache@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz#fdbb6741f36bae9540d12f480ce8254060dccd19" @@ -1588,13 +1323,6 @@ what-the-diff@^0.6.0: resolved "https://registry.yarnpkg.com/what-the-diff/-/what-the-diff-0.6.0.tgz#445cc56a9d8ee9aea0ee1ed943f4957ae009291e" integrity sha512-8BgQ4uo4cxojRXvCIcqDpH4QHaq0Ksn2P3LYfztylC5LDSwZKuGHf0Wf7sAStjPLTcB8eCB8pJJcPQSWfhZlkg== -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa"