Implement toMatchSnapshot() (#2294)

* buggy snapshot

* error output for failed snapshot

* missing first

* hints

* open dir once, better cleanup

* update flag

* truncate on update

* object and class snapshot formatting

* array formatting

* no function name, single item is empty array

* string objects, maps, sets, promise

* avoid using invalid memory

* handle number objects

* handle extending `Number`

* boolean objects

* snapshot tests and test updates

* snapshot format for buffers

* safer snapshot parsing

* property matchers setup

* strings and tests

* generate classes with empty prototype

* optional `propertyMatchers` parameter

* new test folder structure

* strings.eqlLong

* globalObject.throwPretty() and expect.any tests

* add updateSnapshot flag to help

* move snapshot format out of `printErrorlikeObject`

* empty object snapshot format

* separate typed array, remove trailing comma

* use `isCell`, object trailing commas

* handle unicode

* todo for primitive constructors

* switch to `JSC.Node.Syscall.open` and `JSC.Maybe`

* use js parser for snapshot files

* deinit ast, log parse error

* copy/paste most of `exports.ZigConsoleClient`

* remove snapshot option

* remove ordered properties option

* remove snapshot format option from `exports.zig`

* remove extra newlines

* change mode

* update test runner output

* escape backticks faster

* `bunx jest` in temp dir

* remove buffered writer

* add `toMatchSnapshot` to types

* cleanup, switch to `pread`

* cli `--update` flag

* `--update-snapshots`

* remove string object format
This commit is contained in:
Dylan Conway
2023-03-14 16:50:59 -07:00
committed by GitHub
parent 76b875e414
commit 4792abdb7f
41 changed files with 4635 additions and 131 deletions

View File

@@ -0,0 +1,77 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
exports[`toMatchSnapshot errors should throw if arguments are in the wrong order: right spot 1`] = `
{
"a": "oops",
}
`;
exports[`it will create a snapshot file if it doesn't exist 1`] = `
{
"a": {
"b": {
"c": Any<Boolean>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will create a snapshot file if it doesn't exist 2`] = `
{
"a": {
"b": {
"c": Any<String>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will create a snapshot file if it doesn't exist 3`] = `
{
"a": {
"b": {
"c": Any<Number>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will create a snapshot file if it doesn't exist 4`] = `
{
"a": {
"b": {
"c": Any<BigInt>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will create a snapshot file if it doesn't exist 5`] = `
{
"a": Any<Date>,
}
`;
exports[`it will create a snapshot file if it doesn't exist 6`] = `
{
"a": "any",
"b": Any<String>,
"j": Any<Number>,
}
`;
exports[`it will create a snapshot file if it doesn't exist 7`] = `
{
"a": "any",
"b": Any<String>,
"j": Any<RegExp>,
}
`;

View File

@@ -0,0 +1,71 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
exports[`it will work with an existing snapshot file made with bun 1`] = `
{
"a": {
"b": {
"c": Any<Boolean>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will work with an existing snapshot file made with bun 2`] = `
{
"a": {
"b": {
"c": Any<String>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will work with an existing snapshot file made with bun 3`] = `
{
"a": {
"b": {
"c": Any<Number>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will work with an existing snapshot file made with bun 4`] = `
{
"a": {
"b": {
"c": Any<BigInt>,
},
},
"c": 2,
"jkfje": 99238,
}
`;
exports[`it will work with an existing snapshot file made with bun 5`] = `
{
"a": Any<Date>,
}
`;
exports[`it will work with an existing snapshot file made with bun 6`] = `
{
"a": "any",
"b": Any<String>,
"j": Any<Number>,
}
`;
exports[`it will work with an existing snapshot file made with bun 7`] = `
{
"a": "any",
"b": Any<String>,
"j": Any<RegExp>,
}
`;

View File

@@ -0,0 +1,64 @@
import fs from "fs";
beforeAll(() => {
fs.rmSync(import.meta.dir + "/__snapshots__/bun-snapshots.test.ts.snap", { force: true });
});
test("it will create a snapshot file if it doesn't exist", () => {
expect({ a: { b: { c: false } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Boolean) } } });
expect({ a: { b: { c: "string" } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(String) } } });
expect({ a: { b: { c: 4 } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Number) } } });
expect({ a: { b: { c: 2n } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(BigInt) } } });
expect({ a: new Date() }).toMatchSnapshot({ a: expect.any(Date) });
expect({ j: 2, a: "any", b: "any2" }).toMatchSnapshot({ j: expect.any(Number), a: "any", b: expect.any(String) });
expect({ j: /regex/, a: "any", b: "any2" }).toMatchSnapshot({
j: expect.any(RegExp),
a: "any",
b: expect.any(String),
});
});
describe("toMatchSnapshot errors", () => {
it("should throw if property matchers exist and received is not an object", () => {
expect(() => {
expect(1).toMatchSnapshot({ a: 1 });
}).toThrow();
});
it("should throw if property matchers don't match", () => {
expect(() => {
expect({ a: 3 }).toMatchSnapshot({ a: 1 });
}).toThrow();
expect(() => {
expect({ a: 3 }).toMatchSnapshot({ a: expect.any(Date) });
}).toThrow();
expect(() => {
expect({ a: 3 }).toMatchSnapshot({ a: expect.any(String) });
}).toThrow();
expect(() => {
expect({ a: 4n }).toMatchSnapshot({ a: expect.any(Number) });
}).toThrow();
expect(() => {
expect({ a: 3 }).toMatchSnapshot({ a: expect.any(BigInt) });
}).toThrow();
});
it("should throw if arguments are in the wrong order", () => {
expect(() => {
expect({ a: "oops" }).toMatchSnapshot("wrong spot", { a: "oops" });
}).toThrow();
expect(() => {
expect({ a: "oops" }).toMatchSnapshot({ a: "oops" }, "right spot");
}).not.toThrow();
});
it("should throw if expect.any() doesn't received a constructor", () => {
expect(() => {
expect({ a: 4 }).toMatchSnapshot({ a: expect.any() });
}).toThrow();
expect(() => {
expect({ a: 5 }).toMatchSnapshot({ a: expect.any(5) });
}).toThrow();
expect(() => {
expect({ a: 4 }).toMatchSnapshot({ a: expect.any("not a constructor") });
}).toThrow();
});
});

