joist-test-utils 2.3.0 → 2.4.0-next.2

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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/build/RunPlugin.cjs +219 -0
  3. package/build/RunPlugin.cjs.map +1 -0
  4. package/build/RunPlugin.d.cts +12 -0
  5. package/build/RunPlugin.d.cts.map +1 -0
  6. package/build/RunPlugin.d.mts +12 -0
  7. package/build/RunPlugin.d.mts.map +1 -0
  8. package/build/RunPlugin.js +203 -341
  9. package/build/RunPlugin.js.map +1 -1
  10. package/build/_virtual/_rolldown/runtime.cjs +23 -0
  11. package/build/context.cjs +2 -0
  12. package/build/context.d.cts +9 -0
  13. package/build/context.d.cts.map +1 -0
  14. package/build/context.d.mts +9 -0
  15. package/build/context.d.mts.map +1 -0
  16. package/build/context.js +2 -3
  17. package/build/index.cjs +38 -0
  18. package/build/index.cjs.map +1 -0
  19. package/build/index.d.cts +52 -0
  20. package/build/index.d.cts.map +1 -0
  21. package/build/index.d.mts +52 -0
  22. package/build/index.d.mts.map +1 -0
  23. package/build/index.js +25 -41
  24. package/build/index.js.map +1 -1
  25. package/build/run.cjs +77 -0
  26. package/build/run.cjs.map +1 -0
  27. package/build/run.d.cts +17 -0
  28. package/build/run.d.cts.map +1 -0
  29. package/build/run.d.mts +17 -0
  30. package/build/run.d.mts.map +1 -0
  31. package/build/run.js +52 -76
  32. package/build/run.js.map +1 -1
  33. package/build/seed.cjs +54 -0
  34. package/build/seed.cjs.map +1 -0
  35. package/build/{seed.d.ts → seed.d.cts} +9 -6
  36. package/build/seed.d.cts.map +1 -0
  37. package/build/seed.d.mts +35 -0
  38. package/build/seed.d.mts.map +1 -0
  39. package/build/seed.js +47 -53
  40. package/build/seed.js.map +1 -1
  41. package/build/toMatchEntity.cjs +94 -0
  42. package/build/toMatchEntity.cjs.map +1 -0
  43. package/build/toMatchEntity.d.cts +28 -0
  44. package/build/toMatchEntity.d.cts.map +1 -0
  45. package/build/toMatchEntity.d.mts +28 -0
  46. package/build/toMatchEntity.d.mts.map +1 -0
  47. package/build/toMatchEntity.js +73 -109
  48. package/build/toMatchEntity.js.map +1 -1
  49. package/package.json +33 -13
  50. package/build/RunPlugin.d.ts +0 -9
  51. package/build/RunPlugin.d.ts.map +0 -1
  52. package/build/context.d.ts +0 -6
  53. package/build/context.d.ts.map +0 -1
  54. package/build/context.js.map +0 -1
  55. package/build/index.d.ts +0 -42
  56. package/build/index.d.ts.map +0 -1
  57. package/build/run.d.ts +0 -15
  58. package/build/run.d.ts.map +0 -1
  59. package/build/seed.d.ts.map +0 -1
  60. package/build/toMatchEntity.d.ts +0 -27
  61. package/build/toMatchEntity.d.ts.map +0 -1
