chore: simplify ttests (#20733)

This commit is contained in:
Pavel Feldman 2023-02-07 15:11:44 -08:00 committed by GitHub
parent 2d3e4027e7
commit 1b941bcf2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 663 additions and 667 deletions

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should fail', async ({ runInlineTest }) => { test('should fail', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -286,17 +286,17 @@ test('should work with test wrapper', async ({ runInlineTest }) => {
}, { workers: 1, reporter: 'line' }); }, { workers: 1, reporter: 'line' });
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%a.spec', 'a.spec',
'%%helper', 'helper',
'%%b.spec', 'b.spec',
'%%a.spec', 'a.spec',
'%%helper', 'helper',
'%%test1', 'test1',
'%%suite1.test1', 'suite1.test1',
'%%b.spec', 'b.spec',
'%%test2', 'test2',
'%%suite2.test2', 'suite2.test2',
]); ]);
}); });
@ -335,19 +335,19 @@ test('should work with test helper', async ({ runInlineTest }) => {
}, { workers: 1, reporter: 'line' }); }, { workers: 1, reporter: 'line' });
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%a.spec', 'a.spec',
'%%helper-a', 'helper-a',
'%%b.spec', 'b.spec',
'%%helper-b', 'helper-b',
'%%a.spec', 'a.spec',
'%%helper-a', 'helper-a',
'%%test1', 'test1',
'%%suite1.test1', 'suite1.test1',
'%%b.spec', 'b.spec',
'%%helper-b', 'helper-b',
'%%test2', 'test2',
'%%suite2.test2', 'suite2.test2',
]); ]);
}); });
@ -365,7 +365,7 @@ test('should support describe() without a title', async ({ runInlineTest }) => {
}, { reporter: 'list' }); }, { reporter: 'list' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(stripAnsi(result.output)).toContain('a.spec.js:8:17 suite1 suite2 my test'); expect(result.output).toContain('a.spec.js:8:17 suite1 suite2 my test');
}); });
test('test.{skip,fixme} should define a skipped test', async ({ runInlineTest }) => { test('test.{skip,fixme} should define a skipped test', async ({ runInlineTest }) => {

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should run projects with dependencies', async ({ runInlineTest }) => { test('should run projects with dependencies', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -35,7 +35,7 @@ test('should run projects with dependencies', async ({ runInlineTest }) => {
}, { workers: 1 }, undefined, { additionalArgs: ['--project=B', '--project=C'] }); }, { workers: 1 }, undefined, { additionalArgs: ['--project=B', '--project=C'] });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(3); expect(result.passed).toBe(3);
expect(extractLines(result.output)).toEqual(['A', 'B', 'C']); expect(result.outputLines).toEqual(['A', 'B', 'C']);
}); });
test('should not run projects with dependencies when --no-deps is passed', async ({ runInlineTest }) => { test('should not run projects with dependencies when --no-deps is passed', async ({ runInlineTest }) => {
@ -57,7 +57,7 @@ test('should not run projects with dependencies when --no-deps is passed', async
}, { workers: 1 }, undefined, { additionalArgs: ['--no-deps', '--project=B', '--project=C'] }); }, { workers: 1 }, undefined, { additionalArgs: ['--no-deps', '--project=B', '--project=C'] });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(extractLines(result.output)).toEqual(['B', 'C']); expect(result.outputLines).toEqual(['B', 'C']);
}); });
test('should not run project if dependency failed', async ({ runInlineTest }) => { test('should not run project if dependency failed', async ({ runInlineTest }) => {
@ -84,7 +84,7 @@ test('should not run project if dependency failed', async ({ runInlineTest }) =>
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output).toContain('Failed project B'); expect(result.output).toContain('Failed project B');
expect(extractLines(result.output)).toEqual(['A', 'B']); expect(result.outputLines).toEqual(['A', 'B']);
}); });
test('should not run project if dependency failed (2)', async ({ runInlineTest }) => { test('should not run project if dependency failed (2)', async ({ runInlineTest }) => {
@ -110,7 +110,7 @@ test('should not run project if dependency failed (2)', async ({ runInlineTest }
`, `,
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(extractLines(result.output).sort()).toEqual(['A1', 'A2', 'A3', 'B1']); expect(result.outputLines.sort()).toEqual(['A1', 'A2', 'A3', 'B1']);
}); });
test('should filter by project list, but run deps', async ({ runInlineTest }) => { test('should filter by project list, but run deps', async ({ runInlineTest }) => {
@ -133,7 +133,7 @@ test('should filter by project list, but run deps', async ({ runInlineTest }) =>
expect(result.passed).toBe(3); expect(result.passed).toBe(3);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(extractLines(result.output).sort()).toEqual(['A', 'C', 'D']); expect(result.outputLines.sort()).toEqual(['A', 'C', 'D']);
}); });
@ -174,7 +174,7 @@ test('should not filter dependency by only', async ({ runInlineTest }) => {
});`, });`,
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(extractLines(result.output)).toEqual(['setup in setup', 'setup 2 in setup', 'test in browser']); expect(result.outputLines).toEqual(['setup in setup', 'setup 2 in setup', 'test in browser']);
}); });
test('should not filter dependency by only 2', async ({ runInlineTest }) => { test('should not filter dependency by only 2', async ({ runInlineTest }) => {
@ -198,7 +198,7 @@ test('should not filter dependency by only 2', async ({ runInlineTest }) => {
});`, });`,
}, { project: ['setup'] }); }, { project: ['setup'] });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(extractLines(result.output)).toEqual(['setup 2 in setup']); expect(result.outputLines).toEqual(['setup 2 in setup']);
}); });
test('should not filter dependency by only 3', async ({ runInlineTest }) => { test('should not filter dependency by only 3', async ({ runInlineTest }) => {
@ -224,7 +224,7 @@ test('should not filter dependency by only 3', async ({ runInlineTest }) => {
});`, });`,
}, undefined, undefined, { additionalArgs: ['setup-2.ts'] }); }, undefined, undefined, { additionalArgs: ['setup-2.ts'] });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(extractLines(result.output)).toEqual(['setup 2 in setup']); expect(result.outputLines).toEqual(['setup 2 in setup']);
}); });
test('should report skipped dependent tests', async ({ runInlineTest }) => { test('should report skipped dependent tests', async ({ runInlineTest }) => {
@ -261,7 +261,3 @@ test('should report circular dependencies', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain('Circular dependency detected between projects.'); expect(result.output).toContain('Circular dependency detected between projects.');
}); });
function extractLines(output: string): string[] {
return stripAnsi(output).split('\n').filter(line => line.startsWith('%%')).map(line => line.substring(2).trim());
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should load nested as esm when package.json has type module', async ({ runInlineTest }) => { test('should load nested as esm when package.json has type module', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -163,7 +163,7 @@ test('should use source maps', async ({ runInlineTest, nodeVersion }) => {
` `
}, { reporter: 'list' }); }, { reporter: 'list' });
const output = stripAnsi(result.output); const output = result.output;
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(output).toContain('[foo] a.test.ts:7:7 check project name'); expect(output).toContain('[foo] a.test.ts:7:7 check project name');
@ -195,7 +195,7 @@ test('should show the codeframe in errors', async ({ runInlineTest, nodeVersion
FORCE_COLOR: '0', FORCE_COLOR: '0',
}); });
const output = stripAnsi(result.output); const output = result.output;
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(2); expect(result.failed).toBe(2);
expect(output, 'error carrot—via source maps—is positioned appropriately').toContain( expect(output, 'error carrot—via source maps—is positioned appropriately').toContain(

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
function monotonicTime(): number { function monotonicTime(): number {
const [seconds, nanoseconds] = process.hrtime(); const [seconds, nanoseconds] = process.hrtime();
@ -46,7 +46,7 @@ test('should work with not defined errors', async ({ runInlineTest }) => {
foo(); foo();
` `
}); });
expect(stripAnsi(result.output)).toContain('foo is not defined'); expect(result.output).toContain('foo is not defined');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should poll predicate', async ({ runInlineTest }) => { test('should poll predicate', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -78,9 +78,9 @@ test('should respect timeout', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Timeout 100ms exceeded while waiting on the predicate'); expect(result.output).toContain('Timeout 100ms exceeded while waiting on the predicate');
expect(stripAnsi(result.output)).toContain('Received: false'); expect(result.output).toContain('Received: false');
expect(stripAnsi(result.output)).toContain(` expect(result.output).toContain(`
7 | await test.expect.poll(() => false, { timeout: 100 }). 7 | await test.expect.poll(() => false, { timeout: 100 }).
`.trim()); `.trim());
}); });
@ -95,7 +95,7 @@ test('should fail when passed in non-function', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Error: `expect.poll()` accepts only function as a first argument'); expect(result.output).toContain('Error: `expect.poll()` accepts only function as a first argument');
}); });
test('should fail when used with web-first assertion', async ({ runInlineTest }) => { test('should fail when used with web-first assertion', async ({ runInlineTest }) => {
@ -108,7 +108,7 @@ test('should fail when used with web-first assertion', async ({ runInlineTest })
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Error: `expect.poll()` does not support "toHaveText" matcher'); expect(result.output).toContain('Error: `expect.poll()` does not support "toHaveText" matcher');
}); });
test('should time out when running infinite predicate', async ({ runInlineTest }) => { test('should time out when running infinite predicate', async ({ runInlineTest }) => {
@ -121,7 +121,7 @@ test('should time out when running infinite predicate', async ({ runInlineTest }
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Timeout 100ms exceeded'); expect(result.output).toContain('Timeout 100ms exceeded');
}); });
test('should show error that is thrown from predicate', async ({ runInlineTest }) => { test('should show error that is thrown from predicate', async ({ runInlineTest }) => {
@ -134,7 +134,7 @@ test('should show error that is thrown from predicate', async ({ runInlineTest }
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('foo bar baz'); expect(result.output).toContain('foo bar baz');
}); });
test('should not retry predicate that threw an error', async ({ runInlineTest }) => { test('should not retry predicate that threw an error', async ({ runInlineTest }) => {
@ -152,7 +152,7 @@ test('should not retry predicate that threw an error', async ({ runInlineTest })
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('foo bar baz'); expect(result.output).toContain('foo bar baz');
}); });
test('should support .not predicate', async ({ runInlineTest }) => { test('should support .not predicate', async ({ runInlineTest }) => {

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('soft expects should compile', async ({ runTSC }) => { test('soft expects should compile', async ({ runTSC }) => {
const result = await runTSC({ const result = await runTSC({
@ -41,7 +41,7 @@ test('soft expects should work', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('woof-woof'); expect(result.output).toContain('woof-woof');
}); });
test('should report a mixture of soft and non-soft errors', async ({ runInlineTest }) => { test('should report a mixture of soft and non-soft errors', async ({ runInlineTest }) => {
@ -57,10 +57,10 @@ test('should report a mixture of soft and non-soft errors', async ({ runInlineTe
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Error: one plus one'); expect(result.output).toContain('Error: one plus one');
expect(stripAnsi(result.output)).toContain('Error: two times two'); expect(result.output).toContain('Error: two times two');
expect(stripAnsi(result.output)).toContain('Error: three div three'); expect(result.output).toContain('Error: three div three');
expect(stripAnsi(result.output)).not.toContain('Error: six minus four'); expect(result.output).not.toContain('Error: six minus four');
}); });
test('testInfo should contain all soft expect errors', async ({ runInlineTest }) => { test('testInfo should contain all soft expect errors', async ({ runInlineTest }) => {
@ -75,7 +75,7 @@ test('testInfo should contain all soft expect errors', async ({ runInlineTest })
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Error: one plus one'); expect(result.output).toContain('Error: one plus one');
expect(stripAnsi(result.output)).toContain('Error: two times two'); expect(result.output).toContain('Error: two times two');
expect(stripAnsi(result.output)).not.toContain('Error: must be exactly two errors'); expect(result.output).not.toContain('Error: must be exactly two errors');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should retry predicate', async ({ runInlineTest }) => { test('should retry predicate', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -60,9 +60,9 @@ test('should respect timeout', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('Timeout 100ms exceeded while waiting on the predicate'); expect(result.output).toContain('Timeout 100ms exceeded while waiting on the predicate');
expect(stripAnsi(result.output)).toContain('Received: 1'); expect(result.output).toContain('Received: 1');
expect(stripAnsi(result.output)).toContain(` expect(result.output).toContain(`
7 | await test.expect(() => { 7 | await test.expect(() => {
`.trim()); `.trim());
}); });
@ -154,7 +154,7 @@ test('should use custom message', async ({ runInlineTest }) => {
}); });
` `
}); });
expect(stripAnsi(result.output)).toContain('Error: Custom message'); expect(result.output).toContain('Error: Custom message');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
}); });
@ -176,9 +176,9 @@ test('should swallow all soft errors inside toPass matcher, if successful', asyn
}); });
` `
}); });
expect(stripAnsi(result.output)).toContain('Received: "before-toPass"'); expect(result.output).toContain('Received: "before-toPass"');
expect(stripAnsi(result.output)).toContain('Received: "after-toPass"'); expect(result.output).toContain('Received: "after-toPass"');
expect(stripAnsi(result.output)).not.toContain('Received: "inside-toPass-1"'); expect(result.output).not.toContain('Received: "inside-toPass-1"');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
}); });
@ -214,9 +214,9 @@ test('should show only soft errors on last toPass pass', async ({ runInlineTest
}); });
` `
}); });
expect(stripAnsi(result.output)).not.toContain('Received: "inside-toPass-1"'); expect(result.output).not.toContain('Received: "inside-toPass-1"');
expect(stripAnsi(result.output)).not.toContain('Received: "inside-toPass-2"'); expect(result.output).not.toContain('Received: "inside-toPass-2"');
expect(stripAnsi(result.output)).toContain('Received: "inside-toPass-3"'); expect(result.output).toContain('Received: "inside-toPass-3"');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
}); });
@ -233,8 +233,8 @@ test('should work with soft', async ({ runInlineTest }) => {
}); });
` `
}); });
expect(stripAnsi(result.output)).toContain('Received: 1'); expect(result.output).toContain('Received: 1');
expect(stripAnsi(result.output)).toContain('Received: 2'); expect(result.output).toContain('Received: 2');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
}); });

View file

