microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
65.47k stars 3.56k forks source link

[Bug]: `create-playwright` doesn't exclude `playwright-report` in `tsconfig.json`, leading to type errors #31022

Open karlhorky opened 3 months ago

karlhorky commented 3 months ago

Version

1.44.1

Steps to reproduce

  1. Run pnpm create playwright in a checkJs TypeScript project (project has typescript installed and tsconfig.json file with checkJs: true)
  2. Run pnpm playwright test --ui and run one of the tests
  3. Run pnpm tsc
  4. Observe many type errors from files in the /playwright-report/ directory

Expected behavior

Running tsc to check TypeScript types after running create-playwright should lead to zero errors:

➜  a pnpm tsc
➜  a

One way of achieving this would be:

  1. The "exclude" configuration in tsconfig.json file could be written to with the default path playwright-report
  2. create-playwright should ask for the location of the reports folder and use that in the tsconfig.json exclude config (because this path is configurable using reporter[number][1].outputFolder)

Actual behavior

Running tsc to check TypeScript types after running create-playwright leads to many errors, with large errors coming from the .js files inside playwright-report:

➜  a pnpm tsc                      
playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:85 - error TS7034: Variable 'ha' implicitly has type 'any' in some locations where its type cannot be determined.

1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/.test(F),Qe=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(F),Ce=/Edge\/(\d+)/.exec(F),M=We||Qe||Ce,j=M&&(We?document.documentMode||6:+(Ce||Qe)[1]),_=!Ce&&/WebKit\//.test(F),ie=_&&/Qt\/\d+\.\d+/.test(F),G=!Ce&&/Chrome\/(\d+)/.exec(F),se=G&&+G[1],ce=/Opera\//.test(F),Ie=/Apple Computer/.test(navigator.vendor),Te=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(F),Oe=/PhantomJS/.test(F),ae=Ie&&(/Mobile\/\w+/.test(F)||navigator.maxTouchPoints>2),V=/Android/.test(F),oe=ae||V||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(F),xe=ae||/Mac/.test(Ee),_e=/\bCrOS\b/.test(F),ye=/win/i.test(Ee),Me=ce&&F.match(/Version\/(\d*\.\d*)/);Me&&(Me=Number(Me[1])),Me&&Me>=15&&(ce=!1,_=!0);var He=xe&&(ie||ce&&(Me==null||Me<12.11)),ee=Se||M&&j>=9;function X(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var me=function(e,t){var n=e.className,r=X(t).exec(

playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:10879 - error TS7006: Parameter 't' implicitly has an 'any' type.

1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/.

playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:10881 - error TS7006: Parameter 'n' implicitly has an 'any' type.

1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/.test(F),Qe=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(F),Ce=/Edge\/(\d+)/.exec(F),M=We||Qe||Ce,j=M&&(We?document.documentMode||6:+(Ce||Qe)[1]),_=!Ce&&/WebKit\//.test(F),ie=_&&/Qt\/\d+\.\d+/.test(F),G=!Ce&&/Chrome\/(\d+)/.exec(F),se=G&&+G[1],ce=/Opera\//.test(F),Ie=/Apple Computer/.test(navigator.vendor),Te=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(F),Oe=/PhantomJS/.test(F),ae=Ie&&(/Mobile\/\w+/.test(F)||navigator.maxTouchPoints>2),V=/A

There are also 26 other type errors from the tests-examples/demo-todo-app.spec.ts file, but that probably deserves a different, separate issue to fix:

tests-examples/demo-todo-app.spec.ts:19:24 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
  Type 'undefined' is not assignable to type 'string'.

19     await newTodo.fill(TODO_ITEMS[0]);
                          ~~~~~~~~~~~~~

tests-examples/demo-todo-app.spec.ts:24:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'.
  Type 'undefined' is not assignable to type 'string | RegExp'.

24       TODO_ITEMS[0]
         ~~~~~~~~~~~~~

tests-examples/demo-todo-app.spec.ts:28:24 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
  Type 'undefined' is not assignable to type 'string'.

28     await newTodo.fill(TODO_ITEMS[1]);
                          ~~~~~~~~~~~~~

tests-examples/demo-todo-app.spec.ts:33:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'.

33       TODO_ITEMS[0],
         ~~~~~~~~~~~~~