View File

@@ -0,0 +1,13 @@
test("it will work with an existing snapshot file made with bun", () => {
expect({ a: { b: { c: false } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Boolean) } } });
expect({ a: { b: { c: "string" } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(String) } } });
expect({ a: { b: { c: 4 } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Number) } } });
expect({ a: { b: { c: 2n } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(BigInt) } } });
expect({ a: new Date() }).toMatchSnapshot({ a: expect.any(Date) });
expect({ j: 2, a: "any", b: "any2" }).toMatchSnapshot({ j: expect.any(Number), a: "any", b: expect.any(String) });
expect({ j: /regex/, a: "any", b: "any2" }).toMatchSnapshot({
j: expect.any(RegExp),
a: "any",
b: expect.any(String),
});
});

View File

@@ -0,0 +1,45 @@
import { bunExe } from "harness";
import { tmpdir } from "os";
import { mkdirSync, copyFileSync, writeFileSync } from "node:fs";
test("generate jest snapshot output", () => {
// generate jest snapshots and let bun test runner test against them
const tempDir = tmpdir() + "/generate-jest-snapshots";
mkdirSync(tempDir + "/snapshots/more-snapshots", { recursive: true });
copyFileSync(import.meta.dir + "/snapshots/snapshot.test.ts", tempDir + "/snapshots/snapshot.test.ts");
copyFileSync(import.meta.dir + "/snapshots/more.test.ts", tempDir + "/snapshots/more.test.ts");
copyFileSync(import.meta.dir + "/snapshots/moremore.test.ts", tempDir + "/snapshots/moremore.test.ts");
copyFileSync(
import.meta.dir + "/snapshots/more-snapshots/different-directory.test.ts",
tempDir + "/snapshots/more-snapshots/different-directory.test.ts",
);
writeFileSync(tempDir + "/jest.config.js", "");
const { exitCode, stderr } = Bun.spawnSync({
cmd: [bunExe(), "x", "jest", tempDir + "/snapshots/", "--updateSnapshot"],
cwd: tempDir,
});
expect(exitCode).toBe(0);
// ensure snapshot directories exist
mkdirSync(import.meta.dir + "/snapshots/__snapshots__", { recursive: true });
mkdirSync(import.meta.dir + "/snapshots/more-snapshots/__snapshots__", { recursive: true });
copyFileSync(
tempDir + "/snapshots/__snapshots__/snapshot.test.ts.snap",
import.meta.dir + "/snapshots/__snapshots__/snapshot.test.ts.snap",
);
copyFileSync(
tempDir + "/snapshots/__snapshots__/more.test.ts.snap",
import.meta.dir + "/snapshots/__snapshots__/more.test.ts.snap",
);
copyFileSync(
tempDir + "/snapshots/__snapshots__/moremore.test.ts.snap",
import.meta.dir + "/snapshots/__snapshots__/moremore.test.ts.snap",
);
copyFileSync(
tempDir + "/snapshots/more-snapshots/__snapshots__/different-directory.test.ts.snap",
import.meta.dir + "/snapshots/more-snapshots/__snapshots__/different-directory.test.ts.snap",
);
});

View File

