mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
docs: introduce overloads, generate JSDoc for overloads (#8485)
- Each overload, e.g. for `page.evaluate`, shows a nice autocomplete doc, not only the first one. - We can have multiple overloads directly on the docs page, e.g. `test.skip(title, fn)` and `test.skip(condition, description)`. These overloads are internally named `Test.skip#1` and all aliased to `test.skip`.
This commit is contained in:
parent
2f18c62a19
commit
bb5e44fbc4
@ -599,12 +599,9 @@ Timeout in milliseconds.
|
||||
|
||||
|
||||
|
||||
## method: Test.skip#1
|
||||
|
||||
## method: Test.skip
|
||||
|
||||
Skips a test or a group of tests.
|
||||
|
||||
Unconditionally skip a test, this is similar syntax to [`method: Test.(call)`]:
|
||||
Declares a skipped test, similarly to [`method: Test.(call)`]. Skipped test is never run.
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
@ -622,7 +619,72 @@ test.skip('broken test', async ({ page }) => {
|
||||
});
|
||||
```
|
||||
|
||||
Conditionally skip a test with an optional description. In this case, call `test.skip()` inside the test function:
|
||||
### param: Test.skip#1.title
|
||||
- `title` <[string]>
|
||||
|
||||
Test title.
|
||||
|
||||
### param: Test.skip#1.testFunction
|
||||
- `testFunction` <[function]\([Fixtures], [TestInfo]\)>
|
||||
|
||||
Test function that takes one or two arguments: an object with fixtures and optional [TestInfo].
|
||||
|
||||
|
||||
|
||||
## method: Test.skip#2
|
||||
|
||||
Unconditionally skip a test. Test is immediately aborted when you call [`method: Test.skip#2`].
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('skipped test', async ({ page }) => {
|
||||
test.skip();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js js-flavor=ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('skipped test', async ({ page }) => {
|
||||
test.skip();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
Unconditionally skip all tests in a file or [`method: Test.describe`] group:
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.skip();
|
||||
|
||||
test('skipped test 1', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
test('skipped test 2', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js js-flavor=ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.skip();
|
||||
|
||||
test('skipped test 1', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
test('skipped test 2', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## method: Test.skip#3
|
||||
|
||||
Conditionally skip a test with an optional description.
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
@ -642,7 +704,42 @@ test('skip in WebKit', async ({ page, browserName }) => {
|
||||
});
|
||||
```
|
||||
|
||||
Conditionally skip all tests in a file or [`method: Test.describe`] group:
|
||||
Skip from [`method: Test.beforeEach`] hook:
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1');
|
||||
await page.goto('/settings');
|
||||
});
|
||||
```
|
||||
|
||||
```js js-flavor=ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1');
|
||||
await page.goto('/settings');
|
||||
});
|
||||
```
|
||||
|
||||
### param: Test.skip#3.condition
|
||||
- `condition` <[boolean]>
|
||||
|
||||
A skip condition. Test or tests are skipped when the condition is `true`.
|
||||
|
||||
### param: Test.skip#3.description
|
||||
- `description` <[void]|[string]>
|
||||
|
||||
An optional description that will be reflected in a test report.
|
||||
|
||||
|
||||
|
||||
|
||||
## method: Test.skip#4
|
||||
|
||||
Conditionally skips all tests in a file or [`method: Test.describe`] group.
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
@ -670,35 +767,16 @@ test('skip in WebKit 2', async ({ page }) => {
|
||||
});
|
||||
```
|
||||
|
||||
Skip from a hook:
|
||||
|
||||
```js js-flavor=js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
### param: Test.skip#4.condition
|
||||
- `callback` <[function]\([Fixtures]\):[boolean]>
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1');
|
||||
await page.goto('/settings');
|
||||
});
|
||||
```
|
||||
A function that returns whether to skip, based on test fixtures. Test or tests are skipped when the return value is `true`.
|
||||
|
||||
```js js-flavor=ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
### param: Test.skip#4.description
|
||||
- `description` <[void]|[string]>
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1');
|
||||
await page.goto('/settings');
|
||||
});
|
||||
```
|
||||
|
||||
### param: Test.skip.condition
|
||||
- `titleOrCondition` <[string]|[void]|[boolean]|[function]\([Fixtures]\):[boolean]>
|
||||
|
||||
When used with `test.skip('test', () => {})` notation, first argument is a test title. Otherwise it is an optional skip condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are skipped when the condition is `true`.
|
||||
|
||||
### param: Test.skip.description
|
||||
- `testFunctionOrDescription` <[function]\([Fixtures], [TestInfo]\)|[void]|[string]>
|
||||
|
||||
When used with `test.skip('test', () => {})` notation, second argument is a test function. Otherwise it is an optional description that will be reflected in a test report.
|
||||
An optional description that will be reflected in a test report.
|
||||
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ An error thrown during test execution, if any.
|
||||
- type: <[TestStatus]<"passed"|"failed"|"timedOut"|"skipped">>
|
||||
|
||||
Expected status for the currently running test. This is usually `'passed'`, except for a few cases:
|
||||
* `'skipped'` for skipped tests, e.g. with [`method: Test.skip`];
|
||||
* `'skipped'` for skipped tests, e.g. with [`method: Test.skip#2`];
|
||||
* `'failed'` for tests marked as failed with [`method: Test.fail`].
|
||||
|
||||
Expected status is usually compared with the actual [`property: TestInfo.status`]:
|
||||
@ -246,7 +246,7 @@ Timeout in milliseconds.
|
||||
|
||||
## method: TestInfo.skip
|
||||
|
||||
Skips the currently running test. This is similar to [`method: Test.skip`].
|
||||
Skips the currently running test. This is similar to [`method: Test.skip#2`].
|
||||
|
||||
### param: TestInfo.skip.condition
|
||||
- `condition` <[void]|[boolean]>
|
||||
|
@ -18,7 +18,7 @@ Learn more about [test annotations](./test-annotations.md).
|
||||
- type: <[TestStatus]<"passed"|"failed"|"timedOut"|"skipped">>
|
||||
|
||||
Expected test status.
|
||||
* Tests marked as [`method: Test.skip`] or [`method: Test.fixme`] are expected to be `'skipped'`.
|
||||
* Tests marked as [`method: Test.skip#1`] or [`method: Test.fixme`] are expected to be `'skipped'`.
|
||||
* Tests marked as [`method: Test.fail`] are expected to be `'failed'`.
|
||||
* Other tests are expected to be `'passed'`.
|
||||
|
||||
|
1144
types/test.d.ts
vendored
1144
types/test.d.ts
vendored
File diff suppressed because it is too large
Load Diff
3
types/testReporter.d.ts
vendored
3
types/testReporter.d.ts
vendored
@ -113,8 +113,7 @@ export interface TestCase {
|
||||
titlePath(): string[];
|
||||
/**
|
||||
* Expected test status.
|
||||
* - Tests marked as
|
||||
* [test.skip(titleOrCondition, testFunctionOrDescription)](https://playwright.dev/docs/api/class-test#test-skip) or
|
||||
* - Tests marked as [test.skip(title, testFunction)](https://playwright.dev/docs/api/class-test#test-skip-1) or
|
||||
* [test.fixme([condition, description])](https://playwright.dev/docs/api/class-test#test-fixme) are expected to be
|
||||
* `'skipped'`.
|
||||
* - Tests marked as [test.fail([condition, description])](https://playwright.dev/docs/api/class-test#test-fail) are
|
||||
|
1185
types/types.d.ts
vendored
1185
types/types.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -136,7 +136,7 @@ class ApiParser {
|
||||
const clazz = this.classes.get(className);
|
||||
if (!clazz)
|
||||
throw new Error('Invalid class ' + className);
|
||||
const method = clazz.membersArray.find(m => m.kind === 'method' && m.alias === methodName);
|
||||
const method = clazz.membersArray.find(m => m.kind === 'method' && m.name === methodName);
|
||||
if (!method)
|
||||
throw new Error(`Invalid method ${className}.${methodName} when parsing: ${match[0]}`);
|
||||
if (!name)
|
||||
|
@ -312,6 +312,12 @@ Documentation.Member = class {
|
||||
};
|
||||
this.async = false;
|
||||
this.alias = name;
|
||||
this.overloadIndex = 0;
|
||||
if (name.includes('#')) {
|
||||
const match = name.match(/(.*)#(.*)/);
|
||||
this.alias = match[1];
|
||||
this.overloadIndex = (+match[2]) - 1;
|
||||
}
|
||||
/**
|
||||
* Param is true and option false
|
||||
* @type {Boolean}
|
||||
|
@ -87,9 +87,14 @@ class TypesGenerator {
|
||||
return '';
|
||||
handledClasses.add(className);
|
||||
return this.writeComment(docClass.comment) + '\n';
|
||||
}, (className, methodName) => {
|
||||
}, (className, methodName, overloadIndex) => {
|
||||
const docClass = this.docClassForName(className, docsOnlyClassMapping);
|
||||
const method = docClass ? docClass.membersArray.find(m => m.alias === methodName) : undefined;
|
||||
let method;
|
||||
if (docClass) {
|
||||
const methods = docClass.membersArray.filter(m => m.alias === methodName && m.kind !== 'event').sort((a, b) => a.overloadIndex - b.overloadIndex);
|
||||
// Use the last overload when not enough overloads are defined in docs.
|
||||
method = methods.find(m => m.overloadIndex === overloadIndex) || methods[methods.length - 1];
|
||||
}
|
||||
if (docsOnlyClassMapping && !method)
|
||||
return '';
|
||||
this.handledMethods.add(`${className}.${methodName}`);
|
||||
@ -381,7 +386,7 @@ class TypesGenerator {
|
||||
argsFromMember(member, indent, ...namespace) {
|
||||
if (member.kind === 'property')
|
||||
return '';
|
||||
return '(' + member.argsArray.map(arg => `${this.nameForProperty(arg)}: ${this.stringifyComplexType(arg.type, indent, ...namespace, member.name, arg.name)}`).join(', ') + ')';
|
||||
return '(' + member.argsArray.map(arg => `${this.nameForProperty(arg)}: ${this.stringifyComplexType(arg.type, indent, ...namespace, member.alias, arg.alias)}`).join(', ') + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
|
6
utils/generate_types/overrides-test.d.ts
vendored
6
utils/generate_types/overrides-test.d.ts
vendored
@ -229,10 +229,8 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
|
||||
};
|
||||
skip(title: string, testFunction: (args: TestArgs, testInfo: TestInfo) => Promise<void> | void): void;
|
||||
skip(): void;
|
||||
skip(condition: boolean): void;
|
||||
skip(condition: boolean, description: string): void;
|
||||
skip(callback: (args: TestArgs & WorkerArgs) => boolean): void;
|
||||
skip(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void;
|
||||
skip(condition: boolean, description?: string): void;
|
||||
skip(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void;
|
||||
fixme(): void;
|
||||
fixme(condition: boolean): void;
|
||||
fixme(condition: boolean, description: string): void;
|
||||
|
@ -20,7 +20,7 @@ const ts = require('typescript');
|
||||
/**
|
||||
* @param {string} filePath
|
||||
* @param {(className: string) => string} commentForClass
|
||||
* @param {(className: string, methodName: string) => string} commentForMethod
|
||||
* @param {(className: string, methodName: string, overloadIndex: number) => string} commentForMethod
|
||||
* @param {(className: string) => string} extraForClass
|
||||
*/
|
||||
async function parseOverrides(filePath, commentForClass, commentForMethod, extraForClass) {
|
||||
@ -76,13 +76,16 @@ async function parseOverrides(filePath, commentForClass, commentForMethod, extra
|
||||
for (const [name, member] of symbol.members || []) {
|
||||
if (member.flags & ts.SymbolFlags.TypeParameter)
|
||||
continue;
|
||||
if (!member.valueDeclaration)
|
||||
if (!member.declarations)
|
||||
continue;
|
||||
const pos = member.valueDeclaration.getStart(file, false);
|
||||
replacers.push({
|
||||
pos,
|
||||
text: commentForMethod(className, name),
|
||||
});
|
||||
for (let index = 0; index < member.declarations.length; index++) {
|
||||
const declaration = member.declarations[index];
|
||||
const pos = declaration.getStart(file, false);
|
||||
replacers.push({
|
||||
pos,
|
||||
text: commentForMethod(className, name, index),
|
||||
});
|
||||
}
|
||||
}
|
||||
replacers.push({
|
||||
pos: node.getEnd(file) - 1,
|
||||
|
Loading…
x
Reference in New Issue
Block a user