forked from mui/material-ui
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[test] Add E2E website tests (mui#30128)
- Loading branch information
1 parent
2399fff
commit 11e33a8
Showing
8 changed files
with
436 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
const FEATURE_TOGGLE = { | ||
nav_products: true, | ||
enable_product_scope: false, | ||
enable_website_banner: false, | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: {}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TestFixture>({}); | ||
|
||
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'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { PlaywrightTestConfig } from '@playwright/test'; | ||
|
||
export type TestFixture = { materialUrlPrefix: string }; | ||
|
||
const config: PlaywrightTestConfig<TestFixture> = { | ||
use: { | ||
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'https://mui.com', | ||
}, | ||
projects: [ | ||
{ | ||
name: 'current', | ||
use: { | ||
materialUrlPrefix: '', | ||
}, | ||
}, | ||
{ | ||
name: 'new', | ||
use: { | ||
materialUrlPrefix: '/material', | ||
}, | ||
}, | ||
], | ||
}; | ||
|
||
export default config; |
Oops, something went wrong.