@@ -0,0 +1,148 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`d0 d1 t1 1`] = `"hello\`snapshot\\"`;
exports[`d0 d1 t2 1`] = `"hey"`;
exports[`d0 snapshot serialize edgecases 1`] = `1`;
exports[`d0 snapshot serialize edgecases 2`] = `
"12
3
4"
`;
exports[`d0 snapshot serialize edgecases 3`] = `
"
"
`;
exports[`d0 snapshot serialize edgecases 4`] = `
"12
3
4 5 6 7\\
r
r
"
`;
exports[`d0 snapshot serialize edgecases 5`] = `
"12
3
4 5 6 7\\"
`;
exports[`d0 snapshot serialize edgecases 6`] = `
"
"
`;
exports[`d0 snapshot serialize edgecases 7`] = `
"
"
`;
exports[`d0 snapshot serialize edgecases 8`] = `"\\"`;
exports[`d0 snapshot serialize edgecases 9`] = `" "`;
exports[`d0 snapshot serialize edgecases 10`] = `" "`;
exports[`d0 snapshot serialize edgecases 11`] = `" "`;
exports[`d0 snapshot serialize edgecases 12`] = `""`;
exports[`d0 snapshot serialize edgecases 13`] = `" "`;
exports[`d0 snapshot serialize edgecases 14`] = `
"hello sn
apshot"
`;
exports[`d0 snapshot serialize edgecases 15`] = `String {}`;
exports[`d0 snapshot serialize edgecases 16`] = `String {}`;
exports[`d0 snapshot serialize edgecases 17`] = `
"\\
export with test name
"
`;
exports[`d0 snapshot serialize edgecases 18`] = `1`;
exports[`d0 snapshot serialize edgecases 19`] = `2`;
exports[`d0 snapshot serialize edgecases 20`] = `"\`\`\`\`\`\`\`\`\`\\\`\`\`\`\`\`\\\`\\\`\`\`\`\`\`\\\`\`\`\`\`\\\`\`\\\\\`\\\`\`\`\`\`\`\`\`\`\`\`\`"`;
exports[`d0 snapshot serialize edgecases 21`] = `"\`\`\`\`\`\`\`\`\`\\\`\`\`\`\`\`\\\`\\\`\`\`\`\`\`\\\`\`\`\`\`\\\`\`\\\\\`\\\`\`\`\`\`\`\`\`\`\`\`\`\\"`;
exports[`d0 snapshot serialize edgecases 22`] = `"\\\`\`\`\`\`\`\`\`\`\\\`\`\`\`\`\`\\\`\\\`\`\`\`\`\`\\\`\`\`\`\`\\\`\`\\\\\`\\\`\`\`\`\`\`\`\`\`\`\`\`"`;
exports[`d0 snapshot serialize edgecases 23`] = `"\\\`\`\`\`\`\`\`\`\`\\\`\`\`\`\`\`\\\`\\\`\`\`\`\`\`\\\`\`\`\`\`\\\`\`\\\\\`\\\`\`\`\`\`\`\`\`\`\`\`\`\\"`;
exports[`d0 snapshot serialize edgecases 24`] = `"one t\`wo \`three"`;
exports[`d0 snapshot serialize edgecases 25`] = `"one tw\\\`o three"`;
exports[`d0 snapshot serialize edgecases 26`] = `
"
export[\\\`hello snap'shot 2\`] = \`"
`;
exports[`d0 snapshot serialize edgecases 27`] = `
"
export[\`hello snapshot 2\`] = \`"
`;
exports[`d0 snapshot serialize edgecases 28`] = `"\`hello snapshot3 \\\`\`"`;
exports[`d0 snapshot serialize edgecases 29`] = `"\`hello snapshot4 \\\`\\\`"`;
exports[`d0 snapshot serialize edgecases 30`] = `"\\\`hello snapshot5 \\\`\\\`"`;
exports[`d0 snapshot serialize edgecases: one 1`] = `1`;
exports[`d0 snapshot serialize edgecases: one 2`] = `3`;
exports[`d0 snapshot serialize edgecases: ¾ 1`] = `
{
"a": 1,
"b": 2,
"c": 3,
}
`;
exports[`d0 snapshot serialize edgecases: 🐄 1`] = `
{
"a": 1,
"b": 2,
"c": 3,
}
`;
exports[`d0 snapshot serialize edgecases: 😃 1`] = `
{
"a": "🐄",
"b": "🐈",
}
`;
exports[`d0 t3 1`] = `"hello snapshot"`;
exports[`d0 t4 1`] = `"hello\`snapshot\\"`;

View File

@@ -0,0 +1,96 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`test snapshots with Boolean and Number 1`] = `1`;
exports[`test snapshots with Boolean and Number 2`] = `NaN`;
exports[`test snapshots with Boolean and Number 3`] = `Infinity`;
exports[`test snapshots with Boolean and Number 4`] = `-Infinity`;
exports[`test snapshots with Boolean and Number 5`] = `0`;
exports[`test snapshots with Boolean and Number 6`] = `-0`;
exports[`test snapshots with Boolean and Number 7`] = `1.1`;
exports[`test snapshots with Boolean and Number 8`] = `-1.1`;
exports[`test snapshots with Boolean and Number 9`] = `undefined`;
exports[`test snapshots with Boolean and Number 10`] = `null`;
exports[`test snapshots with Boolean and Number 11`] = `"hello"`;
exports[`test snapshots with Boolean and Number 12`] = `""`;
exports[`test snapshots with Boolean and Number 13`] = `Number {}`;
exports[`test snapshots with Boolean and Number 14`] = `Number2 {}`;
exports[`test snapshots with Boolean and Number 15`] = `Number3 {}`;
exports[`test snapshots with Boolean and Number 16`] = `123348923.2341281`;
exports[`test snapshots with Boolean and Number 17`] = `false`;
exports[`test snapshots with Boolean and Number 18`] = `true`;
exports[`test snapshots with Boolean and Number 19`] = `Boolean {}`;
exports[`test snapshots with Boolean and Number 20`] = `Boolean {}`;
exports[`test snapshots with Boolean and Number 21`] = `Boolean2 {}`;
exports[`test snapshots with Boolean and Number 22`] = `Boolean2 {}`;
exports[`test snapshots with Boolean and Number 23`] = `
Boolean3 {
"false": true,
}
`;
exports[`test snapshots with Boolean and Number 24`] = `
Boolean3 {
"false": true,
}
`;
exports[`test snapshots with Boolean and Number 25`] = `
{
"a": {
"b": {
"c": {
"d": {
"e": {
"bigint": Any<BigInt>,
"f": {
"g": {
"compare": "compare",
"h": {
"bool": Any<Boolean>,
"i": Any<Number3>,
},
},
},
"ignore1": 234,
"ignore2": {
"ignore3": 23421,
"ignore4": {
"ignore5": {
"ignore6": "hello",
"ignore7": "done",
},
},
},
},
},
"num": Any<Number>,
"string": Any<String>,
},
},
"j": Any<Date>,
},
"first": Any<Boolean2>,
}
`;

