mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	test: make expectations for some reporter tests readable (#30470)
This commit is contained in:
		
							parent
							
								
									b0fbe058ae
								
							
						
					
					
						commit
						18dcd6adff
					
				@ -14,27 +14,106 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { test, expect, stripAnsi } from './playwright-test-fixtures';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import { test, expect } from './playwright-test-fixtures';
 | 
			
		||||
 | 
			
		||||
const smallReporterJS = `
 | 
			
		||||
const path = require('path');
 | 
			
		||||
 | 
			
		||||
function formatLocation(location) {
 | 
			
		||||
  if (!location)
 | 
			
		||||
    return ' @ <no location>';
 | 
			
		||||
  return ' @ ' + path.basename(location.file) + ':' + location.line;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function formatTitle(test) {
 | 
			
		||||
  let titlePath = test.titlePath();
 | 
			
		||||
  if (!titlePath[0])
 | 
			
		||||
    [, ...titlePath] = titlePath;
 | 
			
		||||
  return titlePath.join(' > ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const asciiRegex = new RegExp('[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)|(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))', 'g');
 | 
			
		||||
function stripAnsi(str) {
 | 
			
		||||
  return str.replace(asciiRegex, '');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Reporter {
 | 
			
		||||
  constructor(options) {
 | 
			
		||||
    this.options = options;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trimError(message) {
 | 
			
		||||
    if (this.options.skipErrorMessage)
 | 
			
		||||
      return '<error message>';
 | 
			
		||||
    const lines = message.split('\\n');
 | 
			
		||||
    return lines[0].trimEnd();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printErrors(errors, prefix) {
 | 
			
		||||
    for (const error of errors) {
 | 
			
		||||
      const errorLocation = this.options.skipErrorLocation ? '' : formatLocation(error.location);
 | 
			
		||||
      console.log((prefix || '  error: ') + this.trimError(error.message) + errorLocation);
 | 
			
		||||
      if (this.options.printErrorSnippet && error.snippet) {
 | 
			
		||||
        const lines = ['======', ...error.snippet.split('\\n'), '======'];
 | 
			
		||||
        console.log(lines.map(line => stripAnsi('  ' + line).trimEnd()).join('\\n'));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printsToStdio() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onBegin(config, suite) {
 | 
			
		||||
    console.log('\\n%%begin');
 | 
			
		||||
    console.log(); // for nicer expectations
 | 
			
		||||
    console.log('onBegin: ' + suite.allTests().length + ' tests total');
 | 
			
		||||
    if (this.options.onBegin)
 | 
			
		||||
      console.log('  options.onBegin=' + this.options.onBegin);
 | 
			
		||||
  }
 | 
			
		||||
  onTestBegin(test) {}
 | 
			
		||||
  onStdOut() {}
 | 
			
		||||
  onStdErr() {}
 | 
			
		||||
  onTestEnd(test, result) {}
 | 
			
		||||
  onTimeout() {}
 | 
			
		||||
 | 
			
		||||
  onTestBegin(test, result) {
 | 
			
		||||
    console.log('onTestBegin: ' + formatTitle(test) + '; retry #' + result.retry);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onTestEnd(test, result) {
 | 
			
		||||
    console.log('onTestEnd: ' + formatTitle(test) + '; retry #' + result.retry);
 | 
			
		||||
    this.printErrors(result.errors);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onStepBegin(test, result, step) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onStepEnd(test, result, step) {
 | 
			
		||||
    if (this.options.printSteps) {
 | 
			
		||||
      console.log('onStepEnd: ' + step.title);
 | 
			
		||||
      if (step.error)
 | 
			
		||||
        this.printErrors([step.error]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // For easier debugging.
 | 
			
		||||
  onStdOut(data) {
 | 
			
		||||
    process.stdout.write(data.toString());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // For easier debugging.
 | 
			
		||||
  onStdErr(data) {
 | 
			
		||||
    process.stderr.write(data.toString());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onError(error) {
 | 
			
		||||
    console.log('\\n%%got error: ' + error.message);
 | 
			
		||||
    this.printErrors([error], 'onError: ');
 | 
			
		||||
  }
 | 
			
		||||
  onEnd() {
 | 
			
		||||
    console.log('\\n%%end');
 | 
			
		||||
 | 
			
		||||
  async onEnd() {
 | 
			
		||||
    await new Promise(f => setTimeout(f, 500));
 | 
			
		||||
    console.log('onEnd');
 | 
			
		||||
    if (this.options.onEnd)
 | 
			
		||||
      console.log('  options.onEnd=' + this.options.onEnd);
 | 
			
		||||
  }
 | 
			
		||||
  onExit() {
 | 
			
		||||
    console.log('\\n%%exit');
 | 
			
		||||
 | 
			
		||||
  async onExit() {
 | 
			
		||||
    console.log('onExit');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
module.exports = Reporter;
 | 
			
		||||
@ -46,52 +125,11 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
 | 
			
		||||
    test('should work with custom reporter', async ({ runInlineTest }) => {
 | 
			
		||||
      const result = await runInlineTest({
 | 
			
		||||
        'reporter.ts': `
 | 
			
		||||
          class Reporter {
 | 
			
		||||
            constructor(options) {
 | 
			
		||||
              this.options = options;
 | 
			
		||||
            }
 | 
			
		||||
            onBegin(config, suite) {
 | 
			
		||||
              console.log('\\n%%reporter-begin-' + this.options.begin + '%%');
 | 
			
		||||
              console.log('\\n%%version-' + config.version);
 | 
			
		||||
            }
 | 
			
		||||
            onTestBegin(test) {
 | 
			
		||||
              const projectName = test.titlePath()[1];
 | 
			
		||||
              console.log('\\n%%reporter-testbegin-' + test.title + '-' + projectName + '%%');
 | 
			
		||||
              const suite = test.parent;
 | 
			
		||||
              if (!suite.tests.includes(test))
 | 
			
		||||
                console.log('\\n%%error-inconsistent-parent');
 | 
			
		||||
              if (test.parent.project().name !== projectName)
 | 
			
		||||
                console.log('\\n%%error-inconsistent-project-name');
 | 
			
		||||
            }
 | 
			
		||||
            onStdOut() {
 | 
			
		||||
              console.log('\\n%%reporter-stdout%%');
 | 
			
		||||
            }
 | 
			
		||||
            onStdErr() {
 | 
			
		||||
              console.log('\\n%%reporter-stderr%%');
 | 
			
		||||
            }
 | 
			
		||||
            onTestEnd(test, result) {
 | 
			
		||||
              console.log('\\n%%reporter-testend-' + test.title + '-' + test.titlePath()[1] + '%%');
 | 
			
		||||
              if (!result.startTime)
 | 
			
		||||
                console.log('\\n%%error-no-start-time');
 | 
			
		||||
            }
 | 
			
		||||
            onTimeout() {
 | 
			
		||||
              console.log('\\n%%reporter-timeout%%');
 | 
			
		||||
            }
 | 
			
		||||
            onError() {
 | 
			
		||||
              console.log('\\n%%reporter-error%%');
 | 
			
		||||
            }
 | 
			
		||||
            async onEnd() {
 | 
			
		||||
              await new Promise(f => setTimeout(f, 500));
 | 
			
		||||
              console.log('\\n%%reporter-end-' + this.options.end + '%%');
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          export default Reporter;
 | 
			
		||||
        `,
 | 
			
		||||
        'reporter.ts': smallReporterJS,
 | 
			
		||||
        'playwright.config.ts': `
 | 
			
		||||
          module.exports = {
 | 
			
		||||
            reporter: [
 | 
			
		||||
              [ './reporter.ts', { begin: 'begin', end: 'end' } ]
 | 
			
		||||
              [ './reporter.ts', { onBegin: 'begin-data', onEnd: 'end-data' } ]
 | 
			
		||||
            ],
 | 
			
		||||
            projects: [
 | 
			
		||||
              { name: 'foo', repeatEach: 2 },
 | 
			
		||||
@ -113,23 +151,25 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { reporter: '', workers: 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(0);
 | 
			
		||||
      expect(result.outputLines).toEqual([
 | 
			
		||||
        'reporter-begin-begin%%',
 | 
			
		||||
        'version-' + require('../../packages/playwright/package.json').version,
 | 
			
		||||
        'reporter-testbegin-is run-foo%%',
 | 
			
		||||
        'reporter-stdout%%',
 | 
			
		||||
        'reporter-stderr%%',
 | 
			
		||||
        'reporter-testend-is run-foo%%',
 | 
			
		||||
        'reporter-testbegin-is run-foo%%',
 | 
			
		||||
        'reporter-stdout%%',
 | 
			
		||||
        'reporter-stderr%%',
 | 
			
		||||
        'reporter-testend-is run-foo%%',
 | 
			
		||||
        'reporter-testbegin-is run-bar%%',
 | 
			
		||||
        'reporter-stdout%%',
 | 
			
		||||
        'reporter-stderr%%',
 | 
			
		||||
        'reporter-testend-is run-bar%%',
 | 
			
		||||
        'reporter-end-end%%',
 | 
			
		||||
      ]);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 3 tests total
 | 
			
		||||
  options.onBegin=begin-data
 | 
			
		||||
onTestBegin: foo > a.test.ts > is run; retry #0
 | 
			
		||||
log
 | 
			
		||||
error
 | 
			
		||||
onTestEnd: foo > a.test.ts > is run; retry #0
 | 
			
		||||
onTestBegin: foo > a.test.ts > is run; retry #0
 | 
			
		||||
log
 | 
			
		||||
error
 | 
			
		||||
onTestEnd: foo > a.test.ts > is run; retry #0
 | 
			
		||||
onTestBegin: bar > a.test.ts > is run; retry #0
 | 
			
		||||
log
 | 
			
		||||
error
 | 
			
		||||
onTestEnd: bar > a.test.ts > is run; retry #0
 | 
			
		||||
onEnd
 | 
			
		||||
  options.onEnd=end-data
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should work without a file extension', async ({ runInlineTest }) => {
 | 
			
		||||
@ -148,11 +188,13 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { reporter: '', workers: 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(0);
 | 
			
		||||
      expect(result.outputLines).toEqual([
 | 
			
		||||
        'begin',
 | 
			
		||||
        'end',
 | 
			
		||||
        'exit',
 | 
			
		||||
      ]);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 1 tests total
 | 
			
		||||
onTestBegin:  > a.test.ts > pass; retry #0
 | 
			
		||||
onTestEnd:  > a.test.ts > pass; retry #0
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should report onEnd after global teardown', async ({ runInlineTest }) => {
 | 
			
		||||
@ -178,12 +220,15 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { reporter: '', workers: 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(0);
 | 
			
		||||
      expect(result.outputLines).toEqual([
 | 
			
		||||
        'begin',
 | 
			
		||||
        'global teardown',
 | 
			
		||||
        'end',
 | 
			
		||||
        'exit',
 | 
			
		||||
      ]);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 1 tests total
 | 
			
		||||
onTestBegin:  > a.test.ts > pass; retry #0
 | 
			
		||||
onTestEnd:  > a.test.ts > pass; retry #0
 | 
			
		||||
 | 
			
		||||
%%global teardown
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should load reporter from node_modules', async ({ runInlineTest }) => {
 | 
			
		||||
@ -202,11 +247,13 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { reporter: '', workers: 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(0);
 | 
			
		||||
      expect(result.outputLines).toEqual([
 | 
			
		||||
        'begin',
 | 
			
		||||
        'end',
 | 
			
		||||
        'exit',
 | 
			
		||||
      ]);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 1 tests total
 | 
			
		||||
onTestBegin:  > a.test.ts > pass; retry #0
 | 
			
		||||
onTestEnd:  > a.test.ts > pass; retry #0
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should not have internal error when steps are finished after timeout', async ({ runInlineTest }) => {
 | 
			
		||||
@ -247,7 +294,12 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { 'reporter': '', 'forbid-only': true });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(1);
 | 
			
		||||
      expect(result.output).toContain(`%%got error: Error: item focused with '.only' is not allowed due to the '--forbid-only' CLI flag: \"a.test.ts pass\"`);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 0 tests total
 | 
			
		||||
onError: Error: item focused with '.only' is not allowed due to the '--forbid-only' CLI flag: "a.test.ts pass" @ a.test.ts:3
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should report no-tests error to reporter', async ({ runInlineTest }) => {
 | 
			
		||||
@ -261,7 +313,12 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { 'reporter': '' });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(1);
 | 
			
		||||
      expect(result.output).toContain(`%%got error: Error: No tests found`);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 0 tests total
 | 
			
		||||
onError: Error: No tests found @ <no location>
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should report require error to reporter', async ({ runInlineTest }) => {
 | 
			
		||||
@ -278,7 +335,13 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { 'reporter': '' });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(1);
 | 
			
		||||
      expect(result.output).toContain(`%%got error: Error: Oh my!`);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 0 tests total
 | 
			
		||||
onError: Error: Oh my! @ a.spec.js:2
 | 
			
		||||
onError: Error: No tests found @ <no location>
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should report global setup error to reporter', async ({ runInlineTest }) => {
 | 
			
		||||
@ -302,7 +365,12 @@ for (const useIntermediateMergeReport of [false, true] as const) {
 | 
			
		||||
      }, { 'reporter': '' });
 | 
			
		||||
 | 
			
		||||
      expect(result.exitCode).toBe(1);
 | 
			
		||||
      expect(result.output).toContain(`%%got error: Error: Oh my!`);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 0 tests total
 | 
			
		||||
onError: Error: Oh my! @ globalSetup.ts:3
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should report correct tests/suites when using grep', async ({ runInlineTest }) => {
 | 
			
		||||
@ -404,32 +472,9 @@ var import_test = __toModule(require("@playwright/test"));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('test and step error should have code snippet', async ({ runInlineTest }) => {
 | 
			
		||||
      const testErrorFile = test.info().outputPath('testError.txt');
 | 
			
		||||
      const stepErrorFile = test.info().outputPath('stepError.txt');
 | 
			
		||||
      const result = await runInlineTest({
 | 
			
		||||
        'reporter.ts': `
 | 
			
		||||
        import fs from 'fs';
 | 
			
		||||
        class Reporter {
 | 
			
		||||
          onStepEnd(test, result, step) {
 | 
			
		||||
            console.log('\\n%%onStepEnd: ' + step.error?.snippet?.length);
 | 
			
		||||
            if (step.error?.snippet)
 | 
			
		||||
              fs.writeFileSync('${stepErrorFile.replace(/\\/g, '\\\\')}', step.error?.snippet);
 | 
			
		||||
          }
 | 
			
		||||
          onTestEnd(test, result) {
 | 
			
		||||
            console.log('\\n%%onTestEnd: ' + result.error?.snippet?.length);
 | 
			
		||||
            if (result.error)
 | 
			
		||||
              fs.writeFileSync('${testErrorFile.replace(/\\/g, '\\\\')}', result.error?.snippet);
 | 
			
		||||
          }
 | 
			
		||||
          onError(error) {
 | 
			
		||||
            console.log('\\n%%onError: ' + error.snippet?.length);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        module.exports = Reporter;`,
 | 
			
		||||
        'playwright.config.ts': `
 | 
			
		||||
          module.exports = {
 | 
			
		||||
            reporter: './reporter',
 | 
			
		||||
          };
 | 
			
		||||
        `,
 | 
			
		||||
        'reporter.ts': smallReporterJS,
 | 
			
		||||
        'playwright.config.ts': `module.exports = { reporter: [['./reporter', { printSteps: true, printErrorSnippet: true }]] };`,
 | 
			
		||||
        'a.spec.js': `
 | 
			
		||||
          const { test, expect } = require('@playwright/test');
 | 
			
		||||
          test('test', async () => {
 | 
			
		||||
@ -439,56 +484,76 @@ var import_test = __toModule(require("@playwright/test"));
 | 
			
		||||
          });
 | 
			
		||||
        `,
 | 
			
		||||
      }, { 'reporter': '', 'workers': 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.output).toContain('onTestEnd: 550');
 | 
			
		||||
      expect(result.output).toContain('onStepEnd: 550');
 | 
			
		||||
      expect(stripAnsi(fs.readFileSync(testErrorFile, 'utf8'))).toBe(`  3 |           test('test', async () => {
 | 
			
		||||
  4 |             await test.step('step', async () => {
 | 
			
		||||
> 5 |               expect(1).toBe(2);
 | 
			
		||||
    |                         ^
 | 
			
		||||
  6 |             });
 | 
			
		||||
  7 |           });
 | 
			
		||||
  8 |         `);
 | 
			
		||||
      expect(stripAnsi(fs.readFileSync(stepErrorFile, 'utf8'))).toBe(`  3 |           test('test', async () => {
 | 
			
		||||
  4 |             await test.step('step', async () => {
 | 
			
		||||
> 5 |               expect(1).toBe(2);
 | 
			
		||||
    |                         ^
 | 
			
		||||
  6 |             });
 | 
			
		||||
  7 |           });
 | 
			
		||||
  8 |         `);
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 1 tests total
 | 
			
		||||
onTestBegin:  > a.spec.js > test; retry #0
 | 
			
		||||
onStepEnd: Before Hooks
 | 
			
		||||
onStepEnd: expect.toBe
 | 
			
		||||
  error: Error: expect(received).toBe(expected) // Object.is equality @ a.spec.js:5
 | 
			
		||||
  ======
 | 
			
		||||
    3 |           test('test', async () => {
 | 
			
		||||
    4 |             await test.step('step', async () => {
 | 
			
		||||
  > 5 |               expect(1).toBe(2);
 | 
			
		||||
      |                         ^
 | 
			
		||||
    6 |             });
 | 
			
		||||
    7 |           });
 | 
			
		||||
    8 |
 | 
			
		||||
  ======
 | 
			
		||||
onStepEnd: step
 | 
			
		||||
  error: Error: expect(received).toBe(expected) // Object.is equality @ a.spec.js:5
 | 
			
		||||
  ======
 | 
			
		||||
    3 |           test('test', async () => {
 | 
			
		||||
    4 |             await test.step('step', async () => {
 | 
			
		||||
  > 5 |               expect(1).toBe(2);
 | 
			
		||||
      |                         ^
 | 
			
		||||
    6 |             });
 | 
			
		||||
    7 |           });
 | 
			
		||||
    8 |
 | 
			
		||||
  ======
 | 
			
		||||
onStepEnd: After Hooks
 | 
			
		||||
onStepEnd: Worker Cleanup
 | 
			
		||||
onTestEnd:  > a.spec.js > test; retry #0
 | 
			
		||||
  error: Error: expect(received).toBe(expected) // Object.is equality @ a.spec.js:5
 | 
			
		||||
  ======
 | 
			
		||||
    3 |           test('test', async () => {
 | 
			
		||||
    4 |             await test.step('step', async () => {
 | 
			
		||||
  > 5 |               expect(1).toBe(2);
 | 
			
		||||
      |                         ^
 | 
			
		||||
    6 |             });
 | 
			
		||||
    7 |           });
 | 
			
		||||
    8 |
 | 
			
		||||
  ======
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('onError should have code snippet', async ({ runInlineTest }) => {
 | 
			
		||||
      const errorFile = test.info().outputPath('error.txt');
 | 
			
		||||
      const result = await runInlineTest({
 | 
			
		||||
        'reporter.ts': `
 | 
			
		||||
        import fs from 'fs';
 | 
			
		||||
        class Reporter {
 | 
			
		||||
          onError(error) {
 | 
			
		||||
            console.log('\\n%%onError: ' + error.snippet?.length);
 | 
			
		||||
            fs.writeFileSync('${errorFile.replace(/\\/g, '\\\\')}', error.snippet);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        module.exports = Reporter;`,
 | 
			
		||||
        'playwright.config.ts': `
 | 
			
		||||
          module.exports = {
 | 
			
		||||
            reporter: './reporter',
 | 
			
		||||
          };
 | 
			
		||||
        `,
 | 
			
		||||
        'reporter.ts': smallReporterJS,
 | 
			
		||||
        'playwright.config.ts': `module.exports = { reporter: [['./reporter', { printSteps: true, printErrorSnippet: true }]] };`,
 | 
			
		||||
        'a.spec.js': `
 | 
			
		||||
          const { test, expect } = require('@playwright/test');
 | 
			
		||||
          throw new Error('test');
 | 
			
		||||
        `,
 | 
			
		||||
      }, { 'reporter': '', 'workers': 1 });
 | 
			
		||||
 | 
			
		||||
      expect(result.output).toContain('onError: 412');
 | 
			
		||||
      expect(stripAnsi(fs.readFileSync(errorFile, 'utf8'))).toBe(`   at a.spec.js:3
 | 
			
		||||
      expect(result.output).toBe(`
 | 
			
		||||
onBegin: 0 tests total
 | 
			
		||||
onError: Error: test @ a.spec.js:3
 | 
			
		||||
  ======
 | 
			
		||||
     at a.spec.js:3
 | 
			
		||||
 | 
			
		||||
  1 |
 | 
			
		||||
  2 |           const { test, expect } = require('@playwright/test');
 | 
			
		||||
> 3 |           throw new Error('test');
 | 
			
		||||
    |                 ^
 | 
			
		||||
  4 |         `);
 | 
			
		||||
    1 |
 | 
			
		||||
    2 |           const { test, expect } = require('@playwright/test');
 | 
			
		||||
  > 3 |           throw new Error('test');
 | 
			
		||||
      |                 ^
 | 
			
		||||
    4 |
 | 
			
		||||
  ======
 | 
			
		||||
onError: Error: No tests found @ <no location>
 | 
			
		||||
onEnd
 | 
			
		||||
onExit
 | 
			
		||||
`);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user