From 29437b3d85c7bf3219ef750156285596798ead35 Mon Sep 17 00:00:00 2001 From: Sean C Davis Date: Tue, 20 Oct 2026 08:22:57 -0400 Subject: [PATCH 1/3] test: let mock extensions routes match any site or account ID Co-Authored-By: Claude Opus 5.5 (1M context) --- tests/integration/utils/mock-api-vitest.ts | 12 ++++++++++++ tests/integration/utils/mock-api.ts | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/integration/utils/mock-api-vitest.ts b/tests/integration/utils/mock-api-vitest.ts index b99049d25a2..055afe82efc 100644 --- a/tests/integration/utils/mock-api-vitest.ts +++ b/tests/integration/utils/mock-api-vitest.ts @@ -84,6 +84,18 @@ export const startMockApi = ({ routes, silent }: MockApiOptions): Promise Date: Tue, 20 Oct 2026 08:23:55 -0400 Subject: [PATCH 2/3] test: route extensions requests to a local mock API during config loading Co-Authored-By: Claude Opus 5.5 (1M context) --- src/commands/base-command.ts | 2 + src/utils/local-api-test-opts.ts | 20 ++++++++++ tests/unit/utils/local-api-test-opts.test.ts | 41 ++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/utils/local-api-test-opts.ts create mode 100644 tests/unit/utils/local-api-test-opts.test.ts diff --git a/src/commands/base-command.ts b/src/commands/base-command.ts index 8358ef06c2d..a4c467d7fd4 100644 --- a/src/commands/base-command.ts +++ b/src/commands/base-command.ts @@ -39,6 +39,7 @@ import { EXIT_CODES } from '../utils/exit-codes.js' import type { FeatureFlags } from '../utils/feature-flags.js' import { getFrameworksAPIPaths } from '../utils/frameworks-api.js' import { getSiteByName } from '../utils/get-site.js' +import { getLocalApiTestOpts } from '../utils/local-api-test-opts.js' import { buildAuthorizeUrl } from '../utils/login-url.js' import openBrowser from '../utils/open-browser.js' import { isInteractive } from '../utils/scripted-commands.js' @@ -845,6 +846,7 @@ export default class BaseCommand extends Command { host: host, pathPrefix: pathPrefix, scheme: scheme, + testOpts: getLocalApiTestOpts({ host, scheme }), offline: offline ?? flags.offline, siteFeatureFlagPrefix: 'cli', featureFlags: this.featureFlags, diff --git a/src/utils/local-api-test-opts.ts b/src/utils/local-api-test-opts.ts new file mode 100644 index 00000000000..2fa138fcb7a --- /dev/null +++ b/src/utils/local-api-test-opts.ts @@ -0,0 +1,20 @@ +const LOOPBACK_HOSTNAMES = new Set(['localhost', '127.0.0.1', '[::1]']) + +export const getLocalApiTestOpts = ({ + host, + scheme, +}: { + host?: string + scheme?: string +}): { host: string; scheme?: string } | undefined => { + if (host === undefined) { + return undefined + } + + try { + const { hostname } = new URL(`http://${host}`) + return LOOPBACK_HOSTNAMES.has(hostname) ? { host, scheme } : undefined + } catch { + return undefined + } +} diff --git a/tests/unit/utils/local-api-test-opts.test.ts b/tests/unit/utils/local-api-test-opts.test.ts new file mode 100644 index 00000000000..aa2c08dd285 --- /dev/null +++ b/tests/unit/utils/local-api-test-opts.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, test } from 'vitest' + +import { getLocalApiTestOpts } from '../../../src/utils/local-api-test-opts.js' + +describe('getLocalApiTestOpts', () => { + test('returns host and scheme for localhost', () => { + expect(getLocalApiTestOpts({ host: 'localhost:1234', scheme: 'http' })).toEqual({ + host: 'localhost:1234', + scheme: 'http', + }) + }) + + test('returns host and scheme for 127.0.0.1', () => { + expect(getLocalApiTestOpts({ host: '127.0.0.1:1234', scheme: 'http' })).toEqual({ + host: '127.0.0.1:1234', + scheme: 'http', + }) + }) + + test('returns host and scheme for [::1]', () => { + expect(getLocalApiTestOpts({ host: '[::1]:1234', scheme: 'http' })).toEqual({ + host: '[::1]:1234', + scheme: 'http', + }) + }) + + test.each(['api.netlify.com', 'api-staging.netlify.com', 'example.com:8080', 'localhost.example.com'])( + 'returns undefined for non-loopback host %s', + (host) => { + expect(getLocalApiTestOpts({ host, scheme: 'https' })).toBeUndefined() + }, + ) + + test('returns undefined when host is undefined', () => { + expect(getLocalApiTestOpts({ host: undefined, scheme: 'http' })).toBeUndefined() + }) + + test('returns undefined when host cannot be parsed', () => { + expect(getLocalApiTestOpts({ host: 'not a host', scheme: 'http' })).toBeUndefined() + }) +}) From dcb7c49cd786b216b7c9a3a73ca34c730e99e7c5 Mon Sep 17 00:00:00 2001 From: Sean C Davis Date: Tue, 20 Oct 2026 08:24:41 -0400 Subject: [PATCH 3/3] test: restore account.id assertion in v2 api context test Co-Authored-By: Claude Opus 5.5 (1M context) --- tests/integration/commands/dev/v2-api.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/integration/commands/dev/v2-api.test.ts b/tests/integration/commands/dev/v2-api.test.ts index f0257274442..6585f5561f8 100644 --- a/tests/integration/commands/dev/v2-api.test.ts +++ b/tests/integration/commands/dev/v2-api.test.ts @@ -67,9 +67,7 @@ describe.concurrent('v2 api', async () => { expect(context).toHaveProperty('ip', expect.stringMatching(/::1|127\.0\.0\.1/)) expect(context).toHaveProperty('geo.city', 'Mock City') expect(context).toHaveProperty('cookies', { foo: 'bar' }) - // TODO: re-enable once the extensions API is mocked. The real one rejects this test's fake token, - // so config resolution falls back to offline and the account is unknown. - // expect(context).toHaveProperty('account.id', 'mock-account-id') + expect(context).toHaveProperty('account.id', 'mock-account-id') expect(context).toHaveProperty('deploy.context', 'dev') expect(context).toHaveProperty('deploy.id', '0') expect(context).toHaveProperty('deploy.published', false)