Note: this is ultimately a problem between chair and keyboard but I'm filing an issue as it might be worth considering to make Playwright more robust against the problem described here. If not, maybe it'll at least help someone else who runs into this in the future.
Context:
- Playwright Version: 1.15.0
- Operating System: Windows
- Node.js version: 16.10.0 (was also able to repro in 14.17.6 LTS)
- Browser: Chromium / All
Code Snippet
Repo: https://github.com/fkleuver/playwright-test-repro
(although it should be reproducible with any setup)
Simplest steps to repro:
cd C:\projects
git clone git@github.com:fkleuver/playwright-test-repro.git
cd playwright-test-repro
npm ci
npm run --prefix ../Playwright-test-repro e2e
# ^ note the capital P
The above repro steps fail with the following error:
Error: test\w3.spec.js:3:1: test() can only be called in a test file
at errorWithLocation (C:\projects\Playwright-test-repro\node_modules\@playwright\test\lib\test\util.js:195:10)
at TestTypeImpl._createTest (C:\projects\Playwright-test-repro\node_modules\@playwright\test\lib\test\testType.js:78:51)
at C:\projects\Playwright-test-repro\node_modules\@playwright\test\lib\test\transform.js:133:12
at file:///C:/projects/Playwright-test-repro/test/w3.spec.js:3:1
at ModuleJob.run (node:internal/modules/esm/module_job:183:25)
at Loader.import (node:internal/modules/esm/loader:178:24)
at importModuleDynamicallyWrapper (node:internal/vm/module:437:15)
at Loader._requireOrImport (C:\projects\playwright-test-repro\node_modules\@playwright\test\lib\test\loader.js:214:52)
at Loader.loadTestFile (C:\projects\playwright-test-repro\node_modules\@playwright\test\lib\test\loader.js:130:7)
at Runner._run (C:\projects\playwright-test-repro\node_modules\@playwright\test\lib\test\runner.js:219:40)
The repro steps may seem a bit contrived but it's simply the easiest way to reproduce if you folks want to debug this.
Describe the bug
The "culprit" is module-scoped variables in Playwright which are used as a cache.
File: src/test/globals.ts (fns setCurrentlyLoadingFileSuite / currentlyLoadingFileSuite)
Apparently when the entry point is invoked with the wrong casing, two of those modules end up being loaded. setCurrentlyLoadingFileSuite is called on one instance of the module whereas currentlyLoadingFileSuite is called on another instance (where the backing currentFileSuite variable is always undefined)
How I ran into this: I had a shortcut to open cmd.exe in C:\Projects\my-project (the actual folder is C:\projects\my-project). Typo, my bad, but it worked fine until I switched from mocha to the playwright test runner.
Since the error itself doesn't really help (nor does googling for it), it took a while to find out the root cause.
Imagine the fun:
- run tests: fails
- try a bunch of things, up to eventually
cd .. && rmdir my-project /s /q followed by a fresh git clone & install
- run tests: succeeds
- open another command prompt to the same folder, run tests: fails (?!)
I don't know the inner workings and constraints of Playwright well enough to confidently suggest any particular solution, but at least detecting duplicate module instantiation to throw a more helpful error in this scenario would seem like good form.
Something like this at the top of globals.ts would accomplish just that:
const s = Symbol.for('__playwright');
if (globalThis[s]) {
throw new Error(`more than one instance of globals.js was loaded`);
} else {
Reflect.defineProperty(globalThis, s, { value: true, configurable: true });
}
Then the error will directly point to this specific issue if it's caused by duplicate module instantiation, rather than potentially send the user on a trail to nowhere :-)
Note: this is ultimately a problem between chair and keyboard but I'm filing an issue as it might be worth considering to make Playwright more robust against the problem described here. If not, maybe it'll at least help someone else who runs into this in the future.
Context:
Code Snippet
Repo: https://github.com/fkleuver/playwright-test-repro
(although it should be reproducible with any setup)
Simplest steps to repro:
The above repro steps fail with the following error:
The repro steps may seem a bit contrived but it's simply the easiest way to reproduce if you folks want to debug this.
Describe the bug
The "culprit" is module-scoped variables in Playwright which are used as a cache.
File:
src/test/globals.ts(fnssetCurrentlyLoadingFileSuite/currentlyLoadingFileSuite)Apparently when the entry point is invoked with the wrong casing, two of those modules end up being loaded.
setCurrentlyLoadingFileSuiteis called on one instance of the module whereascurrentlyLoadingFileSuiteis called on another instance (where the backingcurrentFileSuitevariable is alwaysundefined)How I ran into this: I had a shortcut to open
cmd.exeinC:\Projects\my-project(the actual folder isC:\projects\my-project). Typo, my bad, but it worked fine until I switched from mocha to the playwright test runner.Since the error itself doesn't really help (nor does googling for it), it took a while to find out the root cause.
Imagine the fun:
cd .. && rmdir my-project /s /qfollowed by a fresh git clone & installI don't know the inner workings and constraints of Playwright well enough to confidently suggest any particular solution, but at least detecting duplicate module instantiation to throw a more helpful error in this scenario would seem like good form.
Something like this at the top of
globals.tswould accomplish just that:Then the error will directly point to this specific issue if it's caused by duplicate module instantiation, rather than potentially send the user on a trail to nowhere :-)