diff --git a/std/testing/asserts.ts b/std/testing/asserts.ts index 6dd3af226e..d3f8bb6784 100644 --- a/std/testing/asserts.ts +++ b/std/testing/asserts.ts @@ -156,7 +156,8 @@ export function assertEquals( actualString.split("\n"), expectedString.split("\n") ); - message = buildMessage(diffResult).join("\n"); + const diffMsg = buildMessage(diffResult).join("\n"); + message = `Values are not equal:\n${diffMsg}`; } catch (e) { message = `\n${red(CAN_NOT_DISPLAY)} + \n\n`; } @@ -205,24 +206,41 @@ export function assertStrictEq( expected: unknown, msg?: string ): void { - if (actual !== expected) { - let actualString: string; - let expectedString: string; - try { - actualString = String(actual); - } catch (e) { - actualString = "[Cannot display]"; - } - try { - expectedString = String(expected); - } catch (e) { - expectedString = "[Cannot display]"; - } - if (!msg) { - msg = `actual: ${actualString} expected: ${expectedString}`; - } - throw new AssertionError(msg); + if (actual === expected) { + return; } + + let message: string; + + if (msg) { + message = msg; + } else { + const actualString = format(actual); + const expectedString = format(expected); + + if (actualString === expectedString) { + const withOffset = actualString + .split("\n") + .map((l) => ` ${l}`) + .join("\n"); + message = `Values have the same structure but are not reference-equal:\n\n${red( + withOffset + )}\n`; + } else { + try { + const diffResult = diff( + actualString.split("\n"), + expectedString.split("\n") + ); + const diffMsg = buildMessage(diffResult).join("\n"); + message = `Values are not strictly equal:\n${diffMsg}`; + } catch (e) { + message = `\n${red(CAN_NOT_DISPLAY)} + \n\n`; + } + } + } + + throw new AssertionError(message); } /** diff --git a/std/testing/asserts_test.ts b/std/testing/asserts_test.ts index 65081767c0..1b0f6dd5fb 100644 --- a/std/testing/asserts_test.ts +++ b/std/testing/asserts_test.ts @@ -7,6 +7,7 @@ import { assertArrayContains, assertMatch, assertEquals, + assertStrictEq, assertThrows, AssertionError, equal, @@ -278,7 +279,13 @@ test({ assertThrows( (): void => assertEquals(1, 2), AssertionError, - [...createHeader(), removed(`- 1`), added(`+ 2`), ""].join("\n") + [ + "Values are not equal:", + ...createHeader(), + removed(`- 1`), + added(`+ 2`), + "", + ].join("\n") ); }, }); @@ -289,7 +296,12 @@ test({ assertThrows( (): void => assertEquals(1, "1"), AssertionError, - [...createHeader(), removed(`- 1`), added(`+ "1"`)].join("\n") + [ + "Values are not equal:", + ...createHeader(), + removed(`- 1`), + added(`+ "1"`), + ].join("\n") ); }, }); @@ -301,6 +313,7 @@ test({ (): void => assertEquals([1, "2", 3], ["1", "2", 3]), AssertionError, [ + "Values are not equal:", ...createHeader(), removed(`- [ 1, "2", 3 ]`), added(`+ [ "1", "2", 3 ]`), @@ -317,6 +330,7 @@ test({ (): void => assertEquals({ a: 1, b: "2", c: 3 }, { a: 1, b: 2, c: [3] }), AssertionError, [ + "Values are not equal:", ...createHeader(), removed(`- { a: 1, b: "2", c: 3 }`), added(`+ { a: 1, b: 2, c: [ 3 ] }`), @@ -325,3 +339,51 @@ test({ ); }, }); + +test({ + name: "strict pass case", + fn(): void { + assertStrictEq(true, true); + assertStrictEq(10, 10); + assertStrictEq("abc", "abc"); + + const xs = [1, false, "foo"]; + const ys = xs; + assertStrictEq(xs, ys); + + const x = { a: 1 }; + const y = x; + assertStrictEq(x, y); + }, +}); + +test({ + name: "strict failed with structure diff", + fn(): void { + assertThrows( + (): void => assertStrictEq({ a: 1, b: 2 }, { a: 1, c: [3] }), + AssertionError, + [ + "Values are not strictly equal:", + ...createHeader(), + removed("- { a: 1, b: 2 }"), + added("+ { a: 1, c: [ 3 ] }"), + "", + ].join("\n") + ); + }, +}); + +test({ + name: "strict failed with reference diff", + fn(): void { + assertThrows( + (): void => assertStrictEq({ a: 1, b: 2 }, { a: 1, b: 2 }), + AssertionError, + [ + "Values have the same structure but are not reference-equal:\n", + red(" { a: 1, b: 2 }"), + ].join("\n") + ); + }, +});