test(e2e): teach the eTrade mock to answer "no record"

Every TIN resolved to the same canned company, so the premise of both manual
routes — eTrade holds nothing — could not be reached at all, and neither could
the dead end an ordinary company hits on a TIN with no trade licence.

The answer now follows the TIN's leading digit, so a spec picks its outcome by
picking its number and no per-spec stubbing is needed: 9… returns a
registration with no businesses (the co-operative / investor case, where the
API's resolveCompanyData finds no licence), 8… 404s the registration lookup
entirely, anything else behaves as before.
This commit is contained in:
Nathnael
2026-08-18 11:37:58 +00:00
parent 0608f8a7ea
commit 2f86557f61

View File

@@ -9,10 +9,30 @@
// TLS_CERT_PATH/TLS_KEY_PATH before starting this — nothing shaped like a // TLS_CERT_PATH/TLS_KEY_PATH before starting this — nothing shaped like a
// key/cert is committed here. // key/cert is committed here.
// //
// Every TIN resolves to the same canned company — these specs don't care // A TIN resolves to the same canned company whatever its digits, EXCEPT for
// about per-TIN business logic, only that the lookup succeeds so the rest // the two failure shapes the onboarding specs need — chosen by the TIN's
// of the company-info form (name, address, manager) auto-fills instead of // leading digit so a spec picks its outcome by picking its number, with no
// staying gated behind a "No matching business record" alert. // per-spec stubbing and no state in this process:
//
// 1xxxxxxxxx (default) registration + one business licence → "Verified with eTrade"
// 9xxxxxxxxx registration, but `Businesses: []` → the API's resolveCompanyData
// returns businessInfo: null,
// so /fetch-etrade-info 400s
// with "couldn't find a
// business license for this
// TIN". This is the real
// co-operative / foreign-
// investor case: the TIN is
// registered, the trade
// licence is not.
// 8xxxxxxxxx 404 on the registration lookup → getCompanyInfoByTin throws,
// same 400 to the portal by a
// different route (eTrade knows
// nothing about this TIN at all).
//
// Both failures reach the portal as a 400, which ETradeInfo renders as its
// `notFound` branch: a red dead end for an ordinary company, and the blue
// "that's expected" alert for one that types its registration.
const https = require("node:https"); const https = require("node:https");
const fs = require("node:fs"); const fs = require("node:fs");
@@ -25,6 +45,11 @@ const options = {
), ),
}; };
/** No trade licence on file for this TIN (a co-operative, a foreign investor). */
const TIN_WITHOUT_LICENCE = "9";
/** eTrade holds no registration whatsoever for this TIN. */
const TIN_UNKNOWN = "8";
function companyInfo(tin) { function companyInfo(tin) {
return { return {
Tin: tin, Tin: tin,
@@ -101,8 +126,21 @@ const server = https.createServer(options, (req, res) => {
/^\/api\/Registration\/GetRegistrationInfoByTin\/([^/]+)\/en$/, /^\/api\/Registration\/GetRegistrationInfoByTin\/([^/]+)\/en$/,
); );
if (req.method === "GET" && regMatch) { if (req.method === "GET" && regMatch) {
const tin = regMatch[1];
if (tin.startsWith(TIN_UNKNOWN)) {
res.writeHead(404).end();
return;
}
const info = companyInfo(tin);
// Registered, but holding no trade licence. The API reads `Businesses`
// rather than the HTTP status to decide this, so an empty array is the
// honest shape — not an error.
if (tin.startsWith(TIN_WITHOUT_LICENCE)) info.Businesses = [];
res.writeHead(200, { "content-type": "application/json" }); res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify(companyInfo(regMatch[1]))); res.end(JSON.stringify(info));
return; return;
} }