View File

@@ -0,0 +1,370 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`most types 1`] = `3`;
exports[`most types 2`] = `1`;
exports[`most types 3`] = `2`;
exports[`most types 4`] = `
{
"a": 1,
"b": 2,
"c": 3,
"d": Any<A>,
"e": 5,
"f": 6,
}
`;
exports[`most types 5`] = `
{
"a": {
"b": {
"c": {
"d": {
"e": {
"bigint": Any<BigInt>,
"f": {
"g": {
"compare": "compare",
"h": {
"bool": Any<Boolean>,
"i": Any<Date>,
},
},
},
"ignore1": 234,
"ignore2": {
"ignore3": 23421,
"ignore4": {
"ignore5": {
"ignore6": "hello",
"ignore7": "done",
},
},
},
},
},
"num": Any<Number>,
"string": Any<String>,
},
},
"j": Any<Date>,
},
"first": Any<Date>,
}
`;
exports[`most types: Array 1`] = `[]`;
exports[`most types: Array with empty array 1`] = `
[
[],
]
`;
exports[`most types: Array with multiple empty arrays 1`] = `
[
[],
[],
[],
[],
]
`;
exports[`most types: Array with nested arrays 1`] = `
[
1,
2,
[
3,
4,
],
[
4,
[
5,
6,
],
],
8,
]
`;
exports[`most types: Array2 1`] = `
[
1,
2,
3,
]
`;
exports[`most types: ArrayBuffer 1`] = `ArrayBuffer []`;
exports[`most types: Boolean 1`] = `Boolean {}`;
exports[`most types: Buffer 1`] = `
{
"data": [],
"type": "Buffer",
}
`;
exports[`most types: Buffer with property 1`] = `
{
"data": [
104,
101,
108,
108,
111,
],
"type": "Buffer",
}
`;
exports[`most types: Buffer2 1`] = `
{
"data": [
104,
101,
108,
108,
111,
],
"type": "Buffer",
}
`;
exports[`most types: Buffer3 1`] = `
{
"data": [
104,
101,
108,
96,
10,
10,
96,
],
"type": "Buffer",
}
`;
exports[`most types: Class 1`] = `
A {
"a": 1,
"b": 2,
"c": 3,
}
`;
exports[`most types: DataView 1`] = `DataView []`;
exports[`most types: Date 1`] = `1970-01-01T00:00:00.000Z`;
exports[`most types: Empty Error 1`] = `[Error]`;
exports[`most types: Error 1`] = `[Error: hello]`;
exports[`most types: Float32Array 1`] = `Float32Array []`;
exports[`most types: Float64Array 1`] = `Float64Array []`;
exports[`most types: Function 1`] = `[Function]`;
exports[`most types: Int8Array 1`] = `Int8Array []`;
exports[`most types: Int8Array with elements 1`] = `
Int8Array [
1,
2,
3,
4,
]
`;
exports[`most types: Int8Array with one element 1`] = `
Int8Array [
3,
]
`;
exports[`most types: Int16Array 1`] = `Int16Array []`;
exports[`most types: Int32Array 1`] = `Int32Array []`;
exports[`most types: Map 1`] = `
Map {
1 => "eight",
"seven" => "312390840812",
}
`;
exports[`most types: Number 1`] = `Number {}`;
exports[`most types: Object 1`] = `{}`;
exports[`most types: Object with Buffer 1`] = `
{
"a": {
"data": [
104,
101,
108,
108,
111,
],
"type": "Buffer",
},
}
`;
exports[`most types: Object with Int8Array 1`] = `
{
"a": 1,
"b": Int8Array [
123,
-89,
4,
34,
],
}
`;
exports[`most types: Object with String with property 1`] = `
{
"a": String {},
}
`;
exports[`most types: Object with empty Buffer 1`] = `
{
"a": {
"data": [],
"type": "Buffer",
},
}
`;
exports[`most types: Object with empty String 1`] = `
{
"a": String {},
}
`;
exports[`most types: Object with empty object 1`] = `
{
"a": {},
}
`;
exports[`most types: Object2 1`] = `
{
"a": 1,
"b": 2,
}
`;
exports[`most types: Promise 1`] = `Promise {}`;
exports[`most types: RegExp 1`] = `/hello/`;
exports[`most types: Set 1`] = `Set {}`;
exports[`most types: Set2 1`] = `
Set {
1,
2,
3,
4,
5,
6,
7,
8,
9,
}
`;
exports[`most types: String 1`] = `
String {
"0": "h",
"1": "e",
"2": "l",
"3": "l",
"4": "o",
}
`;
exports[`most types: String with property 1`] = `String {}`;
exports[`most types: Uint8Array 1`] = `Uint8Array []`;
exports[`most types: Uint8ClampedArray 1`] = `Uint8ClampedArray []`;
exports[`most types: Uint16Array 1`] = `Uint16Array []`;
exports[`most types: Uint32Array 1`] = `Uint32Array []`;
exports[`most types: WeakMap 1`] = `WeakMap {}`;
exports[`most types: WeakSet 1`] = `WeakSet {}`;
exports[`most types: arrow function 1`] = `[Function]`;
exports[`most types: empty map 1`] = `Map {}`;
exports[`most types: nested object with Buffer 1`] = `
{
"a": {
"b": {
"data": [
104,
101,
108,
108,
111,
],
"type": "Buffer",
},
},
}
`;
exports[`most types: nested object with empty Buffer 1`] = `
{
"a": {
"b": {
"data": [],
"type": "Buffer",
},
},
}
`;
exports[`most types: nested object with empty Int8Array 1`] = `
{
"a": {
"b": Int8Array [],
},
}
`;
exports[`most types: null 1`] = `null`;
exports[`most types: string 1`] = `"hello string"`;
exports[`most types: testing 4 1`] = `6`;
exports[`most types: testing 4 2`] = `4`;
exports[`most types: testing 5 1`] = `5`;
exports[`most types: testing 7 1`] = `7`;
exports[`most types: testing 7 2`] = `9`;
exports[`most types: testing 7 3`] = `8`;
exports[`most types: undefined 1`] = `undefined`;

