swc/tests/deno-unit/console_test.ts
2020-07-02 13:10:44 +09:00

1178 lines
30 KiB
TypeScript

// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// TODO(ry) The unit test functions in this module are too coarse. They should
// be broken up into smaller bits.
// TODO(ry) These tests currentl strip all the ANSI colors out. We don't have a
// good way to control whether we produce color output or not since
// std/fmt/colors auto determines whether to put colors in or not. We need
// better infrastructure here so we can properly test the colors.
import { assert, assertEquals, unitTest } from "./test_util.ts";
import { stripColor } from "../../../std/fmt/colors.ts";
// Some of these APIs aren't exposed in the types and so we have to cast to any
// in order to "trick" TypeScript.
const {
inspect,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} = Deno as any;
const customInspect = Deno.customInspect;
const {
Console,
stringifyArgs,
// @ts-expect-error TypeScript (as of 3.7) does not support indexing namespaces by symbol
} = Deno[Deno.internal];
function stringify(...args: unknown[]): string {
return stripColor(stringifyArgs(args).replace(/\n$/, ""));
}
// test cases from web-platform-tests
// via https://github.com/web-platform-tests/wpt/blob/master/console/console-is-a-namespace.any.js
unitTest(function consoleShouldBeANamespace(): void {
const prototype1 = Object.getPrototypeOf(console);
const prototype2 = Object.getPrototypeOf(prototype1);
assertEquals(Object.getOwnPropertyNames(prototype1).length, 0);
assertEquals(prototype2, Object.prototype);
});
unitTest(function consoleHasRightInstance(): void {
assert(console instanceof Console);
assertEquals({} instanceof Console, false);
});
unitTest(function consoleTestAssertShouldNotThrowError(): void {
mockConsole((console) => {
console.assert(true);
let hasThrown = undefined;
try {
console.assert(false);
hasThrown = false;
} catch {
hasThrown = true;
}
assertEquals(hasThrown, false);
});
});
unitTest(function consoleTestStringifyComplexObjects(): void {
assertEquals(stringify("foo"), "foo");
assertEquals(stringify(["foo", "bar"]), `[ "foo", "bar" ]`);
assertEquals(stringify({ foo: "bar" }), `{ foo: "bar" }`);
});
unitTest(function consoleTestStringifyQuotes(): void {
assertEquals(stringify(["\\"]), `[ "\\\\" ]`);
assertEquals(stringify(['\\,"']), `[ '\\\\,"' ]`);
assertEquals(stringify([`\\,",'`]), `[ \`\\\\,",'\` ]`);
assertEquals(stringify(["\\,\",',`"]), `[ "\\\\,\\",',\`" ]`);
});
unitTest(function consoleTestStringifyLongStrings(): void {
const veryLongString = "a".repeat(200);
// If we stringify an object containing the long string, it gets abbreviated.
let actual = stringify({ veryLongString });
assert(actual.includes("..."));
assert(actual.length < 200);
// However if we stringify the string itself, we get it exactly.
actual = stringify(veryLongString);
assertEquals(actual, veryLongString);
});
/* eslint-disable @typescript-eslint/explicit-function-return-type */
unitTest(function consoleTestStringifyCircular(): void {
class Base {
a = 1;
m1() {}
}
class Extended extends Base {
b = 2;
m2() {}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const nestedObj: any = {
num: 1,
bool: true,
str: "a",
method() {},
async asyncMethod() {},
*generatorMethod() {},
un: undefined,
nu: null,
arrowFunc: () => {},
extendedClass: new Extended(),
nFunc: new Function(),
extendedCstr: Extended,
};
const circularObj = {
num: 2,
bool: false,
str: "b",
method() {},
un: undefined,
nu: null,
nested: nestedObj,
emptyObj: {},
arr: [1, "s", false, null, nestedObj],
baseClass: new Base(),
};
nestedObj.o = circularObj;
const nestedObjExpected = `{
num: 1,
bool: true,
str: "a",
method: [Function: method],
asyncMethod: [AsyncFunction: asyncMethod],
generatorMethod: [GeneratorFunction: generatorMethod],
un: undefined,
nu: null,
arrowFunc: [Function: arrowFunc],
extendedClass: Extended { a: 1, b: 2 },
nFunc: [Function],
extendedCstr: [Function: Extended],
o: {
num: 2,
bool: false,
str: "b",
method: [Function: method],
un: undefined,
nu: null,
nested: [Circular],
emptyObj: {},
arr: [ 1, "s", false, null, [Circular] ],
baseClass: Base { a: 1 }
}
}`;
assertEquals(stringify(1), "1");
assertEquals(stringify(-0), "-0");
assertEquals(stringify(1n), "1n");
assertEquals(stringify("s"), "s");
assertEquals(stringify(false), "false");
assertEquals(stringify(new Number(1)), "[Number: 1]");
assertEquals(stringify(new Boolean(true)), "[Boolean: true]");
assertEquals(stringify(new String("deno")), `[String: "deno"]`);
assertEquals(stringify(/[0-9]*/), "/[0-9]*/");
assertEquals(
stringify(new Date("2018-12-10T02:26:59.002Z")),
"2018-12-10T02:26:59.002Z"
);
assertEquals(stringify(new Set([1, 2, 3])), "Set { 1, 2, 3 }");
assertEquals(
stringify(
new Map([
[1, "one"],
[2, "two"],
])
),
`Map { 1 => "one", 2 => "two" }`
);
assertEquals(stringify(new WeakSet()), "WeakSet { [items unknown] }");
assertEquals(stringify(new WeakMap()), "WeakMap { [items unknown] }");
assertEquals(stringify(Symbol(1)), "Symbol(1)");
assertEquals(stringify(null), "null");
assertEquals(stringify(undefined), "undefined");
assertEquals(stringify(new Extended()), "Extended { a: 1, b: 2 }");
assertEquals(
stringify(function f(): void {}),
"[Function: f]"
);
assertEquals(
stringify(async function af(): Promise<void> {}),
"[AsyncFunction: af]"
);
assertEquals(
stringify(function* gf() {}),
"[GeneratorFunction: gf]"
);
assertEquals(
stringify(async function* agf() {}),
"[AsyncGeneratorFunction: agf]"
);
assertEquals(
stringify(new Uint8Array([1, 2, 3])),
"Uint8Array(3) [ 1, 2, 3 ]"
);
assertEquals(stringify(Uint8Array.prototype), "TypedArray {}");
assertEquals(
stringify({ a: { b: { c: { d: new Set([1]) } } } }),
"{ a: { b: { c: { d: [Set] } } } }"
);
assertEquals(stringify(nestedObj), nestedObjExpected);
assertEquals(stringify(JSON), 'JSON { Symbol(Symbol.toStringTag): "JSON" }');
assertEquals(
stringify(console),
`{
log: [Function],
debug: [Function],
info: [Function],
dir: [Function],
dirxml: [Function],
warn: [Function],
error: [Function],
assert: [Function],
count: [Function],
countReset: [Function],
table: [Function],
time: [Function],
timeLog: [Function],
timeEnd: [Function],
group: [Function],
groupCollapsed: [Function],
groupEnd: [Function],
clear: [Function],
trace: [Function],
indentLevel: 0,
Symbol(isConsoleInstance): true
}`
);
assertEquals(
stringify({ str: 1, [Symbol.for("sym")]: 2, [Symbol.toStringTag]: "TAG" }),
'TAG { str: 1, Symbol(sym): 2, Symbol(Symbol.toStringTag): "TAG" }'
);
// test inspect is working the same
assertEquals(stripColor(inspect(nestedObj)), nestedObjExpected);
});
/* eslint-enable @typescript-eslint/explicit-function-return-type */
unitTest(function consoleTestStringifyWithDepth(): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const nestedObj: any = { a: { b: { c: { d: { e: { f: 42 } } } } } };
assertEquals(
stripColor(stringifyArgs([nestedObj], { depth: 3 })),
"{ a: { b: { c: [Object] } } }"
);
assertEquals(
stripColor(stringifyArgs([nestedObj], { depth: 4 })),
"{ a: { b: { c: { d: [Object] } } } }"
);
assertEquals(
stripColor(stringifyArgs([nestedObj], { depth: 0 })),
"[Object]"
);
assertEquals(
stripColor(stringifyArgs([nestedObj])),
"{ a: { b: { c: { d: [Object] } } } }"
);
// test inspect is working the same way
assertEquals(
stripColor(inspect(nestedObj, { depth: 4 })),
"{ a: { b: { c: { d: [Object] } } } }"
);
});
unitTest(function consoleTestStringifyLargeObject(): void {
const obj = {
a: 2,
o: {
a: "1",
b: "2",
c: "3",
d: "4",
e: "5",
f: "6",
g: 10,
asd: 2,
asda: 3,
x: { a: "asd", x: 3 },
},
};
assertEquals(
stringify(obj),
`{
a: 2,
o: {
a: "1",
b: "2",
c: "3",
d: "4",
e: "5",
f: "6",
g: 10,
asd: 2,
asda: 3,
x: { a: "asd", x: 3 }
}
}`
);
});
unitTest(function consoleTestStringifyIterable() {
const shortArray = [1, 2, 3, 4, 5];
assertEquals(stringify(shortArray), "[ 1, 2, 3, 4, 5 ]");
const longArray = new Array(200).fill(0);
assertEquals(
stringify(longArray),
`[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
... 100 more items
]`
);
const obj = { a: "a", longArray };
assertEquals(
stringify(obj),
`{
a: "a",
longArray: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
... 100 more items
]
}`
);
const shortMap = new Map([
["a", 0],
["b", 1],
]);
assertEquals(stringify(shortMap), `Map { "a" => 0, "b" => 1 }`);
const longMap = new Map();
for (const key of Array(200).keys()) {
longMap.set(`${key}`, key);
}
assertEquals(
stringify(longMap),
`Map {
"0" => 0,
"1" => 1,
"2" => 2,
"3" => 3,
"4" => 4,
"5" => 5,
"6" => 6,
"7" => 7,
"8" => 8,
"9" => 9,
"10" => 10,
"11" => 11,
"12" => 12,
"13" => 13,
"14" => 14,
"15" => 15,
"16" => 16,
"17" => 17,
"18" => 18,
"19" => 19,
"20" => 20,
"21" => 21,
"22" => 22,
"23" => 23,
"24" => 24,
"25" => 25,
"26" => 26,
"27" => 27,
"28" => 28,
"29" => 29,
"30" => 30,
"31" => 31,
"32" => 32,
"33" => 33,
"34" => 34,
"35" => 35,
"36" => 36,
"37" => 37,
"38" => 38,
"39" => 39,
"40" => 40,
"41" => 41,
"42" => 42,
"43" => 43,
"44" => 44,
"45" => 45,
"46" => 46,
"47" => 47,
"48" => 48,
"49" => 49,
"50" => 50,
"51" => 51,
"52" => 52,
"53" => 53,
"54" => 54,
"55" => 55,
"56" => 56,
"57" => 57,
"58" => 58,
"59" => 59,
"60" => 60,
"61" => 61,
"62" => 62,
"63" => 63,
"64" => 64,
"65" => 65,
"66" => 66,
"67" => 67,
"68" => 68,
"69" => 69,
"70" => 70,
"71" => 71,
"72" => 72,
"73" => 73,
"74" => 74,
"75" => 75,
"76" => 76,
"77" => 77,
"78" => 78,
"79" => 79,
"80" => 80,
"81" => 81,
"82" => 82,
"83" => 83,
"84" => 84,
"85" => 85,
"86" => 86,
"87" => 87,
"88" => 88,
"89" => 89,
"90" => 90,
"91" => 91,
"92" => 92,
"93" => 93,
"94" => 94,
"95" => 95,
"96" => 96,
"97" => 97,
"98" => 98,
"99" => 99,
... 100 more items
}`
);
const shortSet = new Set([1, 2, 3]);
assertEquals(stringify(shortSet), `Set { 1, 2, 3 }`);
const longSet = new Set();
for (const key of Array(200).keys()) {
longSet.add(key);
}
assertEquals(
stringify(longSet),
`Set {
0,
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 more items
}`
);
const withEmptyEl = Array(10);
withEmptyEl.fill(0, 4, 6);
assertEquals(
stringify(withEmptyEl),
`[ <4 empty items>, 0, 0, <4 empty items> ]`
);
/* TODO(ry) Fix this test
const lWithEmptyEl = Array(200);
lWithEmptyEl.fill(0, 50, 80);
assertEquals(
stringify(lWithEmptyEl),
`[
<50 empty items>, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, <120 empty items>
]`
);
*/
});
unitTest(async function consoleTestStringifyPromises(): Promise<void> {
const pendingPromise = new Promise((_res, _rej) => {});
assertEquals(stringify(pendingPromise), "Promise { <pending> }");
const resolvedPromise = new Promise((res, _rej) => {
res("Resolved!");
});
assertEquals(stringify(resolvedPromise), `Promise { "Resolved!" }`);
let rejectedPromise;
try {
rejectedPromise = new Promise((_, rej) => {
rej(Error("Whoops"));
});
await rejectedPromise;
} catch (err) {
// pass
}
const strLines = stringify(rejectedPromise).split("\n");
assertEquals(strLines[0], "Promise {");
assertEquals(strLines[1], " <rejected> Error: Whoops");
});
unitTest(function consoleTestWithCustomInspector(): void {
class A {
[customInspect](): string {
return "b";
}
}
assertEquals(stringify(new A()), "b");
});
unitTest(function consoleTestWithCustomInspectorError(): void {
class A {
[customInspect](): string {
throw new Error("BOOM");
return "b";
}
}
assertEquals(stringify(new A()), "A {}");
class B {
constructor(public field: { a: string }) {}
[customInspect](): string {
return this.field.a;
}
}
assertEquals(stringify(new B({ a: "a" })), "a");
assertEquals(
stringify(B.prototype),
"{ Symbol(Deno.symbols.customInspect): [Function: [Deno.symbols.customInspect]] }"
);
});
unitTest(function consoleTestWithIntegerFormatSpecifier(): void {
assertEquals(stringify("%i"), "%i");
assertEquals(stringify("%i", 42.0), "42");
assertEquals(stringify("%i", 42), "42");
assertEquals(stringify("%i", "42"), "42");
assertEquals(stringify("%i", "42.0"), "42");
assertEquals(stringify("%i", 1.5), "1");
assertEquals(stringify("%i", -0.5), "0");
assertEquals(stringify("%i", ""), "NaN");
assertEquals(stringify("%i", Symbol()), "NaN");
assertEquals(stringify("%i %d", 42, 43), "42 43");
assertEquals(stringify("%d %i", 42), "42 %i");
assertEquals(stringify("%d", 12345678901234567890123), "1");
assertEquals(
stringify("%i", 12345678901234567890123n),
"12345678901234567890123n"
);
});
unitTest(function consoleTestWithFloatFormatSpecifier(): void {
assertEquals(stringify("%f"), "%f");
assertEquals(stringify("%f", 42.0), "42");
assertEquals(stringify("%f", 42), "42");
assertEquals(stringify("%f", "42"), "42");
assertEquals(stringify("%f", "42.0"), "42");
assertEquals(stringify("%f", 1.5), "1.5");
assertEquals(stringify("%f", -0.5), "-0.5");
assertEquals(stringify("%f", Math.PI), "3.141592653589793");
assertEquals(stringify("%f", ""), "NaN");
assertEquals(stringify("%f", Symbol("foo")), "NaN");
assertEquals(stringify("%f", 5n), "5");
assertEquals(stringify("%f %f", 42, 43), "42 43");
assertEquals(stringify("%f %f", 42), "42 %f");
});
unitTest(function consoleTestWithStringFormatSpecifier(): void {
assertEquals(stringify("%s"), "%s");
assertEquals(stringify("%s", undefined), "undefined");
assertEquals(stringify("%s", "foo"), "foo");
assertEquals(stringify("%s", 42), "42");
assertEquals(stringify("%s", "42"), "42");
assertEquals(stringify("%s %s", 42, 43), "42 43");
assertEquals(stringify("%s %s", 42), "42 %s");
assertEquals(stringify("%s", Symbol("foo")), "Symbol(foo)");
});
unitTest(function consoleTestWithObjectFormatSpecifier(): void {
assertEquals(stringify("%o"), "%o");
assertEquals(stringify("%o", 42), "42");
assertEquals(stringify("%o", "foo"), "foo");
assertEquals(stringify("o: %o, a: %O", {}, []), "o: {}, a: []");
assertEquals(stringify("%o", { a: 42 }), "{ a: 42 }");
assertEquals(
stringify("%o", { a: { b: { c: { d: new Set([1]) } } } }),
"{ a: { b: { c: { d: [Set] } } } }"
);
});
unitTest(function consoleTestWithVariousOrInvalidFormatSpecifier(): void {
assertEquals(stringify("%s:%s"), "%s:%s");
assertEquals(stringify("%i:%i"), "%i:%i");
assertEquals(stringify("%d:%d"), "%d:%d");
assertEquals(stringify("%%s%s", "foo"), "%sfoo");
assertEquals(stringify("%s:%s", undefined), "undefined:%s");
assertEquals(stringify("%s:%s", "foo", "bar"), "foo:bar");
assertEquals(stringify("%s:%s", "foo", "bar", "baz"), "foo:bar baz");
assertEquals(stringify("%%%s%%", "hi"), "%hi%");
assertEquals(stringify("%d:%d", 12), "12:%d");
assertEquals(stringify("%i:%i", 12), "12:%i");
assertEquals(stringify("%f:%f", 12), "12:%f");
assertEquals(stringify("o: %o, a: %o", {}), "o: {}, a: %o");
assertEquals(stringify("abc%", 1), "abc% 1");
});
unitTest(function consoleTestCallToStringOnLabel(): void {
const methods = ["count", "countReset", "time", "timeLog", "timeEnd"];
mockConsole((console) => {
for (const method of methods) {
let hasCalled = false;
console[method]({
toString(): void {
hasCalled = true;
},
});
assertEquals(hasCalled, true);
}
});
});
unitTest(function consoleTestError(): void {
class MyError extends Error {
constructor(errStr: string) {
super(errStr);
this.name = "MyError";
}
}
try {
throw new MyError("This is an error");
} catch (e) {
assert(
stringify(e)
.split("\n")[0] // error has been caught
.includes("MyError: This is an error")
);
}
});
unitTest(function consoleTestClear(): void {
mockConsole((console, out) => {
console.clear();
assertEquals(out.toString(), "\x1b[1;1H" + "\x1b[0J");
});
});
// Test bound this issue
unitTest(function consoleDetachedLog(): void {
mockConsole((console) => {
const log = console.log;
const dir = console.dir;
const dirxml = console.dirxml;
const debug = console.debug;
const info = console.info;
const warn = console.warn;
const error = console.error;
const consoleAssert = console.assert;
const consoleCount = console.count;
const consoleCountReset = console.countReset;
const consoleTable = console.table;
const consoleTime = console.time;
const consoleTimeLog = console.timeLog;
const consoleTimeEnd = console.timeEnd;
const consoleGroup = console.group;
const consoleGroupEnd = console.groupEnd;
const consoleClear = console.clear;
log("Hello world");
dir("Hello world");
dirxml("Hello world");
debug("Hello world");
info("Hello world");
warn("Hello world");
error("Hello world");
consoleAssert(true);
consoleCount("Hello world");
consoleCountReset("Hello world");
consoleTable({ test: "Hello world" });
consoleTime("Hello world");
consoleTimeLog("Hello world");
consoleTimeEnd("Hello world");
consoleGroup("Hello world");
consoleGroupEnd();
consoleClear();
});
});
class StringBuffer {
chunks: string[] = [];
add(x: string): void {
this.chunks.push(x);
}
toString(): string {
return this.chunks.join("");
}
}
type ConsoleExamineFunc = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
csl: any,
out: StringBuffer,
err?: StringBuffer,
both?: StringBuffer
) => void;
function mockConsole(f: ConsoleExamineFunc): void {
const out = new StringBuffer();
const err = new StringBuffer();
const both = new StringBuffer();
const csl = new Console(
(x: string, isErr: boolean, printsNewLine: boolean): void => {
const content = x + (printsNewLine ? "\n" : "");
const buf = isErr ? err : out;
buf.add(content);
both.add(content);
}
);
f(csl, out, err, both);
}
// console.group test
unitTest(function consoleGroup(): void {
mockConsole((console, out): void => {
console.group("1");
console.log("2");
console.group("3");
console.log("4");
console.groupEnd();
console.groupEnd();
console.log("5");
console.log("6");
assertEquals(
out.toString(),
`1
2
3
4
5
6
`
);
});
});
// console.group with console.warn test
unitTest(function consoleGroupWarn(): void {
mockConsole((console, _out, _err, both): void => {
assert(both);
console.warn("1");
console.group();
console.warn("2");
console.group();
console.warn("3");
console.groupEnd();
console.warn("4");
console.groupEnd();
console.warn("5");
console.warn("6");
console.warn("7");
assertEquals(
both.toString(),
`1
2
3
4
5
6
7
`
);
});
});
// console.table test
unitTest(function consoleTable(): void {
mockConsole((console, out): void => {
console.table({ a: "test", b: 1 });
assertEquals(
stripColor(out.toString()),
`┌───────┬────────┐
│ (idx) │ Values │
├───────┼────────┤
│ a │ "test" │
│ b │ 1 │
└───────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table({ a: { b: 10 }, b: { b: 20, c: 30 } }, ["c"]);
assertEquals(
stripColor(out.toString()),
`┌───────┬────┐
│ (idx) │ c │
├───────┼────┤
│ a │ │
│ b │ 30 │
└───────┴────┘
`
);
});
mockConsole((console, out): void => {
console.table([1, 2, [3, [4]], [5, 6], [[7], [8]]]);
assertEquals(
stripColor(out.toString()),
`┌───────┬───────┬───────┬────────┐
│ (idx) │ 0 │ 1 │ Values │
├───────┼───────┼───────┼────────┤
│ 0 │ │ │ 1 │
│ 1 │ │ │ 2 │
│ 2 │ 3 │ [ 4 ] │ │
│ 3 │ 5 │ 6 │ │
│ 4 │ [ 7 ] │ [ 8 ] │ │
└───────┴───────┴───────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table(new Set([1, 2, 3, "test"]));
assertEquals(
stripColor(out.toString()),
`┌────────────┬────────┐
│ (iter idx) │ Values │
├────────────┼────────┤
│ 0 │ 1 │
│ 1 │ 2 │
│ 2 │ 3 │
│ 3 │ "test" │
└────────────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table(
new Map([
[1, "one"],
[2, "two"],
])
);
assertEquals(
stripColor(out.toString()),
`┌────────────┬─────┬────────┐
│ (iter idx) │ Key │ Values │
├────────────┼─────┼────────┤
│ 0 │ 1 │ "one" │
│ 1 │ 2 │ "two" │
└────────────┴─────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table({
a: true,
b: { c: { d: 10 }, e: [1, 2, [5, 6]] },
f: "test",
g: new Set([1, 2, 3, "test"]),
h: new Map([[1, "one"]]),
});
assertEquals(
stripColor(out.toString()),
`┌───────┬───────────┬───────────────────┬────────┐
│ (idx) │ c │ e │ Values │
├───────┼───────────┼───────────────────┼────────┤
│ a │ │ │ true │
│ b │ { d: 10 } │ [ 1, 2, [Array] ] │ │
│ f │ │ │ "test" │
│ g │ │ │ │
│ h │ │ │ │
└───────┴───────────┴───────────────────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table([
1,
"test",
false,
{ a: 10 },
["test", { b: 20, c: "test" }],
]);
assertEquals(
stripColor(out.toString()),
`┌───────┬────────┬──────────────────────┬────┬────────┐
│ (idx) │ 0 │ 1 │ a │ Values │
├───────┼────────┼──────────────────────┼────┼────────┤
│ 0 │ │ │ │ 1 │
│ 1 │ │ │ │ "test" │
│ 2 │ │ │ │ false │
│ 3 │ │ │ 10 │ │
│ 4 │ "test" │ { b: 20, c: "test" } │ │ │
└───────┴────────┴──────────────────────┴────┴────────┘
`
);
});
mockConsole((console, out): void => {
console.table([]);
assertEquals(
stripColor(out.toString()),
`┌───────┐
│ (idx) │
├───────┤
└───────┘
`
);
});
mockConsole((console, out): void => {
console.table({});
assertEquals(
stripColor(out.toString()),
`┌───────┐
│ (idx) │
├───────┤
└───────┘
`
);
});
mockConsole((console, out): void => {
console.table(new Set());
assertEquals(
stripColor(out.toString()),
`┌────────────┐
│ (iter idx) │
├────────────┤
└────────────┘
`
);
});
mockConsole((console, out): void => {
console.table(new Map());
assertEquals(
stripColor(out.toString()),
`┌────────────┐
│ (iter idx) │
├────────────┤
└────────────┘
`
);
});
mockConsole((console, out): void => {
console.table("test");
assertEquals(out.toString(), "test\n");
});
mockConsole((console, out): void => {
console.table(["Hello", "你好", "Amapá"]);
assertEquals(
stripColor(out.toString()),
`┌───────┬─────────┐
│ (idx) │ Values │
├───────┼─────────┤
│ 0 │ "Hello" │
│ 1 │ "你好" │
│ 2 │ "Amapá" │
└───────┴─────────┘
`
);
});
mockConsole((console, out): void => {
console.table([
[1, 2],
[3, 4],
]);
assertEquals(
stripColor(out.toString()),
`┌───────┬───┬───┐
│ (idx) │ 0 │ 1 │
├───────┼───┼───┤
│ 0 │ 1 │ 2 │
│ 1 │ 3 │ 4 │
└───────┴───┴───┘
`
);
});
mockConsole((console, out): void => {
console.table({ 1: { a: 4, b: 5 }, 2: null, 3: { b: 6, c: 7 } }, ["b"]);
assertEquals(
stripColor(out.toString()),
`┌───────┬───┐
│ (idx) │ b │
├───────┼───┤
│ 1 │ 5 │
│ 2 │ │
│ 3 │ 6 │
└───────┴───┘
`
);
});
});
// console.log(Error) test
unitTest(function consoleLogShouldNotThrowError(): void {
mockConsole((console) => {
let result = 0;
try {
console.log(new Error("foo"));
result = 1;
} catch (e) {
result = 2;
}
assertEquals(result, 1);
});
// output errors to the console should not include "Uncaught"
mockConsole((console, out): void => {
console.log(new Error("foo"));
assertEquals(out.toString().includes("Uncaught"), false);
});
});
// console.log(Invalid Date) test
unitTest(function consoleLogShoultNotThrowErrorWhenInvalidDateIsPassed(): void {
mockConsole((console, out) => {
const invalidDate = new Date("test");
console.log(invalidDate);
assertEquals(stripColor(out.toString()), "Invalid Date\n");
});
});
// console.dir test
unitTest(function consoleDir(): void {
mockConsole((console, out): void => {
console.dir("DIR");
assertEquals(out.toString(), "DIR\n");
});
mockConsole((console, out): void => {
console.dir("DIR", { indentLevel: 2 });
assertEquals(out.toString(), " DIR\n");
});
});
// console.dir test
unitTest(function consoleDirXml(): void {
mockConsole((console, out): void => {
console.dirxml("DIRXML");
assertEquals(out.toString(), "DIRXML\n");
});
mockConsole((console, out): void => {
console.dirxml("DIRXML", { indentLevel: 2 });
assertEquals(out.toString(), " DIRXML\n");
});
});
// console.trace test
unitTest(function consoleTrace(): void {
mockConsole((console, _out, err): void => {
console.trace("%s", "custom message");
assert(err);
assert(err.toString().includes("Trace: custom message"));
});
});