@@ -1,129 +1,93 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toMatchEntity = toMatchEntity;
4
- const joist_core_1 = require("joist-core");
5
- const joist_utils_1 = require("joist-utils");
6
- // This might be undefined if running outside of jest
7
- const jestMatchers = globalThis[Symbol.for("$$jest-matchers-object")];
8
- const matchers = jestMatchers?.matchers;
1
+ import "./index.js";
2
+ import { BaseEntity, isAsyncProperty, isCollection, isDefined, isEntity, isProperty, isReactiveField, isReference } from "joist-core";
3
+ import { isPlainObject } from "joist-utils";
4
+ //#region src/toMatchEntity.ts
5
+ const isVitest = typeof process !== "undefined" && process.env?.VITEST === "true";
9
6
  /**
10
- * Provides convenient `toMatchObject`-style matching for Joist entities.
11
- *
12
- * The biggest differences over `toMatchObject` are:
13
- *
14
- * - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make
15
- * asserting against the entities look like asserting against POJOs
16
- * - We prune the expected/actual values to be as minimal as possible, to avoid Jest
17
- * recursively crawling into connection pools or other misc non-useful things in the diffs
18
- */
7
+ * Provides convenient `toMatchObject`-style matching for Joist entities.
8
+ *
9
+ * The biggest differences over `toMatchObject` are:
10
+ *
11
+ * - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make
12
+ * asserting against the entities look like asserting against POJOs
13
+ * - We prune the expected/actual values to be as minimal as possible, to avoid Jest
14
+ * recursively crawling into connection pools or other misc non-useful things in the diffs
15
+ */
19
16
  function toMatchEntity(actual, expected) {
20
- // We're given expected, which is an object literal of what the user wants to match
21
- // against (some intermixed POJOs & entities) and actual (which similarly could be
22
- // intermixed POJOs & entities, but will likely be more sprawling because it's the
23
- // full result, and not the subset we're asserting against).
24
- //
25
- // Given this, first make a safe clone of `expected`, i.e. turn entities into strings.
26
- // After that, use `expected` as a template to pick keys out of actual. Finally, do the
27
- // same "clean clone" of actual, and compare the two.
28
- const cleanExpected = deepClone(expected);
29
- const cleanActual = deepClone(deepMirror(cleanExpected, actual));
30
- // Watch for `expect(someAuthor).toMatchEntity(a1)` as we'll turn `someAuthor` into "a:1",
31
- // so can't use toMatchObject anymore.
32
- if (matchers) {
33
- // this is jest
34
- if (typeof cleanActual !== "object") {
35
- // @ts-ignore
36
- return matchers.toEqual.call(this, cleanActual, cleanExpected);
37
- }
38
- else {
39
- // @ts-ignore
40
- return matchers.toMatchObject.call(this, cleanActual, cleanExpected);
41
- }
42
- }
43
- else {
44
- // this is bun--it's matcherHint actually seems to do `toMatchObject` already?
45
- return {
46
- pass: this.equals(cleanActual, cleanExpected),
47
- message: () => this.utils.matcherHint("toMatchEntity", cleanActual, cleanExpected),
48
- };
49
- }
17
+ const matchers = isVitest ? void 0 : globalThis[Symbol.for("$$jest-matchers-object")]?.matchers;
18
+ const cleanExpected = deepClone(expected);
19
+ const cleanActual = deepClone(deepMirror(cleanExpected, actual));
20
+ if (matchers) {
21
+ if (typeof cleanActual !== "object") return matchers.toEqual.call(this, cleanActual, cleanExpected);
22
+ else return matchers.toMatchObject.call(this, cleanActual, cleanExpected);
23
+ } else if (isVitest) return {
24
+ pass: this.equals(cleanActual, cleanExpected, this.customTesters),
25
+ message: () => {
26
+ const hint = this.utils.matcherHint("toMatchEntity", void 0, void 0, { isNot: this.isNot });
27
+ const diff = this.utils.diff(cleanExpected, cleanActual);
28
+ return diff ? `${hint}\n\n${diff}` : hint;
29
+ }
30
+ };
31
+ else return {
32
+ pass: this.equals(cleanActual, cleanExpected),
33
+ message: () => this.utils.matcherHint("toMatchEntity", cleanActual, cleanExpected)
34
+ };
50
35
  }
51
36
  function maybeTestId(maybeEntity) {
52
- return (0, joist_core_1.isEntity)(maybeEntity) ? getTestId(maybeEntity.em, maybeEntity) : maybeEntity;
37
+ return isEntity(maybeEntity) ? getTestId(maybeEntity.em, maybeEntity) : maybeEntity;
53
38
  }
54
39
  /** Returns either the persisted id or `tag#<offset-in-EntityManager>`. */
55
40
  function getTestId(_, entity) {
56
- return entity.toTaggedString();
41
+ return entity.toTaggedString();
57
42
  }
58
43
  /**
59
- * Make a "new actual" based on the subset shape of expected.
60
- *
61
- * We don't have cycle detection, but that should be fine b/c the user types
62
- * out the expected as an object literal, so it shouldn't have cycles
63
- */
44
+ * Make a "new actual" based on the subset shape of expected.
45
+ *
46
+ * We don't have cycle detection, but that should be fine b/c the user types
47
+ * out the expected as an object literal, so it shouldn't have cycles
48
+ */
64
49
  function deepMirror(expected, actual) {
65
- // If we've hit a point where the `expected` input is not a POJO object literal/array
66
- // declaring the subset of the shape to assert against, just return actual as-is.
67
- // This might be a Date (safe) or an Entity (unsafe) or something else, but if so it will
68
- // get cleaned up by the `deepClone` pass.
69
- if (!(0, joist_utils_1.isPlainObject)(expected) && !Array.isArray(expected))
70
- return actual;
71
- if (!(0, joist_core_1.isDefined)(actual))
72
- return actual;
73
- // Make a new actual that is a subset that matches expected
74
- const subset = Array.isArray(expected) ? [] : {};
75
- // If both are arrays, fill out the whole array
76
- const keys = Array.isArray(actual) ? Object.keys(actual) : Object.keys(expected);
77
- for (const key of keys) {
78
- if (key in actual) {
79
- // Even if actualValue is an Entity, if expected has a key drilling in to it, we want to object literal-ize it
80
- subset[key] = deepMirror(expected[key], maybeGetRelation(actual[key]));
81
- }
82
- }
83
- return subset;
50
+ if (!isPlainObject(expected) && !Array.isArray(expected)) return actual;
51
+ if (!isDefined(actual)) return actual;
52
+ const subset = Array.isArray(expected) ? [] : {};
53
+ const keys = Array.isArray(actual) ? Object.keys(actual) : Object.keys(expected);
54
+ for (const key of keys) if (key in actual) subset[key] = deepMirror(expected[key], maybeGetRelation(actual[key]));
55
+ return subset;
84
56
  }
