162 lines
5.4 KiB
TypeScript
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();
|
|
});
|
|
});
|