@ -15,7 +15,7 @@
*/ */
import path from 'path'; import path from 'path';
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should be able to call expect.extend in config', async ({ runInlineTest }) => { test('should be able to call expect.extend in config', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -79,7 +79,7 @@ test('should include custom error message', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(stripAnsi(result.output)).toContain([ expect(result.output).toContain([
` Error: one plus one is two!`, ` Error: one plus one is two!`,
``, ``,
` Expected: 3`, ` Expected: 3`,
@ -494,7 +494,7 @@ test('should reasonably work in global setup', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('> 11 | expect(1).toBe(2);'); expect(result.output).toContain('> 11 | expect(1).toBe(2);');
}); });
test('should support toHaveURL with baseURL from webServer', async ({ runInlineTest }, testInfo) => { test('should support toHaveURL with baseURL from webServer', async ({ runInlineTest }, testInfo) => {
@ -523,7 +523,7 @@ test('should support toHaveURL with baseURL from webServer', async ({ runInlineT
}; };
`, `,
}, { workers: 1 }); }, { workers: 1 });
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('expect(page).toHaveURL'); expect(output).toContain('expect(page).toHaveURL');
expect(output).toContain(`Expected string: \"http://localhost:${port}/kek\"`); expect(output).toContain(`Expected string: \"http://localhost:${port}/kek\"`);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
@ -560,7 +560,7 @@ test('should log scale the time', async ({ runInlineTest }) => {
}); });
`, `,
}, { workers: 1 }); }, { workers: 1 });
const output = stripAnsi(result.output); const output = result.output;
const tokens = output.split('unexpected value'); const tokens = output.split('unexpected value');
// Log scale: 0, 100, 250, 500, 1000, 1000, should be less than 8. // Log scale: 0, 100, 250, 500, 1000, 1000, should be less than 8.
expect(tokens.length).toBeGreaterThan(1); expect(tokens.length).toBeGreaterThan(1);
@ -585,8 +585,8 @@ test('should print expected/received before timeout', async ({ runInlineTest })
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Test timeout of 2000ms exceeded.'); expect(result.output).toContain('Test timeout of 2000ms exceeded.');
expect(stripAnsi(result.output)).toContain('Expected string: "Text 2"'); expect(result.output).toContain('Expected string: "Text 2"');
expect(stripAnsi(result.output)).toContain('Received string: "Text content"'); expect(result.output).toContain('Received string: "Text content"');
}); });
test('should print pending operations for toHaveText', async ({ runInlineTest }) => { test('should print pending operations for toHaveText', async ({ runInlineTest }) => {
@ -602,7 +602,7 @@ test('should print pending operations for toHaveText', async ({ runInlineTest })
}, { workers: 1, timeout: 2000 }); }, { workers: 1, timeout: 2000 });
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Pending operations:'); expect(output).toContain('Pending operations:');
expect(output).toContain('expect(received).toHaveText(expected)'); expect(output).toContain('expect(received).toHaveText(expected)');
expect(output).toContain('Expected string: "Text"'); expect(output).toContain('Expected string: "Text"');
@ -629,8 +629,8 @@ test('should print expected/received on Ctrl+C', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(130); expect(result.exitCode).toBe(130);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.interrupted).toBe(1); expect(result.interrupted).toBe(1);
expect(stripAnsi(result.output)).toContain('Expected string: "Text 2"'); expect(result.output).toContain('Expected string: "Text 2"');
expect(stripAnsi(result.output)).toContain('Received string: "Text content"'); expect(result.output).toContain('Received string: "Text content"');
}); });
test('should print timed out error message', async ({ runInlineTest }) => { test('should print timed out error message', async ({ runInlineTest }) => {
@ -646,7 +646,7 @@ test('should print timed out error message', async ({ runInlineTest }) => {
}, { workers: 1 }); }, { workers: 1 });
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Timed out 1ms waiting for expect(received).toBeChecked()'); expect(output).toContain('Timed out 1ms waiting for expect(received).toBeChecked()');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, countTimes, stripAnsi } from './playwright-test-fixtures'; import { test, expect, countTimes } from './playwright-test-fixtures';
test('should handle fixture timeout', async ({ runInlineTest }) => { test('should handle fixture timeout', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -129,7 +129,7 @@ test('should throw when using non-defined super worker fixture', async ({ runInl
}); });
expect(result.output).toContain(`Fixture "foo" references itself, but does not have a base implementation.`); expect(result.output).toContain(`Fixture "foo" references itself, but does not have a base implementation.`);
expect(result.output).toContain('a.spec.ts:5'); expect(result.output).toContain('a.spec.ts:5');
expect(stripAnsi(result.output)).toContain('const test = pwt.test.extend'); expect(result.output).toContain('const test = pwt.test.extend');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -152,7 +152,7 @@ test('should throw when defining test fixture with the same name as a worker fix
}); });
expect(result.output).toContain(`Fixture "foo" has already been registered as a { scope: 'worker' } fixture defined in e.spec.ts:5:30.`); expect(result.output).toContain(`Fixture "foo" has already been registered as a { scope: 'worker' } fixture defined in e.spec.ts:5:30.`);
expect(result.output).toContain(`e.spec.ts:10`); expect(result.output).toContain(`e.spec.ts:10`);
expect(stripAnsi(result.output)).toContain('const test2 = test1.extend'); expect(result.output).toContain('const test2 = test1.extend');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -175,7 +175,7 @@ test('should throw when defining worker fixture with the same name as a test fix
}); });
expect(result.output).toContain(`Fixture "foo" has already been registered as a { scope: 'test' } fixture defined in e.spec.ts:5:30.`); expect(result.output).toContain(`Fixture "foo" has already been registered as a { scope: 'test' } fixture defined in e.spec.ts:5:30.`);
expect(result.output).toContain(`e.spec.ts:10`); expect(result.output).toContain(`e.spec.ts:10`);
expect(stripAnsi(result.output)).toContain('const test2 = test1.extend'); expect(result.output).toContain('const test2 = test1.extend');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -258,7 +258,7 @@ test('should not reuse fixtures from one file in another one', async ({ runInlin
}); });
expect(result.output).toContain('Test has unknown parameter "foo".'); expect(result.output).toContain('Test has unknown parameter "foo".');
expect(result.output).toContain('b.spec.ts:7'); expect(result.output).toContain('b.spec.ts:7');
expect(stripAnsi(result.output)).toContain(`test('test2', async ({foo}) => {})`); expect(result.output).toContain(`test('test2', async ({foo}) => {})`);
}); });
test('should throw for cycle in two overrides', async ({ runInlineTest }) => { test('should throw for cycle in two overrides', async ({ runInlineTest }) => {
@ -315,7 +315,7 @@ test('should throw for unknown fixture parameter', async ({ runInlineTest }) =>
}); });
expect(result.output).toContain('Fixture "foo" has unknown parameter "bar".'); expect(result.output).toContain('Fixture "foo" has unknown parameter "bar".');
expect(result.output).toContain('f.spec.ts:5'); expect(result.output).toContain('f.spec.ts:5');
expect(stripAnsi(result.output)).toContain('const test = pwt.test.extend'); expect(result.output).toContain('const test = pwt.test.extend');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -407,9 +407,9 @@ test('should give enough time for fixture teardown', async ({ runInlineTest }) =
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Test timeout of 1000ms exceeded while tearing down "fixture".'); expect(result.output).toContain('Test timeout of 1000ms exceeded while tearing down "fixture".');
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%teardown start', 'teardown start',
'%%teardown finished', 'teardown finished',
]); ]);
}); });
@ -430,7 +430,7 @@ test('should not teardown when setup times out', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Test timeout of 1000ms exceeded while setting up "fixture".'); expect(result.output).toContain('Test timeout of 1000ms exceeded while setting up "fixture".');
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
]); ]);
}); });
@ -450,8 +450,8 @@ test('should not report fixture teardown error twice', async ({ runInlineTest })
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Error: Oh my error'); expect(result.output).toContain('Error: Oh my error');
expect(stripAnsi(result.output)).toContain(`throw new Error('Oh my error')`); expect(result.output).toContain(`throw new Error('Oh my error')`);
expect(countTimes(stripAnsi(result.output), 'Oh my error')).toBe(2); expect(countTimes(result.output, 'Oh my error')).toBe(2);
}); });
test('should not report fixture teardown timeout twice', async ({ runInlineTest }) => { test('should not report fixture teardown timeout twice', async ({ runInlineTest }) => {
@ -470,7 +470,7 @@ test('should not report fixture teardown timeout twice', async ({ runInlineTest
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Test timeout of 1000ms exceeded while tearing down "fixture".'); expect(result.output).toContain('Test timeout of 1000ms exceeded while tearing down "fixture".');
expect(stripAnsi(result.output)).not.toContain('pwt.test.extend'); // Should not point to the location. expect(result.output).not.toContain('pwt.test.extend'); // Should not point to the location.
// TODO: this should be "not.toContain" actually. // TODO: this should be "not.toContain" actually.
expect(result.output).toContain('Worker teardown timeout of 1000ms exceeded while tearing down "fixture".'); expect(result.output).toContain('Worker teardown timeout of 1000ms exceeded while tearing down "fixture".');
}); });
@ -514,7 +514,7 @@ test('should report worker fixture teardown with debug info', async ({ runInline
}, { reporter: 'list', timeout: 1000 }); }, { reporter: 'list', timeout: 1000 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(20); expect(result.passed).toBe(20);
expect(stripAnsi(result.output)).toContain([ expect(result.output).toContain([
'Worker teardown timeout of 1000ms exceeded while tearing down "fixture".', 'Worker teardown timeout of 1000ms exceeded while tearing down "fixture".',
'', '',
'Failed worker ran 20 tests, last 10 tests were:', 'Failed worker ran 20 tests, last 10 tests were:',
@ -578,8 +578,8 @@ test('should not run user fn when require fixture has failed', async ({ runInlin
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%foo', 'foo',
]); ]);
}); });
@ -616,5 +616,5 @@ test('should provide helpful error message when digests do not match', async ({
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('Playwright detected inconsistent test.use() options.'); expect(result.output).toContain('Playwright detected inconsistent test.use() options.');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should work', async ({ runInlineTest }) => { test('should work', async ({ runInlineTest }) => {
const { results } = await runInlineTest({ const { results } = await runInlineTest({
@ -168,7 +168,7 @@ test('should fail if parameters are not destructured', async ({ runInlineTest })
}); });
expect(result.output).toContain('First argument must use the object destructuring pattern: abc'); expect(result.output).toContain('First argument must use the object destructuring pattern: abc');
expect(result.output).toContain('a.test.js:11'); expect(result.output).toContain('a.test.js:11');
expect(stripAnsi(result.output)).toContain('function (abc)'); expect(result.output).toContain('function (abc)');
expect(result.results.length).toBe(0); expect(result.results.length).toBe(0);
}); });
@ -182,7 +182,7 @@ test('should fail with an unknown fixture', async ({ runInlineTest }) => {
}); });
expect(result.output).toContain('Test has unknown parameter "asdf".'); expect(result.output).toContain('Test has unknown parameter "asdf".');
expect(result.output).toContain('a.test.js:5'); expect(result.output).toContain('a.test.js:5');
expect(stripAnsi(result.output)).toContain('async ({asdf})'); expect(result.output).toContain('async ({asdf})');
expect(result.results.length).toBe(0); expect(result.results.length).toBe(0);
}); });
@ -375,11 +375,11 @@ test('automatic fixture should start before regular fixture and teardown after',
` `
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%auto-setup', 'auto-setup',
'%%foo-setup', 'foo-setup',
'%%foo-teardown', 'foo-teardown',
'%%auto-teardown', 'auto-teardown',
]); ]);
}); });
@ -664,12 +664,12 @@ test('should run tests in order', async ({ runInlineTest }) => {
`, `,
}, { workers: 1 }); }, { workers: 1 });
expect(result.passed).toBe(3); expect(result.passed).toBe(3);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%beforeEach', 'beforeEach',
'%%test2', 'test2',
'%%afterEach', 'afterEach',
'%%test3', 'test3',
]); ]);
}); });

View file

@ -103,10 +103,10 @@ test('should respect negations and comments in .gitignore', async ({ runInlineTe
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(3); expect(result.passed).toBe(3);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%a.spec.js', 'a.spec.js',
'%%dir1/foo/a.spec.js', 'dir1/foo/a.spec.js',
'%%dir3/a.spec.js', 'dir3/a.spec.js',
]); ]);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => { test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -46,10 +46,10 @@ test('globalSetup and globalTeardown should work', async ({ runInlineTest }) =>
}, { 'config': 'dir' }); }, { 'config': 'dir' });
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%from-global-setup', 'from-global-setup',
'%%from-test', 'from-test',
'%%from-global-teardown', 'from-global-teardown',
]); ]);
}); });
@ -187,7 +187,7 @@ test('globalSetup error should prevent tests from executing', async ({ runInline
`, `,
}, { reporter: 'line' }); }, { reporter: 'line' });
expect(stripAnsi(output)).not.toContain('this test ran'); expect(output).not.toContain('this test ran');
expect(passed).toBe(0); expect(passed).toBe(0);
}); });
@ -337,13 +337,13 @@ test('teardown order', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%setup 1', 'setup 1',
'%%setup 2', 'setup 2',
'%%setup 3', 'setup 3',
'%%teardown 3', 'teardown 3',
'%%teardown 2', 'teardown 2',
'%%teardown 1', 'teardown 1',
]); ]);
}); });
@ -368,17 +368,17 @@ test('teardown after error', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Error: failed teardown 1'); expect(output).toContain('Error: failed teardown 1');
expect(output).toContain('Error: failed teardown 2'); expect(output).toContain('Error: failed teardown 2');
expect(output).toContain('Error: failed teardown 3'); expect(output).toContain('Error: failed teardown 3');
expect(output).toContain('throw new Error(\'failed teardown'); expect(output).toContain('throw new Error(\'failed teardown');
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%setup 1', 'setup 1',
'%%setup 2', 'setup 2',
'%%setup 3', 'setup 3',
'%%teardown 3', 'teardown 3',
'%%teardown 2', 'teardown 2',
'%%teardown 1', 'teardown 1',
]); ]);
}); });

View file

