diff --git a/packages/playwright-test/src/common/fixtures.ts b/packages/playwright-test/src/common/fixtures.ts index 69aedafd29..2b8b5e55d3 100644 --- a/packages/playwright-test/src/common/fixtures.ts +++ b/packages/playwright-test/src/common/fixtures.ts @@ -227,7 +227,7 @@ export function fixtureParameterNames(fn: Function | any, location: Location, on } function innerFixtureParameterNames(fn: Function, location: Location, onError: LoadErrorSink): string[] { - const text = fn.toString(); + const text = filterOutComments(fn.toString()); const match = text.match(/(?:async)?(?:\s+function)?[^(]*\(([^)]*)/); if (!match) return []; @@ -241,11 +241,35 @@ function innerFixtureParameterNames(fn: Function, location: Location, onError: L } const props = splitByComma(firstParam.substring(1, firstParam.length - 1)).map(prop => { const colon = prop.indexOf(':'); - return colon === -1 ? prop : prop.substring(0, colon).trim(); + return colon === -1 ? prop.trim() : prop.substring(0, colon).trim(); }); return props; } +function filterOutComments(s: string): string { + const result: string[] = []; + let commentState: 'none'|'singleline'|'multiline' = 'none'; + for (let i = 0; i < s.length; ++i) { + if (commentState === 'singleline') { + if (s[i] === '\n') + commentState = 'none'; + } else if (commentState === 'multiline') { + if (s[i - 1] === '*' && s[i] === '/') + commentState = 'none'; + } else if (commentState === 'none') { + if (s[i] === '/' && s[i + 1] === '/') { + commentState = 'singleline'; + } else if (s[i] === '/' && s[i + 1] === '*') { + commentState = 'multiline'; + i += 2; + } else { + result.push(s[i]); + } + } + } + return result.join(''); +} + function splitByComma(s: string) { const result: string[] = []; const stack: string[] = []; diff --git a/tests/playwright-test/fixtures.spec.ts b/tests/playwright-test/fixtures.spec.ts index 8595e5afbb..e9c9fa0fb5 100644 --- a/tests/playwright-test/fixtures.spec.ts +++ b/tests/playwright-test/fixtures.spec.ts @@ -32,6 +32,32 @@ test('should work', async ({ runInlineTest }) => { expect(results[0].status).toBe('passed'); }); +test('should work with comments inside fixtures', async ({ runInlineTest }) => { + const { results } = await runInlineTest({ + 'a.test.ts': ` + import { test as base, expect } from '@playwright/test'; + const test = base.extend({ + asdf: async ({}, test) => await test(123), + foo: async ({}, test) => await test('foo'), + bar: async ({}, test) => await test('bar'), + }); + + test('should use asdf', async ({ // }) {,,, /* + asdf, // a comment +/*/aa* /* */ // line // // + /* // */ foo, /* what // */ bar // whoa + /* some // comment */ : // + /* // /* // */ barbar /* /* /* */ + }) => { + expect(asdf).toBe(123); + expect(foo).toBe('foo'); + expect(barbar).toBe('bar'); + }); + `, + }); + expect(results[0].status).toBe('passed'); +}); + test('should work with a sync test function', async ({ runInlineTest }) => { const { results } = await runInlineTest({ 'a.test.ts': `