View File

@@ -0,0 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`snapshots in different directory 1`] = `
"12
3
4"
`;
exports[`snapshots in different directory 2`] = `
"
"
`;
exports[`snapshots in different directory 3`] = `
"12
3
r
\\"
`;
exports[`snapshots in different directory 4`] = `
"12
3
4 5 6 7\\"
`;
exports[`snapshots in different directory 5`] = `
"\\
\\
\\ \\ \\ \\"
`;
exports[`snapshots in different directory 6`] = `
"
"
`;
exports[`snapshots in different directory 7`] = `
"
"
`;
exports[`snapshots in different directory 8`] = `"\\"`;
exports[`snapshots in different directory 9`] = `" "`;
exports[`snapshots in different directory 10`] = `" "`;
exports[`snapshots in different directory 11`] = `" "`;
exports[`snapshots in different directory 12`] = `""`;
exports[`snapshots in different directory 13`] = `
"'
"
`;
exports[`snapshots in different directory 14`] = `
{
"a": {
"b": {
"c": Any<Date>,
},
},
"c": 2,
"jkfje": 99238,
}
`;

View File

@@ -0,0 +1,18 @@
test("snapshots in different directory", () => {
expect("1\b2\n3\r4").toMatchSnapshot();
expect("\r\n").toMatchSnapshot();
expect("1\b2\n3\r r\r\\").toMatchSnapshot();
expect("1\b2\n3\r4\v5\f6\t7\\").toMatchSnapshot();
expect("\\\r\\\n\\\t\\\v\\\f\\\b").toMatchSnapshot();
expect("\r").toMatchSnapshot();
expect("\n").toMatchSnapshot();
expect("\\").toMatchSnapshot();
expect("\v").toMatchSnapshot();
expect("\f").toMatchSnapshot();
expect("\t").toMatchSnapshot();
expect("\b").toMatchSnapshot();
expect("\b'\b\r\r\n\r\n\n\r\n\n\r\r\r").toMatchSnapshot();
expect("\n\\\n");
expect({ a: { b: { c: new Date() } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Date) } } });
});

View File

@@ -0,0 +1,62 @@
describe("d0", () => {
test("snapshot serialize edgecases", () => {
expect(1).toMatchSnapshot();
expect("1\b2\n3\r4").toMatchSnapshot();
expect("\r\n").toMatchSnapshot();
expect("1\b2\n3\r\r\r\r\r\r\r\r\r\r\r\r4\v5\f6\t7\\\n\r\n\n\nr\nr\n").toMatchSnapshot();
expect("1\b2\n3\r4\v5\f6\t7\\").toMatchSnapshot();
expect("\r").toMatchSnapshot();
expect("\n").toMatchSnapshot();
expect("\\").toMatchSnapshot();
expect("\v").toMatchSnapshot();
expect("\f").toMatchSnapshot();
expect("\t").toMatchSnapshot();
expect("\b").toMatchSnapshot();
expect("\b\t").toMatchSnapshot();
expect(`hello sn
apshot`).toMatchSnapshot();
expect(new String()).toMatchSnapshot();
expect(new String("")).toMatchSnapshot();
expect({ a: { b: 1 } }).toEqual({ a: { b: 1 } });
expect("\\\nexport with test name\n\n").toMatchSnapshot();
expect(1).toMatchSnapshot();
expect(1).toMatchSnapshot("one");
expect(2).toMatchSnapshot();
expect(3).toMatchSnapshot("one");
expect("`````````\\``````\\`\\``````\\`````\\``\\\\`\\````````````").toMatchSnapshot();
expect("`````````\\``````\\`\\``````\\`````\\``\\\\`\\````````````\\").toMatchSnapshot();
expect("\\`````````\\``````\\`\\``````\\`````\\``\\\\`\\````````````").toMatchSnapshot();
expect("\\`````````\\``````\\`\\``````\\`````\\``\\\\`\\````````````\\").toMatchSnapshot();
expect("one t`wo `three").toMatchSnapshot();
expect("one tw\\`o three").toMatchSnapshot();
expect("\nexport[\\`hello snap'shot 2`] = `").toMatchSnapshot();
expect("\nexport[`hello snapshot 2`] = `").toMatchSnapshot();
expect("`hello snapshot3 \\``").toMatchSnapshot();
expect("`hello snapshot4 \\`\\`").toMatchSnapshot();
expect("\\`hello snapshot5 \\`\\`").toMatchSnapshot();
expect({ a: 1, b: 2, c: 3 }).toMatchSnapshot("¾");
expect({ a: 1, b: 2, c: 3 }).toMatchSnapshot("\uD83D\uDC04");
expect({ a: "\uD83D\uDC04", b: "🐈" }).toMatchSnapshot("😃");
});
});
describe("d0", () => {
describe("d1", () => {
test("t1", () => {
expect("hello`snapshot\\").toEqual("hello`snapshot\\");
expect("hello`snapshot\\").toMatchSnapshot();
});
test("t2", () => {
expect("hey").toMatchSnapshot();
});
});
test("t3", () => {
expect("hello snapshot").toMatchSnapshot();
});
test("t4", () => {
expect("hello`snapshot\\").toMatchSnapshot();
});
});