@ -17,7 +17,7 @@
import colors from 'colors/safe'; import colors from 'colors/safe';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import { test, expect, stripAnsi, createWhiteImage, paintBlackPixels } from './playwright-test-fixtures'; import { test, expect, createWhiteImage, paintBlackPixels } from './playwright-test-fixtures';
const files = { const files = {
'helper.ts': ` 'helper.ts': `
@ -56,7 +56,7 @@ test('should work with non-txt extensions', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`1,2,34`); expect(result.output).toContain(`1,2,34`);
}); });
@ -130,8 +130,8 @@ Line7`,
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain('Line1'); expect(result.output).toContain('Line1');
expect(result.output).toContain('Line2' + colors.green('2')); expect(result.rawOutput).toContain('Line2' + colors.green('2'));
expect(result.output).toContain('line' + colors.reset(colors.strikethrough(colors.red('1'))) + colors.green('2')); expect(result.rawOutput).toContain('line' + colors.reset(colors.strikethrough(colors.red('1'))) + colors.green('2'));
expect(result.output).toContain('Line3'); expect(result.output).toContain('Line3');
expect(result.output).toContain('Line5'); expect(result.output).toContain('Line5');
expect(result.output).toContain('Line7'); expect(result.output).toContain('Line7');
@ -150,7 +150,7 @@ test('should write detailed failure result to an output folder', async ({ runInl
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const outputText = stripAnsi(result.output); const outputText = result.output;
expect(outputText).toContain('Snapshot comparison failed:'); expect(outputText).toContain('Snapshot comparison failed:');
const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.txt'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.txt');
const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.txt'); const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.txt');
@ -173,7 +173,7 @@ test("doesn\'t create comparison artifacts in an output folder for passed negate
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
const outputText = stripAnsi(result.output); const outputText = result.output;
const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.txt'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.txt');
const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.txt'); const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.txt');
expect(outputText).not.toContain(`Expected: ${expectedSnapshotArtifactPath}`); expect(outputText).not.toContain(`Expected: ${expectedSnapshotArtifactPath}`);
@ -225,7 +225,7 @@ test('should write missing expectations locally twice and continue', async ({ ru
expect(result.output).toContain('Here we are!'); expect(result.output).toContain('Here we are!');
const stackLines = stripAnsi(result.output).split('\n').filter(line => line.includes(' at ')).filter(line => !line.includes(testInfo.outputPath())); const stackLines = result.output.split('\n').filter(line => line.includes(' at ')).filter(line => !line.includes(testInfo.outputPath()));
expect(result.output).toContain('a.spec.js:8'); expect(result.output).toContain('a.spec.js:8');
expect(stackLines.length).toBe(0); expect(stackLines.length).toBe(0);
}); });
@ -450,8 +450,8 @@ test('should respect maxDiffPixels option', async ({ runInlineTest }) => {
}); });
` `
}); });
expect(stripAnsi(result.output)).toContain('120 pixels'); expect(result.output).toContain('120 pixels');
expect(stripAnsi(result.output)).toContain('ratio 0.30'); expect(result.output).toContain('ratio 0.30');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -561,7 +561,7 @@ test('should compare different PNG images', async ({ runInlineTest }, testInfo)
` `
}); });
const outputText = stripAnsi(result.output); const outputText = result.output;
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(outputText).toContain('Screenshot comparison failed:'); expect(outputText).toContain('Screenshot comparison failed:');
const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.png'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.png');
@ -863,7 +863,7 @@ test('should attach expected/actual/diff with snapshot path', async ({ runInline
` `
}); });
const outputText = stripAnsi(result.output); const outputText = result.output;
const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0]; const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0];
for (const attachment of attachments) { for (const attachment of attachments) {
attachment.path = attachment.path.replace(/\\/g, '/').replace(/.*test-results\//, ''); attachment.path = attachment.path.replace(/\\/g, '/').replace(/.*test-results\//, '');
@ -904,7 +904,7 @@ test('should attach expected/actual/diff', async ({ runInlineTest }, testInfo) =
` `
}); });
const outputText = stripAnsi(result.output); const outputText = result.output;
const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0]; const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0];
for (const attachment of attachments) for (const attachment of attachments)
attachment.path = attachment.path.replace(/\\/g, '/').replace(/.*test-results\//, ''); attachment.path = attachment.path.replace(/\\/g, '/').replace(/.*test-results\//, '');
@ -943,7 +943,7 @@ test('should attach expected/actual/diff for different sizes', async ({ runInlin
` `
}); });
const outputText = stripAnsi(result.output); const outputText = result.output;
expect(outputText).toContain('Expected an image 2px by 2px, received 1px by 1px.'); expect(outputText).toContain('Expected an image 2px by 2px, received 1px by 1px.');
expect(outputText).toContain('4 pixels (ratio 1.00 of all image pixels) are different.'); expect(outputText).toContain('4 pixels (ratio 1.00 of all image pixels) are different.');
const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0]; const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0];

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('hooks should work with fixtures', async ({ runInlineTest }) => { test('hooks should work with fixtures', async ({ runInlineTest }) => {
const { results } = await runInlineTest({ const { results } = await runInlineTest({
@ -154,10 +154,10 @@ test('beforeAll should be run once', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll1-1', 'beforeAll1-1',
'%%beforeAll2', 'beforeAll2',
'%%test', 'test',
]); ]);
}); });
@ -278,12 +278,12 @@ test('run hooks after failure', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test', 'test',
'%%afterEach-1', 'afterEach-1',
'%%afterEach-2', 'afterEach-2',
'%%afterAll-1', 'afterAll-1',
'%%afterAll-2', 'afterAll-2',
]); ]);
}); });
@ -302,11 +302,11 @@ test('beforeAll hook should get retry index of the first test', async ({ runInli
}, { retries: 1 }); }, { retries: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeall-retry-0', 'beforeall-retry-0',
'%%test-retry-0', 'test-retry-0',
'%%beforeall-retry-1', 'beforeall-retry-1',
'%%test-retry-1', 'test-retry-1',
]); ]);
}); });
@ -350,10 +350,10 @@ test('max-failures should still run afterEach/afterAll', async ({ runInlineTest
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test', 'test',
'%%afterEach', 'afterEach',
'%%afterAll', 'afterAll',
]); ]);
}); });
@ -379,9 +379,9 @@ test('beforeAll failure should prevent the test, but not afterAll', async ({ run
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%afterAll', 'afterAll',
]); ]);
}); });
@ -405,9 +405,9 @@ test('fixture error should not prevent afterAll', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('bad fixture'); expect(result.output).toContain('bad fixture');
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test', 'test',
'%%afterAll', 'afterAll',
]); ]);
}); });
@ -430,10 +430,10 @@ test('afterEach failure should not prevent afterAll', async ({ runInlineTest })
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('bad afterEach'); expect(result.output).toContain('bad afterEach');
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test', 'test',
'%%afterEach', 'afterEach',
'%%afterAll', 'afterAll',
]); ]);
}); });
@ -478,13 +478,13 @@ test('beforeAll timeout should be reported and prevent more tests', async ({ run
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%afterAll', 'afterAll',
]); ]);
expect(result.output).toContain('"beforeAll" hook timeout of 1000ms exceeded.'); expect(result.output).toContain('"beforeAll" hook timeout of 1000ms exceeded.');
expect(result.output).toContain(`a.test.js:6:12`); expect(result.output).toContain(`a.test.js:6:12`);
expect(stripAnsi(result.output)).toContain(`> 6 | test.beforeAll(async () => {`); expect(result.output).toContain(`> 6 | test.beforeAll(async () => {`);
}); });
test('afterAll timeout should be reported, run other afterAll hooks, and continue testing', async ({ runInlineTest }, testInfo) => { test('afterAll timeout should be reported, run other afterAll hooks, and continue testing', async ({ runInlineTest }, testInfo) => {
@ -513,16 +513,16 @@ test('afterAll timeout should be reported, run other afterAll hooks, and continu
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%afterAll1', 'afterAll1',
'%%afterAll2', 'afterAll2',
'%%test2', 'test2',
'%%afterAll2', 'afterAll2',
]); ]);
expect(result.output).toContain('"afterAll" hook timeout of 1000ms exceeded.'); expect(result.output).toContain('"afterAll" hook timeout of 1000ms exceeded.');
expect(result.output).toContain(`a.test.js:7:14`); expect(result.output).toContain(`a.test.js:7:14`);
expect(stripAnsi(result.output)).toContain(`> 7 | test.afterAll(async () => {`); expect(result.output).toContain(`> 7 | test.afterAll(async () => {`);
}); });
test('beforeAll and afterAll timeouts at the same time should be reported', async ({ runInlineTest }) => { test('beforeAll and afterAll timeouts at the same time should be reported', async ({ runInlineTest }) => {
@ -544,9 +544,9 @@ test('beforeAll and afterAll timeouts at the same time should be reported', asyn
}, { timeout: 1000 }); }, { timeout: 1000 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%afterAll', 'afterAll',
]); ]);
expect(result.output).toContain('"beforeAll" hook timeout of 1000ms exceeded.'); expect(result.output).toContain('"beforeAll" hook timeout of 1000ms exceeded.');
}); });
@ -570,9 +570,9 @@ test('afterEach should get the test status and duration right away', async ({ ru
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(2); expect(result.failed).toBe(2);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%failing: failed; XXms', 'failing: failed; XXms',
'%%timing out: timedOut; XXms', 'timing out: timedOut; XXms',
]); ]);
}); });
@ -598,8 +598,8 @@ test('uncaught error in beforeEach should not be masked by another error', async
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('Expected: 2'); expect(result.output).toContain('Expected: 2');
expect(stripAnsi(result.output)).toContain('Received: 1'); expect(result.output).toContain('Received: 1');
}); });
test('should report error from fixture teardown when beforeAll times out', async ({ runInlineTest }) => { test('should report error from fixture teardown when beforeAll times out', async ({ runInlineTest }) => {
@ -621,8 +621,8 @@ test('should report error from fixture teardown when beforeAll times out', async
}, { timeout: 1000 }); }, { timeout: 1000 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('"beforeAll" hook timeout of 1000ms exceeded.'); expect(result.output).toContain('"beforeAll" hook timeout of 1000ms exceeded.');
expect(stripAnsi(result.output)).toContain('Error: Oh my!'); expect(result.output).toContain('Error: Oh my!');
}); });
test('should not hang and report results when worker process suddenly exits during afterAll', async ({ runInlineTest }) => { test('should not hang and report results when worker process suddenly exits during afterAll', async ({ runInlineTest }) => {
@ -637,7 +637,7 @@ test('should not hang and report results when worker process suddenly exits duri
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Internal error: worker process exited unexpectedly'); expect(result.output).toContain('Internal error: worker process exited unexpectedly');
expect(stripAnsi(result.output)).toContain('[1/1] a.spec.js:6:7 failing due to afterall'); expect(result.output).toContain('[1/1] a.spec.js:6:7 failing due to afterall');
}); });
test('unhandled rejection during beforeAll should be reported and prevent more tests', async ({ runInlineTest }) => { test('unhandled rejection during beforeAll should be reported and prevent more tests', async ({ runInlineTest }) => {
@ -665,12 +665,12 @@ test('unhandled rejection during beforeAll should be reported and prevent more t
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%afterAll', 'afterAll',
]); ]);
expect(result.output).toContain('Error: Oh my'); expect(result.output).toContain('Error: Oh my');
expect(stripAnsi(result.output)).toContain(`> 9 | throw new Error('Oh my');`); expect(result.output).toContain(`> 9 | throw new Error('Oh my');`);
}); });
test('beforeAll and afterAll should have a separate timeout', async ({ runInlineTest }) => { test('beforeAll and afterAll should have a separate timeout', async ({ runInlineTest }) => {
@ -701,12 +701,12 @@ test('beforeAll and afterAll should have a separate timeout', async ({ runInline
}, { timeout: '500' }); }, { timeout: '500' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%beforeAll2', 'beforeAll2',
'%%test', 'test',
'%%afterAll', 'afterAll',
'%%afterAll2', 'afterAll2',
]); ]);
}); });
@ -726,9 +726,9 @@ test('test.setTimeout should work separately in beforeAll', async ({ runInlineTe
}, { timeout: 3000 }); }, { timeout: 3000 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%test', 'test',
]); ]);
}); });
@ -748,9 +748,9 @@ test('test.setTimeout should work separately in afterAll', async ({ runInlineTes
}, { timeout: '1000' }); }, { timeout: '1000' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test', 'test',
'%%afterAll', 'afterAll',
]); ]);
}); });
@ -779,9 +779,9 @@ test('beforeAll failure should only prevent tests that are affected', async ({ r
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll', 'beforeAll',
'%%test3', 'test3',
]); ]);
}); });
@ -863,12 +863,12 @@ test('afterAll should be run for test.skip', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeAll1', 'beforeAll1',
'%%test1', 'test1',
'%%afterAll1', 'afterAll1',
'%%beforeAll2', 'beforeAll2',
'%%test3', 'test3',
'%%afterAll2', 'afterAll2',
]); ]);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
@ -149,5 +149,5 @@ test('should report errors', async ({ runInlineTest }) => {
` `
}, { 'list': true }); }, { 'list': true });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('> 6 | oh = 2;'); expect(result.output).toContain('> 6 | oh = 2;');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import path from 'path'; import path from 'path';
test('should return the location of a syntax error', async ({ runInlineTest }) => { test('should return the location of a syntax error', async ({ runInlineTest }) => {
@ -294,9 +294,9 @@ test('should filter stack trace for simple expect', async ({ runInlineTest }) =>
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-test`); expect(result.output).not.toContain(path.sep + `playwright-test`);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-core`); expect(result.output).not.toContain(path.sep + `playwright-core`);
expect(stripAnsi(result.output)).not.toContain('internal'); expect(result.output).not.toContain('internal');
}); });
test('should filter stack trace for web-first assertions', async ({ runInlineTest }) => { test('should filter stack trace for web-first assertions', async ({ runInlineTest }) => {
@ -309,9 +309,9 @@ test('should filter stack trace for web-first assertions', async ({ runInlineTes
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-test`); expect(result.output).not.toContain(path.sep + `playwright-test`);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-core`); expect(result.output).not.toContain(path.sep + `playwright-core`);
expect(stripAnsi(result.output)).not.toContain('internal'); expect(result.output).not.toContain('internal');
}); });
test('should filter out event emitter from stack traces', async ({ runInlineTest }, testInfo) => { test('should filter out event emitter from stack traces', async ({ runInlineTest }, testInfo) => {
@ -327,7 +327,7 @@ test('should filter out event emitter from stack traces', async ({ runInlineTest
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const outputWithoutGoodStackFrames = stripAnsi(result.output).split('\n').filter(line => !line.includes(testInfo.outputPath())).join('\n'); const outputWithoutGoodStackFrames = result.output.split('\n').filter(line => !line.includes(testInfo.outputPath())).join('\n');
expect(outputWithoutGoodStackFrames).not.toContain('EventEmitter.emit'); expect(outputWithoutGoodStackFrames).not.toContain('EventEmitter.emit');
}); });
@ -342,8 +342,8 @@ test('should filter out syntax error stack traces', async ({ runInlineTest }, te
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).not.toContain('babel'); expect(result.output).not.toContain('babel');
expect(stripAnsi(result.output)).not.toContain(' at '); expect(result.output).not.toContain(' at ');
}); });
test('should filter stack trace for raw errors', async ({ runInlineTest }) => { test('should filter stack trace for raw errors', async ({ runInlineTest }) => {
@ -356,10 +356,10 @@ test('should filter stack trace for raw errors', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('foobar!'); expect(result.output).toContain('foobar!');
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-test`); expect(result.output).not.toContain(path.sep + `playwright-test`);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-core`); expect(result.output).not.toContain(path.sep + `playwright-core`);
expect(stripAnsi(result.output)).not.toContain('internal'); expect(result.output).not.toContain('internal');
}); });
test('should not filter out POM', async ({ runInlineTest }) => { test('should not filter out POM', async ({ runInlineTest }) => {
@ -378,12 +378,12 @@ test('should not filter out POM', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('foo'); expect(result.output).toContain('foo');
expect(stripAnsi(result.output)).toContain('helper.ts'); expect(result.output).toContain('helper.ts');
expect(stripAnsi(result.output)).toContain('expect-test.spec.ts'); expect(result.output).toContain('expect-test.spec.ts');
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-test`); expect(result.output).not.toContain(path.sep + `playwright-test`);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-core`); expect(result.output).not.toContain(path.sep + `playwright-core`);
expect(stripAnsi(result.output)).not.toContain('internal'); expect(result.output).not.toContain('internal');
}); });
test('should filter stack even without default Error.prepareStackTrace', async ({ runInlineTest }) => { test('should filter stack even without default Error.prepareStackTrace', async ({ runInlineTest }) => {
@ -397,12 +397,12 @@ test('should filter stack even without default Error.prepareStackTrace', async (
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain('foobar'); expect(result.output).toContain('foobar');
expect(stripAnsi(result.output)).toContain('expect-test.spec.ts'); expect(result.output).toContain('expect-test.spec.ts');
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-test`); expect(result.output).not.toContain(path.sep + `playwright-test`);
expect(stripAnsi(result.output)).not.toContain(path.sep + `playwright-core`); expect(result.output).not.toContain(path.sep + `playwright-core`);
expect(stripAnsi(result.output)).not.toContain('internal'); expect(result.output).not.toContain('internal');
const stackLines = stripAnsi(result.output).split('\n').filter(line => line.includes(' at ')); const stackLines = result.output.split('\n').filter(line => line.includes(' at '));
expect(stackLines.length).toBe(1); expect(stackLines.length).toBe(1);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('max-failures should work', async ({ runInlineTest }) => { test('max-failures should work', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -144,5 +144,5 @@ test('max-failures should properly shutdown', async ({ runInlineTest }) => {
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('expect(false).toBeTruthy()'); expect(result.output).toContain('expect(false).toBeTruthy()');
}); });

View file

@ -38,6 +38,8 @@ export type CliRunResult = {
export type RunResult = { export type RunResult = {
exitCode: number, exitCode: number,
output: string, output: string,
outputLines: string[],
rawOutput: string,
passed: number, passed: number,
failed: number, failed: number,
flaky: number, flaky: number,
@ -173,9 +175,12 @@ async function runPlaywrightTest(childProcess: CommonFixtures['childProcess'], b
if (report) if (report)
visitSuites(report.suites); visitSuites(report.suites);
const strippedOutput = stripAnsi(output);
return { return {
exitCode, exitCode,
output, output: strippedOutput,
outputLines: strippedOutput.split('\n').filter(line => line.startsWith('%%')).map(line => line.substring(2).trim()),
rawOutput: output,
passed, passed,
failed, failed,
flaky, flaky,

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import fs from 'fs'; import fs from 'fs';
test.describe.configure({ mode: 'parallel' }); test.describe.configure({ mode: 'parallel' });
@ -38,7 +38,7 @@ test('should work with the empty component list', async ({ runInlineTest }, test
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('transforming...'); expect(output).toContain('transforming...');
expect(output.replace(/\\+/g, '/')).toContain('playwright/.cache/playwright/index.html'); expect(output.replace(/\\+/g, '/')).toContain('playwright/.cache/playwright/index.html');
@ -235,7 +235,7 @@ test('should cache build', async ({ runInlineTest }, testInfo) => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output, 'should rebuild bundle').toContain('modules transformed'); expect(output, 'should rebuild bundle').toContain('modules transformed');
}); });
@ -245,7 +245,7 @@ test('should cache build', async ({ runInlineTest }, testInfo) => {
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output, 'should not rebuild bundle').not.toContain('modules transformed'); expect(output, 'should not rebuild bundle').not.toContain('modules transformed');
}); });
@ -265,7 +265,7 @@ test('should cache build', async ({ runInlineTest }, testInfo) => {
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
const output = stripAnsi(result.output); const output = result.output;
expect(output, 'should not rebuild bundle').not.toContain('modules transformed'); expect(output, 'should not rebuild bundle').not.toContain('modules transformed');
}); });
@ -278,7 +278,7 @@ test('should cache build', async ({ runInlineTest }, testInfo) => {
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output, 'should rebuild bundle').toContain('modules transformed'); expect(output, 'should rebuild bundle').toContain('modules transformed');
}); });
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { spawnSync } from 'child_process'; import { spawnSync } from 'child_process';
@ -75,10 +75,10 @@ test('should run in three browsers with --browser', async ({ runInlineTest }) =>
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(3); expect(result.passed).toBe(3);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).sort()).toEqual([ expect(result.outputLines.sort()).toEqual([
'%%browser=chromium', 'browser=chromium',
'%%browser=firefox', 'browser=firefox',
'%%browser=webkit', 'browser=webkit',
]); ]);
}); });
@ -97,8 +97,8 @@ test('should run in one browser with --browser', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).sort()).toEqual([ expect(result.outputLines.sort()).toEqual([
'%%browser=webkit', 'browser=webkit',
]); ]);
}); });
@ -153,8 +153,8 @@ test('should not override use:browserName without projects', async ({ runInlineT
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).sort()).toEqual([ expect(result.outputLines.sort()).toEqual([
'%%browser=webkit', 'browser=webkit',
]); ]);
}); });
@ -173,8 +173,8 @@ test('should override use:browserName with --browser', async ({ runInlineTest })
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).sort()).toEqual([ expect(result.outputLines.sort()).toEqual([
'%%browser=firefox', 'browser=firefox',
]); ]);
}); });
@ -343,7 +343,7 @@ test('should report error and pending operations on timeout', async ({ runInline
expect(result.output).toContain('- locator.click at a.test.ts:9:37'); expect(result.output).toContain('- locator.click at a.test.ts:9:37');
expect(result.output).toContain('- locator.textContent at a.test.ts:10:42'); expect(result.output).toContain('- locator.textContent at a.test.ts:10:42');
expect(result.output).toContain('waiting for'); expect(result.output).toContain('waiting for');
expect(stripAnsi(result.output)).toContain(`10 | page.getByText('More missing').textContent(),`); expect(result.output).toContain(`10 | page.getByText('More missing').textContent(),`);
}); });
test('should report error on timeout with shared page', async ({ runInlineTest }, testInfo) => { test('should report error on timeout with shared page', async ({ runInlineTest }, testInfo) => {
@ -367,7 +367,7 @@ test('should report error on timeout with shared page', async ({ runInlineTest }
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('waiting for getByText(\'Missing\')'); expect(result.output).toContain('waiting for getByText(\'Missing\')');
expect(stripAnsi(result.output)).toContain(`14 | await page.getByText('Missing').click();`); expect(result.output).toContain(`14 | await page.getByText('Missing').click();`);
}); });
test('should report error from beforeAll timeout', async ({ runInlineTest }, testInfo) => { test('should report error from beforeAll timeout', async ({ runInlineTest }, testInfo) => {
@ -391,7 +391,7 @@ test('should report error from beforeAll timeout', async ({ runInlineTest }, tes
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('"beforeAll" hook timeout of 2000ms exceeded.'); expect(result.output).toContain('"beforeAll" hook timeout of 2000ms exceeded.');
expect(result.output).toContain('waiting for'); expect(result.output).toContain('waiting for');
expect(stripAnsi(result.output)).toContain(`11 | page.getByText('More missing').textContent(),`); expect(result.output).toContain(`11 | page.getByText('More missing').textContent(),`);
}); });
test('should not report waitForEventInfo as pending', async ({ runInlineTest }, testInfo) => { test('should not report waitForEventInfo as pending', async ({ runInlineTest }, testInfo) => {
@ -451,7 +451,7 @@ test('should report click error on sigint', async ({ runInlineTest }) => {
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.interrupted).toBe(1); expect(result.interrupted).toBe(1);
expect(stripAnsi(result.output)).toContain(`8 | const promise = page.click('text=Missing');`); expect(result.output).toContain(`8 | const promise = page.click('text=Missing');`);
}); });
test('should work with video: retain-on-failure', async ({ runInlineTest }, testInfo) => { test('should work with video: retain-on-failure', async ({ runInlineTest }, testInfo) => {

View file

@ -15,7 +15,7 @@
*/ */
import path from 'path'; import path from 'path';
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('render text attachment', async ({ runInlineTest }) => { test('render text attachment', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -31,7 +31,7 @@ test('render text attachment', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line' }); }, { reporter: 'line' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain(' attachment #1: attachment (text/plain) ---------------------------------------------------------'); expect(text).toContain(' attachment #1: attachment (text/plain) ---------------------------------------------------------');
expect(text).toContain(' Hello world'); expect(text).toContain(' Hello world');
expect(text).toContain(' ------------------------------------------------------------------------------------------------'); expect(text).toContain(' ------------------------------------------------------------------------------------------------');
@ -52,7 +52,7 @@ test('render screenshot attachment', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line' }); }, { reporter: 'line' });
const text = stripAnsi(result.output).replace(/\\/g, '/'); const text = result.output.replace(/\\/g, '/');
expect(text).toContain(' attachment #1: screenshot (image/png) ----------------------------------------------------------'); expect(text).toContain(' attachment #1: screenshot (image/png) ----------------------------------------------------------');
expect(text).toContain(' test-results/a-one/some/path.png'); expect(text).toContain(' test-results/a-one/some/path.png');
expect(text).toContain(' ------------------------------------------------------------------------------------------------'); expect(text).toContain(' ------------------------------------------------------------------------------------------------');
@ -73,7 +73,7 @@ test('render trace attachment', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line' }); }, { reporter: 'line' });
const text = stripAnsi(result.output).replace(/\\/g, '/'); const text = result.output.replace(/\\/g, '/');
expect(text).toContain(' attachment #1: trace (application/zip) ---------------------------------------------------------'); expect(text).toContain(' attachment #1: trace (application/zip) ---------------------------------------------------------');
expect(text).toContain(' test-results/a-one/trace.zip'); expect(text).toContain(' test-results/a-one/trace.zip');
expect(text).toContain('npx playwright show-trace test-results/a-one/trace.zip'); expect(text).toContain('npx playwright show-trace test-results/a-one/trace.zip');
@ -96,7 +96,7 @@ test(`testInfo.attach errors`, async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line', workers: 1 }); }, { reporter: 'line', workers: 1 });
const text = stripAnsi(result.output).replace(/\\/g, '/'); const text = result.output.replace(/\\/g, '/');
expect(text).toMatch(/Error: ENOENT: no such file or directory, copyfile '.*foo.txt.*'/); expect(text).toMatch(/Error: ENOENT: no such file or directory, copyfile '.*foo.txt.*'/);
expect(text).toContain(`Exactly one of "path" and "body" must be specified`); expect(text).toContain(`Exactly one of "path" and "body" must be specified`);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
@ -113,7 +113,7 @@ test(`testInfo.attach errors with empty path`, async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line', workers: 1 }); }, { reporter: 'line', workers: 1 });
expect(stripAnsi(result.output)).toMatch(/Error: ENOENT: no such file or directory, copyfile ''/); expect(result.output).toMatch(/Error: ENOENT: no such file or directory, copyfile ''/);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -130,7 +130,7 @@ test(`testInfo.attach error in fixture`, async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line', workers: 1 }); }, { reporter: 'line', workers: 1 });
const text = stripAnsi(result.output).replace(/\\/g, '/'); const text = result.output.replace(/\\/g, '/');
expect(text).toMatch(/Error: ENOENT: no such file or directory, copyfile '.*foo.txt.*'/); expect(text).toMatch(/Error: ENOENT: no such file or directory, copyfile '.*foo.txt.*'/);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
@ -155,7 +155,7 @@ test(`testInfo.attach success in fixture`, async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('attachment #1: name (text/plain)'); expect(result.output).toContain('attachment #1: name (text/plain)');
}); });
test(`testInfo.attach allow empty string body`, async ({ runInlineTest }) => { test(`testInfo.attach allow empty string body`, async ({ runInlineTest }) => {
@ -170,7 +170,7 @@ test(`testInfo.attach allow empty string body`, async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toMatch(/^.*attachment #1: name \(text\/plain\).*\n.*\n.*------/gm); expect(result.output).toMatch(/^.*attachment #1: name \(text\/plain\).*\n.*\n.*------/gm);
}); });
test(`testInfo.attach allow empty buffer body`, async ({ runInlineTest }) => { test(`testInfo.attach allow empty buffer body`, async ({ runInlineTest }) => {
@ -185,7 +185,7 @@ test(`testInfo.attach allow empty buffer body`, async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toMatch(/^.*attachment #1: name \(text\/plain\).*\n.*\n.*------/gm); expect(result.output).toMatch(/^.*attachment #1: name \(text\/plain\).*\n.*\n.*------/gm);
}); });
test(`testInfo.attach use name as prefix`, async ({ runInlineTest }) => { test(`testInfo.attach use name as prefix`, async ({ runInlineTest }) => {
@ -207,8 +207,8 @@ test(`testInfo.attach use name as prefix`, async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('attachment #1: some random string (text/plain)'); expect(result.output).toContain('attachment #1: some random string (text/plain)');
expect(stripAnsi(result.output)).toContain('some-random-string-'); expect(result.output).toContain('some-random-string-');
}); });
test(`testInfo.attach name should be sanitized`, async ({ runInlineTest }) => { test(`testInfo.attach name should be sanitized`, async ({ runInlineTest }) => {
@ -230,8 +230,8 @@ test(`testInfo.attach name should be sanitized`, async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('attachment #1: ../../../test (text/plain)'); expect(result.output).toContain('attachment #1: ../../../test (text/plain)');
expect(stripAnsi(result.output)).toContain(`attachments${path.sep}-test`); expect(result.output).toContain(`attachments${path.sep}-test`);
}); });
test(`testInfo.attach name can be empty string`, async ({ runInlineTest }) => { test(`testInfo.attach name can be empty string`, async ({ runInlineTest }) => {
@ -253,8 +253,8 @@ test(`testInfo.attach name can be empty string`, async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('attachment #1: (text/plain)'); expect(result.output).toContain('attachment #1: (text/plain)');
expect(stripAnsi(result.output)).toContain(`attachments${path.sep}-`); expect(result.output).toContain(`attachments${path.sep}-`);
}); });
test(`testInfo.attach throw if name is not string`, async ({ runInlineTest }) => { test(`testInfo.attach throw if name is not string`, async ({ runInlineTest }) => {
@ -276,5 +276,5 @@ test(`testInfo.attach throw if name is not string`, async ({ runInlineTest }) =>
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output)).toContain('"name" should be string.'); expect(result.output).toContain('"name" should be string.');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import * as path from 'path'; import * as path from 'path';
test('handle long test names', async ({ runInlineTest }) => { test('handle long test names', async ({ runInlineTest }) => {
@ -27,7 +27,7 @@ test('handle long test names', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(stripAnsi(result.output)).toContain('expect(1).toBe'); expect(result.output).toContain('expect(1).toBe');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -104,7 +104,7 @@ test('should filter out node_modules error in a codeframe', async ({ runInlineTe
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Error: Assertion error'); expect(output).toContain('Error: Assertion error');
expect(output).toContain('a.spec.ts:7:7 fail'); expect(output).toContain('a.spec.ts:7:7 fail');
expect(output).toContain(` 7 | test('fail', async ({}) => {`); expect(output).toContain(` 7 | test('fail', async ({}) => {`);
@ -167,15 +167,15 @@ test('should print slow tests', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(8); expect(result.passed).toBe(8);
expect(stripAnsi(result.output)).toContain(`Slow test file: [foo] dir${path.sep}a.test.js (`); expect(result.output).toContain(`Slow test file: [foo] dir${path.sep}a.test.js (`);
expect(stripAnsi(result.output)).toContain(`Slow test file: [bar] dir${path.sep}a.test.js (`); expect(result.output).toContain(`Slow test file: [bar] dir${path.sep}a.test.js (`);
expect(stripAnsi(result.output)).toContain(`Slow test file: [baz] dir${path.sep}a.test.js (`); expect(result.output).toContain(`Slow test file: [baz] dir${path.sep}a.test.js (`);
expect(stripAnsi(result.output)).toContain(`Slow test file: [qux] dir${path.sep}a.test.js (`); expect(result.output).toContain(`Slow test file: [qux] dir${path.sep}a.test.js (`);
expect(stripAnsi(result.output)).toContain(`Consider splitting slow test files to speed up parallel execution`); expect(result.output).toContain(`Consider splitting slow test files to speed up parallel execution`);
expect(stripAnsi(result.output)).not.toContain(`Slow test file: [foo] dir${path.sep}b.test.js (`); expect(result.output).not.toContain(`Slow test file: [foo] dir${path.sep}b.test.js (`);
expect(stripAnsi(result.output)).not.toContain(`Slow test file: [bar] dir${path.sep}b.test.js (`); expect(result.output).not.toContain(`Slow test file: [bar] dir${path.sep}b.test.js (`);
expect(stripAnsi(result.output)).not.toContain(`Slow test file: [baz] dir${path.sep}b.test.js (`); expect(result.output).not.toContain(`Slow test file: [baz] dir${path.sep}b.test.js (`);
expect(stripAnsi(result.output)).not.toContain(`Slow test file: [qux] dir${path.sep}b.test.js (`); expect(result.output).not.toContain(`Slow test file: [qux] dir${path.sep}b.test.js (`);
}); });
test('should not print slow parallel tests', async ({ runInlineTest }) => { test('should not print slow parallel tests', async ({ runInlineTest }) => {
@ -199,7 +199,7 @@ test('should not print slow parallel tests', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(stripAnsi(result.output)).not.toContain('Slow test file'); expect(result.output).not.toContain('Slow test file');
}); });
test('should not print slow tests', async ({ runInlineTest }) => { test('should not print slow tests', async ({ runInlineTest }) => {
@ -225,7 +225,7 @@ test('should not print slow tests', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(stripAnsi(result.output)).not.toContain('Slow test'); expect(result.output).not.toContain('Slow test');
}); });
test('should print flaky failures', async ({ runInlineTest }) => { test('should print flaky failures', async ({ runInlineTest }) => {
@ -239,7 +239,7 @@ test('should print flaky failures', async ({ runInlineTest }) => {
}, { retries: '1', reporter: 'list' }); }, { retries: '1', reporter: 'list' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(stripAnsi(result.output)).toContain('expect(testInfo.retry).toBe(1)'); expect(result.output).toContain('expect(testInfo.retry).toBe(1)');
}); });
test('should print flaky timeouts', async ({ runInlineTest }) => { test('should print flaky timeouts', async ({ runInlineTest }) => {
@ -254,7 +254,7 @@ test('should print flaky timeouts', async ({ runInlineTest }) => {
}, { retries: '1', reporter: 'list', timeout: '1000' }); }, { retries: '1', reporter: 'list', timeout: '1000' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(stripAnsi(result.output)).toContain('Test timeout of 1000ms exceeded.'); expect(result.output).toContain('Test timeout of 1000ms exceeded.');
}); });
test('should print stack-less errors', async ({ runInlineTest }) => { test('should print stack-less errors', async ({ runInlineTest }) => {
@ -290,7 +290,7 @@ test('should print errors with inconsistent message/stack', async ({ runInlineTe
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('hi!Error: Hello'); expect(output).toContain('hi!Error: Hello');
expect(output).toContain('function myTest'); expect(output).toContain('function myTest');
}); });
@ -315,7 +315,7 @@ test('should not crash on undefined body with manual attachments', async ({ runI
}); });
`, `,
}); });
expect(stripAnsi(result.output)).not.toContain('Error in reporter'); expect(result.output).not.toContain('Error in reporter');
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -345,7 +345,7 @@ test('should report fatal errors at the end', async ({ runInlineTest }) => {
}, { reporter: 'list' }); }, { reporter: 'list' });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(stripAnsi(result.output)).toContain('2 errors were not a part of any test, see above for details'); expect(result.output).toContain('2 errors were not a part of any test, see above for details');
}); });
test('should contain at most 1 decimal for humanized timing', async ({ runInlineTest }) => { test('should contain at most 1 decimal for humanized timing', async ({ runInlineTest }) => {
@ -357,5 +357,5 @@ test('should contain at most 1 decimal for humanized timing', async ({ runInline
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(stripAnsi(result.output)).toMatch(/\d+ passed \(\d+(\.\d)?(ms|s)\)/); expect(result.output).toMatch(/\d+ passed \(\d+(\.\d)?(ms|s)\)/);
}); });

View file

@ -15,7 +15,7 @@
*/ */
import colors from 'colors/safe'; import colors from 'colors/safe';
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('render expected', async ({ runInlineTest }) => { test('render expected', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -26,7 +26,7 @@ test('render expected', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(result.output).toContain(colors.green('·')); expect(result.rawOutput).toContain(colors.green('·'));
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
}); });
@ -39,7 +39,7 @@ test('render unexpected', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(result.output).toContain(colors.red('F')); expect(result.rawOutput).toContain(colors.red('F'));
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -52,9 +52,9 @@ test('render unexpected after retry', async ({ runInlineTest }) => {
}); });
`, `,
}, { retries: 3 }); }, { retries: 3 });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('×××F'); expect(text).toContain('×××F');
expect(result.output).toContain(colors.red('F')); expect(result.rawOutput).toContain(colors.red('F'));
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });
@ -67,9 +67,9 @@ test('render flaky', async ({ runInlineTest }) => {
}); });
`, `,
}, { retries: 3 }); }, { retries: 3 });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('×××±'); expect(text).toContain('×××±');
expect(result.output).toContain(colors.yellow('±')); expect(result.rawOutput).toContain(colors.yellow('±'));
expect(text).toContain('1 flaky'); expect(text).toContain('1 flaky');
expect(text).toContain('Retry #1'); expect(text).toContain('Retry #1');
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
@ -87,7 +87,7 @@ test('should work from config', async ({ runInlineTest }) => {
}); });
`, `,
}); });
expect(result.output).toContain(colors.green('·')); expect(result.rawOutput).toContain(colors.green('·'));
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
}); });
@ -101,7 +101,7 @@ test('render 243 tests in rows by 80', async ({ runInlineTest }) => {
`, `,
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output).toContain( expect(result.rawOutput).toContain(
colors.green('·').repeat(80) + '\n' + colors.green('·').repeat(80) + '\n' +
colors.green('·').repeat(80) + '\n' + colors.green('·').repeat(80) + '\n' +
colors.green('·').repeat(80) + '\n' + colors.green('·').repeat(80) + '\n' +

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
import path from 'path'; import path from 'path';
function relativeFilePath(file: string): string { function relativeFilePath(file: string): string {
@ -32,7 +32,7 @@ test('print GitHub annotations for success', async ({ runInlineTest }) => {
}); });
` `
}, { reporter: 'github' }); }, { reporter: 'github' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).not.toContain('::error'); expect(text).not.toContain('::error');
expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed'); expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed');
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
@ -47,7 +47,7 @@ test('print GitHub annotations for failed tests', async ({ runInlineTest }, test
}); });
` `
}, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: process.cwd() }); }, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: process.cwd() });
const text = stripAnsi(result.output); const text = result.output;
const testPath = relativeFilePath(testInfo.outputPath('a.test.js')); const testPath = relativeFilePath(testInfo.outputPath('a.test.js'));
expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 example,line=7,col=23:: 1) a.test.js:6:7 example =======================================================================%0A%0A Retry #1`); expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 example,line=7,col=23:: 1) a.test.js:6:7 example =======================================================================%0A%0A Retry #1`);
expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 example,line=7,col=23:: 1) a.test.js:6:7 example =======================================================================%0A%0A Retry #2`); expect(text).toContain(`::error file=${testPath},title=a.test.js:6:7 example,line=7,col=23:: 1) a.test.js:6:7 example =======================================================================%0A%0A Retry #2`);
@ -69,7 +69,7 @@ test('print GitHub annotations for slow tests', async ({ runInlineTest }) => {
}); });
` `
}, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: '' }); }, { retries: 3, reporter: 'github' }, { GITHUB_WORKSPACE: '' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('::warning title=Slow Test,file=a.test.js::a.test.js took'); expect(text).toContain('::warning title=Slow Test,file=a.test.js::a.test.js took');
expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed'); expect(text).toContain('::notice title=🎭 Playwright Run Summary:: 1 passed');
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
@ -88,7 +88,7 @@ test('print GitHub annotations for global error', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'github' }); }, { reporter: 'github' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('::error ::Error: Oh my!%0A%0A'); expect(text).toContain('::error ::Error: Oh my!%0A%0A');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });

