All files / testing / _snapshot_utils.ts

96.00% Branches 24/25
100.00% Functions 7/7
98.39% Lines 61/62
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 
 
x24
x24
x24
 
x24
x5
x5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x24
x101
x101
x101
x101
x101
x101
x101
x101
x101
x101
x101
 
 
 
 
 
 
 
 
x24
x55
x55
x55
x55
x55
 
x24
 
 
 
x24
x112
x9
x112
x86
x98
x17
x17
x17
x17
x17
x112
 
 
 
 
x24
x112
x112
 
x24
x24
 
x105
 
x105
x34
x34
 
 
x105
 
x24
x24
x24
x24
 
x2
x2
x2
x2
x2
x2
x2
x2
x2
 
 
x24

















































































I




















// Copyright 2018-2026 the Deno authors. MIT license.
import type { SnapshotMode, SnapshotOptions } from "./snapshot.ts";
import { diff } from "@std/internal/diff";
import { diffStr } from "@std/internal/diff-str";
import { buildMessage } from "@std/internal/build-message";

export function getErrorMessage(message: string, options: SnapshotOptions) {
  return typeof options.msg === "string" ? options.msg : message;
}

/**
 * Default serializer for `assertSnapshot`.
 *
 * @example Usage
 * ```ts
 * import { serialize } from "@std/testing/snapshot";
 * import { assertEquals } from "@std/assert";
 *
 * assertEquals(serialize({ foo: 42 }), "{\n  foo: 42,\n}")
 * ```
 *
 * @param actual The value to serialize
 * @returns The serialized string
 */
export function serialize(actual: unknown): string {
  return Deno.inspect(actual, {
    depth: Infinity,
    sorted: true,
    trailingComma: true,
    compact: false,
    iterableLimit: Infinity,
    strAbbreviateSize: Infinity,
    breakLength: Infinity,
    escapeSequences: false,
  }).replaceAll("\r", "\\r");
}

/**
 * Converts a string to a valid JavaScript string which can be wrapped in backticks.
 *
 * @example
 *
 * "special characters (\ ` $) will be escaped" -> "special characters (\\ \` \$) will be escaped"
 */
export function escapeStringForJs(str: string) {
  return str
    .replace(/\\/g, "\\\\")
    .replace(/`/g, "\\`")
    .replace(/\$/g, "\\$");
}

let _mode: SnapshotMode;
/**
 * Get the snapshot mode.
 */
export function getMode(options: SnapshotOptions) {
  if (options.mode) {
    return options.mode;
  } else if (_mode) {
    return _mode;
  } else {
    _mode = Deno.args.some((arg) => arg === "--update" || arg === "-u")
      ? "update"
      : "assert";
    return _mode;
  }
}

/**
 * Return `true` when snapshot mode is `update`.
 */
export function getIsUpdate(options: SnapshotOptions) {
  return getMode(options) === "update";
}

export function getOptions<T>(
  msgOrOpts?: string | T,
): T {
  if (msgOrOpts === undefined) return {} as T;

  if (typeof msgOrOpts === "object" && msgOrOpts !== null) {
    return msgOrOpts;
  }

  return { msg: msgOrOpts } as T;
}

export function getSnapshotNotMatchMessage(
  actualSnapshot: string,
  expectedSnapshot: string,
  options: SnapshotOptions,
) {
  const stringDiff = !actualSnapshot.includes("\n");
  const diffResult = stringDiff
    ? diffStr(actualSnapshot, expectedSnapshot)
    : diff(actualSnapshot.split("\n"), expectedSnapshot.split("\n"));
  const diffMsg = buildMessage(diffResult, { stringDiff }).join("\n");
  const message =
    `Snapshot does not match:\n${diffMsg}\nTo update snapshots, run\n    deno test --allow-read --allow-write [files]... -- --update\n`;
  return getErrorMessage(message, options);
}

// TODO (WWRS): Remove this when we drop support for Deno 1.x
export const LINT_SUPPORTED = !Deno.version.deno.startsWith("1.");