From 1fc4d0768a6d13824241b0da0a70bc08606bb297 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 5 Oct 2026 08:41:53 -0700 Subject: [PATCH 1/2] fix: make the generated tsconfig.json cover the generated files The generated tsconfig.json only included `./src`, which a new project does not have, so the Playwright config and tests were not part of any TypeScript project. With TypeScript 6 defaulting `types` to `[]`, editors then report `Cannot find name 'process'` in playwright.config.ts. Include the test directory and playwright.config.ts, drop the leftover component testing `jsx` option, and leave an existing tsconfig.json untouched instead of overwriting it (or failing in --quiet mode). Fixes https://github.com/microsoft/playwright/issues/43097 --- assets/tsconfig.json | 12 ++++++++---- src/generator.ts | 7 +++++-- tests/integration.spec.ts | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/assets/tsconfig.json b/assets/tsconfig.json index c3fc42c..4d9b085 100644 --- a/assets/tsconfig.json +++ b/assets/tsconfig.json @@ -1,9 +1,13 @@ { "compilerOptions": { - "allowSyntheticDefaultImports": true, - "noEmit": true, - "jsx": "react-jsx", + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", "types": ["node"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true }, - "include": ["./src"], + "include": ["{{testDir}}", "playwright.config.ts"] } diff --git a/src/generator.ts b/src/generator.ts index f69c768..7679d26 100644 --- a/src/generator.ts +++ b/src/generator.ts @@ -159,8 +159,11 @@ export class Generator { for (const browserName of ['chromium', 'firefox', 'webkit']) sections.set(browserName, !this.options.browser || this.options.browser.includes(browserName) ? 'show' : 'comment'); - if (answers.language === 'TypeScript') - files.set('tsconfig.json', this._readAsset('tsconfig.json')); + if (answers.language === 'TypeScript' && !fs.existsSync(path.join(this.rootDir, 'tsconfig.json'))) { + files.set('tsconfig.json', executeTemplate(this._readAsset('tsconfig.json'), { + testDir: answers.testDir || '.', + }, new Map())); + } files.set(`playwright.config.${fileExtension}`, executeTemplate(this._readAsset(`playwright.config.${fileExtension}`), { testDir: answers.testDir || '', diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index 2187600..8db69f8 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -103,6 +103,26 @@ test('should generate be able to run TS examples successfully', { lock: 'apt-get await exec(packageManagerToNpxCommand(packageManager), ['playwright', 'test']); }); +for (const testDir of ['tests', 'e2e']) { + test(`should generate a tsconfig.json that type-checks the generated files in ${testDir}`, async ({ run, dir, exec, packageManager }) => { + test.skip(packageManager !== 'npm' && packageManager !== 'pnpm', 'tsc cannot resolve modules with PnP'); + await run([], { installGitHubActions: false, testDir, language: 'TypeScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: false }); + const tsc = require.resolve('typescript/bin/tsc'); + const { stdout } = await exec('node', [tsc, '-p', '.', '--listFilesOnly']); + const files = stdout.split('\n').map(f => path.relative(dir, f.trim())).filter(f => f && !f.startsWith('node_modules') && !f.startsWith('..')); + expect(files.sort()).toEqual(['playwright.config.ts', path.join(testDir, 'example.spec.ts')].sort()); + await exec('node', [tsc, '-p', '.']); + }); +} + +test('should not overwrite an existing tsconfig.json', async ({ run, dir }) => { + const tsconfig = JSON.stringify({ compilerOptions: { strict: true } }); + fs.writeFileSync(path.join(dir, 'tsconfig.json'), tsconfig); + await run(['--quiet'], { installGitHubActions: false, testDir: 'tests', language: 'TypeScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: false }); + expect(fs.readFileSync(path.join(dir, 'tsconfig.json'), 'utf8')).toBe(tsconfig); + expect(fs.existsSync(path.join(dir, 'playwright.config.ts'))).toBeTruthy(); +}); + test('should generate be able to run JS examples successfully', { lock: 'apt-get' }, async ({ run, dir, exec, packageManager }) => { test.slow(); await run([], { installGitHubActions: false, testDir: 'tests', language: 'JavaScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: true }); From f54fa1ea260a025b181a7f5b3a103e173400b103 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 5 Oct 2026 13:13:04 -0700 Subject: [PATCH 2/2] test: match tsc file list by suffix to work on macOS and Windows --- tests/integration.spec.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index 8db69f8..c8c4504 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -104,13 +104,16 @@ test('should generate be able to run TS examples successfully', { lock: 'apt-get }); for (const testDir of ['tests', 'e2e']) { - test(`should generate a tsconfig.json that type-checks the generated files in ${testDir}`, async ({ run, dir, exec, packageManager }) => { + test(`should generate a tsconfig.json that type-checks the generated files in ${testDir}`, async ({ run, exec, packageManager }) => { test.skip(packageManager !== 'npm' && packageManager !== 'pnpm', 'tsc cannot resolve modules with PnP'); await run([], { installGitHubActions: false, testDir, language: 'TypeScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: false }); const tsc = require.resolve('typescript/bin/tsc'); const { stdout } = await exec('node', [tsc, '-p', '.', '--listFilesOnly']); - const files = stdout.split('\n').map(f => path.relative(dir, f.trim())).filter(f => f && !f.startsWith('node_modules') && !f.startsWith('..')); - expect(files.sort()).toEqual(['playwright.config.ts', path.join(testDir, 'example.spec.ts')].sort()); + // tsc prints absolute paths with forward slashes, resolved through symlinks (e.g. /private/var on macOS). + const files = stdout.split('\n').map(f => f.trim().replace(/\\/g, '/')).filter(f => f && !f.includes('/node_modules/')); + expect(files).toHaveLength(2); + expect(files.some(f => f.endsWith('/playwright.config.ts'))).toBeTruthy(); + expect(files.some(f => f.endsWith(`/${testDir}/example.spec.ts`))).toBeTruthy(); await exec('node', [tsc, '-p', '.']); }); }