View file

@ -17,7 +17,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import url from 'url'; import url from 'url';
import { test as baseTest, expect, createImage, stripAnsi } from './playwright-test-fixtures'; import { test as baseTest, expect, createImage } from './playwright-test-fixtures';
import type { HttpServer } from '../../packages/playwright-core/lib/utils'; import type { HttpServer } from '../../packages/playwright-core/lib/utils';
import { startHtmlReportServer } from '../../packages/playwright-test/lib/reporters/html'; import { startHtmlReportServer } from '../../packages/playwright-test/lib/reporters/html';
import { spawnAsync } from 'playwright-core/lib/utils'; import { spawnAsync } from 'playwright-core/lib/utils';
@ -905,7 +905,7 @@ test('should report clashing folders', async ({ runInlineTest }) => {
`, `,
}, {}, {}, { usesCustomReporters: true }); }, {}, {}, { usesCustomReporters: true });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Configuration Error'); expect(output).toContain('Configuration Error');
expect(output).toContain('html-report'); expect(output).toContain('html-report');
}); });

View file

@ -221,7 +221,7 @@ test('should add dot in addition to file json with CI', async ({ runInlineTest }
`, `,
}, { reporter: '' }, { CI: '1' }); }, { reporter: '' }, { CI: '1' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output)).toContain('·'); expect(result.output).toContain('·');
expect(fs.existsSync(testInfo.outputPath('a.json'))).toBeTruthy(); expect(fs.existsSync(testInfo.outputPath('a.json'))).toBeTruthy();
}); });
@ -238,7 +238,7 @@ test('should add line in addition to file json without CI', async ({ runInlineTe
`, `,
}, { reporter: '' }, { PW_TEST_DEBUG_REPORTERS: '1' }); }, { reporter: '' }, { PW_TEST_DEBUG_REPORTERS: '1' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output)).toContain('[1/1] a.test.js:6:7 one'); expect(result.output).toContain('[1/1] a.test.js:6:7 one');
expect(fs.existsSync(testInfo.outputPath('a.json'))).toBeTruthy(); expect(fs.existsSync(testInfo.outputPath('a.json'))).toBeTruthy();
}); });
test('should have starting time in results', async ({ runInlineTest }, testInfo) => { test('should have starting time in results', async ({ runInlineTest }, testInfo) => {

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('render unexpected after retry', async ({ runInlineTest }) => { test('render unexpected after retry', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -25,7 +25,7 @@ test('render unexpected after retry', async ({ runInlineTest }) => {
}); });
`, `,
}, { retries: 3, reporter: 'line' }); }, { retries: 3, reporter: 'line' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('[1/1] a.test.js:6:7 one'); expect(text).toContain('[1/1] a.test.js:6:7 one');
expect(text).toContain('[2/1] (retries) a.test.js:6:7 one (retry #1)'); expect(text).toContain('[2/1] (retries) a.test.js:6:7 one (retry #1)');
expect(text).toContain('[3/1] (retries) a.test.js:6:7 one (retry #2)'); expect(text).toContain('[3/1] (retries) a.test.js:6:7 one (retry #2)');
@ -48,7 +48,7 @@ test('render flaky', async ({ runInlineTest }) => {
}); });
`, `,
}, { retries: 3, reporter: 'line' }); }, { retries: 3, reporter: 'line' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('1 flaky'); expect(text).toContain('1 flaky');
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
}); });
@ -64,7 +64,7 @@ test('should print flaky failures', async ({ runInlineTest }) => {
}, { retries: '1', reporter: 'line' }); }, { retries: '1', reporter: 'line' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(stripAnsi(result.output)).toContain('expect(testInfo.retry).toBe(1)'); expect(result.output).toContain('expect(testInfo.retry).toBe(1)');
}); });
test('should work on CI', async ({ runInlineTest }) => { test('should work on CI', async ({ runInlineTest }) => {
@ -76,7 +76,7 @@ test('should work on CI', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'line' }, { CI: '1' }); }, { reporter: 'line' }, { CI: '1' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain('[1/1] a.test.js:6:7 one'); expect(text).toContain('[1/1] a.test.js:6:7 one');
expect(text).toContain('1 failed'); expect(text).toContain('1 failed');
expect(text).toContain('1) a.test'); expect(text).toContain('1) a.test');
@ -95,7 +95,7 @@ test('should print output', async ({ runInlineTest }) => {
` `
}, { reporter: 'line' }); }, { reporter: 'line' });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output)).toContain([ expect(result.output).toContain([
'a.spec.ts:6:7 foobar', 'a.spec.ts:6:7 foobar',
'one', 'one',
'', '',

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === 'win32' && process.env.TERM_PROGRAM !== 'vscode' && !process.env.WT_SESSION; const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === 'win32' && process.env.TERM_PROGRAM !== 'vscode' && !process.env.WT_SESSION;
const POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? 'ok' : '✓ '; const POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? 'ok' : '✓ ';
@ -40,7 +40,7 @@ test('render each test with project name', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'list', workers: '1' }); }, { reporter: 'list', workers: '1' });
const text = stripAnsi(result.output); const text = result.output;
expect(text).toContain(`${NEGATIVE_STATUS_MARK} 1 [foo] a.test.ts:6:7 fails`); expect(text).toContain(`${NEGATIVE_STATUS_MARK} 1 [foo] a.test.ts:6:7 fails`);
expect(text).toContain(`${POSITIVE_STATUS_MARK} 2 [foo] a.test.ts:9:7 passes`); expect(text).toContain(`${POSITIVE_STATUS_MARK} 2 [foo] a.test.ts:9:7 passes`);
@ -67,7 +67,7 @@ test('render steps', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PWTEST_TTY_WIDTH: '80' }); }, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PWTEST_TTY_WIDTH: '80' });
const text = stripAnsi(result.output); const text = result.output;
const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/\d+ms/, 'Xms')); const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/\d+ms/, 'Xms'));
lines.pop(); // Remove last item that contains [v] and time in ms. lines.pop(); // Remove last item that contains [v] and time in ms.
expect(lines).toEqual([ expect(lines).toEqual([
@ -103,7 +103,7 @@ test('render steps inlint', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' }); }, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' });
const text = stripAnsi(result.output); const text = result.output;
const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/\d+ms/, 'Xms')); const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/\d+ms/, 'Xms'));
lines.pop(); // Remove last item that contains [v] and time in ms. lines.pop(); // Remove last item that contains [v] and time in ms.
expect(lines).toEqual([ expect(lines).toEqual([
@ -134,7 +134,7 @@ test('very long console line should not mess terminal', async ({ runInlineTest }
`, `,
}, { reporter: 'list' }, { PWTEST_TTY_WIDTH: TTY_WIDTH + '' }); }, { reporter: 'list' }, { PWTEST_TTY_WIDTH: TTY_WIDTH + '' });
const renderedText = simpleAnsiRenderer(result.output, TTY_WIDTH); const renderedText = simpleAnsiRenderer(result.rawOutput, TTY_WIDTH);
if (process.platform === 'win32') if (process.platform === 'win32')
expect(renderedText).toContain(' ok 1 a.test.ts:6:7 passes'); expect(renderedText).toContain(' ok 1 a.test.ts:6:7 passes');
else else
@ -152,7 +152,7 @@ test('render retries', async ({ runInlineTest }) => {
}); });
`, `,
}, { reporter: 'list', retries: '1' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' }); }, { reporter: 'list', retries: '1' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' });
const text = stripAnsi(result.output); const text = result.output;
const lines = text.split('\n').filter(l => l.startsWith('0 :') || l.startsWith('1 :')).map(l => l.replace(/[\dm]+s/, 'XXms')); const lines = text.split('\n').filter(l => l.startsWith('0 :') || l.startsWith('1 :')).map(l => l.replace(/[\dm]+s/, 'XXms'));
expect(lines).toEqual([ expect(lines).toEqual([
@ -185,7 +185,7 @@ test('should truncate long test names', async ({ runInlineTest }) => {
}, { reporter: 'list', retries: 0 }, { PWTEST_TTY_WIDTH: 50 }); }, { reporter: 'list', retries: 0 }, { PWTEST_TTY_WIDTH: 50 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const lines = stripAnsi(result.output).split('\n').slice(3, 11); const lines = result.output.split('\n').slice(3, 11);
expect(lines.every(line => line.length <= 50)).toBe(true); expect(lines.every(line => line.length <= 50)).toBe(true);
expect(lines[0]).toBe(` 1 … a.test.ts:6:7 failure in very long name`); expect(lines[0]).toBe(` 1 … a.test.ts:6:7 failure in very long name`);

View file

@ -135,22 +135,22 @@ test('should work with custom reporter', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%reporter-begin-begin%%', 'reporter-begin-begin%%',
'%%version-' + require('../../packages/playwright-test/package.json').version, 'version-' + require('../../packages/playwright-test/package.json').version,
'%%reporter-testbegin-is run-foo%%', 'reporter-testbegin-is run-foo%%',
'%%reporter-stdout%%', 'reporter-stdout%%',
'%%reporter-stderr%%', 'reporter-stderr%%',
'%%reporter-testend-is run-foo%%', 'reporter-testend-is run-foo%%',
'%%reporter-testbegin-is run-foo%%', 'reporter-testbegin-is run-foo%%',
'%%reporter-stdout%%', 'reporter-stdout%%',
'%%reporter-stderr%%', 'reporter-stderr%%',
'%%reporter-testend-is run-foo%%', 'reporter-testend-is run-foo%%',
'%%reporter-testbegin-is run-bar%%', 'reporter-testbegin-is run-bar%%',
'%%reporter-stdout%%', 'reporter-stdout%%',
'%%reporter-stderr%%', 'reporter-stderr%%',
'%%reporter-testend-is run-bar%%', 'reporter-testend-is run-bar%%',
'%%reporter-end-end%%', 'reporter-end-end%%',
]); ]);
}); });
@ -170,9 +170,9 @@ test('should work without a file extension', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%begin', 'begin',
'%%end', 'end',
]); ]);
}); });
@ -198,10 +198,10 @@ test('should report onEnd after global teardown', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%begin', 'begin',
'%%global teardown', 'global teardown',
'%%end', 'end',
]); ]);
}); });
@ -221,9 +221,9 @@ test('should load reporter from node_modules', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%begin', 'begin',
'%%end', 'end',
]); ]);
}); });
@ -251,31 +251,31 @@ test('should report expect steps', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).map(stripEscapedAscii)).toEqual([ expect(result.outputLines).toEqual([
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`, `begin {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`,
`%% end {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`, `end {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`,
`%% begin {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`, `begin {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\"}`,
`%% end {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\",\"error\":{\"message\":\"expect(received).toBeTruthy()\\n\\nReceived: false\",\"stack\":\"<stack>\"}}`, `end {\"title\":\"expect.toBeTruthy\",\"category\":\"expect\",\"error\":{\"message\":\"\\u001b[2mexpect(\\u001b[22m\\u001b[31mreceived\\u001b[39m\\u001b[2m).\\u001b[22mtoBeTruthy\\u001b[2m()\\u001b[22m\\n\\nReceived: \\u001b[31mfalse\\u001b[39m\",\"stack\":\"<stack>\"}}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"expect.not.toBeTruthy\",\"category\":\"expect\"}`, `begin {\"title\":\"expect.not.toBeTruthy\",\"category\":\"expect\"}`,
`%% end {\"title\":\"expect.not.toBeTruthy\",\"category\":\"expect\"}`, `end {\"title\":\"expect.not.toBeTruthy\",\"category\":\"expect\"}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`,
`%% begin {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`, `begin {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`,
`%% end {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`, `end {\"title\":\"expect.not.toHaveTitle\",\"category\":\"expect\"}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`,
]); ]);
}); });
@ -321,49 +321,49 @@ test('should report api steps', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).map(stripEscapedAscii)).toEqual([ expect(result.outputLines).toEqual([
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`,
`%% begin {\"title\":\"page.waitForNavigation\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.waitForNavigation\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"page.goto(data:text/html,<button></button>)\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.goto(data:text/html,<button></button>)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.waitForNavigation\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.waitForNavigation\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.goto(data:text/html,<button></button>)\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.goto(data:text/html,<button></button>)\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% begin {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api"}`, `begin {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api"}`,
`%% end {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api","error":{"message":"<message>","stack":"<stack>"}}`, `end {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api","error":{"message":"<message>","stack":"<stack>"}}`,
`%% begin {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api"}`, `begin {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api"}`,
`%% end {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api","error":{"message":"<message>","stack":"<stack>"}}`, `end {"title":"apiRequestContext.get(http://localhost2)","category":"pw:api","error":{"message":"<message>","stack":"<stack>"}}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"}`, `begin {\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"}`, `end {\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"},{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"apiRequestContext.dispose\",\"category\":\"pw:api\"},{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`,
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"beforeAll hook\",\"category\":\"hook\"}`, `begin {\"title\":\"beforeAll hook\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browser.newPage\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browser.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browser.newPage\",\"category\":\"pw:api\"}`, `end {\"title\":\"browser.newPage\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"beforeAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"browser.newPage\",\"category\":\"pw:api\"},{\"title\":\"page.setContent\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"beforeAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"browser.newPage\",\"category\":\"pw:api\"},{\"title\":\"page.setContent\",\"category\":\"pw:api\"}]}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"beforeAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"browser.newPage\",\"category\":\"pw:api\"},{\"title\":\"page.setContent\",\"category\":\"pw:api\"}]}]}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"beforeAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"browser.newPage\",\"category\":\"pw:api\"},{\"title\":\"page.setContent\",\"category\":\"pw:api\"}]}]}`,
`%% begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.click(button)\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"afterAll hook\",\"category\":\"hook\"}`, `begin {\"title\":\"afterAll hook\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"page.close\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.close\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"afterAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"page.close\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"afterAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"page.close\",\"category\":\"pw:api\"}]}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"afterAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"page.close\",\"category\":\"pw:api\"}]}]}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"afterAll hook\",\"category\":\"hook\",\"steps\":[{\"title\":\"page.close\",\"category\":\"pw:api\"}]}]}`,
]); ]);
}); });
@ -386,19 +386,19 @@ test('should report api step failure', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%')).map(stripEscapedAscii)).toEqual([ expect(result.outputLines).toEqual([
`%% begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"Before Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"Before Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.newPage\",\"category\":\"pw:api\"}]}`,
`%% begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"page.click(input)\",\"category\":\"pw:api\"}`, `begin {\"title\":\"page.click(input)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.click(input)\",\"category\":\"pw:api\",\"error\":{\"message\":\"page.click: Timeout 1ms exceeded.\\n=========================== logs ===========================\\nwaiting for locator('input')\\n============================================================\",\"stack\":\"<stack>\"}}`, `end {\"title\":\"page.click(input)\",\"category\":\"pw:api\",\"error\":{\"message\":\"page.click: Timeout 1ms exceeded.\\n=========================== logs ===========================\\nwaiting for locator('input')\\n============================================================\",\"stack\":\"<stack>\"}}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`, `end {\"title\":\"After Hooks\",\"category\":\"hook\",\"steps\":[{\"title\":\"browserContext.close\",\"category\":\"pw:api\"}]}`,
]); ]);
}); });
@ -445,19 +445,19 @@ test('should show nice stacks for locators', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.output).not.toContain('Internal error'); expect(result.output).not.toContain('Internal error');
expect(result.output.split('\n').filter(line => line.startsWith('%%')).map(stripEscapedAscii)).toEqual([ expect(result.outputLines).toEqual([
`%% begin {"title":"Before Hooks","category":"hook"}`, `begin {"title":"Before Hooks","category":"hook"}`,
`%% begin {"title":"browserContext.newPage","category":"pw:api"}`, `begin {"title":"browserContext.newPage","category":"pw:api"}`,
`%% end {"title":"browserContext.newPage","category":"pw:api"}`, `end {"title":"browserContext.newPage","category":"pw:api"}`,
`%% end {"title":"Before Hooks","category":"hook","steps":[{"title":"browserContext.newPage","category":"pw:api"}]}`, `end {"title":"Before Hooks","category":"hook","steps":[{"title":"browserContext.newPage","category":"pw:api"}]}`,
`%% begin {"title":"page.setContent","category":"pw:api"}`, `begin {"title":"page.setContent","category":"pw:api"}`,
`%% end {"title":"page.setContent","category":"pw:api"}`, `end {"title":"page.setContent","category":"pw:api"}`,
`%% begin {"title":"locator.evaluate(button)","category":"pw:api"}`, `begin {"title":"locator.evaluate(button)","category":"pw:api"}`,
`%% end {"title":"locator.evaluate(button)","category":"pw:api"}`, `end {"title":"locator.evaluate(button)","category":"pw:api"}`,
`%% begin {"title":"After Hooks","category":"hook"}`, `begin {"title":"After Hooks","category":"hook"}`,
`%% begin {"title":"browserContext.close","category":"pw:api"}`, `begin {"title":"browserContext.close","category":"pw:api"}`,
`%% end {"title":"browserContext.close","category":"pw:api"}`, `end {"title":"browserContext.close","category":"pw:api"}`,
`%% end {"title":"After Hooks","category":"hook","steps":[{"title":"browserContext.close","category":"pw:api"}]}`, `end {"title":"After Hooks","category":"hook","steps":[{"title":"browserContext.close","category":"pw:api"}]}`,
]); ]);
}); });
@ -628,8 +628,3 @@ test('parallelIndex is presented in onTestEnd', async ({ runInlineTest }) => {
expect(result.output).toContain('parallelIndex: 0'); expect(result.output).toContain('parallelIndex: 0');
}); });
function stripEscapedAscii(str: string) {
return str.replace(/\\u00[a-z0-9][a-z0-9]\[[^m]+m/g, '');
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should respect path resolver', async ({ runInlineTest }) => { test('should respect path resolver', async ({ runInlineTest }) => {
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11656' }); test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11656' });
@ -395,7 +395,7 @@ test('should not respect path resolver for JS files w/o allowJS', async ({ runIn
`, `,
}); });
expect(stripAnsi(result.output)).toContain('Cannot find module \'util/b\''); expect(result.output).toContain('Cannot find module \'util/b\'');
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should retry failures', async ({ runInlineTest }) => { test('should retry failures', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -127,7 +127,7 @@ test('should retry timeout', async ({ runInlineTest }) => {
expect(exitCode).toBe(1); expect(exitCode).toBe(1);
expect(passed).toBe(0); expect(passed).toBe(0);
expect(failed).toBe(1); expect(failed).toBe(1);
expect(stripAnsi(output).split('\n')[2]).toBe('××T'); expect(output.split('\n')[2]).toBe('××T');
}); });
test('should fail on unexpected pass with retries', async ({ runInlineTest }) => { test('should fail on unexpected pass with retries', async ({ runInlineTest }) => {
@ -158,7 +158,7 @@ test('should retry unexpected pass', async ({ runInlineTest }) => {
expect(exitCode).toBe(1); expect(exitCode).toBe(1);
expect(passed).toBe(0); expect(passed).toBe(0);
expect(failed).toBe(1); expect(failed).toBe(1);
expect(stripAnsi(output).split('\n')[2]).toBe('××F'); expect(output.split('\n')[2]).toBe('××F');
}); });
test('should not retry expected failure', async ({ runInlineTest }) => { test('should not retry expected failure', async ({ runInlineTest }) => {
@ -178,7 +178,7 @@ test('should not retry expected failure', async ({ runInlineTest }) => {
expect(exitCode).toBe(0); expect(exitCode).toBe(0);
expect(passed).toBe(2); expect(passed).toBe(2);
expect(failed).toBe(0); expect(failed).toBe(0);
expect(stripAnsi(output).split('\n')[2]).toBe('··'); expect(output.split('\n')[2]).toBe('··');
}); });
test('should retry unhandled rejection', async ({ runInlineTest }) => { test('should retry unhandled rejection', async ({ runInlineTest }) => {
@ -196,7 +196,7 @@ test('should retry unhandled rejection', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output).split('\n')[2]).toBe('××F'); expect(result.output.split('\n')[2]).toBe('××F');
expect(result.output).toContain('Unhandled rejection'); expect(result.output).toContain('Unhandled rejection');
}); });
@ -217,7 +217,7 @@ test('should retry beforeAll failure', async ({ runInlineTest }) => {
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(stripAnsi(result.output).split('\n')[2]).toBe('×°×°F°'); expect(result.output.split('\n')[2]).toBe('×°×°F°');
expect(result.output).toContain('BeforeAll is bugged!'); expect(result.output).toContain('BeforeAll is bugged!');
}); });
@ -239,6 +239,6 @@ test('should retry worker fixture setup failure', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output).split('\n')[2]).toBe('××F'); expect(result.output.split('\n')[2]).toBe('××F');
expect(result.output).toContain('worker setup is bugged!'); expect(result.output).toContain('worker setup is bugged!');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import path from 'path'; import path from 'path';
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('it should not allow multiple tests with the same name per suite', async ({ runInlineTest }) => { test('it should not allow multiple tests with the same name per suite', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -50,7 +50,7 @@ test('it should not allow multiple tests with the same name in multiple files',
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain('Error: duplicate test title'); expect(result.output).toContain('Error: duplicate test title');
expect(stripAnsi(result.output)).toContain(`test('i-am-a-duplicate'`); expect(result.output).toContain(`test('i-am-a-duplicate'`);
expect(result.output).toContain(`tests${path.sep}example1.spec.js:6`); expect(result.output).toContain(`tests${path.sep}example1.spec.js:6`);
expect(result.output).toContain(`tests${path.sep}example1.spec.js:7`); expect(result.output).toContain(`tests${path.sep}example1.spec.js:7`);
expect(result.output).toContain(`tests${path.sep}example2.spec.js:6`); expect(result.output).toContain(`tests${path.sep}example2.spec.js:6`);
@ -66,7 +66,7 @@ test('it should not allow a focused test when forbid-only is used', async ({ run
}, { 'forbid-only': true }); }, { 'forbid-only': true });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain('Error: focused item found in the --forbid-only mode'); expect(result.output).toContain('Error: focused item found in the --forbid-only mode');
expect(stripAnsi(result.output)).toContain(`test.only('i-am-focused'`); expect(result.output).toContain(`test.only('i-am-focused'`);
expect(result.output).toContain(`tests${path.sep}focused-test.spec.js:6`); expect(result.output).toContain(`tests${path.sep}focused-test.spec.js:6`);
}); });
@ -246,12 +246,12 @@ test('should not stall when workers are available', async ({ runInlineTest }) =>
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%passes-2-started', 'passes-2-started',
'%%fails-1-started', 'fails-1-started',
'%%fails-1-done', 'fails-1-done',
'%%passes-1', 'passes-1',
'%%passes-2-done', 'passes-2-done',
]); ]);
}); });
@ -283,13 +283,13 @@ test('should teardown workers that are redundant', async ({ runInlineTest }) =>
}, { workers: 2 }); }, { workers: 2 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(stripAnsi(result.output).split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%worker setup', 'worker setup',
'%%worker setup', 'worker setup',
'%%test-done', 'test-done',
'%%worker teardown', 'worker teardown',
'%%test-done', 'test-done',
'%%worker teardown', 'worker teardown',
]); ]);
}); });
@ -355,7 +355,7 @@ test('sigint should stop global setup', async ({ runInlineTest }) => {
}, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 }); }, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 });
expect(result.exitCode).toBe(130); expect(result.exitCode).toBe(130);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Global setup'); expect(output).toContain('Global setup');
expect(output).not.toContain('Global teardown'); expect(output).not.toContain('Global teardown');
}); });
@ -396,7 +396,7 @@ test('sigint should stop plugins', async ({ runInlineTest }) => {
}, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 }); }, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 });
expect(result.exitCode).toBe(130); expect(result.exitCode).toBe(130);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Plugin1 setup'); expect(output).toContain('Plugin1 setup');
expect(output).not.toContain('Plugin1 teardown'); expect(output).not.toContain('Plugin1 teardown');
expect(output).not.toContain('Plugin2 setup'); expect(output).not.toContain('Plugin2 setup');
@ -437,7 +437,7 @@ test('sigint should stop plugins 2', async ({ runInlineTest }) => {
}, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 }); }, { 'workers': 1 }, {}, { sendSIGINTAfter: 1 });
expect(result.exitCode).toBe(130); expect(result.exitCode).toBe(130);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
const output = stripAnsi(result.output); const output = result.output;
expect(output).toContain('Plugin1 setup'); expect(output).toContain('Plugin1 setup');
expect(output).toContain('Plugin2 setup'); expect(output).toContain('Plugin2 setup');
expect(output).toContain('Plugin1 teardown'); expect(output).toContain('Plugin1 teardown');
@ -455,9 +455,9 @@ test('should not crash with duplicate titles and .only', async ({ runInlineTest
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain(`Error: duplicate test title`); expect(result.output).toContain(`Error: duplicate test title`);
expect(stripAnsi(result.output)).toContain(`test('non unique title'`); expect(result.output).toContain(`test('non unique title'`);
expect(stripAnsi(result.output)).toContain(`test.skip('non unique title'`); expect(result.output).toContain(`test.skip('non unique title'`);
expect(stripAnsi(result.output)).toContain(`test.only('non unique title'`); expect(result.output).toContain(`test.only('non unique title'`);
expect(result.output).toContain(`example.spec.ts:6`); expect(result.output).toContain(`example.spec.ts:6`);
expect(result.output).toContain(`example.spec.ts:7`); expect(result.output).toContain(`example.spec.ts:7`);
expect(result.output).toContain(`example.spec.ts:8`); expect(result.output).toContain(`example.spec.ts:8`);
@ -474,7 +474,7 @@ test('should not crash with duplicate titles and line filter', async ({ runInlin
}, {}, {}, { additionalArgs: ['example.spec.ts:8'] }); }, {}, {}, { additionalArgs: ['example.spec.ts:8'] });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain(`Error: duplicate test title`); expect(result.output).toContain(`Error: duplicate test title`);
expect(stripAnsi(result.output)).toContain(`test('non unique title'`); expect(result.output).toContain(`test('non unique title'`);
expect(result.output).toContain(`example.spec.ts:6`); expect(result.output).toContain(`example.spec.ts:6`);
expect(result.output).toContain(`example.spec.ts:7`); expect(result.output).toContain(`example.spec.ts:7`);
expect(result.output).toContain(`example.spec.ts:8`); expect(result.output).toContain(`example.spec.ts:8`);
@ -495,6 +495,6 @@ test('should not load tests not matching filter', async ({ runInlineTest }) => {
}, {}, {}, { additionalArgs: ['a.spec.ts'] }); }, {}, {}, { additionalArgs: ['a.spec.ts'] });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(stripAnsi(result.output)).not.toContain('in example.spec.ts'); expect(result.output).not.toContain('in example.spec.ts');
expect(stripAnsi(result.output)).toContain('in a.spec.ts'); expect(result.output).toContain('in a.spec.ts');
}); });

