All files / testing / _snapshot_utils.ts

94.12% Branches 16/17
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
x29
x29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x24
x125
x125
x125
x125
x125
x125
x125
x125
x125
x125
x125
 
 
 
 
 
 
 
 
x24
x79
x79
x79
x79
x79
 
x24
 
 
 
x24
x136
x145
x136
x423
x337
x354
x354
x354
x354
x354
x136
 
 
 
 
x24
x136
x136
 
x24
x24
 
x129
 
x129
x237
x237
 
 
x129
 
x24
x24
x24
x24
 
x26
x26
x26
x26
x78
x26
x26
x26
x26
 
 
x24

















































































I




















// Copyright 2018-2025 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.");