Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,510 @@
/**
* Second targeted branch-coverage suite — closes the remaining
* istanbul branch gaps (default-arms of `??` chains, "fetch undefined"
* arms of per-provider `common()`, parseInbound default-fall-through
* shapes, http content-type-absent path, default baseUrl path for
* AWS SNS, conditional-spread absent-arms for delivery receipts, and
* the non-object `safeJsonObject` fallback).
*/
import { afterEach, describe, expect, it } from "@suaveplan/testing/runner";
import { AwsSnsProvider } from "../src/aws-sns/aws-sns.js";
import { httpRequest } from "../src/http/http.js";
import { MessageBirdProvider } from "../src/messagebird/messagebird.js";
import { PlivoProvider } from "../src/plivo/plivo.js";
import { TwilioProvider } from "../src/twilio/twilio.js";
import type { FetchLike } from "../src/types/provider.js";
import { VonageProvider } from "../src/vonage/vonage.js";
import {
jsonResponder,
type RecordingServer,
startRecordingServer,
} from "./setup/http-server.js";
let server: RecordingServer | undefined;
afterEach(async () => {
if (server) {
await server.close();
server = undefined;
}
});
/**
* Temporarily replace `globalThis.fetch` with a path-rewriting fetch that
* routes any URL to the recording server's origin via the captured
* platform fetch. Restores the original on exit. Used so providers
* constructed without an explicit `fetch` config option exercise the
* "this.fetch !== undefined === false" arm of their `common()` helper.
*/
async function withGlobalFetch<T>(
origin: string,
body: () => Promise<T>
): Promise<T> {
const original = globalThis.fetch;
const rewriter = async (
input: RequestInfo | URL,
init?: RequestInit
): Promise<Response> => {
const inputUrl =
typeof input === "string" || input instanceof URL
? new URL(input.toString())
: new URL(input.url);
const rerouted = `${origin}${inputUrl.pathname}${inputUrl.search}`;
return original.call(globalThis, rerouted, init);
};
Object.defineProperty(globalThis, "fetch", {
configurable: true,
writable: true,
value: rewriter as unknown as typeof fetch,
});
try {
return await body();
} finally {
Object.defineProperty(globalThis, "fetch", {
configurable: true,
writable: true,
value: original,
});
}
}
describe("http.ts — headers.get('content-type') returns null", () => {
it("treats a missing content-type header as empty and falls back to start-byte JSON sniffing", {
timeout: 5000,
}, async () => {
const fetchImpl: FetchLike = async () =>
({
ok: true,
status: 200,
headers: { get: () => null },
text: async () => '{"k":1}',
}) as unknown as Response;
const { data } = await httpRequest<{ k: number }>({
method: "GET",
url: "https://x/",
fetch: fetchImpl,
});
expect(data).toEqual({ k: 1 });
});
});
describe("Twilio — getStatus without date_created falls back to a fresh Date", () => {
it("returns a Date timestamp when date_created is omitted", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({ sid: "S", status: "sent", to: "+1" })
);
const t = new TwilioProvider({
accountSid: "AC",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await t.getStatus("S");
expect(r.timestamp).toBeInstanceOf(Date);
});
});
describe("common() — this.fetch === undefined arm (default global fetch)", () => {
it("Twilio.send works when no explicit fetch is configured", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({ sid: "S", status: "queued", to: "+1" })
);
const localServer = server;
const t = new TwilioProvider({
accountSid: "AC",
authToken: "T",
baseUrl: server.origin,
});
const r = await withGlobalFetch(localServer.origin, () =>
t.send({ to: "+1", body: "x" })
);
expect(r.messageId).toBe("S");
});
it("Vonage.send works when no explicit fetch is configured", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
"message-count": "1",
messages: [{ to: "1", "message-id": "x", status: "0" }],
})
);
const localServer = server;
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
});
const r = await withGlobalFetch(localServer.origin, () =>
v.send({ to: "+1", body: "hi" })
);
expect(r.messageId).toBe("x");
});
it("MessageBird.send works when no explicit fetch is configured", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
id: "mb",
originator: "S",
body: "x",
type: "sms",
recipients: {
totalCount: 1,
items: [{ recipient: 1, status: "sent" }],
},
})
);
const localServer = server;
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
});
const r = await withGlobalFetch(localServer.origin, () =>
m.send({ to: "+1", body: "x" })
);
expect(r.messageId).toBe("mb");
});
it("Plivo.send works when no explicit fetch is configured", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder(
{
api_id: "x",
message: "ok",
message_uuid: ["u1"],
},
202
)
);
const localServer = server;
const p = new PlivoProvider({
authId: "A",
authToken: "T",
baseUrl: server.origin,
});
const r = await withGlobalFetch(localServer.origin, () =>
p.send({ to: "+1", body: "x" })
);
expect(r.messageId).toBe("u1");
});
it("AwsSns.send works when no explicit fetch is configured", {
timeout: 5000,
}, async () => {
const PUBLISH_XML =
'<?xml version="1.0"?><PublishResponse><PublishResult><MessageId>x</MessageId></PublishResult></PublishResponse>';
server = await startRecordingServer((_req, res) => {
res.writeHead(200, { "content-type": "text/xml" });
res.end(PUBLISH_XML);
});
const localServer = server;
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
now: () => new Date("2026-04-24T10:00:00Z"),
});
const r = await withGlobalFetch(localServer.origin, () =>
a.send({ to: "+1", body: "hi" })
);
expect(r.messageId).toBe("x");
});
});
describe("AWS SNS — default baseUrl path (config.baseUrl omitted)", () => {
it("constructs the default https://sns.<region>.amazonaws.com base URL when baseUrl is omitted", {
timeout: 5000,
}, async () => {
// We exercise the `?? \`https://${host}\`` default arm of the
// constructor; the resulting fetch URL hits the AWS host, but
// the swapped global fetch routes it to our recording server.
const PUBLISH_XML =
'<?xml version="1.0"?><PublishResponse><PublishResult><MessageId>m1</MessageId></PublishResult></PublishResponse>';
server = await startRecordingServer((_req, res) => {
res.writeHead(200, { "content-type": "text/xml" });
res.end(PUBLISH_XML);
});
const localServer = server;
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
now: () => new Date("2026-04-24T10:00:00Z"),
});
const r = await withGlobalFetch(localServer.origin, () =>
a.send({ to: "+1", body: "hi" })
);
expect(r.messageId).toBe("m1");
});
});
describe("AWS SNS — parseInbound delivery receipt without errorCode", () => {
it("omits errorCode when the SNS Message payload has no string errorCode field", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
const evt = a.parseInbound({
Type: "Notification",
MessageId: "m1",
Subject: "AWS SMS Delivery Receipt",
Message: JSON.stringify({ status: "DELIVERED" }),
Timestamp: "2026-04-24T10:00:00Z",
TopicArn: "arn:aws:sns:us-east-1:000000000000:topic",
Signature: "",
SigningCertURL: "",
SignatureVersion: "1",
});
expect(evt.type).toBe("delivery_receipt");
if (evt.type === "delivery_receipt") {
expect(evt.errorCode).toBeUndefined();
}
});
it("falls back to '' status when the SNS Message payload lacks a status field (delivery receipt path)", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
const evt = a.parseInbound({
Type: "Notification",
MessageId: "m2",
Subject: "AWS SMS Delivery Receipt",
Message: JSON.stringify({}),
Timestamp: "2026-04-24T10:00:00Z",
TopicArn: "arn:aws:sns:us-east-1:000000000000:topic",
Signature: "",
SigningCertURL: "",
SignatureVersion: "1",
});
expect(evt.type).toBe("delivery_receipt");
if (evt.type === "delivery_receipt") {
// `mapStatus("")` defaults to "failed" per the SNS table.
expect(evt.status).toBe("failed");
}
});
});
describe("AWS SNS — safeJsonObject non-object fallback", () => {
it("parseInbound treats a non-object JSON payload as an empty object (covers the `typeof === 'object' && !== null` else arm)", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
// `42` parses to a number — `typeof parsed === "object"` is false,
// so safeJsonObject returns `{}`. The non-delivery-receipt branch
// then produces a message_received event with empty fields.
const evt = a.parseInbound({
Type: "Notification",
MessageId: "mX",
Message: "42",
Timestamp: "2026-04-24T10:00:00Z",
TopicArn: "arn:aws:sns:us-east-1:000000000000:topic",
Signature: "",
SigningCertURL: "",
SignatureVersion: "1",
});
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.from).toBe("");
expect(evt.to).toBe("");
expect(evt.body).toBe("");
}
});
});
describe("AWS SNS — fetchPem default-fetch arm (no provider fetch configured)", () => {
it("verifyNotification fetches the SNS signing cert via globalThis.fetch when no fetch is configured", {
timeout: 5000,
}, async () => {
const PEM =
"-----BEGIN CERTIFICATE-----\nMIIB\n-----END CERTIFICATE-----\n";
server = await startRecordingServer((_req, res) => {
res.writeHead(200, {
"content-type": "application/x-pem-file",
});
res.end(PEM);
});
const localServer = server;
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
now: () => new Date("2026-04-24T10:00:00Z"),
});
const ok = await withGlobalFetch(localServer.origin, () =>
a.verifyNotification(
{
Type: "Notification",
MessageId: "m",
Message: "{}",
Timestamp: "2026-04-24T10:00:00Z",
TopicArn: "arn:aws:sns:us-east-1:0:t",
Signature: "x",
SigningCertURL: `${localServer.origin}/cert.pem`,
SignatureVersion: "1",
},
async () => true
)
);
expect(ok).toBe(true);
});
});
describe("MessageBird — verifyWebhookSignature without nowMs (default arm)", () => {
it("accepts a JWT issued at the real wall-clock when nowMs is omitted", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const { createHmac } = await import("node:crypto");
const b64url = (input: Buffer | string): string => {
const buf =
typeof input === "string" ? Buffer.from(input, "utf8") : input;
return buf
.toString("base64")
.replace(/=+$/, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
};
const nowSec = Math.floor(Date.now() / 1000);
const header = b64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
const payload = b64url(
JSON.stringify({ iat: nowSec - 1, exp: nowSec + 60 })
);
const sig = createHmac("sha256", "secret")
.update(`${header}.${payload}`)
.digest();
const token = `${header}.${payload}.${b64url(sig)}`;
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
fetch: server.fetch,
});
const ok = await m.verifyWebhookSignature(token, "secret", {});
expect(ok).toBe(true);
});
});
describe("MessageBird — parseInbound fallthrough defaults", () => {
it("returns message_received with from='' when originator is absent", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
fetch: server.fetch,
});
const evt = m.parseInbound({ recipient: "+2", payload: "hello" });
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.from).toBe("");
expect(evt.body).toBe("hello");
}
});
it("returns message_received with body='' when neither payload nor body is present", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
fetch: server.fetch,
});
const evt = m.parseInbound({
originator: "+1",
recipient: "+2",
});
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.body).toBe("");
}
});
});
describe("Plivo — parseInbound fallthrough defaults", () => {
it("returns message_received with from='' when From is absent", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const p = new PlivoProvider({
authId: "A",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
const evt = p.parseInbound({ To: "+2", Text: "hello" });
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.from).toBe("");
}
});
it("returns message_received with body='' when neither Text nor text is present", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const p = new PlivoProvider({
authId: "A",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
const evt = p.parseInbound({ From: "+1", To: "+2" });
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.body).toBe("");
}
});
});
describe("Vonage — parseInbound fallthrough default", () => {
it("returns message_received with body='' when text is absent", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({}));
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
fetch: server.fetch,
});
const evt = v.parseInbound({ msisdn: "+1", to: "+2" });
expect(evt.type).toBe("message_received");
if (evt.type === "message_received") {
expect(evt.body).toBe("");
}
});
});