View file

@ -16,7 +16,7 @@
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
async function getSnapshotPaths(runInlineTest, testInfo, playwrightConfig, pathArgs) { async function getSnapshotPaths(runInlineTest, testInfo, playwrightConfig, pathArgs) {
const SEPARATOR = '==== 8< ---- '; const SEPARATOR = '==== 8< ---- ';
@ -39,7 +39,7 @@ async function getSnapshotPaths(runInlineTest, testInfo, playwrightConfig, pathA
` `
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
const allSegments = stripAnsi(result.output).split(SEPARATOR); const allSegments = result.output.split(SEPARATOR);
const projToSnapshot = {}; const projToSnapshot = {};
for (let i = 1; i < allSegments.length; i += 3) for (let i = 1; i < allSegments.length; i += 3)
projToSnapshot[allSegments[i]] = path.relative(testInfo.outputDir, allSegments[i + 1]); projToSnapshot[allSegments[i]] = path.relative(testInfo.outputDir, allSegments[i + 1]);

View file

@ -29,13 +29,13 @@ test('should get top level stdio', async ({ runInlineTest }) => {
` `
}); });
// top level logs appear twice, because the file is required twice // top level logs appear twice, because the file is required twice
expect(result.output.split('\n').filter(x => x.startsWith('%%')).sort()).toEqual([ expect(result.outputLines.sort()).toEqual([
'%% stderr in a test', 'stderr in a test',
'%% stdout in a test', 'stdout in a test',
'%% top level stderr', 'top level stderr',
'%% top level stderr', 'top level stderr',
'%% top level stdout', 'top level stdout',
'%% top level stdout', 'top level stdout',
]); ]);
}); });
@ -55,9 +55,9 @@ test('should get stdio from worker fixture teardown', async ({ runInlineTest })
test('is a test', async ({fixture}) => {}); test('is a test', async ({fixture}) => {});
` `
}); });
expect(result.output.split('\n').filter(x => x.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%% worker setup', 'worker setup',
'%% worker teardown' 'worker teardown'
]); ]);
}); });
@ -92,8 +92,8 @@ test('should support console colors', async ({ runInlineTest }) => {
expect(result.output).toContain(`process.stdout.isTTY = true`); expect(result.output).toContain(`process.stdout.isTTY = true`);
expect(result.output).toContain(`process.stderr.isTTY = true`); expect(result.output).toContain(`process.stderr.isTTY = true`);
// The output should have colors. // The output should have colors.
expect(result.output).toContain(`{ b: \x1b[33mtrue\x1b[39m, n: \x1b[33m123\x1b[39m, s: \x1b[32m'abc'\x1b[39m }`); expect(result.rawOutput).toContain(`{ b: \x1b[33mtrue\x1b[39m, n: \x1b[33m123\x1b[39m, s: \x1b[32m'abc'\x1b[39m }`);
expect(result.output).toContain(`{ b: \x1b[33mfalse\x1b[39m, n: \x1b[33m123\x1b[39m, s: \x1b[32m'abc'\x1b[39m }`); expect(result.rawOutput).toContain(`{ b: \x1b[33mfalse\x1b[39m, n: \x1b[33m123\x1b[39m, s: \x1b[32m'abc'\x1b[39m }`);
}); });
test('should override hasColors and getColorDepth', async ({ runInlineTest }) => { test('should override hasColors and getColorDepth', async ({ runInlineTest }) => {

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should work directly', async ({ runInlineTest }) => { test('should work directly', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -84,7 +84,7 @@ test('should throw outside test', async ({ runInlineTest }) => {
test('test 1', async ({title}) => {}); test('test 1', async ({title}) => {});
`, `,
}); });
const output = stripAnsi(result.output); const output = result.output;
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(output).toContain('test.info() can only be called while test is running'); expect(output).toContain('test.info() can only be called while test is running');
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi, expectTestHelper } from './playwright-test-fixtures'; import { test, expect, expectTestHelper } from './playwright-test-fixtures';
test('test modifiers should work', async ({ runInlineTest }) => { test('test modifiers should work', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -443,10 +443,10 @@ test('test.skip with worker fixtures only should skip before hooks and tests', a
expect(result.report.suites[0].specs[0].tests[0].annotations).toEqual([]); expect(result.report.suites[0].specs[0].tests[0].annotations).toEqual([]);
expect(result.report.suites[0].suites![0].specs[0].tests[0].annotations).toEqual([{ type: 'skip', description: 'reason' }]); expect(result.report.suites[0].suites![0].specs[0].tests[0].annotations).toEqual([{ type: 'skip', description: 'reason' }]);
expect(result.report.suites[0].suites![0].suites![0].specs[0].tests[0].annotations).toEqual([{ type: 'skip', description: 'reason' }]); expect(result.report.suites[0].suites![0].suites![0].specs[0].tests[0].annotations).toEqual([{ type: 'skip', description: 'reason' }]);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%beforeEach', 'beforeEach',
'%%passed', 'passed',
'%%skip', 'skip',
]); ]);
}); });
@ -509,7 +509,7 @@ test('modifier timeout should be reported', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('"skip" modifier timeout of 2000ms exceeded.'); expect(result.output).toContain('"skip" modifier timeout of 2000ms exceeded.');
expect(stripAnsi(result.output)).toContain('6 | test.skip(async () => new Promise(() => {}));'); expect(result.output).toContain('6 | test.skip(async () => new Promise(() => {}));');
}); });
test('should not run hooks if modifier throws', async ({ runInlineTest }) => { test('should not run hooks if modifier throws', async ({ runInlineTest }) => {
@ -539,8 +539,8 @@ test('should not run hooks if modifier throws', async ({ runInlineTest }) => {
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%modifier', 'modifier',
]); ]);
}); });
@ -576,21 +576,21 @@ test('should report skipped tests in-order with correct properties', async ({ ru
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%begin-test1', 'begin-test1',
'%%end-test1', 'end-test1',
'%%expectedStatus-passed', 'expectedStatus-passed',
'%%timeout-1234', 'timeout-1234',
'%%retries-3', 'retries-3',
'%%begin-test2', 'begin-test2',
'%%end-test2', 'end-test2',
'%%expectedStatus-skipped', 'expectedStatus-skipped',
'%%timeout-1234', 'timeout-1234',
'%%retries-3', 'retries-3',
'%%begin-test3', 'begin-test3',
'%%end-test3', 'end-test3',
'%%expectedStatus-passed', 'expectedStatus-passed',
'%%timeout-1234', 'timeout-1234',
'%%retries-3', 'retries-3',
]); ]);
}); });