85
57
  /** Make a clone of `obj`, but only recurse into POJOs and Arrays, and replace entities if we find them. */
86
- function deepClone(obj, map = new WeakMap()) {
87
- if (obj instanceof joist_core_1.BaseEntity) {
88
- return maybeTestId(obj);
89
- }
90
- else if (obj && typeof obj === "object" && ((0, joist_utils_1.isPlainObject)(obj) || Array.isArray(obj))) {
91
- if (map.has(obj))
92
- return map.get(obj);
93
- const result = Array.isArray(obj) ? [] : {};
94
- map.set(obj, result);
95
- Object.assign(result, ...Object.keys(obj).map((key) => ({ [key]: deepClone(obj[key], map) })));
96
- return result;
97
- }
98
- else {
99
- return obj;
100
- }
58
+ function deepClone(obj, map = /* @__PURE__ */ new WeakMap()) {
59
+ if (obj instanceof BaseEntity) return maybeTestId(obj);
60
+ else if (obj && typeof obj === "object" && (isPlainObject(obj) || Array.isArray(obj))) {
61
+ if (map.has(obj)) return map.get(obj);
62
+ const result = Array.isArray(obj) ? [] : {};
63
+ map.set(obj, result);
64
+ Object.assign(result, ...Object.keys(obj).map((key) => ({ [key]: deepClone(obj[key], map) })));
65
+ return result;
66
+ } else return obj;
101
67
  }
102
68
  /** Flattens/simplifies relations into their actual value, i.e. "calls get". */
103
69
  function maybeGetRelation(actualValue) {
104
- if ((0, joist_core_1.isReference)(actualValue) ||
105
- (0, joist_core_1.isCollection)(actualValue) ||
106
- (0, joist_core_1.isProperty)(actualValue) ||
107
- (0, joist_core_1.isReactiveField)(actualValue)) {
108
- return getWithSoftDeleted(actualValue);
109
- }
110
- return actualValue;
70
+ if (isReference(actualValue) || isCollection(actualValue) || isProperty(actualValue) || isReactiveField(actualValue) || isAsyncProperty(actualValue)) return getWithSoftDeleted(actualValue);
71
+ return actualValue;
111
72
  }
112
73
  /**
113
- * Adds back soft-deleted to `.get`.
114
- *
115
- * In Joist, `.get` filters both soft and hard deleted entities, because `.get`
116
- * is likely used by real business logic that doesn't want to see either.
117
- *
118
- * However, in tests with `toMatchEntity`, we take a stronger stance that the
119
- * developer needs to know "this is _soft_ deleted and not hard deleted", so
120
- * we add-back soft deleted entities.
121
- *
122
- * We do this by calling `getWithDeleted`, which returns all hard and soft
123
- * deleted entities, and then filtering out the hard deletes.
124
- */
74
+ * Adds back soft-deleted to `.get`.
75
+ *
76
+ * In Joist, `.get` filters both soft and hard deleted entities, because `.get`
77
+ * is likely used by real business logic that doesn't want to see either.
78
+ *
79
+ * However, in tests with `toMatchEntity`, we take a stronger stance that the
80
+ * developer needs to know "this is _soft_ deleted and not hard deleted", so
81
+ * we add-back soft deleted entities.
82
+ *
83
+ * We do this by calling `getWithDeleted`, which returns all hard and soft
84
+ * deleted entities, and then filtering out the hard deletes.
85
+ */
125
86
  function getWithSoftDeleted(relation) {
126
- const r = "getWithDeleted" in relation ? relation.getWithDeleted : relation.get;
127
- return Array.isArray(r) ? r.filter((e) => !e.isDeletedEntity) : r;
87
+ const r = "getWithDeleted" in relation ? relation.getWithDeleted : relation.get;
88
+ return Array.isArray(r) ? r.filter((e) => !e.isDeletedEntity) : r;
128
89
  }
90
+ //#endregion
91
+ export { toMatchEntity };
92
+
129
93
  //# sourceMappingURL=toMatchEntity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toMatchEntity.js","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toMatchEntity.js","names":[],"sources":["../src/toMatchEntity.ts"],"sourcesContent":["import {\n BaseEntity,\n type Entity,\n type EntityManager,\n type Property,\n type ReadOnlyCollection,\n type Reference,\n isAsyncProperty,\n isCollection,\n isDefined,\n isEntity,\n isProperty,\n isReactiveField,\n isReference,\n} from \"joist-core\";\nimport { isPlainObject } from \"joist-utils\";\n\nimport { type CustomMatcherResult } from \"./index.ts\";\n\n// Vitest also populates the `$$jest-matchers-object` symbol, but the matchers it stores there are\n// chai-based and assume `this` is a chai Assertion (with a `this.assert` method), which our custom\n// matcher's `this` context is not--so calling them throws `this.assert is not a function`. Only take\n// the Jest fast-path under actual Jest, and route Vitest through the `this.equals` path below (like Bun).\nconst isVitest = typeof process !== \"undefined\" && process.env?.VITEST === \"true\";\n\n/**\n * Provides convenient `toMatchObject`-style matching for Joist entities.\n *\n * The biggest differences over `toMatchObject` are:\n *\n * - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make\n * asserting against the entities look like asserting against POJOs\n * - We prune the expected/actual values to be as minimal as possible, to avoid Jest\n * recursively crawling into connection pools or other misc non-useful things in the diffs\n */\nexport function toMatchEntity<T>(this: any, actual: unknown, expected: MatchedEntity<T>): CustomMatcherResult {\n // This module can load before Jest initializes its matcher state, so read the global when invoked.\n const matchers = isVitest ? undefined : (globalThis as any)[Symbol.for(\"$$jest-matchers-object\")]?.matchers;\n // We're given expected, which is an object literal of what the user wants to match\n // against (some intermixed POJOs & entities) and actual (which similarly could be\n // intermixed POJOs & entities, but will likely be more sprawling because it's the\n // full result, and not the subset we're asserting against).\n //\n // Given this, first make a safe clone of `expected`, i.e. turn entities into strings.\n // After that, use `expected` as a template to pick keys out of actual. Finally, do the\n // same \"clean clone\" of actual, and compare the two.\n const cleanExpected = deepClone(expected);\n const cleanActual = deepClone(deepMirror(cleanExpected, actual));\n\n // Watch for `expect(someAuthor).toMatchEntity(a1)` as we'll turn `someAuthor` into \"a:1\",\n // so can't use toMatchObject anymore.\n if (matchers) {\n // this is jest\n if (typeof cleanActual !== \"object\") {\n // @ts-ignore\n return matchers.toEqual.call(this, cleanActual, cleanExpected);\n } else {\n // @ts-ignore\n return matchers.toMatchObject.call(this, cleanActual, cleanExpected);\n }\n } else if (isVitest) {\n // `deepMirror` already pruned `cleanActual` down to the subset of keys that `cleanExpected`\n // declares, so a full `this.equals` deep-equality behaves like Jest's `toMatchObject`. We pass\n // `this.customTesters` so `areEntitiesEqual` still applies. Building the diff into `message`\n // (like Jest's `toMatchObject`) keeps the failure output readable both in the terminal and in\n // `toThrowErrorMatchingInlineSnapshot`, instead of the default `expect([object Object])...`.\n const pass = this.equals(cleanActual, cleanExpected, this.customTesters);\n return {\n pass,\n message: () => {\n const hint = this.utils.matcherHint(\"toMatchEntity\", undefined, undefined, { isNot: this.isNot });\n const diff = this.utils.diff(cleanExpected, cleanActual);\n return diff ? `${hint}\\n\\n${diff}` : hint;\n },\n };\n } else {\n // This is Bun, whose matcher `this.utils` only exposes `matcherHint`.\n return {\n pass: this.equals(cleanActual, cleanExpected),\n message: () => this.utils.matcherHint(\"toMatchEntity\", cleanActual, cleanExpected),\n };\n }\n}\n\nfunction maybeTestId(maybeEntity: any): any {\n return isEntity(maybeEntity) ? getTestId(maybeEntity.em, maybeEntity) : maybeEntity;\n}\n\n/** Returns either the persisted id or `tag#<offset-in-EntityManager>`. */\nfunction getTestId(_: EntityManager, entity: Entity): string {\n return entity.toTaggedString();\n}\n\n/**\n * Given a Joist entity `T`, \"flattens out\" the Reference/Collections.\n *\n * I.e. so that you can `toMatchEntity({ otherEntity: { name: \"foo\" } })` even though\n * `otherEntity` is technically a joist `Reference` or `Collection`.\n *\n * We allow `| null` so that `toMatchEntity` can work against optional fields\n * that are returned from GraphQL object resolvers.\n */\nexport type MatchedEntity<T> =\n T extends ReadonlyArray<infer U>\n ? ReadonlyArray<MatchedEntity<U>>\n :\n | undefined\n | T\n | {\n [K in keyof T]?: T[K] extends Reference<any, infer U, any>\n ? MatchedEntity<U> | U\n : T[K] extends ReadOnlyCollection<any, infer U>\n ? Array<MatchedEntity<U> | U>\n : T[K] extends Property<any, infer V>\n ? V\n : T[K] extends Entity | null | undefined\n ? MatchedEntity<T[K]> | T[K] | null | undefined\n : T[K] extends ReadonlyArray<(infer U) | undefined>\n ? readonly (MatchedEntity<U> | U | undefined)[]\n : T[K] extends ReadonlyArray<infer U> | null\n ? readonly (MatchedEntity<U> | U | null)[]\n : // We recurse similar to a DeepPartial\n MatchedEntity<T[K]> | null;\n };\n\n/**\n * Make a \"new actual\" based on the subset shape of expected.\n *\n * We don't have cycle detection, but that should be fine b/c the user types\n * out the expected as an object literal, so it shouldn't have cycles\n */\nfunction deepMirror(expected: any, actual: any): any {\n // If we've hit a point where the `expected` input is not a POJO object literal/array\n // declaring the subset of the shape to assert against, just return actual as-is.\n // This might be a Date (safe) or an Entity (unsafe) or something else, but if so it will\n // get cleaned up by the `deepClone` pass.\n if (!isPlainObject(expected) && !Array.isArray(expected)) return actual;\n if (!isDefined(actual)) return actual;\n // Make a new actual that is a subset that matches expected\n const subset: any = Array.isArray(expected) ? [] : ({} as any);\n // If both are arrays, fill out the whole array\n const keys = Array.isArray(actual) ? Object.keys(actual) : Object.keys(expected);\n for (const key of keys) {\n if (key in actual) {\n // Even if actualValue is an Entity, if expected has a key drilling in to it, we want to object literal-ize it\n subset[key] = deepMirror((expected as any)[key], maybeGetRelation(actual[key]));\n }\n }\n return subset;\n}\n\n/** Make a clone of `obj`, but only recurse into POJOs and Arrays, and replace entities if we find them. */\nfunction deepClone(obj: unknown, map = new WeakMap()): unknown {\n if (obj instanceof BaseEntity) {\n return maybeTestId(obj);\n } else if (obj && typeof obj === \"object\" && (isPlainObject(obj) || Array.isArray(obj))) {\n if (map.has(obj)) return map.get(obj);\n const result = Array.isArray(obj) ? [] : {};\n map.set(obj, result);\n Object.assign(result, ...Object.keys(obj).map((key) => ({ [key]: deepClone((obj as any)[key], map) })));\n return result;\n } else {\n return obj;\n }\n}\n\n/** Flattens/simplifies relations into their actual value, i.e. \"calls get\". */\nfunction maybeGetRelation(actualValue: unknown): unknown {\n if (\n isReference(actualValue) ||\n isCollection(actualValue) ||\n isProperty(actualValue) ||\n isReactiveField(actualValue) ||\n // hasAsyncPropertys will work if they've been already loaded, so let the user try it\n isAsyncProperty(actualValue)\n ) {\n return getWithSoftDeleted(actualValue);\n }\n return actualValue;\n}\n\n/**\n * Adds back soft-deleted to `.get`.\n *\n * In Joist, `.get` filters both soft and hard deleted entities, because `.get`\n * is likely used by real business logic that doesn't want to see either.\n *\n * However, in tests with `toMatchEntity`, we take a stronger stance that the\n * developer needs to know \"this is _soft_ deleted and not hard deleted\", so\n * we add-back soft deleted entities.\n *\n * We do this by calling `getWithDeleted`, which returns all hard and soft\n * deleted entities, and then filtering out the hard deletes.\n */\nfunction getWithSoftDeleted(relation: any): any {\n const r = \"getWithDeleted\" in relation ? relation.getWithDeleted : relation.get;\n return Array.isArray(r) ? r.filter((e: any) => !e.isDeletedEntity) : r;\n}\n"],"mappings":";;;;AAuBA,MAAM,WAAW,OAAO,YAAY,eAAe,QAAQ,KAAK,WAAW;;;;;;;;;;;AAY3E,SAAgB,cAA4B,QAAiB,UAAiD;CAE5G,MAAM,WAAW,WAAW,KAAA,IAAa,WAAmB,OAAO,IAAI,wBAAwB,EAAE,EAAE;CASnG,MAAM,gBAAgB,UAAU,QAAQ;CACxC,MAAM,cAAc,UAAU,WAAW,eAAe,MAAM,CAAC;CAI/D,IAAI,UAAU;EAEZ,IAAI,OAAO,gBAAgB,UAEzB,OAAO,SAAS,QAAQ,KAAK,MAAM,aAAa,aAAa;OAG7D,OAAO,SAAS,cAAc,KAAK,MAAM,aAAa,aAAa;CAEvE,OAAO,IAAI,UAOT,OAAO;EACL,MAFW,KAAK,OAAO,aAAa,eAAe,KAAK,aAErD;EACH,eAAe;GACb,MAAM,OAAO,KAAK,MAAM,YAAY,iBAAiB,KAAA,GAAW,KAAA,GAAW,EAAE,OAAO,KAAK,MAAM,CAAC;GAChG,MAAM,OAAO,KAAK,MAAM,KAAK,eAAe,WAAW;GACvD,OAAO,OAAO,GAAG,KAAK,MAAM,SAAS;EACvC;CACF;MAGA,OAAO;EACL,MAAM,KAAK,OAAO,aAAa,aAAa;EAC5C,eAAe,KAAK,MAAM,YAAY,iBAAiB,aAAa,aAAa;CACnF;AAEJ;AAEA,SAAS,YAAY,aAAuB;CAC1C,OAAO,SAAS,WAAW,IAAI,UAAU,YAAY,IAAI,WAAW,IAAI;AAC1E;;AAGA,SAAS,UAAU,GAAkB,QAAwB;CAC3D,OAAO,OAAO,eAAe;AAC/B;;;;;;;AAwCA,SAAS,WAAW,UAAe,QAAkB;CAKnD,IAAI,CAAC,cAAc,QAAQ,KAAK,CAAC,MAAM,QAAQ,QAAQ,GAAG,OAAO;CACjE,IAAI,CAAC,UAAU,MAAM,GAAG,OAAO;CAE/B,MAAM,SAAc,MAAM,QAAQ,QAAQ,IAAI,CAAC,IAAK,CAAC;CAErD,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ;CAC/E,KAAK,MAAM,OAAO,MAChB,IAAI,OAAO,QAET,OAAO,OAAO,WAAY,SAAiB,MAAM,iBAAiB,OAAO,IAAI,CAAC;CAGlF,OAAO;AACT;;AAGA,SAAS,UAAU,KAAc,sBAAM,IAAI,QAAQ,GAAY;CAC7D,IAAI,eAAe,YACjB,OAAO,YAAY,GAAG;MACjB,IAAI,OAAO,OAAO,QAAQ,aAAa,cAAc,GAAG,KAAK,MAAM,QAAQ,GAAG,IAAI;EACvF,IAAI,IAAI,IAAI,GAAG,GAAG,OAAO,IAAI,IAAI,GAAG;EACpC,MAAM,SAAS,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;EAC1C,IAAI,IAAI,KAAK,MAAM;EACnB,OAAO,OAAO,QAAQ,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK,SAAS,GAAG,MAAM,UAAW,IAAY,MAAM,GAAG,EAAE,EAAE,CAAC;EACtG,OAAO;CACT,OACE,OAAO;AAEX;;AAGA,SAAS,iBAAiB,aAA+B;CACvD,IACE,YAAY,WAAW,KACvB,aAAa,WAAW,KACxB,WAAW,WAAW,KACtB,gBAAgB,WAAW,KAE3B,gBAAgB,WAAW,GAE3B,OAAO,mBAAmB,WAAW;CAEvC,OAAO;AACT;;;;;;;;;;;;;;AAeA,SAAS,mBAAmB,UAAoB;CAC9C,MAAM,IAAI,oBAAoB,WAAW,SAAS,iBAAiB,SAAS;CAC5E,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,QAAQ,MAAW,CAAC,EAAE,eAAe,IAAI;AACvE"}
package/package.json CHANGED
@@ -1,29 +1,49 @@
1
1
  {
2
2
  "name": "joist-test-utils",
3
- "version": "2.3.0",
3
+ "version": "2.4.0-next.2",
4
4
  "license": "MIT",
5
- "main": "build/index.js",
6
- "types": "build/index.d.ts",
7
- "scripts": {
8
- "format": "prettier --ignore-path ../../../.prettierignore --write '{schema,migrations,src}/**/*.{ts,js,tsx,jsx,graphql}'"
5
+ "type": "module",
6
+ "main": "build/index.cjs",
7
+ "module": "build/index.js",
8
+ "types": "build/index.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "bun": {
12
+ "types": "./build/index.d.mts",
13
+ "default": "./build/index.js"
14
+ },
15
+ "module-sync": {
16
+ "types": "./build/index.d.mts",
17
+ "default": "./build/index.js"
18
+ },
19
+ "import": {
20
+ "types": "./build/index.d.mts",
21
+ "default": "./build/index.js"
22
+ },
23
+ "require": {
24
+ "types": "./build/index.d.cts",
25
+ "default": "./build/index.cjs"
26
+ },
27
+ "default": "./build/index.js"
28
+ }
9
29
  },
