All files / testing / assert.ts

100.00% Branches 5/5
100.00% Lines 40/40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
 
x59
x59
x59
 
x59
 
 
 
 
 
 
 
 
x59
x83
x83
x83
x83
x83
x332
x83
x83
x83
x83
x83
x83
x91
x91
x364
x107
x115
x115
x119
x119
x119
x119
x119
x119
x115
x107
x83
x99
x99
x99
x83
x83
x83
x83
x83
















































// deno-lint-ignore-file no-console
import type { Promisable } from "@libs/typing"
import { expect } from "./expect.ts"
import { basename, dirname, fromFileUrl } from "@std/path"
import { yellow } from "@std/fmt/colors"
export type { Promisable }
export * from "@std/assert"

/** Options for `assertConsoleSnapshot()`. */
export type AssertConsoleSnapshotOptions = {
  /** Whether to capture console output and update snapshots. Defaults to `Deno.args` including `--update-snapshots`. */
  capture?: boolean
}

/** Captures and matches console output against stored snapshots. */
export async function assertConsoleSnapshot(meta: ImportMeta, fn: () => Promisable<unknown>, { capture = Deno.args.includes("--update-snapshots") }: AssertConsoleSnapshotOptions = {}): Promise<void> {
  const path = fromFileUrl(meta.resolve(`./fixtures/snapshots/${basename(meta.url, ".ts")}`))
  const snapshot = {
    stdout: await Deno.readTextFile(`${path}.stdout.snap`).catch(() => ""),
    stderr: await Deno.readTextFile(`${path}.stderr.snap`).catch(() => ""),
  }
  const captured = { stdout: "", stderr: "" }
  const { log, error } = console
  try {
    console.log = (message: unknown) => captured.stdout += `${message}\n`
    console.error = (message: unknown) => captured.stderr += `${message}\n`
    await fn()
    if (capture) {
      const { ensureDir } = await import("@std/fs")
      await ensureDir(dirname(path))
      for (const channel of ["stdout", "stderr"] as const) {
        if (snapshot[channel] !== captured[channel]) {
          const filepath = `${path}.${channel}.snap`
          if (captured[channel]) {
            await Deno.writeTextFile(filepath, captured[channel])
            log(yellow(`> updated snapshot: ${filepath}`))
          } else {
            await Deno.remove(filepath)
            log(yellow(`> removed snapshot: ${filepath}`))
          }
        }
      }
    } else {
      expect(captured.stdout).toEqual(snapshot.stdout)
      expect(captured.stderr).toEqual(snapshot.stderr)
    }
  } finally {
    console.log = log
    console.error = error
  }
}