Files
suaveplan/packages/communication/messaging/sms-providers/tests/coverage.test.ts
2026-05-27 23:29:53 +01:00

162 lines
5.4 KiB
TypeScript

/**
* 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();
});
});