From 16c8df5596ace93f9d33b7776308235d445edde9 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Fri, 25 Sep 2026 23:26:33 +0000 Subject: [PATCH 1/6] test: [Task] Block real outbound network in unit tests with nock.disableNetConnect() in mocha-bootstrap.js (b/566321794) --- src/test/helpers/mocha-bootstrap.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index 0dc5b8efd84..b2ab00a3d82 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -20,6 +20,11 @@ if (typeof nodeFetch.Headers.prototype.getSetCookie !== "function") { // Force nock to execute its side-effects (patching http/https) immediately on load void nock; +// Unit tests must never reach real Google APIs: unmatched requests now fail fast with +// NetConnectNotAllowedError instead of depending on network latency (flaky 2000ms timeouts). +nock.disableNetConnect(); +nock.enableNetConnect(/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/); + chai.use(chaiAsPromised); chai.use(sinonChai); From af65f778de203c97d1f72b8ed13325648dd735a3 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Sat, 26 Sep 2026 00:28:47 +0000 Subject: [PATCH 2/6] fix(test): only disable outbound network for unit tests, allowing integration test suites to access network --- src/test/helpers/mocha-bootstrap.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index b2ab00a3d82..843f82f95f6 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -22,8 +22,14 @@ void nock; // Unit tests must never reach real Google APIs: unmatched requests now fail fast with // NetConnectNotAllowedError instead of depending on network latency (flaky 2000ms timeouts). -nock.disableNetConnect(); -nock.enableNetConnect(/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/); +// Integration tests (under scripts/) need real outbound network access. +const isIntegrationTest = process.argv.some((arg) => + /(^|[/\\])(scripts|dev[/\\]scripts)[/\\]/.test(arg), +); +if (!isIntegrationTest) { + nock.disableNetConnect(); + nock.enableNetConnect(/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/); +} chai.use(chaiAsPromised); chai.use(sinonChai); From 1a4b10fa4704ea8cf30abe35fc52bd7a30c98792 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Wed, 30 Sep 2026 19:52:46 +0000 Subject: [PATCH 3/6] fix(test): re-assert net-connect restrictions in mocha hooks and guard enableNetConnect --- src/test/helpers/mocha-bootstrap.js | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index 843f82f95f6..fdea0d39115 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -20,15 +20,37 @@ if (typeof nodeFetch.Headers.prototype.getSetCookie !== "function") { // Force nock to execute its side-effects (patching http/https) immediately on load void nock; -// Unit tests must never reach real Google APIs: unmatched requests now fail fast with +const LOOPBACK_REGEXP = /^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/; + +// Unit tests must never reach real Google APIs: unmatched requests fail fast with // NetConnectNotAllowedError instead of depending on network latency (flaky 2000ms timeouts). // Integration tests (under scripts/) need real outbound network access. -const isIntegrationTest = process.argv.some((arg) => - /(^|[/\\])(scripts|dev[/\\]scripts)[/\\]/.test(arg), -); +const isIntegrationTest = + process.env.FIREBASE_ALLOW_NET_CONNECT === "true" || + process.argv.some((arg) => /(^|[/\\])(scripts|dev[/\\]scripts)[/\\]/.test(arg)); + +function enforceNetConnectPolicy() { + if (!isIntegrationTest) { + nock.disableNetConnect(); + nock.enableNetConnect(LOOPBACK_REGEXP); + } +} + +enforceNetConnectPolicy(); + if (!isIntegrationTest) { - nock.disableNetConnect(); - nock.enableNetConnect(/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/); + const origEnableNetConnect = nock.enableNetConnect.bind(nock); + nock.enableNetConnect = function (matcher) { + const isUnscoped = + !matcher || + matcher === ".*" || + matcher === "*" || + (matcher instanceof RegExp && (matcher.source === ".*" || matcher.source === "^.*$")); + if (isUnscoped) { + return origEnableNetConnect(LOOPBACK_REGEXP); + } + return origEnableNetConnect(matcher); + }; } chai.use(chaiAsPromised); @@ -59,6 +81,7 @@ function cleanup() { } nock.cleanAll(); + enforceNetConnectPolicy(); // Safely clean up custom nock (src/test/helpers/nock.ts) if required by tests for (const key of Object.keys(require.cache)) { @@ -80,6 +103,7 @@ function cleanup() { exports.mochaHooks = { beforeEach() { + enforceNetConnectPolicy(); suiteFakes = new Set(typeof sinon.getFakes === "function" ? sinon.getFakes() : []); }, afterEach: cleanup, From df099ad8808b8390b39abfb6cdd8ecef172b4a0c Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 1 Oct 2026 16:50:58 +0000 Subject: [PATCH 4/6] fix(test): scope net-connect enforcement per test file and remove env var escape hatch --- src/test/helpers/mocha-bootstrap.js | 47 ++++++++++++----------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index fdea0d39115..59157ba1a50 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -1,3 +1,4 @@ +const path = require("path"); const chai = require("chai"); const chaiAsPromised = require("chai-as-promised"); const sinon = require("sinon"); @@ -22,37 +23,26 @@ void nock; const LOOPBACK_REGEXP = /^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/; -// Unit tests must never reach real Google APIs: unmatched requests fail fast with -// NetConnectNotAllowedError instead of depending on network latency (flaky 2000ms timeouts). -// Integration tests (under scripts/) need real outbound network access. -const isIntegrationTest = - process.env.FIREBASE_ALLOW_NET_CONNECT === "true" || - process.argv.some((arg) => /(^|[/\\])(scripts|dev[/\\]scripts)[/\\]/.test(arg)); +function isIntegrationTestFile(filePath) { + if (!filePath) { + return false; + } + const rel = path.relative(process.cwd(), filePath); + return /^(scripts|dev[/\\]scripts)[/\\]/.test(rel); +} -function enforceNetConnectPolicy() { - if (!isIntegrationTest) { +function enforceNetConnectPolicy(ctx) { + const currentFile = ctx && ctx.currentTest && ctx.currentTest.file; + if (!isIntegrationTestFile(currentFile)) { nock.disableNetConnect(); nock.enableNetConnect(LOOPBACK_REGEXP); + } else { + nock.enableNetConnect(); } } enforceNetConnectPolicy(); -if (!isIntegrationTest) { - const origEnableNetConnect = nock.enableNetConnect.bind(nock); - nock.enableNetConnect = function (matcher) { - const isUnscoped = - !matcher || - matcher === ".*" || - matcher === "*" || - (matcher instanceof RegExp && (matcher.source === ".*" || matcher.source === "^.*$")); - if (isUnscoped) { - return origEnableNetConnect(LOOPBACK_REGEXP); - } - return origEnableNetConnect(matcher); - }; -} - chai.use(chaiAsPromised); chai.use(sinonChai); @@ -66,8 +56,9 @@ let suiteFakes = new Set(); * Global teardown hook executed after every test case. * Hermetically restores Sinon stubs, spies, and mocks created during the test, * resets standard Nock HTTP interceptors, and resets custom Undici Nock interceptors if loaded. + * @param {object} [ctx] - Mocha context for the completed test. */ -function cleanup() { +function cleanup(ctx) { if (typeof sinon.getFakes === "function") { for (const fake of sinon.getFakes()) { if (!suiteFakes.has(fake)) { @@ -81,7 +72,7 @@ function cleanup() { } nock.cleanAll(); - enforceNetConnectPolicy(); + enforceNetConnectPolicy(ctx); // Safely clean up custom nock (src/test/helpers/nock.ts) if required by tests for (const key of Object.keys(require.cache)) { @@ -103,8 +94,10 @@ function cleanup() { exports.mochaHooks = { beforeEach() { - enforceNetConnectPolicy(); + enforceNetConnectPolicy(this); suiteFakes = new Set(typeof sinon.getFakes === "function" ? sinon.getFakes() : []); }, - afterEach: cleanup, + afterEach() { + cleanup(this); + }, }; From 17716a87f943c15786b9fc0390cdf97fe65bf830 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 1 Oct 2026 18:31:13 +0000 Subject: [PATCH 5/6] fix(test): invert condition in enforceNetConnectPolicy for readability --- src/test/helpers/mocha-bootstrap.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index 59157ba1a50..ad2a3f1a191 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -33,11 +33,11 @@ function isIntegrationTestFile(filePath) { function enforceNetConnectPolicy(ctx) { const currentFile = ctx && ctx.currentTest && ctx.currentTest.file; - if (!isIntegrationTestFile(currentFile)) { + if (isIntegrationTestFile(currentFile)) { + nock.enableNetConnect(); + } else { nock.disableNetConnect(); nock.enableNetConnect(LOOPBACK_REGEXP); - } else { - nock.enableNetConnect(); } } From 4713b65593fdb99cd4d3a2b6b40f430f12ff8089 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 1 Oct 2026 19:50:27 +0000 Subject: [PATCH 6/6] fix(test): remove top-level enforceNetConnectPolicy call --- src/test/helpers/mocha-bootstrap.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/helpers/mocha-bootstrap.js b/src/test/helpers/mocha-bootstrap.js index ad2a3f1a191..33f03ad851e 100644 --- a/src/test/helpers/mocha-bootstrap.js +++ b/src/test/helpers/mocha-bootstrap.js @@ -41,8 +41,6 @@ function enforceNetConnectPolicy(ctx) { } } -enforceNetConnectPolicy(); - chai.use(chaiAsPromised); chai.use(sinonChai);