Initial Commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# `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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user