@specific.dev/spectest 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/recorder.ts CHANGED
@@ -25,7 +25,8 @@ export type TestEvent =
25
25
  | TerminalStepEvent
26
26
  | WaitEvent
27
27
  | FakeEvent
28
- | EnvEvent;
28
+ | EnvEvent
29
+ | EmailEvent;
29
30
 
30
31
  interface BaseEvent {
31
32
  /** Order of *start* within the test. Reserved when an op begins (see
@@ -275,6 +276,69 @@ export interface FakeEvent extends BaseEvent {
275
276
  error?: string;
276
277
  }
277
278
 
279
+ /**
280
+ * One captured email, as embedded on an {@link EmailEvent}. The HTML and
281
+ * text bodies ride along (truncated to the output cap) so the dashboard
282
+ * can render the actual email a test asserted against.
283
+ */
284
+ export interface EmailEventMessage {
285
+ /** Sender address. */
286
+ from?: string;
287
+ /** Recipient addresses. */
288
+ to?: string[];
289
+ cc?: string[];
290
+ bcc?: string[];
291
+ subject?: string;
292
+ /** RFC date of the message, ISO-formatted. */
293
+ date?: string;
294
+ /** HTML body (truncated to the output cap). */
295
+ html?: string;
296
+ htmlTruncated?: boolean;
297
+ /** Plain-text body (truncated to the output cap). */
298
+ text?: string;
299
+ textTruncated?: boolean;
300
+ attachments?: { filename: string; contentType: string; size: number }[];
301
+ }
302
+
303
+ /** One row of a mailbox listing embedded on an {@link EmailEvent}. */
304
+ export interface EmailEventSummary {
305
+ from?: string;
306
+ to?: string[];
307
+ subject?: string;
308
+ /** Plain-text preview of the body. */
309
+ snippet?: string;
310
+ date?: string;
311
+ }
312
+
313
+ /**
314
+ * One call to an email service's helpers (`ctx.svc.<name>.lastEmail(...)`
315
+ * etc.). Single-message ops embed the full captured message — including its
316
+ * HTML body — so timelines can render the email itself; listing ops embed
317
+ * compact summaries. The return value is `wrap()`ped against this event's
318
+ * seq, so `expect(...)` on it nests under this step (same mechanism as
319
+ * http/db/fake). Inside a `ctx.poll` predicate the event ride-alongs with
320
+ * the poll's iteration events: failed iterations get truncated, the winning
321
+ * one survives as a child of the `wait` event.
322
+ */
323
+ export interface EmailEvent extends BaseEvent {
324
+ kind: "email";
325
+ /** Service key of the mail server (`ctx.svc.<service>`). */
326
+ service: string;
327
+ /** Helper called, e.g. `"lastEmail"`. */
328
+ op: string;
329
+ /** Human-readable match criteria, e.g. `to alice@example.com`. */
330
+ query?: string;
331
+ /** Number of matching messages (listing ops / mailbox size on error). */
332
+ count?: number;
333
+ /** The captured message (single-message ops). */
334
+ message?: EmailEventMessage;
335
+ /** Message summaries (listing ops). */
336
+ messages?: EmailEventSummary[];
337
+ durationMs: number;
338
+ /** Set if the op threw (e.g. the mail server's query API failed). */
339
+ error?: string;
340
+ }
341
+
278
342
  /**
279
343
  * A runtime mutation of the environment — `ctx.startService` /
280
344
  * `ctx.stopService` / `ctx.dnsName`, whether called from a test or from a
@@ -663,6 +727,13 @@ export function recordEnv(
663
727
  return active() ? current!.push({ kind: "env", ...ev }, reservation) : undefined;
664
728
  }
665
729
 
730
+ export function recordEmail(
731
+ ev: Omit<EmailEvent, "seq" | "tOffsetMs" | "kind">,
732
+ reservation?: EventReservation,
733
+ ): number | undefined {
734
+ return active() ? current!.push({ kind: "email", ...ev }, reservation) : undefined;
735
+ }
736
+
666
737
  /**
667
738
  * Recorded once per `ctx.poll(...)` call. Stands in for the suppressed
668
739
  * intermediate iterations and gives downstream tagged values