View File

@@ -0,0 +1,317 @@
/**
* Targeted branch-coverage suite for the conditional spreads
* (`...(x ? {y:x} : {})`) and default-config paths that the per-provider
* feature tests skip for readability.
*/
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { AwsSnsProvider } from "../src/aws-sns/aws-sns.js";
import { MessageBirdProvider } from "../src/messagebird/messagebird.js";
import { PlivoProvider } from "../src/plivo/plivo.js";
import { TwilioProvider } from "../src/twilio/twilio.js";
import { VonageProvider } from "../src/vonage/vonage.js";
import {
jsonResponder,
type RecordingServer,
startRecordingServer,
} from "./setup/http-server.js";
let server!: RecordingServer;
afterEach(async () => {
await server.close();
});
describe("branch coverage — Twilio", () => {
it("getStatus returns a report with errorCode + errorMessage when present", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
sid: "S",
status: "failed",
to: "+1",
date_created: "2026-04-24T10:00:00Z",
error_code: 30007,
error_message: "carrier",
})
);
const t = new TwilioProvider({
accountSid: "AC",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await t.getStatus("S");
expect(r.errorCode).toBe("30007");
expect(r.errorMessage).toBe("carrier");
});
it("send omits From when message.from is undefined", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({ sid: "S", status: "queued", to: "+1" })
);
const t = new TwilioProvider({
accountSid: "AC",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
await t.send({ to: "+1", body: "x" });
expect(server.requests[0]!.body).not.toContain("From=");
});
});
describe("branch coverage — Vonage", () => {
it("send omits from when message.from is undefined", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
"message-count": "1",
messages: [{ to: "1", "message-id": "x", status: "0" }],
})
);
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
fetch: server.fetch,
});
await v.send({ to: "+1", body: "hi" });
expect(server.requests[0]!.body).not.toContain("from=");
});
it("send returns sent without errorCode/errorMessage when status=0 and no error-text", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
"message-count": "1",
messages: [{ to: "1", "message-id": "x", status: "0" }],
})
);
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await v.send({ to: "+1", body: "hi" });
expect(r.errorCode).toBeUndefined();
expect(r.errorMessage).toBeUndefined();
});
it("getStatus omits errorCode / errorMessage when absent", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
"message-id": "x",
to: "1",
status: "delivered",
})
);
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await v.getStatus("x");
expect(r.errorCode).toBeUndefined();
expect(r.errorMessage).toBeUndefined();
});
});
describe("branch coverage — Plivo", () => {
it("getStatus omits errorCode when absent", { timeout: 5000 }, async () => {
server = await startRecordingServer(
jsonResponder({
api_id: "x",
message_uuid: "u",
to_number: "+1",
message_state: "sent",
})
);
const p = new PlivoProvider({
authId: "A",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await p.getStatus("u");
expect(r.errorCode).toBeUndefined();
});
});
describe("branch coverage — AWS SNS", () => {
it("send falls through to a default `now` factory", {
timeout: 5000,
}, async () => {
const PUBLISH_XML =
'<?xml version="1.0"?><PublishResponse><PublishResult><MessageId>x</MessageId></PublishResult></PublishResponse>';
server = await startRecordingServer((_req, res) => {
res.writeHead(200, { "content-type": "text/xml" });
res.end(PUBLISH_XML);
});
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await a.send({ to: "+1", body: "hi" });
expect(r.messageId).toBe("x");
});
});
describe("branch coverage — MessageBird", () => {
it("send works without options (signal omitted)", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
id: "mb1",
originator: "S",
body: "x",
type: "sms",
recipients: {
totalCount: 1,
items: [{ recipient: 1, status: "sent" }],
},
})
);
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
fetch: server.fetch,
});
const r = await m.send({ to: "+1", body: "hi" });
expect(r.messageId).toBe("mb1");
});
});
describe("branch coverage — default baseUrl path", () => {
it("Twilio falls through to the documented default base URL", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({ sid: "S", status: "queued", to: "+1" })
);
const t = new TwilioProvider({
accountSid: "AC",
authToken: "T",
fetch: server.fetch,
});
const r = await t.send({ to: "+1", body: "x" });
expect(r.messageId).toBe("S");
});
it("Vonage falls through to the documented default base URL", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
"message-count": "1",
messages: [{ to: "1", "message-id": "x", status: "0" }],
})
);
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
fetch: server.fetch,
});
const r = await v.send({ to: "+1", body: "x" });
expect(r.messageId).toBe("x");
});
it("MessageBird falls through to the documented default base URL", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder({
id: "mb",
originator: "S",
body: "x",
type: "sms",
recipients: {
totalCount: 1,
items: [{ recipient: 1, status: "sent" }],
},
})
);
const m = new MessageBirdProvider({
accessKey: "K",
fetch: server.fetch,
});
const r = await m.send({ to: "+1", body: "x" });
expect(r.messageId).toBe("mb");
});
it("Plivo falls through to the documented default base URL", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(
jsonResponder(
{
api_id: "x",
message: "ok",
message_uuid: ["u1"],
},
202
)
);
const p = new PlivoProvider({
authId: "A",
authToken: "T",
fetch: server.fetch,
});
const r = await p.send({ to: "+1", body: "x" });
expect(r.messageId).toBe("u1");
});
});
describe("branch coverage — extractSnsMessageId fallback for non-object/non-string", () => {
it("returns undefined for a plain object without MessageId", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({ random: "x" }));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
await expect(a.send({ to: "+1", body: "x" })).rejects.toBeTruthy();
});
it("returns undefined for a non-string MessageId on the JSON shape", {
timeout: 5000,
}, async () => {
server = await startRecordingServer(jsonResponder({ MessageId: 42 }));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
await expect(a.send({ to: "+1", body: "x" })).rejects.toBeTruthy();
});
});
beforeEach(() => {
// no-op: each it() block sets up its own server before any work.
});

