From d3131a2a9be25dabfc22b59c9249bb02f957a60c Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 27 Oct 2026 23:06:44 -0700 Subject: [PATCH] test(v2): scan every v2 source for a hardcoded production API host (TASK-428) The invariant listed three files by name, so a copy surface added later (the invite modal, Your Team) could hardcode api.commonly.me and pass. Scan all non-test v2 sources instead, and keep the non-default URL check on the setup command. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: dart Agent-Model: claude/claude-haiku-5-5/default --- .../byo-setup-command-invariant.test.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/frontend/src/v2/__tests__/byo-setup-command-invariant.test.ts b/frontend/src/v2/__tests__/byo-setup-command-invariant.test.ts index 83835ec646..b25c6d970d 100644 --- a/frontend/src/v2/__tests__/byo-setup-command-invariant.test.ts +++ b/frontend/src/v2/__tests__/byo-setup-command-invariant.test.ts @@ -7,12 +7,16 @@ const fs = require('fs'); const path = require('path'); const { daemonSetupCommand } = require('../utils/daemonSetupCommand'); -const SOURCES = [ - 'components/V2AgentBYO.tsx', - 'components/V2AgentRuntimeGrants.tsx', - 'components/V2ConnectPage.tsx', -]; -const read = (rel) => fs.readFileSync(path.join(__dirname, '..', rel), 'utf8'); +// Every v2 source file, not a fixed list: a new surface that hardcodes the host +// (the invite modal, Your Team, a future copy button) must fail here too. +const walk = (dir) => fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) return ['__tests__', '__mocks__'].includes(entry.name) ? [] : walk(full); + return /\.(tsx?|jsx?)$/.test(entry.name) && !/\.test\./.test(entry.name) ? [full] : []; +}); +const V2_ROOT = path.join(__dirname, '..'); +const SOURCES = walk(V2_ROOT).map((file) => path.relative(V2_ROOT, file)); +const read = (rel) => fs.readFileSync(path.join(V2_ROOT, rel), 'utf8'); describe('copy-paste setup commands follow the page instance', () => { beforeEach(() => { process.env.REACT_APP_API_URL = 'https://api-dev.example.test/'; }); @@ -24,7 +28,8 @@ describe('copy-paste setup commands follow the page instance', () => { expect(command).not.toMatch(/commonly\.me/); }); - test('no BYO, Connect or runtime source hardcodes the production API host', () => { + test('no v2 source hardcodes the production API host', () => { + expect(SOURCES.length).toBeGreaterThan(20); SOURCES.forEach((rel) => { expect([rel, read(rel).match(/api\.commonly\.me/g)]).toEqual([rel, null]); });