10
30
  "files": [
11
31
  "build"
12
32
  ],
33
+ "dependencies": {
34
+ "dotenv": "^17.4.2"
35
+ },
13
36
  "peerDependencies": {
14
- "joist-core": "2.3.0",
15
- "joist-utils": "2.3.0",
16
- "pg": "^8.22.0"
37
+ "joist-core": "2.4.0-next.2",
38
+ "joist-utils": "2.4.0-next.2",
39
+ "pg": "^8.23.0"
17
40
  },
18
41
  "devDependencies": {
19
- "@swc/core": "^1.15.43",
42
+ "@swc/core": "^1.16.1",
20
43
  "@swc/jest": "^0.2.39",
21
44
  "@types/jest": "^30.0.0",
22
45
  "jest": "30.4.2",
23
- "prettier": "^3.8.4",
24
- "prettier-plugin-organize-imports": "^4.3.0",
25
- "ts-node-dev": "^2.0.0",
26
46
  "tsconfig-paths": "^4.2.0",
27
- "typescript": "6.0.3"
47
+ "typescript": "7.0.2"
28
48
  }
29
49
  }
@@ -1,9 +0,0 @@
1
- import { EntityManager, JoinRowTodo, Plugin, Todo } from "joist-core";
2
- export declare class RunPlugin extends Plugin {
3
- #private;
4
- readonly em: EntityManager;
5
- constructor(em: EntityManager);
6
- maybeCloneForNewEm(): this;
7
- afterWrite(entityTodos: Record<string, Todo>, joinRowTodos: Record<string, JoinRowTodo>): void;
8
- }
9
- //# sourceMappingURL=RunPlugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RunPlugin.d.ts","sourceRoot":"","sources":["../src/RunPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,aAAa,EAQb,WAAW,EAMX,MAAM,EAMN,IAAI,EACL,MAAM,YAAY,CAAC;AAOpB,qBAAa,SAAU,SAAQ,MAAM;;aAGP,EAAE,EAAE,aAAa;gBAAjB,EAAE,EAAE,aAAa;IAI7C,kBAAkB;IAIlB,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;CAyMxF"}
@@ -1,6 +0,0 @@
1
- import { EntityManager } from "joist-core";
2
- /** A very basic context that has `em` as the Joist `EntityManager`. */
3
- export type Context = {
4
- em: EntityManager;
5
- };
6
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,uEAAuE;AACvE,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,aAAa,CAAA;CAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":""}
package/build/index.d.ts DELETED
@@ -1,42 +0,0 @@
1
- import { MatchedEntity } from "./toMatchEntity";
2
- export { Context } from "./context";
3
- export { ContextFn, makeRun, makeRunEach, newContext, run, runEach } from "./run";
4
- export { RunPlugin } from "./RunPlugin";
5
- export { seed, SeedConfig } from "./seed";
6
- export { toMatchEntity } from "./toMatchEntity";
7
- export interface CustomMatcherResult {
8
- pass: boolean;
9
- message: () => string;
10
- }
11
- declare global {
12
- namespace jest {
13
- interface Matchers<R extends void | Promise<void>, T = {}> {
14
- toMatchEntity(expected: MatchedEntity<T>): CustomMatcherResult;
15
- }
16
- }
17
- }
18
- declare module "expect" {
19
- interface Matchers<R extends void | Promise<void>, T = unknown> {
20
- toMatchEntity(expected: MatchedEntity<T>): CustomMatcherResult;
21
- }
22
- }
23
- declare module "bun:test" {
24
- interface Matchers<T = unknown> {
25
- toMatchEntity(expected: MatchedEntity<T>): CustomMatcherResult;
26
- }
27
- }
28
- /**
29
- * A custom equality tester for Jest, i.e. install it like:
30
- *
31
- * ```
32
- * import { expect } from "@jest/globals";
33
- * expect.addEqualityTesters([areEntitiesEqual]);
34
- * ```
35
- *
36
- * This is necessary because Jest's `expect` uses deep equality for instances
37
- * of classes, but the `__data` key marked as non-enumerable, and all properties
38
- * made lazy and defined as getters on the prototype, there are no keys on the
39
- * individual objects left for Jest to see & realize "these are different".
40
- */
41
- export declare function areEntitiesEqual(a: unknown, b: unknown): boolean | undefined;
42
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YACvD,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC;SAChE;KACF;CACF;AAED,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,QAAQ,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,OAAO;QAC5D,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC;KAChE;CACF;AAGD,OAAO,QAAQ,UAAU,CAAC;IACxB,UAAU,QAAQ,CAAC,CAAC,GAAG,OAAO;QAC5B,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC;KAChE;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,uBAUtD"}
package/build/run.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import { Context } from "./context";
2
- type MaybePromise<T> = T | Promise<T>;
3
- export type ContextFn<C> = (ctx: C) => MaybePromise<C>;
4
- /** Runs the `fn` in a dedicated / non-test Unit of Work . */
5
- export declare function run<C extends Context, T>(ctx: C, fn: (ctx: C) => MaybePromise<T>, contextFn?: ContextFn<C>): Promise<T>;
6
- /** Creates a `run` with a custom `newContext` method. */
7
- export declare function makeRun<C extends Context>(contextFn: ContextFn<C>): <T>(ctx: C, fn: (ctx: C) => MaybePromise<T>) => Promise<T>;
8
- /** Runs the `fn` in a dedicated / non-test Unit of Work for each value in `values */
9
- export declare function runEach<C extends Context, T, U>(ctx: C, valuesFn: () => U[], fn: (ctx: C, value: U) => MaybePromise<T>, contextFn?: ContextFn<C>): Promise<T[]>;
10
- /** Creates a `runEach` with a custom `newContext` method. */
11
- export declare function makeRunEach<C extends Context>(contextFn: ContextFn<C>): <T, U>(ctx: C, valuesFn: () => U[], fn: (ctx: C, value: U) => MaybePromise<T>) => Promise<T[]>;
12
- /** A default `newContext` that assumes `ctx.em` is where the `EntityManager` lives. */
13
- export declare function newContext<C extends Context>(ctx: C): C;
14
- export {};
15
- //# sourceMappingURL=run.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC;AAMvD,6DAA6D;AAC7D,wBAAsB,GAAG,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAC5C,GAAG,EAAE,CAAC,EACN,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,EAC/B,SAAS,GAAE,SAAS,CAAC,CAAC,CAAc,GACnC,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,yDAAyD;AACzD,wBAAgB,OAAO,CAAC,CAAC,SAAS,OAAO,EACvC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GACtB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAE5D;AAED,qFAAqF;AACrF,wBAAsB,OAAO,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC,EACnD,GAAG,EAAE,CAAC,EACN,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,EACzC,SAAS,GAAE,SAAS,CAAC,CAAC,CAAc,GACnC,OAAO,CAAC,CAAC,EAAE,CAAC,CAad;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,EAC3C,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GACtB,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAEhG;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAMvD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAyB,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CA0BpH"}
@@ -1,27 +0,0 @@
1
- import { Entity, Property, ReadOnlyCollection, Reference } from "joist-core";
2
- import { CustomMatcherResult } from "./index";
3
- /**
4
- * Provides convenient `toMatchObject`-style matching for Joist entities.
5
- *
6
- * The biggest differences over `toMatchObject` are:
7
- *
8
- * - We un-wrap relations like m2o/o2m to just the underlying object/arrays, to make
9
- * asserting against the entities look like asserting against POJOs
10
- * - We prune the expected/actual values to be as minimal as possible, to avoid Jest
11
- * recursively crawling into connection pools or other misc non-useful things in the diffs
12
- */
13
- export declare function toMatchEntity<T>(this: any, actual: unknown, expected: MatchedEntity<T>): CustomMatcherResult;
14
- /**
15
- * Given a Joist entity `T`, "flattens out" the Reference/Collections.
16
- *
17
- * I.e. so that you can `toMatchEntity({ otherEntity: { name: "foo" } })` even though
18
- * `otherEntity` is technically a joist `Reference` or `Collection`.
19
- *
20
- * We allow `| null` so that `toMatchEntity` can work against optional fields
21
- * that are returned from GraphQL object resolvers.
22
- */
23
- export type MatchedEntity<T> = T extends ReadonlyArray<infer U> ? ReadonlyArray<MatchedEntity<U>> : undefined | T | {
24
- [K in keyof T]?: T[K] extends Reference<any, infer U, any> ? MatchedEntity<U> | U : T[K] extends ReadOnlyCollection<any, infer U> ? Array<MatchedEntity<U> | U> : T[K] extends Property<any, infer V> ? V : T[K] extends Entity | null | undefined ? MatchedEntity<T[K]> | T[K] | null | undefined : T[K] extends ReadonlyArray<infer U | undefined> ? readonly (MatchedEntity<U> | U | undefined)[] : T[K] extends ReadonlyArray<infer U> | null ? readonly (MatchedEntity<U> | U | null)[] : // We recurse similar to a DeepPartial
25
- MatchedEntity<T[K]> | null;
26
- };
27
- //# sourceMappingURL=toMatchEntity.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toMatchEntity.d.ts","sourceRoot":"","sources":["../src/toMatchEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAQN,QAAQ,EACR,kBAAkB,EAClB,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAM9C;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,mBAAmB,CA8B5G;AAWD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IACzB,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAC5B,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAE3B,SAAS,GACT,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,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAC3C,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAC3B,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GACjC,CAAC,GACD,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC,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,GAC7C,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,GACxC,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;CACzC,CAAC"}