/**
* Shared test helpers.
*
* Both outbound calls this package makes — the AWS SNS `Publish` request and
* the sent.dm phone lookup — go through `fetch`. Stubbing `fetch` keeps the
* suite offline and deterministic; without it the VoIP tests hit a public API
* that rate-limits (HTTP 429) and the send tests hit SNS with fake credentials.
*/
import { vi } from 'vitest';
export const TEST_API_KEY = 'test-api-key';
export const TEST_MESSAGE_ID = 'test-message-id-0001';
/** The subset of an SNS `Publish` response that `parseXMLResponse` reads. */
const snsPublishOk = `
${TEST_MESSAGE_ID}
`;
export interface NetworkStubOptions {
/** What the phone lookup should report the number as. */
lookup?: 'voip' | 'cellular' | 'landline' | 'none';
/** Make the phone lookup fail with this status instead of answering. */
lookupStatus?: number;
}
/**
* Replace `globalThis.fetch` for the duration of a test. Any URL the package
* is not expected to call fails the test rather than escaping to the network.
*/
export function stubNetwork(options: NetworkStubOptions = {}) {
const { lookup = 'cellular', lookupStatus } = options;
const lookupBodies = {
voip: { carrier: { name: 'Bandwidth', type: 'voip' }, portability: { line_type: 'landline' } },
cellular: { carrier: { name: 'Verizon Wireless', type: 'cellular' }, portability: { line_type: 'landline' } },
landline: { carrier: { name: 'AT&T', type: 'landline' }, portability: { line_type: 'landline' } },
none: null,
} as const;
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
if (url.includes('amazonaws.com')) {
return new Response(snsPublishOk, {
status: 200,
headers: { 'Content-Type': 'text/xml' },
});
}
if (url.includes('sent.dm/api/phone-lookup')) {
if (lookupStatus) {
return new Response('rate limited', { status: lookupStatus });
}
return new Response(JSON.stringify(lookupBodies[lookup]), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
throw new Error(`Unexpected network call in tests: ${url}`);
});
vi.stubGlobal('fetch', fetchMock);
return fetchMock;
}
/** Build a JSON POST request carrying the given auth headers. */
export function apiRequest(
path: string,
body: unknown,
headers: Record = { 'X-API-Key': TEST_API_KEY },
) {
return new Request(`http://localhost${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(body),
});
}