From 123825ba2b26186f3230ac3bdde9bd7d3ce5e6e9 Mon Sep 17 00:00:00 2001 From: Mert Can Altin Date: Sun, 23 Aug 2026 14:46:50 +0300 Subject: [PATCH] fix(cli): call defaultRegistryDirectory() when resolving the cache file `registry.defaultRegistryDirectory` became a function upstream in microsoft/playwright#41942 and arrived here with the roll to 1.63.0-alpha-2026-08-05. `cacheFile()` still used it as a string, so `path.join()` threw, `readCache()`/`writeCache()` swallowed the TypeError, and the update check was never cached: every single CLI invocation fetched the npm registry and re-ran the installed-skill check. Locally that is ~480ms per command instead of ~125ms. Tests always set PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST, so the default branch was never exercised. Add a regression test that points HOME at a temp directory and asserts the cache file is written. Also hoist `cacheFile()` out of the try blocks so only I/O and parse failures are swallowed there, instead of masking a path-computation bug as "no cache". --- playwright-cli.js | 7 ++++--- tests/integration.spec.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/playwright-cli.js b/playwright-cli.js index 81dbbe8..a3cc4ed 100755 --- a/playwright-cli.js +++ b/playwright-cli.js @@ -87,13 +87,14 @@ function printNotice(current, latest) { } function cacheFile() { - const dir = process.env.PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST || registry.defaultRegistryDirectory; + const dir = process.env.PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST || registry.defaultRegistryDirectory(); return path.join(dir, 'cli-update-check.json'); } function readCache() { + const file = cacheFile(); try { - const data = JSON.parse(fs.readFileSync(cacheFile(), 'utf8')); + const data = JSON.parse(fs.readFileSync(file, 'utf8')); if (typeof data.lastCheck === 'number') return data; } catch { @@ -105,8 +106,8 @@ function readCache() { * @param {*} data */ function writeCache(data) { + const file = cacheFile(); try { - const file = cacheFile(); fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, JSON.stringify(data)); } catch { diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index d39f87d..9e898a2 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -103,3 +103,36 @@ test('does not warn when installed skill only differs in line endings', async ({ error: expect.not.stringContaining('does not match the tool version'), })); }); + +test('caches the update check in the default registry directory', async ({}) => { + // Redirect the home/cache directories so the real user cache is untouched, and + // leave PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST empty so the default path is used. + const home = test.info().outputPath('home'); + fs.mkdirSync(home, { recursive: true }); + const env = { + CI: '', + NO_UPDATE_NOTIFIER: '', + PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST: '', + HOME: home, + USERPROFILE: home, + XDG_CACHE_HOME: path.join(home, '.cache'), + LOCALAPPDATA: path.join(home, 'AppData', 'Local'), + }; + + expect(await runCli(['--version'], env)).toEqual(expect.objectContaining({ exitCode: 0 })); + + const found: string[] = []; + const walk = (dir: string) => { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) + walk(full); + else if (entry.name === 'cli-update-check.json') + found.push(full); + } + }; + walk(home); + + expect(found).toHaveLength(1); + expect(JSON.parse(fs.readFileSync(found[0], 'utf8')).lastCheck).toEqual(expect.any(Number)); +});