joist-test-utils 1.108.5 → 1.108.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/toMatchEntity.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/// <reference types="jest" />
|
|
2
2
|
import CustomMatcherResult = jest.CustomMatcherResult;
|
|
3
3
|
import { AsyncProperty, Collection, Entity, Reference } from "joist-orm";
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Provides convenient `toMatchObject`-style matching for Joist entities.
|
|
6
|
+
*
|
|
7
|
+
* The biggest differences over `toMatchObject` are:
|
|
8
|
+
*
|
|
9
|
+
* - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make
|
|
10
|
+
* asserting against the entities look like asserting against POJOs
|
|
11
|
+
* - We prune the expected/actual values to be as minimal as possible, to avoid Jest
|
|
12
|
+
* recursively crawling into connection pools or other misc non-useful things in the diffs
|
|
13
|
+
*/
|
|
14
|
+
export declare function toMatchEntity<T extends object>(actual: T, expected: MatchedEntity<T>): CustomMatcherResult;
|
|
5
15
|
/**
|
|
6
16
|
* Given a Joist entity `T`, "flattens out" the Reference/Collections.
|
|
7
17
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toMatchEntity.d.ts","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":";AAAA,OAAO,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;AAItD,OAAO,EACL,aAAa,
|
|
1
|
+
{"version":3,"file":"toMatchEntity.d.ts","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":";AAAA,OAAO,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;AAItD,OAAO,EACL,aAAa,EAEb,UAAU,EACV,MAAM,EAQN,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAoB1G;AAgBD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB,CAAC,GACD;KACG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,GACtD,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GACpB,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GACrC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAC3B,CAAC,CAAC,CAAC,CAAC,SAAS,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GACxC,CAAC,GACD,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,GACtC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,GAC7C,CAAC,CAAC,CAAC,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,GAC/C,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,EAAE,GAC7C,CAAC,CAAC,CAAC,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAC1C,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAExC,AADA,sCAAsC;IACtC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;CAC/B,CAAC"}
|
package/build/toMatchEntity.js
CHANGED
|
@@ -8,75 +8,37 @@ exports.toMatchEntity = void 0;
|
|
|
8
8
|
const matchers_1 = __importDefault(require("expect/build/matchers"));
|
|
9
9
|
const is_plain_object_1 = require("is-plain-object");
|
|
10
10
|
const joist_orm_1 = require("joist-orm");
|
|
11
|
+
/**
|
|
12
|
+
* Provides convenient `toMatchObject`-style matching for Joist entities.
|
|
13
|
+
*
|
|
14
|
+
* The biggest differences over `toMatchObject` are:
|
|
15
|
+
*
|
|
16
|
+
* - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make
|
|
17
|
+
* asserting against the entities look like asserting against POJOs
|
|
18
|
+
* - We prune the expected/actual values to be as minimal as possible, to avoid Jest
|
|
19
|
+
* recursively crawling into connection pools or other misc non-useful things in the diffs
|
|
20
|
+
*/
|
|
11
21
|
function toMatchEntity(actual, expected) {
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
(0, joist_orm_1.isPersistedAsyncProperty)(actualValue)) {
|
|
32
|
-
actualValue = getWithSoftDeleted(actualValue);
|
|
33
|
-
}
|
|
34
|
-
if (actualValue instanceof Array) {
|
|
35
|
-
const actualList = actualValue;
|
|
36
|
-
const expectedList = expectedValue;
|
|
37
|
-
const cleanList = [];
|
|
38
|
-
// Do a hacky zip of each actual/expected pair
|
|
39
|
-
for (let i = 0; i < Math.max(actualList.length, expectedList.length); i++) {
|
|
40
|
-
const actualI = actualList[i];
|
|
41
|
-
const expectedI = expectedList[i];
|
|
42
|
-
// If actual is a list of entities (and expected is not), make a copy of each
|
|
43
|
-
// so that we can recurse into their `{ title: ... }` properties.
|
|
44
|
-
if ((0, joist_orm_1.isEntity)(actualI) && (0, is_plain_object_1.isPlainObject)(expectedI)) {
|
|
45
|
-
const cleanI = Array.isArray(expectedI) ? [] : {};
|
|
46
|
-
queue.push([actualI, expectedI, cleanI]);
|
|
47
|
-
cleanList.push(cleanI);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// Given we're stopping here, make sure neither side is an entity
|
|
51
|
-
if (i < expectedList.length) {
|
|
52
|
-
expectedList[i] = maybeTestId(expectedI);
|
|
53
|
-
}
|
|
54
|
-
if (i < actualList.length) {
|
|
55
|
-
cleanList.push(maybeTestId(actualI));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
clean[key] = cleanList;
|
|
60
|
-
}
|
|
61
|
-
else if ((0, is_plain_object_1.isPlainObject)(expectedValue)) {
|
|
62
|
-
// We have an expected value that the user wants to fuzzy match against, so recurse
|
|
63
|
-
// to pick out a subset of clean values (i.e. not the connection pool) to assert against.
|
|
64
|
-
const cleanValue = Array.isArray(expectedValue) ? [] : {};
|
|
65
|
-
queue.push([actualValue, expectedValue, cleanValue]);
|
|
66
|
-
clean[key] = cleanValue;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
// We've hit a non-list/non-object literal expected value, so clean both
|
|
70
|
-
// expected+clean keys to make sure they're not entities, and stop recursion.
|
|
71
|
-
if (key in expected)
|
|
72
|
-
expected[key] = maybeTestId(expectedValue);
|
|
73
|
-
if (actual && key in actual)
|
|
74
|
-
clean[key] = maybeTestId(actualValue);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
22
|
+
// We're given expected, which is an object literal of what the user wants to match
|
|
23
|
+
// against (some intermixed POJOs & entities) and actual (which similarly could be
|
|
24
|
+
// intermixed POJOs & entities, but will likely be more sprawling because it's the
|
|
25
|
+
// full result, and not the subset we're asserting against).
|
|
26
|
+
//
|
|
27
|
+
// Given this, first make a safe clone of `expected`, i.e. turn entities into strings.
|
|
28
|
+
// After that, use `expected` as a template to pick keys out of actual. Finally, do the
|
|
29
|
+
// same "clean clone" of actual, and compare the two.
|
|
30
|
+
const cleanExpected = deepClone(expected);
|
|
31
|
+
const cleanActual = deepClone(deepMirror(cleanExpected, actual));
|
|
32
|
+
// Watch for `expect(someAuthor).toMatchEntity(a1)` as we'll turn `someAuthor` into "a:1`,
|
|
33
|
+
// so can't use toMatchObject anymore.
|
|
34
|
+
if (typeof cleanActual !== "object") {
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
return matchers_1.default.toEqual.call(this, cleanActual, cleanExpected);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
return matchers_1.default.toMatchObject.call(this, cleanActual, cleanExpected);
|
|
77
41
|
}
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
return matchers_1.default.toMatchObject.call(this, clean, expected);
|
|
80
42
|
}
|
|
81
43
|
exports.toMatchEntity = toMatchEntity;
|
|
82
44
|
function maybeTestId(maybeEntity) {
|
|
@@ -91,6 +53,58 @@ function getTestId(em, entity) {
|
|
|
91
53
|
const sameType = em.entities.filter((e) => e instanceof meta.cstr);
|
|
92
54
|
return `${meta.tagName}#${sameType.indexOf(entity) + 1}`;
|
|
93
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Make a "new actual" based on the subset shape of expected.
|
|
58
|
+
*
|
|
59
|
+
* We don't have cycle detection, but that should be fine b/c the user types
|
|
60
|
+
* out the expected as an object literal, so it shouldn't have cycles
|
|
61
|
+
*/
|
|
62
|
+
function deepMirror(expected, actual) {
|
|
63
|
+
// If we've hit a point where the `expected` input is not a POJO object literal/array
|
|
64
|
+
// declaring the subset of the shape to assert against, just return actual as-is.
|
|
65
|
+
// This might be a Date (safe) or an Entity (unsafe) or something else, but if so it will
|
|
66
|
+
// get cleaned up by the `deepClone` pass.
|
|
67
|
+
if (!(0, is_plain_object_1.isPlainObject)(expected) && !Array.isArray(expected))
|
|
68
|
+
return actual;
|
|
69
|
+
// Make a new actual that is a subset that matches expected
|
|
70
|
+
const subset = Array.isArray(expected) ? [] : {};
|
|
71
|
+
// If both are arrays, fill out the whole array
|
|
72
|
+
const keys = Array.isArray(actual) ? Object.keys(actual) : Object.keys(expected);
|
|
73
|
+
for (const key of keys) {
|
|
74
|
+
if (key in actual) {
|
|
75
|
+
// Even if actualValue is an Entity, if expected has a key drilling in to it, we want to object literal-ize it
|
|
76
|
+
subset[key] = deepMirror(expected[key], maybeGetRelation(actual[key]));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return subset;
|
|
80
|
+
}
|
|
81
|
+
/** Make a clone of `obj`, but only recurse into POJOs and Arrays, and replace entities if we find them. */
|
|
82
|
+
function deepClone(obj, map = new WeakMap()) {
|
|
83
|
+
if (obj instanceof joist_orm_1.BaseEntity) {
|
|
84
|
+
return maybeTestId(obj);
|
|
85
|
+
}
|
|
86
|
+
else if (obj && typeof obj === "object" && ((0, is_plain_object_1.isPlainObject)(obj) || Array.isArray(obj))) {
|
|
87
|
+
if (map.has(obj))
|
|
88
|
+
return map.get(obj);
|
|
89
|
+
const result = Array.isArray(obj) ? [] : {};
|
|
90
|
+
map.set(obj, result);
|
|
91
|
+
Object.assign(result, ...Object.keys(obj).map((key) => ({ [key]: deepClone(obj[key], map) })));
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return obj;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Flattens/simplifies relations into their actual value, i.e. "calls get". */
|
|
99
|
+
function maybeGetRelation(actualValue) {
|
|
100
|
+
if ((0, joist_orm_1.isReference)(actualValue) ||
|
|
101
|
+
(0, joist_orm_1.isCollection)(actualValue) ||
|
|
102
|
+
(0, joist_orm_1.isAsyncProperty)(actualValue) ||
|
|
103
|
+
(0, joist_orm_1.isPersistedAsyncProperty)(actualValue)) {
|
|
104
|
+
return getWithSoftDeleted(actualValue);
|
|
105
|
+
}
|
|
106
|
+
return actualValue;
|
|
107
|
+
}
|
|
94
108
|
/**
|
|
95
109
|
* Adds back soft-deleted to `.get`.
|
|
96
110
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toMatchEntity.js","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":";;;;;;AACA,aAAa;AACb,qEAA6C;AAC7C,qDAAgD;AAChD,
|
|
1
|
+
{"version":3,"file":"toMatchEntity.js","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":"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"}
|