chore: harden markdown link validation (#30221)

This commit is contained in:
Max Schmitt 2024-04-03 17:51:32 +02:00 committed by GitHub
parent 0734d1e733
commit 010bc29a3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 57 additions and 45 deletions

View File

@ -6,9 +6,6 @@
Error is raised whenever certain operations are terminated abnormally, e.g.
browser closes while [`method: Page.evaluate`] is running. All Playwright exceptions
inherit from this class.
- [error.message](./class-error.md#errormessage)
- [error.name](./class-error.md#errorname)
- [error.stack](./class-error.md#errorstack)
## property: Error.message
* since: v1.11

View File

@ -30,7 +30,7 @@ To add a [GitHub Actions](https://docs.github.com/en/actions) file first create
#### You will learn
* langs: python, java, csharp
- [How to run tests on push/pull_request](/ci.md#on-pushpull_request)
- [How to run tests on push/pull_request](/ci-intro.md#on-pushpull_request)
- [How to view test logs](/ci-intro.md#viewing-test-logs)
- [How to view the trace](/ci-intro.md#viewing-the-trace)

View File

@ -80,14 +80,14 @@ npx playwright test --debug
```
#### Debug one test on all browsers
To debug one test on a specific line run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](/test-configuration.md#multiple-browsers) and open the inspector.
To debug one test on a specific line run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers) and open the inspector.
```bash
npx playwright test example.spec.ts:10 --debug
```
#### Debug on a specific browser
In Playwright you can configure projects in your [`playwright.config`](/test-configuration.md#multiple-browsers). Once configured you can then debug your tests on a specific browser or mobile viewport using the `--project` flag followed by the name of the project configured in your `playwright.config`.
In Playwright you can configure projects in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers). Once configured you can then debug your tests on a specific browser or mobile viewport using the `--project` flag followed by the name of the project configured in your `playwright.config`.
```bash
npx playwright test --project=chromium --debug

View File

@ -644,7 +644,7 @@ This version was also tested against the following stable channels:
### New APIs & changes
- Default assertions timeout now can be changed with [`setDefaultAssertionTimeout`](./test-assertions#playwright-assertions-set-default-assertion-timeout).
- Default assertions timeout now can be changed with [`setDefaultAssertionTimeout`](./api/class-playwrightassertions#playwright-assertions-set-default-assertion-timeout).
### Announcements

View File

@ -262,7 +262,7 @@ test('pass', async ({ page }) => {
});
```
See the documentation [for a full example](./test-assertions.md#add-custom-matchers-using-expectextend).
See the documentation [for a full example](./test-assertions#add-custom-matchers-using-expectextend).
### Merge test fixtures
@ -1753,7 +1753,7 @@ This version was also tested against the following stable channels:
### Locator Improvements
- [`method: Locator.dragTo`]
- [`expect(locator).toBeChecked({ checked })`](./test-assertions#locator-assertions-to-be-checked)
- [`expect(locator).toBeChecked({ checked })`](./api/class-locatorassertions#locator-assertions-to-be-checked)
- Each locator can now be optionally filtered by the text it contains:
```js
await page.locator('li', { hasText: 'my item' }).locator('button').click();
@ -1908,7 +1908,7 @@ Playwright Trace Viewer is now **available online** at https://trace.playwright.
- [`testInfo.parallelIndex`](./api/class-testinfo#test-info-parallel-index)
- [`testInfo.titlePath`](./api/class-testinfo#test-info-title-path)
- [`testOptions.trace`](./api/class-testoptions#test-options-trace) has new options
- [`expect.toMatchSnapshot`](./test-assertions#expectvaluetomatchsnapshotname-options) supports subdirectories
- [`expect.toMatchSnapshot`](./api/class-genericassertions.md) supports subdirectories
- [`reporter.printsToStdio()`](./api/class-reporter#reporter-prints-to-stdio)
@ -2189,25 +2189,25 @@ By default, the timeout for assertions is not set, so it'll wait forever, until
List of all new assertions:
- [`expect(locator).toBeChecked()`](./test-assertions#expectlocatortobechecked)
- [`expect(locator).toBeDisabled()`](./test-assertions#expectlocatortobedisabled)
- [`expect(locator).toBeEditable()`](./test-assertions#expectlocatortobeeditable)
- [`expect(locator).toBeEmpty()`](./test-assertions#expectlocatortobeempty)
- [`expect(locator).toBeEnabled()`](./test-assertions#expectlocatortobeenabled)
- [`expect(locator).toBeFocused()`](./test-assertions#expectlocatortobefocused)
- [`expect(locator).toBeHidden()`](./test-assertions#expectlocatortobehidden)
- [`expect(locator).toBeVisible()`](./test-assertions#expectlocatortobevisible)
- [`expect(locator).toContainText(text, options?)`](./test-assertions#expectlocatortocontaintexttext-options)
- [`expect(locator).toHaveAttribute(name, value)`](./test-assertions#expectlocatortohaveattributename-value)
- [`expect(locator).toHaveClass(expected)`](./test-assertions#expectlocatortohaveclassexpected)
- [`expect(locator).toHaveCount(count)`](./test-assertions#expectlocatortohavecountcount)
- [`expect(locator).toHaveCSS(name, value)`](./test-assertions#expectlocatortohavecssname-value)
- [`expect(locator).toHaveId(id)`](./test-assertions#expectlocatortohaveidid)
- [`expect(locator).toHaveJSProperty(name, value)`](./test-assertions#expectlocatortohavejspropertyname-value)
- [`expect(locator).toHaveText(expected, options)`](./test-assertions#expectlocatortohavetextexpected-options)
- [`expect(page).toHaveTitle(title)`](./test-assertions#expectpagetohavetitletitle)
- [`expect(page).toHaveURL(url)`](./test-assertions#expectpagetohaveurlurl)
- [`expect(locator).toHaveValue(value)`](./test-assertions#expectlocatortohavevaluevalue)
- [`expect(locator).toBeChecked()`](./api/class-locatorassertions#locator-assertions-to-be-checked)
- [`expect(locator).toBeDisabled()`](./api/class-locatorassertions#locator-assertions-to-be-disabled)
- [`expect(locator).toBeEditable()`](./api/class-locatorassertions#locator-assertions-to-be-editable)
- [`expect(locator).toBeEmpty()`](./api/class-locatorassertions#locator-assertions-to-be-empty)
- [`expect(locator).toBeEnabled()`](./api/class-locatorassertions#locator-assertions-to-be-enabled)
- [`expect(locator).toBeFocused()`](./api/class-locatorassertions#locator-assertions-to-be-focused)
- [`expect(locator).toBeHidden()`](./api/class-locatorassertions#locator-assertions-to-be-hidden)
- [`expect(locator).toBeVisible()`](./api/class-locatorassertions#locator-assertions-to-be-visible)
- [`expect(locator).toContainText(text, options?)`](./api/class-locatorassertions#locator-assertions-to-contain-text)
- [`expect(locator).toHaveAttribute(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-attribute)
- [`expect(locator).toHaveClass(expected)`](./api/class-locatorassertions#locator-assertions-to-have-class)
- [`expect(locator).toHaveCount(count)`](./api/class-locatorassertions#locator-assertions-to-have-count)
- [`expect(locator).toHaveCSS(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-css)
- [`expect(locator).toHaveId(id)`](./api/class-locatorassertions#locator-assertions-to-have-id)
- [`expect(locator).toHaveJSProperty(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-js-property)
- [`expect(locator).toHaveText(expected, options)`](./api/class-locatorassertions#locator-assertions-to-have-text)
- [`expect(page).toHaveTitle(title)`](./api/class-pageassertions#page-assertions-to-have-title)
- [`expect(page).toHaveURL(url)`](./api/class-pageassertions#page-assertions-to-have-url)
- [`expect(locator).toHaveValue(value)`](./api/class-locatorassertions#locator-assertions-to-have-value)
#### ⛓ Serial mode with [`describe.serial`](./api/class-test#test-describe-serial)
@ -2243,7 +2243,7 @@ Step information is exposed in reporters API.
#### 🌎 Launch web server before running tests
To launch a server during the tests, use the [`webServer`](./test-webserver) option in the configuration file. The server will wait for a given url to be available before running the tests, and the url will be passed over to Playwright as a [`baseURL`](./api/class-fixtures#fixtures-base-url) when creating a context.
To launch a server during the tests, use the [`webServer`](./test-webserver) option in the configuration file. The server will wait for a given url to be available before running the tests, and the url will be passed over to Playwright as a [`baseURL`](./api/class-testoptions#test-options-base-url) when creating a context.
```ts title="playwright.config.ts"
import { defineConfig } from '@playwright/test';
@ -2272,7 +2272,7 @@ Learn more in the [documentation](./test-webserver).
#### Playwright Test
- **⚡️ Introducing [Reporter API](https://github.com/microsoft/playwright/blob/65a9037461ffc15d70cdc2055832a0c5512b227c/packages/playwright-test/types/testReporter.d.ts)** which is already used to create an [Allure Playwright reporter](https://github.com/allure-framework/allure-js/pull/297).
- **⛺️ New [`baseURL` fixture](./test-configuration#basic-options)** to support relative paths in tests.
- **⛺️ New [`baseURL` fixture](./test-configuration#basic-configuration)** to support relative paths in tests.
#### Playwright

View File

@ -89,7 +89,7 @@ If your custom reporter does not print anything to the terminal, implement [`met
**Merged report API notes**
When merging mutliple [`blob`](./test-reporters#blob-reporter) reports via [`merge-reports`](./test-sharding#merge-reports-cli) CLI
When merging multiple [`blob`](../test-reporters#blob-reporter) reports via [`merge-reports`](../test-sharding#merge-reports-cli) CLI
command, the same [Reporter] API is called to produce final reports and all existing reporters
should work without any changes. There some subtle differences though which might affect some custom
reporters.

View File

@ -99,7 +99,7 @@ await expect(page.getByText('the lion king')).toBeVisible();
await expect(page.getByText('the mummy')).toBeHidden();
```
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#expectpoll) instead.
```js
await expect.poll(async () => {

View File

@ -22,7 +22,7 @@ Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright
## Recording a Trace
By default the [playwright.config](/test-configuration.md#record-test-trace) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retries` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
By default the [playwright.config](./trace-viewer.md#recording-a-trace-on-ci) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retries` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
```js title="playwright.config.ts"
import { defineConfig } from '@playwright/test';

View File

@ -336,8 +336,8 @@ export interface FullResult {
*
* **Merged report API notes**
*
* When merging mutliple [`blob`](https://playwright.dev/docs/api/test-reporters#blob-reporter) reports via
* [`merge-reports`](https://playwright.dev/docs/api/test-sharding#merge-reports-cli) CLI command, the same {@link Reporter} API is called to
* When merging multiple [`blob`](https://playwright.dev/docs/test-reporters#blob-reporter) reports via
* [`merge-reports`](https://playwright.dev/docs/test-sharding#merge-reports-cli) CLI command, the same {@link Reporter} API is called to
* produce final reports and all existing reporters should work without any changes. There some subtle differences
* though which might affect some custom reporters.
* - Projects from different shards are always kept as separate {@link TestProject} objects. E.g. if project

View File

@ -133,14 +133,14 @@ async function run() {
for (const lang of langs) {
try {
let documentation = parseApi(path.join(documentationRoot, 'api'));
documentation.filterForLanguage(lang);
if (lang === 'js') {
const testDocumentation = parseApi(path.join(documentationRoot, 'test-api'), path.join(documentationRoot, 'api', 'params.md'));
testDocumentation.filterForLanguage('js');
const testReporterDocumentation = parseApi(path.join(documentationRoot, 'test-reporter-api'));
testReporterDocumentation.filterForLanguage('js');
documentation = documentation.mergeWith(testDocumentation).mergeWith(testReporterDocumentation);
documentation = documentation.mergeWith(
parseApi(path.join(documentationRoot, 'test-api'), path.join(documentationRoot, 'api', 'params.md'))
).mergeWith(
parseApi(path.join(documentationRoot, 'test-reporter-api'))
);
}
documentation.filterForLanguage(lang);
// This validates member links.
documentation.setLinkRenderer(() => undefined);
@ -153,8 +153,18 @@ async function run() {
for (const cls of documentation.classesArray) {
const filePath = path.join(documentationRoot, 'api', 'class-' + cls.name.toLowerCase() + '.md');
for (const member of cls.membersArray)
mdSections.add(filePath + '#' + toKebabCase(cls.name).toLowerCase() + '-' + toKebabCase(member.name).toLowerCase());
for (const member of cls.membersArray) {
const memberHash = filePath + '#' + toKebabCase(cls.name).toLowerCase() + '-' + toKebabCase(member.name).toLowerCase()
mdSections.add(memberHash);
for (const arg of member.argsArray) {
mdSections.add(memberHash + '-option-' + toKebabCase(arg.name).toLowerCase());
if (arg.name === "options" && arg.type) {
for (const option of arg.type.deepProperties())
mdSections.add(memberHash + '-option-' + toKebabCase(option.name).toLowerCase());
}
}
}
for (const event of cls.eventsArray)
mdSections.add(filePath + '#' + toKebabCase(cls.name).toLowerCase() + '-event-' + toKebabCase(event.name).toLowerCase());
}
@ -211,7 +221,8 @@ async function run() {
}
if (!node.text)
return;
for (const [, mdLinkName, mdLink] of node.text.matchAll(/\[([\w\s\d]+)\]\((.*?)\)/g)) {
// Match links in a lax way (.+), so they can include spaces, backticks etc.
for (const [, mdLinkName, mdLink] of node.text.matchAll(/\[(.+)\]\((.*?)\)/g)) {
const isExternal = mdLink.startsWith('http://') || mdLink.startsWith('https://');
if (isExternal)
continue;
@ -296,6 +307,10 @@ async function getBrowserVersions() {
return result;
}
/**
* @param {string} text
* @returns {string}
*/
function mdSectionHash(text) {
return text.toLowerCase().replace(/\s/g, '-').replace(/[^-_a-z0-9]/g, '').replace(/^-+/, '');
}