Skip to content

[BUG] test runner breaks when invoked by path name with the wrong casing #9193

@fkleuver

Description

@fkleuver

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 :-)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions