Skip to content

Commit 29ebd0d

Browse files
committed
Release 2.0.3
1 parent 3ce6d0f commit 29ebd0d

File tree

7 files changed

+77
-88
lines changed

7 files changed

+77
-88
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mattapperson/slapshot",
3-
"version": "2.0.2",
3+
"version": "2.0.3",
44
"main": "lib/index.js",
55
"description": "Mock method calls with snapshots, run your intigation tests online or offline!",
66
"license": "MIT",

src/__snapshots__/memorize.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ exports[`Test: nested APIs with functions throw an error when called unless mock
3838

3939
exports[`Test: resolves from disk on 2nd hit | Memorized Name: c | Call iteration: 0`] = `{"results":{"foo":"bar"}}`;
4040

41-
exports[`Test: thrown errors are replayed | Memorized Name: error | Call iteration: 0`] = `{"results":null,"thrownError":"{\\"type\\":\\"Error\\",\\"message\\":\\"foo\\",\\"name\\":\\"Error\\",\\"stack\\":\\"Error: foo\\\\n at memorize_1.memorize (/Users/mattapperson/development/slapshot/src/memorize.test.ts:321:19)\\\\n at Object.memorize (/Users/mattapperson/development/slapshot/src/memorize.ts:57:33)\\\\n at expect (/Users/mattapperson/development/slapshot/src/memorize.test.ts:320:9)\\\\n at Object.<anonymous> (/Users/mattapperson/development/slapshot/node_modules/expect/build/toThrowMatchers.js:81:11)\\\\n at Object.throwingMatcher [as toThrowError] (/Users/mattapperson/development/slapshot/node_modules/expect/build/index.js:342:33)\\\\n at /Users/mattapperson/development/slapshot/src/memorize.test.ts:323:8\\\\n at Generator.next (<anonymous>)\\\\n at /Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:110:75\\\\n at new Promise (<anonymous>)\\\\n at Object.__awaiter (/Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:106:16)\\\\n at Object.<anonymous>.test (/Users/mattapperson/development/slapshot/src/memorize.test.ts:313:47)\\\\n at Object.asyncJestTest (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)\\\\n at resolve (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:43:12)\\\\n at new Promise (<anonymous>)\\\\n at mapper (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:26:19)\\\\n at promise.then (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:73:41)\\"}"}`;
41+
exports[`Test: thrown errors are replayed | Memorized Name: error | Call iteration: 0`] = `{"results":null,"thrownError":"{\\"type\\":\\"Error\\",\\"message\\":\\"foo\\",\\"name\\":\\"Error\\",\\"stack\\":\\"Error: foo\\\\n at memorize_1.memorize (/Users/mattapperson/development/slapshot/src/memorize.test.ts:331:19)\\\\n at Object.memorize (/Users/mattapperson/development/slapshot/src/memorize.ts:41:33)\\\\n at expect (/Users/mattapperson/development/slapshot/src/memorize.test.ts:330:9)\\\\n at Object.<anonymous> (/Users/mattapperson/development/slapshot/node_modules/expect/build/toThrowMatchers.js:81:11)\\\\n at Object.throwingMatcher [as toThrowError] (/Users/mattapperson/development/slapshot/node_modules/expect/build/index.js:342:33)\\\\n at /Users/mattapperson/development/slapshot/src/memorize.test.ts:333:8\\\\n at Generator.next (<anonymous>)\\\\n at /Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:110:75\\\\n at new Promise (<anonymous>)\\\\n at Object.__awaiter (/Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:106:16)\\\\n at Object.<anonymous>.test (/Users/mattapperson/development/slapshot/src/memorize.test.ts:323:47)\\\\n at Object.asyncJestTest (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)\\\\n at resolve (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:43:12)\\\\n at new Promise (<anonymous>)\\\\n at mapper (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:26:19)\\\\n at promise.then (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:73:41)\\"}"}`;
4242

43-
exports[`Test: thrown errors are replayed with custom properties | Memorized Name: error | Call iteration: 0`] = `{"results":null,"thrownError":"{\\"type\\":\\"Error\\",\\"message\\":\\"foo\\",\\"name\\":\\"Error\\",\\"stack\\":\\"Error: foo\\\\n at memorize_1.memorize (/Users/mattapperson/development/slapshot/src/memorize.test.ts:352:19)\\\\n at Object.memorize (/Users/mattapperson/development/slapshot/src/memorize.ts:57:33)\\\\n at expect (/Users/mattapperson/development/slapshot/src/memorize.test.ts:351:9)\\\\n at Object.<anonymous> (/Users/mattapperson/development/slapshot/node_modules/expect/build/toThrowMatchers.js:81:11)\\\\n at Object.throwingMatcher [as toThrowError] (/Users/mattapperson/development/slapshot/node_modules/expect/build/index.js:342:33)\\\\n at /Users/mattapperson/development/slapshot/src/memorize.test.ts:354:8\\\\n at Generator.next (<anonymous>)\\\\n at /Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:110:75\\\\n at new Promise (<anonymous>)\\\\n at Object.__awaiter (/Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:106:16)\\\\n at Object.<anonymous>.test (/Users/mattapperson/development/slapshot/src/memorize.test.ts:336:70)\\\\n at Object.asyncJestTest (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)\\\\n at resolve (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:43:12)\\\\n at new Promise (<anonymous>)\\\\n at mapper (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:26:19)\\\\n at promise.then (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:73:41)\\",\\"customProp\\":\\"bar\\"}"}`;
43+
exports[`Test: thrown errors are replayed with custom properties | Memorized Name: error | Call iteration: 0`] = `{"results":null,"thrownError":"{\\"type\\":\\"Error\\",\\"message\\":\\"foo\\",\\"name\\":\\"Error\\",\\"stack\\":\\"Error: foo\\\\n at memorize_1.memorize (/Users/mattapperson/development/slapshot/src/memorize.test.ts:362:19)\\\\n at Object.memorize (/Users/mattapperson/development/slapshot/src/memorize.ts:41:33)\\\\n at expect (/Users/mattapperson/development/slapshot/src/memorize.test.ts:361:9)\\\\n at Object.<anonymous> (/Users/mattapperson/development/slapshot/node_modules/expect/build/toThrowMatchers.js:81:11)\\\\n at Object.throwingMatcher [as toThrowError] (/Users/mattapperson/development/slapshot/node_modules/expect/build/index.js:342:33)\\\\n at /Users/mattapperson/development/slapshot/src/memorize.test.ts:364:8\\\\n at Generator.next (<anonymous>)\\\\n at /Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:110:75\\\\n at new Promise (<anonymous>)\\\\n at Object.__awaiter (/Users/mattapperson/development/slapshot/node_modules/tslib/tslib.js:106:16)\\\\n at Object.<anonymous>.test (/Users/mattapperson/development/slapshot/src/memorize.test.ts:346:70)\\\\n at Object.asyncJestTest (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)\\\\n at resolve (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:43:12)\\\\n at new Promise (<anonymous>)\\\\n at mapper (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:26:19)\\\\n at promise.then (/Users/mattapperson/development/slapshot/node_modules/jest-jasmine2/build/queueRunner.js:73:41)\\",\\"customProp\\":\\"bar\\"}"}`;
4444

4545
exports[`Test: throws error of non-matching snap when validateSnapshot is set to true | Memorized Name: validateSnapshot | Call iteration: 0`] = `{"results":22,"thrownError":null}`;
4646

src/get_from_jest_context.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from "path";
2+
23
const testMap: any = {};
34

45
export const getFromJestContext = (snapshotName: string, pure: boolean) => {
@@ -33,12 +34,20 @@ export const getFromJestContext = (snapshotName: string, pure: boolean) => {
3334
testFileName
3435
);
3536

37+
let snapshot;
38+
try {
39+
snapshot = JSON.parse(jestContext.snapshotData[fullSnapshotName]);
40+
} catch (_e) {
41+
snapshot = jestContext.snapshotData[fullSnapshotName];
42+
}
43+
3644
return {
45+
snapshot,
3746
slapFilePath,
3847
testFileName,
3948
testFilePath,
4049
fullSnapshotName,
41-
shouldUpdateSnapshot:
50+
shouldForceUpdateSnapshot:
4251
(process.env
4352
.SLAPSHOT_HACK_BYPASS_JEST_SHOULD_UPDATE_SNAPSHOTS_FOR_TESTS ===
4453
undefined &&

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { callWhenOnline } from "./call_when_online";
22
import "./hack_context";
33
import { memorize } from "./memorize";
4+
export * from "./types";
45

56
export default {
67
callWhenOnline,

src/memorize.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ test("writes a __snapshot__ file to disk", async () => {
5858
expect(mockedConsole).not.toBeCalled();
5959
});
6060

61+
test("throws an error is offline, and no snapshot recorded", () => {
62+
process.env.SLAPSHOT_HACK_BYPASS_JEST_SHOULD_UPDATE_SNAPSHOTS_FOR_TESTS =
63+
"false";
64+
process.env.SLAPSHOT_ONLINE = "false";
65+
66+
expect(() => {
67+
memorize("no snapshot", () => 22);
68+
}).toThrow();
69+
});
70+
6171
test("resolves from disk on 2nd hit", async () => {
6272
process.env.SLAPSHOT_HACK_BYPASS_JEST_SHOULD_UPDATE_SNAPSHOTS_FOR_TESTS =
6373
"true";

src/memorize.ts

Lines changed: 46 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,42 @@ import hydrateError from "utils-error-reviver";
33
// @ts-ignore
44
import errorToJSON from "utils-error-to-json";
55
import { getFromJestContext } from "./get_from_jest_context";
6+
import { MissingSnapshotError } from "./mising_snapshot_error";
7+
import { MismatchSnapshotError } from "./mising_snapshot_error copy";
68
import { safeSnapshot } from "./safeSnapshot";
7-
import { SlapshotDataFormat, Snapshot } from "./types";
9+
import {
10+
MemorizeOptions,
11+
SlapshotDataFormat,
12+
ValidationOptions
13+
} from "./types";
814
import { runInOnlineMode } from "./utils";
915

10-
type ValidationCallback = (liveData: any, snapshottedData: any) => void;
11-
type ValidationOptions = boolean | ValidationCallback;
12-
1316
export function memorize<ReturnedData = any>(
1417
snapshotName: string,
15-
method: () => Promise<ReturnedData> | ReturnedData,
16-
{
17-
pure = true,
18-
validateSnapshot = false
19-
}: { pure?: boolean; validateSnapshot?: ValidationOptions } = {}
18+
fnToSnapshot: () => Promise<ReturnedData> | ReturnedData,
19+
{ pure = true, validateSnapshot = false }: MemorizeOptions = {}
2020
): Promise<ReturnedData> | ReturnedData {
21-
const testData = getFromJestContext(snapshotName, pure);
22-
23-
let snapshot;
24-
25-
try {
26-
snapshot = JSON.parse(testData.snapshotData[testData.fullSnapshotName]);
27-
} catch (_e) {
28-
snapshot = testData.snapshotData[testData.fullSnapshotName];
29-
}
30-
31-
const snap = snapshot || ({} as Snapshot);
32-
if (!testData.shouldUpdateSnapshot && !runInOnlineMode() && !snapshot) {
33-
throw new Error(
34-
`Missing snapshot
35-
- Snapshot name: ${testData.fullSnapshotName}
36-
- In snapshot file: ${testData.testFileName}
37-
- Test file: ${testData.testFilePath}
38-
39-
${process.env.SLAPSHOT_RERUN_MESSAGE ||
40-
"Please re-run Jest with the env var SLAPSHOT_ONLINE=true"}.`.replace(
41-
new RegExp(" ", "g"),
42-
""
43-
)
44-
);
21+
const jestData = getFromJestContext(snapshotName, pure);
22+
23+
if (
24+
!jestData.shouldForceUpdateSnapshot &&
25+
!runInOnlineMode() &&
26+
!jestData.snapshot
27+
) {
28+
throw new MissingSnapshotError(jestData);
4529
}
4630

4731
if (!runInOnlineMode()) {
48-
testData.markSnapAsUsed(testData.fullSnapshotName);
49-
return returnValues(safeSnapshot(snap, false));
32+
jestData.markSnapAsUsed(jestData.fullSnapshotName);
33+
return returnValues(safeSnapshot(jestData.snapshot, false));
5034
}
5135

5236
let methodResults: SlapshotDataFormat = {
5337
results: null,
5438
thrownError: null
5539
};
5640
try {
57-
methodResults.results = method();
41+
methodResults.results = fnToSnapshot();
5842
} catch (e) {
5943
methodResults.thrownError = JSON.stringify(errorToJSON(e));
6044
}
@@ -63,97 +47,75 @@ export function memorize<ReturnedData = any>(
6347
return Promise.resolve(methodResults.results)
6448
.catch(error => {
6549
return resolveData(
66-
snap,
67-
testData.fullSnapshotName,
6850
{
6951
thrownError: JSON.stringify(errorToJSON(error)),
7052
results: null
7153
},
72-
testData,
54+
jestData,
7355
validateSnapshot
7456
);
7557
})
7658
.then(methodResults => {
7759
return resolveData(
78-
snap,
79-
testData.fullSnapshotName,
8060
{
8161
results: methodResults
8262
},
83-
testData,
63+
jestData,
8464
validateSnapshot
8565
);
8666
});
8767
}
8868

89-
return resolveData(
90-
snap,
91-
testData.fullSnapshotName,
92-
methodResults,
93-
testData,
94-
validateSnapshot
95-
);
69+
return resolveData(methodResults, jestData, validateSnapshot);
9670
}
9771

9872
function resolveData(
99-
snap: any,
100-
fullSnapshotName: string,
10173
methodResults: SlapshotDataFormat,
102-
testData: ReturnType<typeof getFromJestContext>,
74+
jestData: ReturnType<typeof getFromJestContext>,
10375
validateSnapshot: ValidationOptions
10476
) {
105-
if (!testData.shouldUpdateSnapshot && runInOnlineMode()) {
106-
let snapDataToCompare = snap;
107-
77+
let methodResultsStringified;
78+
if (!jestData.shouldForceUpdateSnapshot && runInOnlineMode()) {
10879
if (validateSnapshot && typeof validateSnapshot === "function") {
109-
validateSnapshot(methodResults, snapDataToCompare);
80+
validateSnapshot(methodResults, jestData.snapshot);
11081
} else {
111-
if (typeof snapDataToCompare === "object") {
112-
snapDataToCompare = JSON.stringify(snapDataToCompare);
82+
let snapAsString = jestData.snapshot;
83+
if (typeof jestData.snapshot === "object") {
84+
snapAsString = JSON.stringify(jestData.snapshot);
11385
}
11486

115-
let methodResultsToCompare: any = methodResults;
116-
if (typeof methodResultsToCompare === "object") {
117-
methodResultsToCompare = JSON.stringify(
118-
safeSnapshot(methodResultsToCompare)
87+
if (typeof methodResults === "object") {
88+
methodResultsStringified = JSON.stringify(
89+
safeSnapshot(methodResults)
11990
);
12091
}
12192

12293
if (
123-
(snap.results || snap.thrownError) &&
124-
methodResultsToCompare !== snapDataToCompare
94+
jestData.snapshot &&
95+
(jestData.snapshot.results || jestData.snapshot.thrownError) &&
96+
methodResultsStringified !== snapAsString
12597
) {
126-
const defaultWarning = `[Warning] Integration test result does not match the memorized snap file:
127-
- Snapshot name: ${fullSnapshotName}
128-
- Test file: ${testData.testFilePath
129-
.split(".")
130-
.slice(0, -1)
131-
.join(".")}
132-
- Live result: ${methodResultsToCompare}
133-
- Existing Snap: ${snapDataToCompare}
134-
135-
${process.env.SLAPSHOT_RERUN_MESSAGE ||
136-
"Please re-run Jest with the env var SLAPSHOT_ONLINE=true"}.`.replace(
137-
new RegExp(" ", "g"),
138-
""
98+
const warning = new MismatchSnapshotError(
99+
jestData,
100+
methodResultsStringified
139101
);
140102

141103
if (!validateSnapshot) {
142-
console.warn(defaultWarning);
104+
console.warn(warning.message);
143105
} else if (typeof validateSnapshot === "boolean") {
144-
throw new Error(defaultWarning);
106+
throw warning;
145107
}
146108
}
147109
}
148-
testData.markSnapAsUsed(testData.fullSnapshotName);
110+
jestData.markSnapAsUsed(jestData.fullSnapshotName);
149111
return returnValues(methodResults);
150112
}
151113

152-
testData.addSnapshot(
153-
fullSnapshotName,
154-
JSON.stringify(safeSnapshot(methodResults))
114+
jestData.addSnapshot(
115+
jestData.fullSnapshotName,
116+
methodResultsStringified || JSON.stringify(safeSnapshot(methodResults))
155117
);
156-
testData.markSnapAsUsed(testData.fullSnapshotName);
118+
jestData.markSnapAsUsed(jestData.fullSnapshotName);
157119
return returnValues(methodResults);
158120
}
159121

src/types.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@ export type SlapshotDataFormat = { thrownError?: any; results: any };
33
export interface Snapshot {
44
[key: string]: SlapshotDataFormat;
55
}
6+
7+
export type ValidationCallback = (liveData: any, snapshottedData: any) => void;
8+
export type ValidationOptions = boolean | ValidationCallback;
9+
export type MemorizeOptions = {
10+
pure?: boolean;
11+
validateSnapshot?: ValidationOptions;
12+
};

0 commit comments

Comments
 (0)