View File

@@ -0,0 +1,161 @@
/**
* Coverage-completion suite — exercises the branches that the per-
* provider feature tests skip for readability (timeoutMs / signal pass-
* through, error-path send increments, defaultFetch construction).
*/
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { AwsSnsProvider } from "../src/aws-sns/aws-sns.js";
import { SMS_PROVIDERS_CODES } from "../src/error-codes/error-codes.js";
import { httpRequest } from "../src/http/http.js";
import { MessageBirdProvider } from "../src/messagebird/messagebird.js";
import { PlivoProvider } from "../src/plivo/plivo.js";
import { TwilioProvider } from "../src/twilio/twilio.js";
import { VonageProvider } from "../src/vonage/vonage.js";
import {
jsonResponder,
type RecordingServer,
startRecordingServer,
} from "./setup/http-server.js";
let server!: RecordingServer;
beforeEach(async () => {
server = await startRecordingServer(jsonResponder({}, 500));
});
afterEach(async () => {
await server.close();
});
describe("coverage — provider config seams (signal + timeoutMs)", () => {
it("Twilio threads config.signal + config.timeoutMs into the request init", {
timeout: 5000,
}, async () => {
const ctrl = new AbortController();
const t = new TwilioProvider({
accountSid: "AC1",
authToken: "tok",
baseUrl: server.origin,
fetch: server.fetch,
signal: ctrl.signal,
timeoutMs: 10_000,
});
await expect(
t.send({ to: "+1", from: "+1", body: "hi" })
).rejects.toMatchObject({ code: SMS_PROVIDERS_CODES.HTTP_ERROR });
});
it("Vonage threads config.signal + config.timeoutMs", {
timeout: 5000,
}, async () => {
const ctrl = new AbortController();
const v = new VonageProvider({
apiKey: "k",
apiSecret: "s",
baseUrl: server.origin,
fetch: server.fetch,
signal: ctrl.signal,
timeoutMs: 10_000,
});
await expect(
v.send({ to: "+1", from: "+1", body: "hi" })
).rejects.toMatchObject({ code: SMS_PROVIDERS_CODES.HTTP_ERROR });
});
it("MessageBird threads config.signal + config.timeoutMs and counts errors", {
timeout: 5000,
}, async () => {
const ctrl = new AbortController();
const m = new MessageBirdProvider({
accessKey: "K",
baseUrl: server.origin,
fetch: server.fetch,
signal: ctrl.signal,
timeoutMs: 10_000,
});
await expect(
m.send({ to: "+1", from: "+1", body: "hi" })
).rejects.toMatchObject({ code: SMS_PROVIDERS_CODES.HTTP_ERROR });
});
it("Plivo threads config.signal + config.timeoutMs and counts errors", {
timeout: 5000,
}, async () => {
const ctrl = new AbortController();
const p = new PlivoProvider({
authId: "A",
authToken: "T",
baseUrl: server.origin,
fetch: server.fetch,
signal: ctrl.signal,
timeoutMs: 10_000,
});
await expect(
p.send({ to: "+1", from: "+1", body: "hi" })
).rejects.toMatchObject({ code: SMS_PROVIDERS_CODES.HTTP_ERROR });
});
it("AwsSnsProvider threads config.signal + config.timeoutMs", {
timeout: 5000,
}, async () => {
const ctrl = new AbortController();
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
signal: ctrl.signal,
timeoutMs: 10_000,
now: () => new Date("2026-04-24T10:00:00Z"),
});
await expect(a.send({ to: "+1", body: "hi" })).rejects.toMatchObject({
code: SMS_PROVIDERS_CODES.HTTP_ERROR,
});
});
});
describe("coverage — extractSnsMessageId fallback for non-string/non-object data", () => {
it("returns undefined for numeric data", { timeout: 5000 }, async () => {
await server.close();
// Respond with a JSON number — extractSnsMessageId hits the
// final `return undefined` branch.
server = await startRecordingServer(jsonResponder(42));
const a = new AwsSnsProvider({
region: "us-east-1",
accessKeyId: "K",
secretAccessKey: "S",
baseUrl: server.origin,
fetch: server.fetch,
now: () => new Date("2026-04-24T10:00:00Z"),
});
await expect(a.send({ to: "+1", body: "hi" })).rejects.toMatchObject({
code: SMS_PROVIDERS_CODES.HTTP_ERROR,
});
});
});
describe("coverage — httpRequest defaultFetch resolution", () => {
it("falls through to globalThis.fetch when `fetch` is omitted", {
timeout: 5000,
}, async () => {
// We do not actually let the call escape — we abort immediately
// so the call rejects after touching the defaultFetch branch.
const ctrl = new AbortController();
ctrl.abort(new Error("local"));
await expect(
httpRequest({
method: "GET",
url: `${server.origin}/`,
signal: ctrl.signal,
provider: "p",
})
).rejects.toBeTruthy();
});
});