View File

@@ -0,0 +1,118 @@
class Number2 extends Number {
constructor(value) {
super(value);
}
}
class Number3 extends Number2 {
constructor(value) {
super(value);
}
}
class Boolean2 extends Boolean {
constructor(value) {
super(value);
}
}
class Boolean3 extends Boolean2 {
constructor(value) {
super(value);
}
false = true;
helloBoolean3() {
return "true";
}
}
test("test snapshots with Boolean and Number", () => {
expect(1).toMatchSnapshot();
expect(NaN).toMatchSnapshot();
expect(Infinity).toMatchSnapshot();
expect(-Infinity).toMatchSnapshot();
expect(0).toMatchSnapshot();
expect(-0).toMatchSnapshot();
expect(1.1).toMatchSnapshot();
expect(-1.1).toMatchSnapshot();
expect(undefined).toMatchSnapshot();
expect(null).toMatchSnapshot();
expect("hello").toMatchSnapshot();
expect("").toMatchSnapshot();
expect(new Number(1)).toMatchSnapshot();
expect(new Number2(1)).toMatchSnapshot();
expect(new Number3(1)).toMatchSnapshot();
expect(123348923.2341281).toMatchSnapshot();
expect(false).toMatchSnapshot();
expect(true).toMatchSnapshot();
expect(new Boolean(false)).toMatchSnapshot();
expect(new Boolean(true)).toMatchSnapshot();
expect(new Boolean2(true)).toMatchSnapshot();
expect(new Boolean2(false)).toMatchSnapshot();
expect(new Boolean3(true)).toMatchSnapshot();
expect(new Boolean3(false)).toMatchSnapshot();
expect({
first: new Boolean2(false),
a: {
j: new Date(),
b: {
c: {
num: 1,
d: {
e: {
bigint: 123n,
f: {
g: {
h: {
i: new Number3(2),
bool: true,
},
compare: "compare",
},
},
ignore1: 234,
ignore2: {
ignore3: 23421,
ignore4: {
ignore5: {
ignore6: "hello",
ignore7: "done",
},
},
},
},
},
string: "hello",
},
},
},
}).toMatchSnapshot({
first: expect.any(Boolean2),
a: {
j: expect.any(Date),
b: {
c: {
num: expect.any(Number),
string: expect.any(String),
d: {
e: {
bigint: expect.any(BigInt),
f: {
g: {
compare: "compare",
h: {
i: expect.any(Number3),
bool: expect.any(Boolean),
},
},
},
},
},
},
},
},
});
});

View File