View file

@ -126,10 +126,10 @@ test('should be unique for beforeAll hook from different workers', async ({ runI
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output.split('\n').filter(x => x.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
`%%${testInfo.outputPath('test-results', 'a-fails')}`, `${testInfo.outputPath('test-results', 'a-fails')}`,
`%%${testInfo.outputPath('test-results', 'a-fails-retry1')}`, `${testInfo.outputPath('test-results', 'a-fails-retry1')}`,
`%%${testInfo.outputPath('test-results', 'a-passes')}`, `${testInfo.outputPath('test-results', 'a-passes')}`,
]); ]);
}); });
@ -395,7 +395,7 @@ test('should allow nonAscii characters in the output dir', async ({ runInlineTes
}); });
`, `,
}); });
const outputDir = result.output.split('\n').filter(x => x.startsWith('%%'))[0].slice('%%'.length); const outputDir = result.outputLines[0];
expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my-test-こんにちは世界')); expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my-test-こんにちは世界'));
}); });
@ -410,7 +410,7 @@ test('should allow shorten long output dirs characters in the output dir', async
}); });
`, `,
}); });
const outputDir = result.output.split('\n').filter(x => x.startsWith('%%'))[0].slice('%%'.length); const outputDir = result.outputLines[0];
expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'very-deep-and-long-file-name-that-i-want-to-be-99202--keeps-going-and-going-and-we-should-shorten-it')); expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'very-deep-and-long-file-name-that-i-want-to-be-99202--keeps-going-and-going-and-we-should-shorten-it'));
}); });
@ -423,7 +423,7 @@ test('should not mangle double dashes', async ({ runInlineTest }, testInfo) => {
}); });
`, `,
}); });
const outputDir = result.output.split('\n').filter(x => x.startsWith('%%'))[0].slice('%%'.length); const outputDir = result.outputLines[0];
expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my--file-my--test')); expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my--file-my--test'));
}); });
@ -438,6 +438,6 @@ test('should allow include the describe name the output dir', async ({ runInline
}); });
`, `,
}); });
const outputDir = result.output.split('\n').filter(x => x.startsWith('%%'))[0].slice('%%'.length); const outputDir = result.outputLines[0];
expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my-test-hello-world')); expect(outputDir).toBe(path.join(testInfo.outputDir, 'test-results', 'my-test-hello-world'));
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, countTimes, stripAnsi } from './playwright-test-fixtures'; import { test, expect, countTimes } from './playwright-test-fixtures';
test('test.describe.parallel should throw inside test.describe.serial', async ({ runInlineTest }) => { test('test.describe.parallel should throw inside test.describe.serial', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -197,8 +197,8 @@ test('parallel mode should minimize running beforeAll/afterAll hooks', async ({
}, { workers: 1 }); }, { workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(countTimes(stripAnsi(result.output), '%%beforeAll')).toBe(1); expect(countTimes(result.output, '%%beforeAll')).toBe(1);
expect(countTimes(stripAnsi(result.output), '%%afterAll')).toBe(1); expect(countTimes(result.output, '%%afterAll')).toBe(1);
}); });
test('parallel mode should minimize running beforeAll/afterAll hooks 2', async ({ runInlineTest }) => { test('parallel mode should minimize running beforeAll/afterAll hooks 2', async ({ runInlineTest }) => {
@ -220,6 +220,6 @@ test('parallel mode should minimize running beforeAll/afterAll hooks 2', async (
}, { workers: 2 }); }, { workers: 2 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(countTimes(stripAnsi(result.output), '%%beforeAll')).toBe(2); expect(countTimes(result.output, '%%beforeAll')).toBe(2);
expect(countTimes(stripAnsi(result.output), '%%afterAll')).toBe(2); expect(countTimes(result.output, '%%afterAll')).toBe(2);
}); });

