Files
skills/docs/communication/emails/emailer/src/fakes/fake-smtp-client.md
2026-05-29 08:20:56 +01:00

2.4 KiB

fake-smtp-client.ts

Purpose

Deterministic test double for SmtpClientLike. Tests queue scripted responses, invoke the wrapped SmtpTransport, and inspect the captured calls — without vi.mock, without a real SMTP server, and without monkey-patching globals. Shipping the fake from the package itself means downstream consumers can test their integration against the same exact shape SmtpTransport produces, without re-implementing the protocol fake.

Features

  • push(response) queues a scripted outcome (info for success, reject for failure).
  • calls captures every sendMail invocation in FIFO order so assertions can target individual recipients / headers / attachments.
  • scheduleVerify(true | false | Error) programs the next verify() call.
  • verifyCalls and closeCalls track lifecycle so tests can assert cleanup behaviour.

Usage: Basic

import { FakeSmtpClient } from "@suaveplan/emailer/fakes/fake-smtp-client";
import { SmtpTransport } from "@suaveplan/emailer/transports/smtp";

const adapter = new FakeSmtpClient();
adapter.push({ info: { messageId: "<abc@host>" } });

const transport = new SmtpTransport();
await transport.initialize({ client: adapter });
const r = await transport.send({ to: "u@x.y", subject: "hi", text: "hi" });

Usage: Advanced

import { FakeSmtpClient } from "@suaveplan/emailer/fakes/fake-smtp-client";

const adapter = new FakeSmtpClient();
adapter.push({ reject: new Error("connection refused") });
adapter.push({ info: { messageId: "<1@h>", accepted: ["a@b.c"] } });
adapter.scheduleVerify(true);

// First send fails, second succeeds, verify returns true.

API Reference

  • class FakeSmtpClient implements SmtpClientLike
  • interface FakeSmtpResponse { info?, reject? }
  • interface FakeSmtpCall { payload: SmtpSendPayload }

Implementation Notes

  • The fake is intentionally minimal — it carries no SMTP state, no auth, no connection pool. The point is that SmtpTransport only ever calls three methods (sendMail, verify, close), and the fake reproduces exactly those three semantics with FIFO scripting.
  • scheduleVerify(Error) is single-use — after the next verify throws, the reject queue clears. Subsequent calls return the most-recently scheduled boolean (default true).
  • closeCalls increments on every close, allowing tests to assert idempotent close behaviour without inspecting private state.