@@ -0,0 +1,161 @@
function test1000000(arg1, arg218718132) {}
test("most types", () => {
expect(test1000000).toMatchSnapshot("Function");
expect(null).toMatchSnapshot("null");
expect(() => {}).toMatchSnapshot("arrow function");
expect(7).toMatchSnapshot("testing 7");
expect(6).toMatchSnapshot("testing 4");
expect(5).toMatchSnapshot("testing 5");
expect(4).toMatchSnapshot("testing 4");
expect(3).toMatchSnapshot();
expect(1).toMatchSnapshot();
expect(2).toMatchSnapshot();
expect(9).toMatchSnapshot("testing 7");
expect(8).toMatchSnapshot("testing 7");
expect(undefined).toMatchSnapshot("undefined");
expect("hello string").toMatchSnapshot("string");
expect([[]]).toMatchSnapshot("Array with empty array");
expect([[], [], [], []]).toMatchSnapshot("Array with multiple empty arrays");
expect([1, 2, [3, 4], [4, [5, 6]], 8]).toMatchSnapshot("Array with nested arrays");
let buf = new Buffer("hello");
buf.x = "yyyyyyyyyy";
expect(buf).toMatchSnapshot("Buffer with property");
expect(new Buffer("hello")).toMatchSnapshot("Buffer2");
expect(new Buffer("hel`\n\n`")).toMatchSnapshot("Buffer3");
expect({ a: new Buffer("hello") }).toMatchSnapshot("Object with Buffer");
expect({ a: { b: new Buffer("hello") } }).toMatchSnapshot("nested object with Buffer");
expect({ a: { b: new Buffer("") } }).toMatchSnapshot("nested object with empty Buffer");
expect({ a: new Buffer("") }).toMatchSnapshot("Object with empty Buffer");
expect(new Buffer("")).toMatchSnapshot("Buffer");
expect(new Date(0)).toMatchSnapshot("Date");
expect(new Error("hello")).toMatchSnapshot("Error");
expect(new Error()).toMatchSnapshot("Empty Error");
expect(new Map()).toMatchSnapshot("empty map");
expect(
new Map([
[1, "eight"],
["seven", "312390840812"],
]),
).toMatchSnapshot("Map");
expect(new Set()).toMatchSnapshot("Set");
expect(new Set([1, 2, 3, 4, 5, 6, 7, 8, 9])).toMatchSnapshot("Set2");
expect(new WeakMap()).toMatchSnapshot("WeakMap");
expect(new WeakSet()).toMatchSnapshot("WeakSet");
expect(new Promise(() => {})).toMatchSnapshot("Promise");
expect(new RegExp("hello")).toMatchSnapshot("RegExp");
let s = new String("");
expect(s).toMatchSnapshot("String with property");
expect({ a: s }).toMatchSnapshot("Object with String with property");
expect({ a: new String() }).toMatchSnapshot("Object with empty String");
expect(new String("hello")).toMatchSnapshot("String");
expect(new Number(7)).toMatchSnapshot("Number");
expect({ a: {} }).toMatchSnapshot("Object with empty object");
expect(new Boolean(true)).toMatchSnapshot("Boolean");
expect(new Int8Array([3])).toMatchSnapshot("Int8Array with one element");
expect(new Int8Array([1, 2, 3, 4])).toMatchSnapshot("Int8Array with elements");
expect(new Int8Array()).toMatchSnapshot("Int8Array");
expect({ a: 1, b: new Int8Array([123, 423, 4, 34]) }).toMatchSnapshot("Object with Int8Array");
expect({ a: { b: new Int8Array([]) } }).toMatchSnapshot("nested object with empty Int8Array");
expect(new Uint8Array()).toMatchSnapshot("Uint8Array");
expect(new Uint8ClampedArray()).toMatchSnapshot("Uint8ClampedArray");
expect(new Int16Array()).toMatchSnapshot("Int16Array");
expect(new Uint16Array()).toMatchSnapshot("Uint16Array");
expect(new Int32Array()).toMatchSnapshot("Int32Array");
expect(new Uint32Array()).toMatchSnapshot("Uint32Array");
expect(new Float32Array()).toMatchSnapshot("Float32Array");
expect(new Float64Array()).toMatchSnapshot("Float64Array");
expect(new ArrayBuffer(0)).toMatchSnapshot("ArrayBuffer");
expect(new DataView(new ArrayBuffer(0))).toMatchSnapshot("DataView");
expect({}).toMatchSnapshot("Object");
expect({ a: 1, b: 2 }).toMatchSnapshot("Object2");
expect([]).toMatchSnapshot("Array");
expect([1, 2, 3]).toMatchSnapshot("Array2");
class A {
a = 1;
b = 2;
constructor() {
this.c = 3;
}
d() {
return 4;
}
get e() {
return 5;
}
set e(value) {
this.f = value;
}
}
expect(new A()).toMatchSnapshot("Class");
expect({ a: 1, b: 2, c: 3, d: new A(), e: 5, f: 6 }).toMatchSnapshot({ d: expect.any(A) });
expect({
first: new Date(),
a: {
j: new Date(),
b: {
c: {
num: 1,
d: {
e: {
bigint: 123n,
f: {
g: {
h: {
i: new Date(),
bool: true,
},
compare: "compare",
},
},
ignore1: 234,
ignore2: {
ignore3: 23421,
ignore4: {
ignore5: {
ignore6: "hello",
ignore7: "done",
},
},
},
},
},
string: "hello",
},
},
},
}).toMatchSnapshot({
first: expect.any(Date),
a: {
j: expect.any(Date),
b: {
c: {
num: expect.any(Number),
string: expect.any(String),
d: {
e: {
bigint: expect.any(BigInt),
f: {
g: {
compare: "compare",
h: {
i: expect.any(Date),
bool: expect.any(Boolean),
},
},
},
},
},
},
},
},
});
});
it("should work with expect.anything()", () => {
// expect({ a: 0 }).toMatchSnapshot({ a: expect.anything() });
});

View File