tests-examples/demo-todo-app.spec.ts:34:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'.

34       TODO_ITEMS[1]
         ~~~~~~~~~~~~~

I also created:

Additional context

No response

Environment

System:
    OS: macOS 14.5
    CPU: (8) arm64 Apple M1
    Memory: 83.81 MB / 16.00 GB
  Binaries:
    Node: 20.13.1 - /opt/homebrew/bin/node
    npm: 10.5.2 - /opt/homebrew/bin/npm
    pnpm: 9.1.2 - /opt/homebrew/bin/pnpm
    bun: 1.1.4 - /opt/homebrew/bin/bun
  IDEs:
    VSCode: 1.89.1 - /opt/homebrew/bin/code
  Languages:
    Bash: 5.2.0 - /opt/homebrew/bin/bash
  npmPackages:
    @playwright/test: ^1.44.1 => 1.44.1
mxschmitt commented 3 months ago

There are also 26 other type errors from the tests-examples/demo-todo-app.spec.ts file, but that probably deserves a different, separate issue to fix:

Would it be possible to share your tsconfig with us? Curious how you ended up with the errors.

Running tsc to check TypeScript types after running create-playwright leads to many errors, with large errors coming from the .js files inside playwright-report:

tsconfigs are specific to projects - some use extends, some include, some exclude some rootDir. create-playwright works for most projects while this would be outside of the scope and the user would need to make this adjustment on his own.

karlhorky commented 3 months ago

Would it be possible to share your tsconfig with us?

Sure, see below:

tsconfig.json

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "target": "ES2015",
    "module": "Preserve",
    "moduleDetection": "force",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "checkJs": true,
    "allowSyntheticDefaultImports": true,
    "downlevelIteration": true,
    "forceConsistentCasingInFileNames": true,
    "jsx": "react-jsx",
    "noEmit": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true,
    "strict": true,
    "incremental": true,
    "noUncheckedIndexedAccess": true
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "**/*.js",
    "**/*.jsx",
    "**/*.cjs",
    "**/*.mjs",
    ".next/types/**/*.ts"
  ],
  "exclude": ["node_modules", "build"]
}

I also created a reproduction repo along with a failing GitHub Actions workflow (Gist of workflow test run logs) and linked in the original issue description above, my steps:

