summaryrefslogtreecommitdiff
path: root/testing/format.ts
diff options
context:
space:
mode:
Diffstat (limited to 'testing/format.ts')
-rw-r--r--testing/format.ts303
1 files changed, 158 insertions, 145 deletions
diff --git a/testing/format.ts b/testing/format.ts
index 8434db1c2..9a8b02ac6 100644
--- a/testing/format.ts
+++ b/testing/format.ts
@@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*
*/
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Refs = any[];
export type Optional<T> = { [K in keyof T]?: T[K] };
@@ -32,7 +33,7 @@ export interface Config {
}
export type Printer = (
- val: any,
+ val: unknown,
config: Config,
indentation: string,
depth: number,
@@ -66,12 +67,15 @@ interface BasicValueOptions {
* Explicitly comparing typeof constructor to function avoids undefined as name
* when mock identity-obj-proxy returns the key as the value for any key.
*/
-const getConstructorName = (val: new (...args: any[]) => any) =>
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const getConstructorName = (val: new (...args: any[]) => any): string =>
(typeof val.constructor === "function" && val.constructor.name) || "Object";
/* global window */
/** Is val is equal to global window object? Works even if it does not exist :) */
-const isWindow = (val: any) => typeof window !== "undefined" && val === window;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const isWindow = (val: any): val is Window =>
+ typeof window !== "undefined" && val === window;
const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
@@ -116,11 +120,12 @@ function printError(val: Error): string {
* data-types in JS.
*/
function printBasicValue(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
val: any,
{ printFunctionName, escapeRegex, escapeString }: BasicValueOptions
): string | null {
if (val === true || val === false) {
- return "" + val;
+ return String(val);
}
if (val === undefined) {
return "undefined";
@@ -136,9 +141,9 @@ function printBasicValue(
}
if (typeOf === "string") {
if (escapeString) {
- return '"' + val.replace(/"|\\/g, "\\$&") + '"';
+ return `"${val.replace(/"|\\/g, "\\$&")}"`;
}
- return '"' + val + '"';
+ return `"${val}"`;
}
if (typeOf === "function") {
return printFunction(val, printFunctionName);
@@ -185,95 +190,8 @@ function printBasicValue(
return null;
}
-/**
- * Handles more complex objects ( such as objects with circular references.
- * maps and sets etc )
- */
-function printComplexValue(
- val: any,
- config: Config,
- indentation: string,
- depth: number,
- refs: Refs,
- hasCalledToJSON?: boolean
-): string {
- if (refs.indexOf(val) !== -1) {
- return "[Circular]";
- }
- refs = refs.slice();
- refs.push(val);
-
- const hitMaxDepth = ++depth > config.maxDepth;
- const { min, callToJSON } = config;
-
- if (
- callToJSON &&
- !hitMaxDepth &&
- val.toJSON &&
- typeof val.toJSON === "function" &&
- !hasCalledToJSON
- ) {
- return printer(val.toJSON(), config, indentation, depth, refs, true);
- }
-
- const toStringed = toString.call(val);
- if (toStringed === "[object Arguments]") {
- return hitMaxDepth
- ? "[Arguments]"
- : (min ? "" : "Arguments ") +
- "[" +
- printListItems(val, config, indentation, depth, refs, printer) +
- "]";
- }
- if (isToStringedArrayType(toStringed)) {
- return hitMaxDepth
- ? "[" + val.constructor.name + "]"
- : (min ? "" : val.constructor.name + " ") +
- "[" +
- printListItems(val, config, indentation, depth, refs, printer) +
- "]";
- }
- if (toStringed === "[object Map]") {
- return hitMaxDepth
- ? "[Map]"
- : "Map {" +
- printIteratorEntries(
- val.entries(),
- config,
- indentation,
- depth,
- refs,
- printer,
- " => "
- ) +
- "}";
- }
- if (toStringed === "[object Set]") {
- return hitMaxDepth
- ? "[Set]"
- : "Set {" +
- printIteratorValues(
- val.values(),
- config,
- indentation,
- depth,
- refs,
- printer
- ) +
- "}";
- }
-
- // Avoid failure to serialize global window object in jsdom test environment.
- // For example, not even relevant if window is prop of React element.
- return hitMaxDepth || isWindow(val)
- ? "[" + getConstructorName(val) + "]"
- : (min ? "" : getConstructorName(val) + " ") +
- "{" +
- printObjectProperties(val, config, indentation, depth, refs, printer) +
- "}";
-}
-
function printer(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
val: any,
config: Config,
indentation: string,
@@ -285,6 +203,7 @@ function printer(
if (basicResult !== null) {
return basicResult;
}
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
return printComplexValue(
val,
config,
@@ -295,30 +214,44 @@ function printer(
);
}
-const getConfig = (options: Options): Config => ({
- ...options,
- indent: options.min ? "" : createIndent(options.indent),
- spacingInner: options.min ? " " : "\n",
- spacingOuter: options.min ? "" : "\n"
-});
+/**
+ * Return items (for example, of an array)
+ * with spacing, indentation, and comma
+ * without surrounding punctuation (for example, brackets)
+ */
+function printListItems(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ list: any,
+ config: Config,
+ indentation: string,
+ depth: number,
+ refs: Refs,
+ printer: Printer
+): string {
+ let result = "";
-function createIndent(indent: number): string {
- return new Array(indent + 1).join(" ");
-}
+ if (list.length) {
+ result += config.spacingOuter;
-const getKeysOfEnumerableProperties = (object: {}) => {
- const keys: Array<string | symbol> = Object.keys(object).sort();
+ const indentationNext = indentation + config.indent;
- if (Object.getOwnPropertySymbols) {
- Object.getOwnPropertySymbols(object).forEach(symbol => {
- if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {
- keys.push(symbol);
+ for (let i = 0; i < list.length; i++) {
+ result +=
+ indentationNext +
+ printer(list[i], config, indentationNext, depth, refs);
+
+ if (i < list.length - 1) {
+ result += "," + config.spacingInner;
+ } else if (!config.min) {
+ result += ",";
}
- });
+ }
+
+ result += config.spacingOuter + indentation;
}
- return keys;
-};
+ return result;
+}
/**
* Return entries (for example, of a map)
@@ -326,6 +259,7 @@ const getKeysOfEnumerableProperties = (object: {}) => {
* without surrounding punctuation (for example, braces)
*/
function printIteratorEntries(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
iterator: any,
config: Config,
indentation: string,
@@ -384,6 +318,7 @@ function printIteratorEntries(
* without surrounding punctuation (braces or brackets)
*/
function printIteratorValues(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
iterator: Iterator<any>,
config: Config,
indentation: string,
@@ -419,43 +354,19 @@ function printIteratorValues(
return result;
}
-/**
- * Return items (for example, of an array)
- * with spacing, indentation, and comma
- * without surrounding punctuation (for example, brackets)
- */
-function printListItems(
- list: any,
- config: Config,
- indentation: string,
- depth: number,
- refs: Refs,
- printer: Printer
-): string {
- let result = "";
-
- if (list.length) {
- result += config.spacingOuter;
-
- const indentationNext = indentation + config.indent;
-
- for (let i = 0; i < list.length; i++) {
- result +=
- indentationNext +
- printer(list[i], config, indentationNext, depth, refs);
+const getKeysOfEnumerableProperties = (object: {}): Array<string | symbol> => {
+ const keys: Array<string | symbol> = Object.keys(object).sort();
- if (i < list.length - 1) {
- result += "," + config.spacingInner;
- } else if (!config.min) {
- result += ",";
+ if (Object.getOwnPropertySymbols) {
+ Object.getOwnPropertySymbols(object).forEach(symbol => {
+ if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {
+ keys.push(symbol);
}
- }
-
- result += config.spacingOuter + indentation;
+ });
}
- return result;
-}
+ return keys;
+};
/**
* Return properties of an object
@@ -505,10 +416,112 @@ function printObjectProperties(
}
/**
+ * Handles more complex objects ( such as objects with circular references.
+ * maps and sets etc )
+ */
+function printComplexValue(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ val: any,
+ config: Config,
+ indentation: string,
+ depth: number,
+ refs: Refs,
+ hasCalledToJSON?: boolean
+): string {
+ if (refs.indexOf(val) !== -1) {
+ return "[Circular]";
+ }
+ refs = refs.slice();
+ refs.push(val);
+
+ const hitMaxDepth = ++depth > config.maxDepth;
+ const { min, callToJSON } = config;
+
+ if (
+ callToJSON &&
+ !hitMaxDepth &&
+ val.toJSON &&
+ typeof val.toJSON === "function" &&
+ !hasCalledToJSON
+ ) {
+ return printer(val.toJSON(), config, indentation, depth, refs, true);
+ }
+
+ const toStringed = toString.call(val);
+ if (toStringed === "[object Arguments]") {
+ return hitMaxDepth
+ ? "[Arguments]"
+ : (min ? "" : "Arguments ") +
+ "[" +
+ printListItems(val, config, indentation, depth, refs, printer) +
+ "]";
+ }
+ if (isToStringedArrayType(toStringed)) {
+ return hitMaxDepth
+ ? `[${val.constructor.name}]`
+ : (min ? "" : `${val.constructor.name} `) +
+ "[" +
+ printListItems(val, config, indentation, depth, refs, printer) +
+ "]";
+ }
+ if (toStringed === "[object Map]") {
+ return hitMaxDepth
+ ? "[Map]"
+ : "Map {" +
+ printIteratorEntries(
+ val.entries(),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer,
+ " => "
+ ) +
+ "}";
+ }
+ if (toStringed === "[object Set]") {
+ return hitMaxDepth
+ ? "[Set]"
+ : "Set {" +
+ printIteratorValues(
+ val.values(),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer
+ ) +
+ "}";
+ }
+
+ // Avoid failure to serialize global window object in jsdom test environment.
+ // For example, not even relevant if window is prop of React element.
+ return hitMaxDepth || isWindow(val)
+ ? "[" + getConstructorName(val) + "]"
+ : (min ? "" : getConstructorName(val) + " ") +
+ "{" +
+ printObjectProperties(val, config, indentation, depth, refs, printer) +
+ "}";
+}
+
+// TODO this is better done with `.padStart()`
+function createIndent(indent: number): string {
+ return new Array(indent + 1).join(" ");
+}
+
+const getConfig = (options: Options): Config => ({
+ ...options,
+ indent: options.min ? "" : createIndent(options.indent),
+ spacingInner: options.min ? " " : "\n",
+ spacingOuter: options.min ? "" : "\n"
+});
+
+/**
* Returns a presentation string of your `val` object
* @param val any potential JavaScript object
* @param options Custom settings
*/
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function format(val: any, options: Optional<Options> = {}): string {
const opts = Object.keys(DEFAULT_OPTIONS).reduce(
(acc: Options, k: keyof Options) => {