View file

@ -48,10 +48,10 @@ test('test.describe.serial should work', async ({ runInlineTest }) => {
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(2); expect(result.skipped).toBe(2);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%test2', 'test2',
'%%test3', 'test3',
]); ]);
}); });
@ -88,10 +88,10 @@ test('test.describe.serial should work in describe', async ({ runInlineTest }) =
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(2); expect(result.skipped).toBe(2);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%test2', 'test2',
'%%test3', 'test3',
]); ]);
}); });
@ -129,14 +129,14 @@ test('test.describe.serial should work with retry', async ({ runInlineTest }) =>
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%test2', 'test2',
'%%test3', 'test3',
'%%test1', 'test1',
'%%test2', 'test2',
'%%test3', 'test3',
'%%test4', 'test4',
]); ]);
}); });
@ -166,12 +166,12 @@ test('test.describe.serial should work with retry and beforeAll failure', async
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%beforeAll', 'beforeAll',
'%%test1', 'test1',
'%%beforeAll', 'beforeAll',
'%%test2', 'test2',
]); ]);
}); });
@ -203,12 +203,12 @@ test('test.describe.serial should work with retry and afterAll failure', async (
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test1', 'test1',
'%%afterAll', 'afterAll',
'%%test1', 'test1',
'%%afterAll', 'afterAll',
'%%test2', 'test2',
]); ]);
}); });
@ -236,9 +236,9 @@ test('test.describe.serial.only should work', async ({ runInlineTest }) => {
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%test2', 'test2',
'%%test3', 'test3',
]); ]);
}); });
@ -273,10 +273,10 @@ test('test.describe.serial should work with test.fail', async ({ runInlineTest }
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.skipped).toBe(1); expect(result.skipped).toBe(1);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%zero', 'zero',
'%%one', 'one',
'%%two', 'two',
]); ]);
}); });
@ -312,14 +312,14 @@ test('test.describe.serial should work with test.fail and retries', async ({ run
expect(result.flaky).toBe(1); expect(result.flaky).toBe(1);
expect(result.failed).toBe(0); expect(result.failed).toBe(0);
expect(result.skipped).toBe(0); expect(result.skipped).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%zero', 'zero',
'%%one', 'one',
'%%two', 'two',
'%%zero', 'zero',
'%%one', 'one',
'%%two', 'two',
'%%three', 'three',
]); ]);
}); });
@ -355,16 +355,16 @@ test('test.describe.serial should work inside test.describe.parallel', async ({
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(result.output).toContain('Running 4 tests using 2 workers'); expect(result.output).toContain('Running 4 tests using 2 workers');
const lines = result.output.split('\n').filter(line => line.startsWith('%%')); const lines = result.outputLines;
// First test in each worker started before the second test in the other. // First test in each worker started before the second test in the other.
// This means they were actually running in parallel. // This means they were actually running in parallel.
expect(lines.indexOf('%%1-one')).toBeLessThan(lines.indexOf('%%2-two')); expect(lines.indexOf('1-one')).toBeLessThan(lines.indexOf('2-two'));
expect(lines.indexOf('%%2-one')).toBeLessThan(lines.indexOf('%%1-two')); expect(lines.indexOf('2-one')).toBeLessThan(lines.indexOf('1-two'));
expect(lines.sort()).toEqual([ expect(lines.sort()).toEqual([
'%%1-one', '1-one',
'%%1-two', '1-two',
'%%2-one', '2-one',
'%%2-two', '2-two',
]); ]);
}); });
@ -389,8 +389,8 @@ test('test.describe.serial should work with fullyParallel', async ({ runInlineTe
}, { workers: 2 }); }, { workers: 2 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%one', 'one',
'%%two', 'two',
]); ]);
}); });

