joist-test-utils 1.0.0
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/index.d.ts +10 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/build/toMatchEntity.d.ts +13 -0
- package/build/toMatchEntity.js +86 -0
- package/build/toMatchEntity.js.map +1 -0
- package/package.json +24 -0
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
import { MatchedEntity } from "./toMatchEntity";
|
|
3
|
+
export { toMatchEntity } from "./toMatchEntity";
|
|
4
|
+
declare global {
|
|
5
|
+
namespace jest {
|
|
6
|
+
interface Matchers<R, T = {}> {
|
|
7
|
+
toMatchEntity(expected: MatchedEntity<T>): Promise<CustomMatcherResult>;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toMatchEntity = void 0;
|
|
4
|
+
var toMatchEntity_1 = require("./toMatchEntity");
|
|
5
|
+
Object.defineProperty(exports, "toMatchEntity", { enumerable: true, get: function () { return toMatchEntity_1.toMatchEntity; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,iDAAgD;AAAvC,8GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
import CustomMatcherResult = jest.CustomMatcherResult;
|
|
3
|
+
import { Collection, Entity, Reference } from "joist-orm";
|
|
4
|
+
export declare function toMatchEntity<T>(actual: Entity, expected: MatchedEntity<T>): Promise<CustomMatcherResult>;
|
|
5
|
+
/**
|
|
6
|
+
* Given a Joist entity `T`, "flattens out" the Reference/Collections.
|
|
7
|
+
*
|
|
8
|
+
* I.e. so that you can `toMatchEntity({ otherEntity: { name: "foo" } })` even though
|
|
9
|
+
* `otherEntity` is technically a joist `Reference` or `Collection`.
|
|
10
|
+
*/
|
|
11
|
+
export declare type MatchedEntity<T> = {
|
|
12
|
+
[K in keyof T]?: T[K] extends Reference<any, infer U, any> ? MatchedEntity<U> | U : T[K] extends Collection<any, infer U> ? Array<MatchedEntity<U> | U> : T[K];
|
|
13
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toMatchEntity = void 0;
|
|
4
|
+
const joist_orm_1 = require("joist-orm");
|
|
5
|
+
async function toMatchEntity(actual, expected) {
|
|
6
|
+
// Because the `actual` entity has lots of __orm, Reference, Collection, etc cruft in it,
|
|
7
|
+
// we make a simplified copy of it, where we use the keys in `expected` to pull out/eval a
|
|
8
|
+
// subset of the complex keys in an entity to be "dumb data" versions of themselves.
|
|
9
|
+
const clean = {};
|
|
10
|
+
const { em } = actual;
|
|
11
|
+
// Because we might assert again `expect(entity).toMatchEntity({ children: [{ name: "p1" }])`, we keep
|
|
12
|
+
// a queue of entities/copies to make, and work through it as we recurse through the expected/actual pair.
|
|
13
|
+
const queue = [[actual, expected, clean]];
|
|
14
|
+
while (queue.length > 0) {
|
|
15
|
+
const [actual, expected, clean] = queue.pop();
|
|
16
|
+
const keys = Object.keys(expected);
|
|
17
|
+
for (const key of keys) {
|
|
18
|
+
const value = actual[key];
|
|
19
|
+
if (value && ((0, joist_orm_1.isReference)(value) || (0, joist_orm_1.isCollection)(value))) {
|
|
20
|
+
// If something has a `.load` it could be a Reference.load or a Collection.load, either way lazy load it
|
|
21
|
+
const loaded = await value.load();
|
|
22
|
+
if (loaded instanceof Array) {
|
|
23
|
+
const actualList = loaded;
|
|
24
|
+
const expectedList = expected[key];
|
|
25
|
+
const cleanList = [];
|
|
26
|
+
// Do a hacky zip of each actual/expected pair
|
|
27
|
+
for (let i = 0; i < Math.max(actualList.length, expectedList.length); i++) {
|
|
28
|
+
const actualI = actualList[i];
|
|
29
|
+
const expectedI = expectedList[i];
|
|
30
|
+
// If actual is a list of entities (and expected is not), make a copy of each
|
|
31
|
+
// so that we can recurse into their `{ title: ... }` properties.
|
|
32
|
+
if ((0, joist_orm_1.isEntity)(actualI) && !(0, joist_orm_1.isEntity)(expectedI) && expectedI) {
|
|
33
|
+
const cleanI = {};
|
|
34
|
+
queue.push([actualI, expectedI, cleanI]);
|
|
35
|
+
cleanList.push(cleanI);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Given we're stopping here, make sure neither side is an entity
|
|
39
|
+
if (i < expectedList.length) {
|
|
40
|
+
expectedList[i] = maybeTestId(em, expectedI);
|
|
41
|
+
}
|
|
42
|
+
if (i < actualList.length) {
|
|
43
|
+
cleanList.push(maybeTestId(em, actualI));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
clean[key] = cleanList;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// If the `.load` result wasn't a list, assume it's an entity that we'll copy
|
|
51
|
+
if ((0, joist_orm_1.isEntity)(loaded) && !(0, joist_orm_1.isEntity)(expected[key])) {
|
|
52
|
+
const loadedClean = {};
|
|
53
|
+
queue.push([loaded, expected[key], loadedClean]);
|
|
54
|
+
clean[key] = loadedClean;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
expected[key] = maybeTestId(em, expected[key]);
|
|
58
|
+
clean[key] = maybeTestId(em, loaded);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Otherwise assume it's regular data. Probably need to handle getters/promises?
|
|
64
|
+
clean[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Blatantly grab `toMatchObject` from the guts of expect
|
|
69
|
+
const { getMatchers } = require("expect/build/jestMatchersObject");
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
return getMatchers().toMatchObject.call(this, clean, expected);
|
|
72
|
+
}
|
|
73
|
+
exports.toMatchEntity = toMatchEntity;
|
|
74
|
+
function maybeTestId(em, maybeEntity) {
|
|
75
|
+
return (0, joist_orm_1.isEntity)(maybeEntity) ? getTestId(em, maybeEntity) : maybeEntity;
|
|
76
|
+
}
|
|
77
|
+
/** Returns either the persisted id or `tag#<offset-in-EntityManager>`. */
|
|
78
|
+
function getTestId(em, entity) {
|
|
79
|
+
if (entity.id) {
|
|
80
|
+
return entity.id;
|
|
81
|
+
}
|
|
82
|
+
const meta = (0, joist_orm_1.getMetadata)(entity);
|
|
83
|
+
const sameType = em.entities.filter((e) => e instanceof meta.cstr);
|
|
84
|
+
return `${meta.tagName}#${sameType.indexOf(entity) + 1}`;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=toMatchEntity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toMatchEntity.js","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "joist-test-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"format": "prettier --write '{schema,migrations,src}/**/*.{ts,js,tsx,jsx,graphql}'"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"build"
|
|
12
|
+
],
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@swc/core": "^1.2.124",
|
|
15
|
+
"@swc/jest": "^0.2.16",
|
|
16
|
+
"@types/jest": "^26.0.24",
|
|
17
|
+
"jest": "^27.0.6",
|
|
18
|
+
"prettier": "^2.5.1",
|
|
19
|
+
"prettier-plugin-organize-imports": "^2.3.4",
|
|
20
|
+
"ts-node-dev": "^1.1.8",
|
|
21
|
+
"tsconfig-paths": "^3.10.1",
|
|
22
|
+
"typescript": "^4.5.2"
|
|
23
|
+
}
|
|
24
|
+
}
|