Show command line logs of full steps ```bash ➜ p mkdir a ➜ p cd a ➜ a code . # I created the `tsconfig.json` file here ➜ a pnpm init ➜ a pnpm add --save-dev typescript ... ➜ a pnpm create playwright .../18fc4dd80e0-12747 | +1 + .../18fc4dd80e0-12747 | Progress: resolved 1, reused 1, downloaded 0, added 1, done Getting started with writing end-to-end tests with Playwright: Initializing project in '.' ✔ Where to put your end-to-end tests? · tests ✔ Add a GitHub Actions workflow? (y/N) · false ✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · true Installing Playwright Test (pnpm add --save-dev @playwright/test)… Packages: +4 ++++ Progress: resolved 5, reused 5, downloaded 0, added 4, done devDependencies: + @playwright/test 1.44.1 Done in 713ms Installing Types (pnpm add --save-dev @types/node)… Packages: +2 ++ Progress: resolved 7, reused 7, downloaded 0, added 2, done devDependencies: + @types/node 20.12.12 Done in 521ms Writing playwright.config.ts. Writing tests/example.spec.ts. Writing tests-examples/demo-todo-app.spec.ts. Writing package.json. Downloading browsers (pnpm exec playwright install)… ✔ Success! Created a Playwright Test project at /Users/k/p/a Inside that directory, you can run several commands: pnpm exec playwright test Runs the end-to-end tests. pnpm exec playwright test --ui Starts the interactive UI mode. pnpm exec playwright test --project=chromium Runs the tests only on Desktop Chrome. pnpm exec playwright test example Runs the tests in a specific file. pnpm exec playwright test --debug Runs the tests in debug mode. pnpm exec playwright codegen Auto generate tests with Codegen. We suggest that you begin by typing: pnpm exec playwright test And check out the following files: - ./tests/example.spec.ts - Example end-to-end test - ./tests-examples/demo-todo-app.spec.ts - Demo Todo App end-to-end tests - ./playwright.config.ts - Playwright Test configuration Visit https://playwright.dev/docs/intro for more information. ✨ Happy hacking! 🎭 ➜ a git:(main) ✗ pnpm playwright test --ui # I ran the first test here ➜ a pnpm tsc playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:85 - error TS7034: Variable 'ha' implicitly has type 'any' in some locations where its type cannot be determined. 1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/.test(F),Qe=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(F),Ce=/Edge\/(\d+)/.exec(F),M=We||Qe||Ce,j=M&&(We?document.documentMode||6:+(Ce||Qe)[1]),_=!Ce&&/WebKit\//.test(F),ie=_&&/Qt\/\d+\.\d+/.test(F),G=!Ce&&/Chrome\/(\d+)/.exec(F),se=G&&+G[1],ce=/Opera\//.test(F),Ie=/Apple Computer/.test(navigator.vendor),Te=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(F),Oe=/PhantomJS/.test(F),ae=Ie&&(/Mobile\/\w+/.test(F)||navigator.maxTouchPoints>2),V=/Android/.test(F),oe=ae||V||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(F),xe=ae||/Mac/.test(Ee),_e=/\bCrOS\b/.test(F),ye=/win/i.test(Ee),Me=ce&&F.match(/Version\/(\d*\.\d*)/);Me&&(Me=Number(Me[1])),Me&&Me>=15&&(ce=!1,_=!0);var He=xe&&(ie||ce&&(Me==null||Me<12.11)),ee=Se||M&&j>=9;function X(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var me=function(e,t){var n=e.className,r=X(t).exec( playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:10879 - error TS7006: Parameter 't' implicitly has an 'any' type. 1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/. playwright-report/trace/assets/codeMirrorModule-D-hINnYb.js:1:10881 - error TS7006: Parameter 'n' implicitly has an 'any' type. 1 import{n as mu,o as bu}from"./testServerConnection-CpiRu-AA.js";var ho={exports:{}},ha;function Ar(){return ha||(ha=1,function(yr,Or){(function(F,Ee){yr.exports=Ee()})(mu,function(){var F=navigator.userAgent,Ee=navigator.platform,Se=/gecko\/\d/i.test(F),We=/MSIE \d/.test(F),Qe=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(F),Ce=/Edge\/(\d+)/.exec(F),M=We||Qe||Ce,j=M&&(We?document.documentMode||6:+(Ce||Qe)[1]),_=!Ce&&/WebKit\//.test(F),ie=_&&/Qt\/\d+\.\d+/.test(F),G=!Ce&&/Chrome\/(\d+)/.exec(F),se=G&&+G[1],ce=/Opera\//.test(F),Ie=/Apple Computer/.test(navigator.vendor),Te=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(F),Oe=/PhantomJS/.test(F),ae=Ie&&(/Mobile\/\w+/.test(F)||navigator.maxTouchPoints>2),V=/A ... more ... tests-examples/demo-todo-app.spec.ts:19:24 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. 19 await newTodo.fill(TODO_ITEMS[0]); ~~~~~~~~~~~~~ tests-examples/demo-todo-app.spec.ts:24:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'. Type 'undefined' is not assignable to type 'string | RegExp'. 24 TODO_ITEMS[0] ~~~~~~~~~~~~~ tests-examples/demo-todo-app.spec.ts:28:24 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. 28 await newTodo.fill(TODO_ITEMS[1]); ~~~~~~~~~~~~~ tests-examples/demo-todo-app.spec.ts:33:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'. 33 TODO_ITEMS[0], ~~~~~~~~~~~~~ tests-examples/demo-todo-app.spec.ts:34:7 - error TS2322: Type 'string | undefined' is not assignable to type 'string | RegExp'. 34 TODO_ITEMS[1] ~~~~~~~~~~~~~ ```

tsconfigs are specific to projects - some use extends, some include, some exclude some rootDir

Agreed, not every config can be supported

But checking .some(excludeEntry => excludeEntry === 'playwright-report') and then doing .push('playwright-report') to the exclude array in tsconfig.json would be:

create-playwright works for most projects

This is what I'm challenging - I assert that:

  1. create-playwright does not work for most TypeScript projects, as it does not work for the config above which is not an uncommon config
  2. create-playwright does not do anything to TypeScript projects to prevent type errors with files that it creates out of the box

create-playwright should work with common TypeScript configurations out of the box.