View file

@ -256,19 +256,19 @@ test('should report test.step from fixtures', async ({ runInlineTest }) => {
}, { reporter: '', workers: 1 }); }, { reporter: '', workers: 1 });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
`%% begin Before Hooks`, `begin Before Hooks`,
`%% begin setup foo`, `begin setup foo`,
`%% end setup foo`, `end setup foo`,
`%% end Before Hooks`, `end Before Hooks`,
`%% begin test step`, `begin test step`,
`%% begin inside foo`, `begin inside foo`,
`%% end inside foo`, `end inside foo`,
`%% end test step`, `end test step`,
`%% begin After Hooks`, `begin After Hooks`,
`%% begin teardown foo`, `begin teardown foo`,
`%% end teardown foo`, `end teardown foo`,
`%% end After Hooks`, `end After Hooks`,
]); ]);
}); });

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should merge options', async ({ runInlineTest }) => { test('should merge options', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -90,7 +90,7 @@ test('should throw when setting worker options in describe', async ({ runInlineT
`Cannot use({ foo }) in a describe group, because it forces a new worker.`, `Cannot use({ foo }) in a describe group, because it forces a new worker.`,
`Make it top-level in the test file or put in the configuration file.`, `Make it top-level in the test file or put in the configuration file.`,
].join('\n')); ].join('\n'));
expect(stripAnsi(result.output)).toContain(`{ foo: 'bar' }`); expect(result.output).toContain(`{ foo: 'bar' }`);
}); });
test('should run tests with different worker options', async ({ runInlineTest }) => { test('should run tests with different worker options', async ({ runInlineTest }) => {

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should run fixture teardown on timeout', async ({ runInlineTest }) => { test('should run fixture teardown on timeout', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -198,7 +198,7 @@ test('should respect fixture timeout', async ({ runInlineTest }) => {
expect(result.failed).toBe(2); expect(result.failed).toBe(2);
expect(result.output).toContain('Fixture "custom title" timeout of 500ms exceeded.'); expect(result.output).toContain('Fixture "custom title" timeout of 500ms exceeded.');
expect(result.output).toContain('Fixture "slowTeardown" timeout of 400ms exceeded.'); expect(result.output).toContain('Fixture "slowTeardown" timeout of 400ms exceeded.');
expect(stripAnsi(result.output)).toContain('> 5 | const test = pwt.test.extend({'); expect(result.output).toContain('> 5 | const test = pwt.test.extend({');
}); });
test('should respect test.setTimeout in the worker fixture', async ({ runInlineTest }) => { test('should respect test.setTimeout in the worker fixture', async ({ runInlineTest }) => {
@ -332,12 +332,12 @@ test('test timeout should still run hooks before fixtures teardown', async ({ ru
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('Test timeout of 100ms exceeded.'); expect(result.output).toContain('Test timeout of 100ms exceeded.');
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
'%%before-auto', 'before-auto',
'%%test', 'test',
'%%afterAll-1', 'afterAll-1',
'%%afterAll-2', 'afterAll-2',
'%%after-auto', 'after-auto',
]); ]);
}); });

View file

@ -18,7 +18,7 @@ import * as fs from 'fs';
import { PNG } from 'playwright-core/lib/utilsBundle'; import { PNG } from 'playwright-core/lib/utilsBundle';
import * as path from 'path'; import * as path from 'path';
import { pathToFileURL } from 'url'; import { pathToFileURL } from 'url';
import { test, expect, stripAnsi, createImage, paintBlackPixels } from './playwright-test-fixtures'; import { test, expect, createImage, paintBlackPixels } from './playwright-test-fixtures';
import { comparePNGs } from '../config/comparator'; import { comparePNGs } from '../config/comparator';
test.describe.configure({ mode: 'parallel' }); test.describe.configure({ mode: 'parallel' });
@ -48,9 +48,9 @@ test('should fail to screenshot a page with infinite animation', async ({ runInl
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`Timeout 2000ms exceeded`); expect(result.output).toContain(`Timeout 2000ms exceeded`);
expect(stripAnsi(result.output)).toContain(`expect.toHaveScreenshot with timeout 2000ms`); expect(result.output).toContain(`expect.toHaveScreenshot with timeout 2000ms`);
expect(stripAnsi(result.output)).toContain(`generating new stable screenshot expectation`); expect(result.output).toContain(`generating new stable screenshot expectation`);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(true); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(true);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-previous.png'))).toBe(true); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-previous.png'))).toBe(true);
@ -128,7 +128,7 @@ test('should fail with proper error when unsupported argument is given', async (
` `
}, { 'update-snapshots': true }); }, { 'update-snapshots': true });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`Expected options.clip.width not to be 0`); expect(result.output).toContain(`Expected options.clip.width not to be 0`);
}); });
test('should have scale:css by default', async ({ runInlineTest }, testInfo) => { test('should have scale:css by default', async ({ runInlineTest }, testInfo) => {
@ -198,13 +198,13 @@ test('should report toHaveScreenshot step with expectation name in title', async
}, { 'reporter': '', 'workers': 1, 'update-snapshots': true }); }, { 'reporter': '', 'workers': 1, 'update-snapshots': true });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.output.split('\n').filter(line => line.startsWith('%%'))).toEqual([ expect(result.outputLines).toEqual([
`%% end browserContext.newPage`, `end browserContext.newPage`,
`%% end Before Hooks`, `end Before Hooks`,
`%% end expect.toHaveScreenshot(foo.png)`, `end expect.toHaveScreenshot(foo.png)`,
`%% end expect.toHaveScreenshot(is-a-test-1.png)`, `end expect.toHaveScreenshot(is-a-test-1.png)`,
`%% end browserContext.close`, `end browserContext.close`,
`%% end After Hooks`, `end After Hooks`,
]); ]);
}); });
@ -319,8 +319,8 @@ test('should fail to screenshot an element with infinite animation', async ({ ru
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`Timeout 2000ms exceeded`); expect(result.output).toContain(`Timeout 2000ms exceeded`);
expect(stripAnsi(result.output)).toContain(`expect.toHaveScreenshot with timeout 2000ms`); expect(result.output).toContain(`expect.toHaveScreenshot with timeout 2000ms`);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-previous.png'))).toBe(true); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-previous.png'))).toBe(true);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(true); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(true);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false);
@ -347,8 +347,8 @@ test('should fail to screenshot an element that keeps moving', async ({ runInlin
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`Timeout 2000ms exceeded`); expect(result.output).toContain(`Timeout 2000ms exceeded`);
expect(stripAnsi(result.output)).toContain(`element is not stable - waiting`); expect(result.output).toContain(`element is not stable - waiting`);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(false); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-actual.png'))).toBe(false);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-expected.png'))).toBe(false);
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-diff.png'))).toBe(false); expect(fs.existsSync(testInfo.outputPath('test-results', 'a-is-a-test', 'is-a-test-1-diff.png'))).toBe(false);
@ -427,8 +427,8 @@ test('should fail when screenshot is different size', async ({ runInlineTest })
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`verifying given screenshot expectation`); expect(result.output).toContain(`verifying given screenshot expectation`);
expect(stripAnsi(result.output)).toContain(`captured a stable screenshot`); expect(result.output).toContain(`captured a stable screenshot`);
expect(result.output).toContain('Expected an image 22px by 33px, received 1280px by 720px.'); expect(result.output).toContain('Expected an image 22px by 33px, received 1280px by 720px.');
}); });
@ -444,7 +444,7 @@ test('should fail when given non-png snapshot name', async ({ runInlineTest }) =
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`Screenshot name "snapshot.jpeg" must have '.png' extension`); expect(result.output).toContain(`Screenshot name "snapshot.jpeg" must have '.png' extension`);
}); });
test('should fail when given buffer', async ({ runInlineTest }) => { test('should fail when given buffer', async ({ runInlineTest }) => {
@ -457,7 +457,7 @@ test('should fail when given buffer', async ({ runInlineTest }) => {
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(stripAnsi(result.output)).toContain(`toHaveScreenshot can be only used with Page or Locator objects`); expect(result.output).toContain(`toHaveScreenshot can be only used with Page or Locator objects`);
}); });
test('should fail when screenshot is different pixels', async ({ runInlineTest }) => { test('should fail when screenshot is different pixels', async ({ runInlineTest }) => {
@ -495,7 +495,7 @@ test('doesn\'t create comparison artifacts in an output folder for passed negate
}); });
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
const outputText = stripAnsi(result.output); const outputText = result.output;
const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.png'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.png');
const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.png'); const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.png');
expect(outputText).not.toContain(`Expected: ${expectedSnapshotArtifactPath}`); expect(outputText).not.toContain(`Expected: ${expectedSnapshotArtifactPath}`);
@ -565,7 +565,7 @@ test('should write missing expectations locally twice and continue', async ({ ru
expect(result.output).toContain('Here we are!'); expect(result.output).toContain('Here we are!');
const stackLines = stripAnsi(result.output).split('\n').filter(line => line.includes(' at ')).filter(line => !line.includes(testInfo.outputPath())); const stackLines = result.output.split('\n').filter(line => line.includes(' at ')).filter(line => !line.includes(testInfo.outputPath()));
expect(result.output).toContain('a.spec.js:5'); expect(result.output).toContain('a.spec.js:5');
expect(stackLines.length).toBe(0); expect(stackLines.length).toBe(0);
}); });
@ -960,7 +960,7 @@ test('should attach expected/actual/diff when sizes are different', async ({ run
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
const outputText = stripAnsi(result.output); const outputText = result.output;
expect(outputText).toContain('Expected an image 2px by 2px, received 1280px by 720px.'); expect(outputText).toContain('Expected an image 2px by 2px, received 1280px by 720px.');
expect(outputText).toContain('4 pixels (ratio 0.01 of all image pixels) are different.'); expect(outputText).toContain('4 pixels (ratio 0.01 of all image pixels) are different.');
const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0]; const attachments = outputText.split('\n').filter(l => l.startsWith('## ')).map(l => l.substring(3)).map(l => JSON.parse(l))[0];

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect, stripAnsi } from './playwright-test-fixtures'; import { test, expect } from './playwright-test-fixtures';
test('should print dependencies in CJS mode', async ({ runInlineTest }) => { test('should print dependencies in CJS mode', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
@ -44,7 +44,7 @@ test('should print dependencies in CJS mode', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
const output = stripAnsi(result.output); const output = result.output;
const deps = JSON.parse(output.match(/###(.*)###/)![1]); const deps = JSON.parse(output.match(/###(.*)###/)![1]);
expect(deps).toEqual({ expect(deps).toEqual({
'a.test.ts': ['helperA.ts'], 'a.test.ts': ['helperA.ts'],
@ -82,7 +82,7 @@ test('should print dependencies in ESM mode', async ({ runInlineTest, nodeVersio
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(2); expect(result.passed).toBe(2);
const output = stripAnsi(result.output); const output = result.output;
const deps = JSON.parse(output.match(/###(.*)###/)![1]); const deps = JSON.parse(output.match(/###(.*)###/)![1]);
expect(deps).toEqual({ expect(deps).toEqual({
'a.test.ts': ['helperA.ts'], 'a.test.ts': ['helperA.ts'],