diff --git a/.circleci/config.yml b/.circleci/config.yml index c8f3bf5ff9a2c8..156b53330497d9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,6 +15,10 @@ parameters: description: The name of the workflow to run type: string default: pipeline + e2e-base-url: + description: The base url for running end-to-end test + type: string + default: '' defaults: &defaults parameters: @@ -26,6 +30,10 @@ defaults: &defaults description: A particular type of tests that should be run type: string default: undefined + e2e-base-url: + description: The base url for running end-to-end test + type: string + default: << pipeline.parameters.e2e-base-url >> environment: # Keep in sync with "Save playwright cache" PLAYWRIGHT_BROWSERS_PATH: /tmp/pw-browsers @@ -373,6 +381,21 @@ jobs: - run: name: Test umd release command: yarn test:umd + test_e2e_website: + <<: *defaults + docker: + - image: mcr.microsoft.com/playwright@sha256:f08e263c95e83334104e6e2fee047ad92062a03af6ae94c0f8686ba2b3014823 + environment: + NODE_ENV: development # Needed if playwright is in `devDependencies` + steps: + - checkout + - install_js: + browsers: true + - run: + name: yarn test:e2e-website + command: yarn test:e2e-website + environment: + PLAYWRIGHT_TEST_BASE_URL: << parameters.e2e-base-url >> test_profile: <<: *defaults docker: @@ -750,6 +773,15 @@ workflows: - test_bundle_size_monitor: requires: - checkout + e2e-website: + when: + equal: [e2e-website, << pipeline.parameters.workflow >>] + jobs: + - checkout + - test_e2e_website: + requires: + - checkout + bundling: when: equal: [bundling, << pipeline.parameters.workflow >>] diff --git a/docs/src/featureToggle.ts b/docs/src/featureToggle.ts index 7a161d4a896c51..1d4e86ecfc3cac 100644 --- a/docs/src/featureToggle.ts +++ b/docs/src/featureToggle.ts @@ -1,5 +1,6 @@ const FEATURE_TOGGLE = { nav_products: true, + enable_product_scope: false, enable_website_banner: false, }; diff --git a/netlify/functions/deploy-succeeded.js b/netlify/functions/deploy-succeeded.js new file mode 100644 index 00000000000000..d59ce476da8138 --- /dev/null +++ b/netlify/functions/deploy-succeeded.js @@ -0,0 +1,43 @@ +const fetch = require('node-fetch'); + +/** + * @param {object} event + * @param {string} event.body - https://jsoneditoronline.org/#left=cloud.fb1a4fa30a4f475fa6887071c682e2c1 + */ +exports.handler = async (event) => { + const { payload } = JSON.parse(event.body); + const repo = payload.review_url.match(/github\.com\/(.*)\/pull\/(.*)/); + if (!repo) { + throw new Error(`No repo found at review_url: ${payload.review_url}`); + } + + // eslint-disable-next-line no-console + console.info(`repo:`, repo[1]); + // eslint-disable-next-line no-console + console.info(`PR:`, repo[2]); + // eslint-disable-next-line no-console + console.info(`url:`, payload.deploy_ssl_url); + + // for more details > https://circleci.com/docs/2.0/api-developers-guide/# + await fetch(`https://circleci.com/api/v2/project/gh/${repo[1]}/pipeline`, { + method: 'POST', + headers: { + 'Content-type': 'application/json', + // token from https://app.netlify.com/sites/material-ui/settings/deploys#environment-variables + 'Circle-Token': process.env.CIRCLE_CI_TOKEN, + }, + body: JSON.stringify({ + // For PR, /head is needed. https://support.circleci.com/hc/en-us/articles/360049841151 + branch: `pull/${repo[2]}/head`, + parameters: { + // the parameters defined in .circleci/config.yml + workflow: 'e2e-website', // name of the workflow + 'e2e-base-url': payload.deploy_ssl_url, // deploy preview url + }, + }), + }); + return { + statusCode: 200, + body: {}, + }; +}; diff --git a/package.json b/package.json index 493596ac5a8ba9..e2e39363cfa021 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,8 @@ "test:e2e:dev": "concurrently \"yarn test:e2e:build --watch\" \"yarn test:e2e:server\"", "test:e2e:run": "mocha --config test/e2e/.mocharc.js 'test/e2e/**/*.test.{js,ts,tsx}'", "test:e2e:server": "serve test/e2e", + "test:e2e-website": "playwright test test/e2e-website --config test/e2e-website/playwright.config.ts", + "test:e2e-website:dev": "PLAYWRIGHT_TEST_BASE_URL=http://localhost:3000 playwright test test/e2e-website --config test/e2e-website/playwright.config.ts", "test:karma": "cross-env NODE_ENV=test karma start test/karma.conf.js", "test:karma:profile": "cross-env NODE_ENV=test karma start test/karma.conf.profile.js", "test:regressions": "cross-env NODE_ENV=production yarn test:regressions:build && concurrently --success first --kill-others \"yarn test:regressions:run\" \"yarn test:regressions:server\"", @@ -79,6 +81,7 @@ "@emotion/styled": "^11.6.0", "@eps1lon/enzyme-adapter-react-17": "^0.1.0", "@octokit/rest": "^18.12.0", + "@playwright/test": "1.17.1", "@rollup/plugin-replace": "^3.0.0", "@testing-library/dom": "^8.11.1", "@testing-library/react": "^12.1.2", diff --git a/test/e2e-website/README.md b/test/e2e-website/README.md new file mode 100644 index 00000000000000..951cccebdb14bb --- /dev/null +++ b/test/e2e-website/README.md @@ -0,0 +1,12 @@ +# Docs end-to-end testing + +## Running locally + +1. Run `yarn docs:dev` to start docs in development server. +2. Run `yarn test:e2e-website` in a separate terminal to run the test suites (`*.spec.ts`) inside `test/e2e-website` folder. + +> use --headed to run tests in headed browsers, check out [Playwright CLI](https://playwright.dev/docs/intro#command-line) for more options + +## CI + +After netlify deploy the preview site, the `netlify/functions/deploy-succeeded.js` hook calls CircleCI API to run the `e2e-website` workflow against the deployed url. diff --git a/test/e2e-website/material-docs.spec.ts b/test/e2e-website/material-docs.spec.ts new file mode 100644 index 00000000000000..cb5c5b205d20ad --- /dev/null +++ b/test/e2e-website/material-docs.spec.ts @@ -0,0 +1,134 @@ +import { test as base, expect } from '@playwright/test'; +import kebabCase from 'lodash/kebabCase'; +import FEATURE_TOGGLE from 'docs/src/featureToggle'; +import { TestFixture } from './playwright.config'; + +const test = base.extend({}); + +test.beforeEach(async ({ materialUrlPrefix }) => { + test.skip( + !!materialUrlPrefix && !FEATURE_TOGGLE.enable_product_scope, + "Migration haven't started yet", + ); +}); + +test.describe.parallel('Material docs', () => { + test('should have correct link with hash in the TOC', async ({ page, materialUrlPrefix }) => { + await page.goto(`${materialUrlPrefix}/getting-started/installation/`); + + const anchors = page.locator('[aria-label="Page table of contents"] ul a'); + + const anchorTexts = await anchors.allTextContents(); + + await Promise.all( + anchorTexts.map((text, index) => { + return expect(anchors.nth(index)).toHaveAttribute( + 'href', + `${materialUrlPrefix}/getting-started/installation/#${kebabCase(text)}`, + ); + }), + ); + }); + + test.describe.parallel('Demo page', () => { + test('should have correct link for API section', async ({ page, materialUrlPrefix }) => { + await page.goto(`${materialUrlPrefix}/components/cards/`); + + const anchors = await page.locator('div > h2#heading-api ~ ul a'); + + const anchorTexts = await anchors.allTextContents(); + + await Promise.all( + anchorTexts.map((text, index) => { + return expect(anchors.nth(index)).toHaveAttribute( + 'href', + `${materialUrlPrefix}/api/${kebabCase(text)}/`, + ); + }), + ); + }); + + test('should have correct link for sidebar anchor', async ({ page, materialUrlPrefix }) => { + await page.goto(`${materialUrlPrefix}/components/cards/`); + + const anchor = await page.locator('nav[aria-label="documentation"] ul a:text-is("Card")'); + + await expect(anchor).toHaveAttribute('href', `${materialUrlPrefix}/components/cards/`); + }); + }); + + test.describe.parallel('API page', () => { + test('should have correct link for sidebar anchor', async ({ page, materialUrlPrefix }) => { + await page.goto(`${materialUrlPrefix}/api/card/`); + + const anchor = await page.locator('nav[aria-label="documentation"] ul a:text-is("Card")'); + + await expect(anchor).toHaveAttribute('app-drawer-active', ''); + await expect(anchor).toHaveAttribute('href', `${materialUrlPrefix}/api/card/`); + }); + + test('all the links in the main content should have correct prefix', async ({ + page, + materialUrlPrefix, + }) => { + await page.goto(`${materialUrlPrefix}/api/card/`); + + const anchors = await page.locator('div#main-content a'); + + const handles = await anchors.elementHandles(); + + const links = await Promise.all(handles.map((elm) => elm.getAttribute('href'))); + + links.forEach((link) => { + if ( + [ + '/getting-started', + '/components', + '/api', + '/customization', + '/guides', + '/discover-more', + ].some((path) => link.replace(materialUrlPrefix, '').startsWith(path)) + ) { + expect(link.startsWith(materialUrlPrefix)).toBeTruthy(); + } + + if (link.replace(materialUrlPrefix, '').startsWith('/system')) { + expect(link.startsWith('/system')).toBeTruthy(); + expect(link.match(/\/system{1}/g)).toHaveLength(1); // should not have repeated `/system/system/*` + } + + if (link.replace(materialUrlPrefix, '').startsWith('/styles')) { + expect(link.startsWith('/styles')).toBeTruthy(); + expect(link.match(/\/styles{1}/g)).toHaveLength(1); // should not have repeated `/system/system/*` + } + }); + }); + }); + + test.describe.parallel('Search', () => { + test('should have correct link when searching component', async ({ page }) => { + await page.goto('/getting-started/installation/'); + + await page.keyboard.press('Meta+k'); + + await page.type('input#docsearch-input', 'card', { delay: 50 }); + + const anchor = await page.locator('.DocSearch-Hits a:has-text("Card")'); + + await expect(anchor.first()).toHaveAttribute('href', '/components/cards/#main-content'); + }); + + test('should have correct link when searching API', async ({ page }) => { + await page.goto('/getting-started/installation/'); + + await page.keyboard.press('Meta+k'); + + await page.type('input#docsearch-input', 'card api', { delay: 50 }); + + const anchor = await page.locator('.DocSearch-Hits a:has-text("Card API")'); + + await expect(anchor.first()).toHaveAttribute('href', '/api/card/#main-content'); + }); + }); +}); diff --git a/test/e2e-website/playwright.config.ts b/test/e2e-website/playwright.config.ts new file mode 100644 index 00000000000000..1bb30b272bb7a0 --- /dev/null +++ b/test/e2e-website/playwright.config.ts @@ -0,0 +1,25 @@ +import { PlaywrightTestConfig } from '@playwright/test'; + +export type TestFixture = { materialUrlPrefix: string }; + +const config: PlaywrightTestConfig = { + use: { + baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'https://mui.com', + }, + projects: [ + { + name: 'current', + use: { + materialUrlPrefix: '', + }, + }, + { + name: 'new', + use: { + materialUrlPrefix: '/material', + }, + }, + ], +}; + +export default config; diff --git a/yarn.lock b/yarn.lock index b8bfe8db3f5a18..47e76511034de6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -141,7 +141,7 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0": +"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== @@ -153,7 +153,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== -"@babel/core@>=7.9.0", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.16.0", "@babel/core@^7.7.5": +"@babel/core@>=7.9.0", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.8", "@babel/core@^7.16.0", "@babel/core@^7.7.5": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== @@ -432,7 +432,7 @@ "@babel/helper-remap-async-to-generator" "^7.16.4" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.16.0": +"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.14.5", "@babel/plugin-proposal-class-properties@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" integrity sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A== @@ -449,7 +449,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.16.0": +"@babel/plugin-proposal-dynamic-import@^7.14.5", "@babel/plugin-proposal-dynamic-import@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz#783eca61d50526202f9b296095453977e88659f1" integrity sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ== @@ -457,7 +457,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.16.0": +"@babel/plugin-proposal-export-namespace-from@^7.14.5", "@babel/plugin-proposal-export-namespace-from@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz#9c01dee40b9d6b847b656aaf4a3976a71740f222" integrity sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA== @@ -473,7 +473,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.16.0": +"@babel/plugin-proposal-logical-assignment-operators@^7.14.5", "@babel/plugin-proposal-logical-assignment-operators@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz#a711b8ceb3ffddd3ef88d3a49e86dbd3cc7db3fd" integrity sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q== @@ -481,7 +481,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" integrity sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ== @@ -489,7 +489,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.16.0": +"@babel/plugin-proposal-numeric-separator@^7.14.5", "@babel/plugin-proposal-numeric-separator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz#5d418e4fbbf8b9b7d03125d3a52730433a373734" integrity sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q== @@ -516,7 +516,7 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.16.0": +"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.14.5", "@babel/plugin-proposal-optional-chaining@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" integrity sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg== @@ -525,7 +525,7 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.0": +"@babel/plugin-proposal-private-methods@^7.14.5", "@babel/plugin-proposal-private-methods@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz#b4dafb9c717e4301c5776b30d080d6383c89aff6" integrity sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg== @@ -533,7 +533,7 @@ "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-private-property-in-object@^7.16.0": +"@babel/plugin-proposal-private-property-in-object@^7.14.5", "@babel/plugin-proposal-private-property-in-object@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz#69e935b2c5c79d2488112d886f0c4e2790fee76f" integrity sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw== @@ -803,7 +803,7 @@ "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.16.0": +"@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.14.5", "@babel/plugin-transform-modules-commonjs@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" integrity sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ== @@ -1121,7 +1121,7 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.0" "@babel/plugin-transform-react-pure-annotations" "^7.16.0" -"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.0": +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.14.5", "@babel/preset-typescript@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz#b0b4f105b855fb3d631ec036cdc9d1ffd1fa5eac" integrity sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg== @@ -1605,10 +1605,10 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/types@^27.0.6": - version "27.0.6" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.6.tgz#9a992bc517e0c49f035938b8549719c2de40706b" - integrity sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g== +"@jest/types@^27.2.5", "@jest/types@^27.4.2": + version "27.4.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" + integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -2308,26 +2308,12 @@ glob-to-regexp "^0.3.0" "@mui/core@^5.0.0-alpha.54": - version "5.0.0-alpha.59" - dependencies: - "@babel/runtime" "^7.16.3" - "@emotion/is-prop-valid" "^1.1.1" - "@mui/utils" "^5.2.3" - "@popperjs/core" "^2.4.4" - clsx "^1.1.1" - prop-types "^15.7.2" - react-is "^17.0.2" + version "0.0.0" + uid "" "@mui/core@link:./packages/mui-base": - version "5.0.0-alpha.59" - dependencies: - "@babel/runtime" "^7.16.3" - "@emotion/is-prop-valid" "^1.1.1" - "@mui/utils" "^5.2.3" - "@popperjs/core" "^2.4.4" - clsx "^1.1.1" - prop-types "^15.7.2" - react-is "^17.0.2" + version "0.0.0" + uid "" "@mui/x-data-grid-generator@^5.0.1": version "5.0.1" @@ -2711,6 +2697,47 @@ dependencies: "@octokit/openapi-types" "^11.1.0" +"@playwright/test@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.17.1.tgz#9e5aca496d2c90ce95ca19ac2c3a8867a4f606d3" + integrity sha512-mMZS5OMTN/vUlqd1JZkFoAk2FsIZ4/E/00tw5it2c/VF4+3z/aWO+PPd8ShEGzYME7B16QGWNPjyFpDQI1t4RQ== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/core" "^7.14.8" + "@babel/plugin-proposal-class-properties" "^7.14.5" + "@babel/plugin-proposal-dynamic-import" "^7.14.5" + "@babel/plugin-proposal-export-namespace-from" "^7.14.5" + "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" + "@babel/plugin-proposal-numeric-separator" "^7.14.5" + "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/plugin-proposal-private-methods" "^7.14.5" + "@babel/plugin-proposal-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-transform-modules-commonjs" "^7.14.5" + "@babel/preset-typescript" "^7.14.5" + colors "^1.4.0" + commander "^8.2.0" + debug "^4.1.1" + expect "=27.2.5" + jest-matcher-utils "=27.2.5" + jpeg-js "^0.4.2" + mime "^2.4.6" + minimatch "^3.0.3" + ms "^2.1.2" + open "^8.3.0" + pirates "^4.0.1" + pixelmatch "^5.2.1" + playwright-core "=1.17.1" + pngjs "^5.0.0" + rimraf "^3.0.2" + source-map-support "^0.4.18" + stack-utils "^2.0.3" + yazl "^2.5.1" + "@polka/url@^1.0.0-next.9": version "1.0.0-next.11" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71" @@ -3477,6 +3504,11 @@ dependencies: "@sinonjs/fake-timers" "^7.1.0" +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + "@types/styled-components@5.1.17": version "5.1.17" resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.17.tgz#0b5ecf748eb5fb81db4b4115b168a162379c181b" @@ -4050,7 +4082,7 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-regex@^5.0.0, ansi-regex@^5.0.1: +ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -6688,6 +6720,11 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -6785,6 +6822,11 @@ diacritic@0.0.2: resolved "https://registry.yarnpkg.com/diacritic/-/diacritic-0.0.2.tgz#fc2a887b5a5bc0a0a854fb614c7c2f209061ee04" integrity sha1-/CqIe1pbwKCoVPthTHwvIJBh7gQ= +diff-sequences@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" + integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== + diff@5.0.0, diff@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -7778,6 +7820,18 @@ expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@=27.2.5: + version "27.2.5" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.2.5.tgz#16154aaa60b4d9a5b0adacfea3e4d6178f4b93fd" + integrity sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA== + dependencies: + "@jest/types" "^27.2.5" + ansi-styles "^5.0.0" + jest-get-type "^27.0.6" + jest-matcher-utils "^27.2.5" + jest-message-util "^27.2.5" + jest-regex-util "^27.0.6" + express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -9486,7 +9540,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-docker@^2.0.0: +is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== @@ -9762,7 +9816,7 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^2.1.1: +is-wsl@^2.1.1, is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -9935,6 +9989,61 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jest-diff@^27.2.5, jest-diff@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.2.tgz#786b2a5211d854f848e2dcc1e324448e9481f36f" + integrity sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.4.0" + jest-get-type "^27.4.0" + pretty-format "^27.4.2" + +jest-get-type@^27.0.6, jest-get-type@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" + integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== + +jest-matcher-utils@=27.2.5: + version "27.2.5" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz#4684faaa8eb32bf15e6edaead6834031897e2980" + integrity sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg== + dependencies: + chalk "^4.0.0" + jest-diff "^27.2.5" + jest-get-type "^27.0.6" + pretty-format "^27.2.5" + +jest-matcher-utils@^27.2.5: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz#d17c5038607978a255e0a9a5c32c24e984b6c60b" + integrity sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ== + dependencies: + chalk "^4.0.0" + jest-diff "^27.4.2" + jest-get-type "^27.4.0" + pretty-format "^27.4.2" + +jest-message-util@^27.2.5: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.2.tgz#07f3f1bf207d69cf798ce830cc57f1a849f99388" + integrity sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.4.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + pretty-format "^27.4.2" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-regex-util@^27.0.6: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" + integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== + jest-worker@27.0.0-next.5: version "27.0.0-next.5" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.0-next.5.tgz#5985ee29b12a4e191f4aae4bb73b97971d86ec28" @@ -11362,7 +11471,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -11564,7 +11673,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -11828,11 +11937,6 @@ node-html-parser@1.4.9: dependencies: he "1.2.0" -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - node-preload@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" @@ -12270,6 +12374,15 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +open@^8.3.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -12861,12 +12974,17 @@ pinpoint@^1.1.0: resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" integrity sha1-DPd1eml38b9/ajIge3CeN3OI6HQ= -pirates@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== +pirates@^4.0.0, pirates@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" + integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== + +pixelmatch@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.2.1.tgz#9e4e4f4aa59648208a31310306a5bed5522b0d65" + integrity sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ== dependencies: - node-modules-regexp "^1.0.0" + pngjs "^4.0.1" pkg-dir@^2.0.0: version "2.0.0" @@ -12930,6 +13048,11 @@ playwright@^1.17.1: dependencies: playwright-core "=1.17.1" +pngjs@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-4.0.1.tgz#f803869bb2fc1bfe1bf99aa4ec21c108117cfdbe" + integrity sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg== + pngjs@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" @@ -13074,13 +13197,13 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@^27.0.2: - version "27.0.6" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" - integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ== +pretty-format@^27.0.2, pretty-format@^27.2.5, pretty-format@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.2.tgz#e4ce92ad66c3888423d332b40477c87d1dac1fb8" + integrity sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw== dependencies: - "@jest/types" "^27.0.6" - ansi-regex "^5.0.0" + "@jest/types" "^27.4.2" + ansi-regex "^5.0.1" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -14861,6 +14984,13 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.4.18: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map-support@^0.5.16, source-map-support@~0.5.19: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"