Provide nock api

This commit is contained in:
Fang-Pen Lin
2025-11-12 20:34:07 -08:00
parent 79ddc8465c
commit 89baed638d
4 changed files with 41 additions and 102 deletions

View File

@@ -26,7 +26,6 @@ import { TSmtpService } from "@app/services/smtp/smtp-service";
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
import { globalRateLimiterCfg } from "./config/rateLimiter";
import { mockThirdPartyApiCalls } from "./mock-third-party-api-calls";
import { addErrorsToResponseSchemas } from "./plugins/add-errors-to-response-schemas";
import { apiMetrics } from "./plugins/api-metrics";
import { fastifyErrHandler } from "./plugins/error-handler";
@@ -67,12 +66,6 @@ export const main = async ({
}: TMain) => {
const appCfg = getConfig();
if (appCfg.shouldMockThirdPartyApiCalls) {
logger?.info("Mocking third party API calls for BDD");
// Note: to make BDD tests much easier, we mock some third party API calls here
mockThirdPartyApiCalls();
}
const server = fastify({
logger: appCfg.NODE_ENV === "test" ? false : logger,
genReqId: () => `req-${alphaNumericNanoId(14)}`,

View File

@@ -1,95 +0,0 @@
import nock from "nock";
const CLOUDFLARE_ACCOUNT_ID = "A2A6347F-88B5-442D-9798-95E408BC7701";
// We mock the Cloudflare account API calls to let adding app connection much easier in BDD tests.
// It's mainly for the DNS provider validation in ACME challenge validation.
const mockCloudflare = () => {
nock("https://api.cloudflare.com:443")
.get("/client/v4/accounts/MOCK_ACCOUNT_ID")
.reply(200, {
result: {
id: CLOUDFLARE_ACCOUNT_ID,
name: "Mock Account",
type: "standard",
settings: {
enforce_twofactor: true,
api_access_enabled: null,
access_approval_expiry: null,
abuse_contact_email: null,
user_groups_ui_beta: false
},
legacy_flags: {
enterprise_zone_quota: { maximum: 0, current: 0, available: 0 }
},
created_on: "2013-04-18T00:41:02.215243Z"
},
success: true,
errors: [],
messages: []
});
nock("https://api.cloudflare.com:443")
.get("/client/v4/zones")
.reply(200, {
result: [
{
id: "2DF47D5E-7FE2-4BD9-8503-BF27ACE6EBE5",
name: "example.com",
status: "active",
paused: false,
type: "full",
development_mode: 0,
name_servers: ["abby.ns.cloudflare.com", "cody.ns.cloudflare.com"],
original_name_servers: ["ns1gmz.name.com", "ns2fgp.name.com", "ns3jwx.name.com", "ns4lny.name.com"],
original_registrar: "name.com, inc. (id: 625)",
original_dnshost: null,
modified_on: "2025-11-05T18:08:57.046348Z",
created_on: "2025-11-05T18:05:52.536690Z",
activated_on: "2025-11-05T18:08:57.046348Z",
vanity_name_servers: [],
vanity_name_servers_ips: null,
meta: {
step: 2,
custom_certificate_quota: 0,
page_rule_quota: 3,
phishing_detected: false
},
owner: { id: null, type: "user", email: null },
account: {
id: CLOUDFLARE_ACCOUNT_ID,
name: "Mock Account"
},
tenant: { id: null, name: null },
tenant_unit: { id: null },
permissions: ["#dns_records:edit", "#dns_records:read", "#zone:read"],
plan: {
id: "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
name: "Free Website",
price: 0,
currency: "USD",
frequency: "",
is_subscribed: false,
can_subscribe: false,
legacy_id: "free",
legacy_discount: false,
externally_managed: false
}
}
],
result_info: {
page: 1,
per_page: 20,
total_pages: 1,
count: 1,
total_count: 1
},
success: true,
errors: [],
messages: []
});
};
export const mockThirdPartyApiCalls = () => {
mockCloudflare();
};

View File

@@ -0,0 +1,33 @@
import { z } from "zod";
import { getConfig } from "@app/lib/config/env";
import { ForbiddenRequestError } from "@app/lib/errors";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import nock, { Definition } from "nock";
export const registerBddNockRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/define",
schema: {
body: z.object({ definition: z.string() }),
response: {
200: z.object({ status: z.string() })
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const appCfg = getConfig();
// Note: Please note that this API is only available in development mode and only for BDD tests.
// This endpoint should NEVER BE ENABLED IN PRODUCTION!
if (appCfg.NODE_ENV !== "development" || !appCfg.isBddNockApiEnabled) {
throw new ForbiddenRequestError({ message: "BDD Nock API is not enabled" });
}
const { body } = req;
const { definition } = body;
nock.define(definition as unknown as Definition[]);
return { status: "ok" };
}
});
};

View File

@@ -6,8 +6,10 @@ import { registerCmekRouter } from "@app/server/routes/v1/cmek-router";
import { registerDashboardRouter } from "@app/server/routes/v1/dashboard-router";
import { registerSecretSyncRouter, SECRET_SYNC_REGISTER_ROUTER_MAP } from "@app/server/routes/v1/secret-sync-routers";
import { getConfig } from "@app/lib/config/env";
import { registerAdminRouter } from "./admin-router";
import { registerAuthRoutes } from "./auth-router";
import { registerBddNockRouter } from "./bdd-nock-router";
import { registerProjectBotRouter } from "./bot-router";
import { registerCaRouter } from "./certificate-authority-router";
import { CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP } from "./certificate-authority-routers";
@@ -237,4 +239,10 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
await server.register(registerEventRouter, { prefix: "/events" });
await server.register(registerUpgradePathRouter, { prefix: "/upgrade-path" });
// Note: This is a special route for BDD tests. It's only available in development mode and only for BDD tests.
// This route should NEVER BE ENABLED IN PRODUCTION!
if (getConfig().isBddNockApiEnabled) {
await server.register(registerBddNockRouter, { prefix: "/bdd-nock" });
}
};