View File

@@ -0,0 +1,41 @@
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "@suaveplan/testing/runner";
const SRC_ROOT = join(__dirname, "..", "src");
function walkTypescript(dir: string): string[] {
const entries = readdirSync(dir);
const files: string[] = [];
for (const entry of entries) {
const full = join(dir, entry);
const st = statSync(full);
if (st.isDirectory()) {
files.push(...walkTypescript(full));
} else if (
entry.endsWith(".ts") &&
!entry.endsWith(".test.ts") &&
!entry.endsWith(".spec.ts")
) {
files.push(full);
}
}
return files;
}
describe("universal dep graph", () => {
it("src contains no node/bun/fs/path/stream/net/http/crypto imports", {
timeout: 5000,
}, () => {
const banned =
/from\s+['"](node:|bun:|fs|path|stream|net|http|crypto)['"]/;
const offenders: string[] = [];
for (const file of walkTypescript(SRC_ROOT)) {
const text = readFileSync(file, "utf8");
if (banned.test(text)) {
offenders.push(file);
}
}
expect(offenders).toEqual([]);
});
});

View File

@@ -0,0 +1,85 @@
/**
* Test-only helpers that stand up a real `node:http` server on a random
* port and route a `FetchLike` through it. Used by every provider's
* `*.test.ts` to exercise the full HTTP path without mocks.
*
* Lives under `tests/setup/` (not `src/`) so the universal dep-graph
* scan never sees it.
*/
import {
createServer,
type IncomingMessage,
type Server,
type ServerResponse,
} from "node:http";
import type { FetchLike } from "../../src/types/provider.js";
export interface RecordedRequest {
readonly method: string;
readonly path: string;
readonly headers: Record<string, string | string[] | undefined>;
readonly body: string;
}
export interface RecordingServer {
readonly origin: string;
readonly requests: RecordedRequest[];
readonly fetch: FetchLike;
close: () => Promise<void>;
}
export type Responder = (
req: IncomingMessage,
res: ServerResponse,
body: string
) => void | Promise<void>;
/**
* Stand up an HTTP server on a random port, capture every request, and
* return a `FetchLike` that proxies any URL (regardless of original
* scheme/host) to the local server preserving the path and method.
*/
export async function startRecordingServer(
respond: Responder
): Promise<RecordingServer> {
const requests: RecordedRequest[] = [];
const server: Server = createServer((req, res) => {
const chunks: Buffer[] = [];
req.on("data", (c) => chunks.push(c));
req.on("end", () => {
const body = Buffer.concat(chunks).toString("utf8");
requests.push({
method: req.method ?? "GET",
path: req.url ?? "/",
headers: { ...req.headers },
body,
});
respond(req, res, body);
});
});
await new Promise<void>((r) => server.listen(0, "127.0.0.1", r));
const addr = server.address();
if (addr === null || typeof addr === "string") {
throw new Error("server.address() returned an unexpected value");
}
const origin = `http://127.0.0.1:${addr.port}`;
const fetchImpl: FetchLike = async (url, init) => {
const u = new URL(url);
const rerouted = `${origin}${u.pathname}${u.search}`;
return globalThis.fetch(rerouted, init);
};
const close = async (): Promise<void> => {
await new Promise<void>((resolve, reject) => {
server.close((err) => (err ? reject(err) : resolve()));
});
};
return { origin, requests, fetch: fetchImpl, close };
}
/** Convenience: respond with a JSON body + status. */
export function jsonResponder(body: unknown, status = 200): Responder {
return (_req, res) => {
res.writeHead(status, { "content-type": "application/json" });
res.end(typeof body === "string" ? body : JSON.stringify(body));
};
}

View File

@@ -0,0 +1,7 @@
// Polyfill setup for @suaveplan/sms-providers tests.
//
// Every provider test injects a `FetchLike` that either returns a canned
// `Response` or proxies through a real `node:http` server on a random port,
// so production code never reaches into a platform fetch. This file mirrors
// the sibling-package layout and gives vitest a stable setup-file path.
export {};