@@ -15,7 +15,7 @@ it("when prototype defines the same property, don't print the same property twic
};
var obj = Object.create(base);
obj.foo = "456";
expect(Bun.inspect(obj).trim()).toBe('{\n foo: "456"\n}'.trim());
expect(Bun.inspect(obj).trim()).toBe('{\n "foo": "456"\n}'.trim());
});
it("Blob inspect", () => {
@@ -194,10 +194,10 @@ it("inspect", () => {
expect(Bun.inspect(1, "hi")).toBe("1 hi");
expect(Bun.inspect([])).toBe("[]");
expect(Bun.inspect({})).toBe("{}");
expect(Bun.inspect({ hello: 1 })).toBe("{\n hello: 1\n}");
expect(Bun.inspect({ hello: 1, there: 2 })).toBe("{\n hello: 1,\n there: 2\n}");
expect(Bun.inspect({ hello: "1", there: 2 })).toBe('{\n hello: "1",\n there: 2\n}');
expect(Bun.inspect({ 'hello-"there': "1", there: 2 })).toBe('{\n "hello-\\"there": "1",\n there: 2\n}');
expect(Bun.inspect({ hello: 1 })).toBe('{\n "hello": 1\n}');
expect(Bun.inspect({ hello: 1, there: 2 })).toBe('{\n "hello": 1,\n "there": 2\n}');
expect(Bun.inspect({ hello: "1", there: 2 })).toBe('{\n "hello": "1",\n "there": 2\n}');
expect(Bun.inspect({ 'hello-"there': "1", there: 2 })).toBe('{\n "hello-\\"there": "1",\n "there": 2\n}');
var str = "123";
while (str.length < 4096) {
str += "123";

View File

@@ -11,21 +11,21 @@ Symbol(Symbol Description)
2000-06-27T02:24:34.304Z
[ 123, 456, 789 ]
{
name: "foo"
"name": "foo"
}
{
a: 123,
b: 456,
c: 789
"a": 123,
"b": 456,
"c": 789
}
{
a: {
b: {
c: 123
"a": {
"b": {
"c": 123
},
bacon: true
"bacon": true
},
name: "bar"
"name": "bar"
}
Promise { <pending> }
[Function]
@@ -36,10 +36,10 @@ Promise { <pending> }
Is it a bug or a feature that formatting numbers like 123 is colored
String 123 should be 2nd word, 456 == 456 and percent s %s == What okay
{
foo: {
name: "baz"
"foo": {
"name": "baz"
},
bar: [Circular]
"bar": [Circular]
} am
[
{}, {}, {}, {}

View File

@@ -3,34 +3,34 @@ import { describe, it, expect } from "bun:test";
describe("url", () => {
it("prints", () => {
expect(Bun.inspect(new URL("https://example.com"))).toBe(`URL {
href: "https://example.com/",
origin: "https://example.com",
protocol: "https:",
username: "",
password: "",
host: "example.com",
hostname: "example.com",
port: "",
pathname: "/",
hash: "",
search: "",
searchParams: URLSearchParams {
append: [Function: append],
delete: [Function: delete],
get: [Function: get],
getAll: [Function: getAll],
has: [Function: has],
set: [Function: set],
sort: [Function: sort],
entries: [Function: entries],
keys: [Function: keys],
values: [Function: values],
forEach: [Function: forEach],
toString: [Function: toString],
[Symbol(Symbol.iterator)]: [Function: entries]
"href": "https://example.com/",
"origin": "https://example.com",
"protocol": "https:",
"username": "",
"password": "",
"host": "example.com",
"hostname": "example.com",
"port": "",
"pathname": "/",
"hash": "",
"search": "",
"searchParams": URLSearchParams {
"append": [Function: append],
"delete": [Function: delete],
"get": [Function: get],
"getAll": [Function: getAll],
"has": [Function: has],
"set": [Function: set],
"sort": [Function: sort],
"entries": [Function: entries],
"keys": [Function: keys],
"values": [Function: values],
"forEach": [Function: forEach],
"toString": [Function: toString],
[Symbol(Symbol.iterator)]: [Function: entries],
},
toJSON: [Function: toJSON],
toString: [Function: toString]
"toJSON": [Function: toJSON],
"toString": [Function: toString],
}`);
expect(
@@ -38,34 +38,34 @@ describe("url", () => {
new URL("https://github.com/oven-sh/bun/issues/135?hello%20i%20have%20spaces%20thank%20you%20good%20night"),
),
).toBe(`URL {
href: "https://github.com/oven-sh/bun/issues/135?hello%20i%20have%20spaces%20thank%20you%20good%20night",
origin: "https://github.com",
protocol: "https:",
username: "",
password: "",
host: "github.com",
hostname: "github.com",
port: "",
pathname: "/oven-sh/bun/issues/135",
hash: "",
search: "?hello%20i%20have%20spaces%20thank%20you%20good%20night",
searchParams: URLSearchParams {
append: [Function: append],
delete: [Function: delete],
get: [Function: get],
getAll: [Function: getAll],
has: [Function: has],
set: [Function: set],
sort: [Function: sort],
entries: [Function: entries],
keys: [Function: keys],
values: [Function: values],
forEach: [Function: forEach],
toString: [Function: toString],
[Symbol(Symbol.iterator)]: [Function: entries]
"href": "https://github.com/oven-sh/bun/issues/135?hello%20i%20have%20spaces%20thank%20you%20good%20night",
"origin": "https://github.com",
"protocol": "https:",
"username": "",
"password": "",
"host": "github.com",
"hostname": "github.com",
"port": "",
"pathname": "/oven-sh/bun/issues/135",
"hash": "",
"search": "?hello%20i%20have%20spaces%20thank%20you%20good%20night",
"searchParams": URLSearchParams {
"append": [Function: append],
"delete": [Function: delete],
"get": [Function: get],
"getAll": [Function: getAll],
"has": [Function: has],
"set": [Function: set],
"sort": [Function: sort],
"entries": [Function: entries],
"keys": [Function: keys],
"values": [Function: values],
"forEach": [Function: forEach],
"toString": [Function: toString],
[Symbol(Symbol.iterator)]: [Function: entries],
},
toJSON: [Function: toJSON],
toString: [Function: toString]
"toJSON": [Function: toJSON],
"toString": [Function: toString],
}`);
});
it("works", () => {