@cedarjs/testing 7.0.0-canary.3086 → 7.0.0-canary.3088

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.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Whether `e` is a constraint violation that scenario teardown recovers from
3
+ * by emptying the table later, rather than an error worth raising.
4
+ */
5
+ export declare function isHandledTeardownError(e: unknown): boolean;
6
+ /**
7
+ * Empties every table in `order`, deferring a table to the end of the order
8
+ * when a foreign key says another table has to be emptied first, and
9
+ * returning the order that worked so the next run can start with it.
10
+ *
11
+ * A table that cannot be emptied in any order (a trigger that aborts the
12
+ * delete, or a foreign key no ordering satisfies) would otherwise be deferred
13
+ * forever, since deferring appends to the order being walked. Deferring every
14
+ * table still waiting without emptying one means no order works, so the
15
+ * driver's error is raised instead.
16
+ */
17
+ export declare function emptyTablesInWorkingOrder(order: string[], emptyTable: (modelName: string) => Promise<unknown>): Promise<string[]>;
18
+ //# sourceMappingURL=teardown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teardown.d.ts","sourceRoot":"","sources":["../../../src/api/vitest/teardown.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAQ1D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAClD,OAAO,CAAC,MAAM,EAAE,CAAC,CA+BnB"}
@@ -0,0 +1,43 @@
1
+ const RETRYABLE_ERROR_KINDS = [
2
+ "ForeignKeyConstraintViolation",
3
+ "RestrictViolation"
4
+ ];
5
+ function property(value, key) {
6
+ return typeof value === "object" && value !== null ? value[key] : void 0;
7
+ }
8
+ function isHandledTeardownError(e) {
9
+ const cause = property(
10
+ property(property(e, "meta"), "driverAdapterError"),
11
+ "cause"
12
+ );
13
+ const kind = property(cause, "kind");
14
+ return typeof kind === "string" && RETRYABLE_ERROR_KINDS.includes(kind);
15
+ }
16
+ async function emptyTablesInWorkingOrder(order, emptyTable) {
17
+ const remaining = [...order];
18
+ let pendingCount = remaining.length;
19
+ let deferralsSinceLastEmptied = 0;
20
+ for (const modelName of remaining) {
21
+ if (modelName === null) {
22
+ continue;
23
+ }
24
+ try {
25
+ await emptyTable(modelName);
26
+ pendingCount--;
27
+ deferralsSinceLastEmptied = 0;
28
+ } catch (e) {
29
+ console.error("teardown error\n", e);
30
+ if (!isHandledTeardownError(e) || deferralsSinceLastEmptied >= pendingCount) {
31
+ throw e;
32
+ }
33
+ deferralsSinceLastEmptied++;
34
+ remaining[remaining.indexOf(modelName)] = null;
35
+ remaining.push(modelName);
36
+ }
37
+ }
38
+ return remaining.filter((name) => name !== null);
39
+ }
40
+ export {
41
+ emptyTablesInWorkingOrder,
42
+ isHandledTeardownError
43
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"vitest-api.setup.d.ts","sourceRoot":"","sources":["../../../src/api/vitest/vitest-api.setup.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA0C1D,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;CAC3E;AAUD,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,cAAc,EAAE,cAAc,CAAA;IAElC,IAAI,uBAAuB,EAAE,OAAO,CAAA;CACrC"}
1
+ {"version":3,"file":"vitest-api.setup.d.ts","sourceRoot":"","sources":["../../../src/api/vitest/vitest-api.setup.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA4C1D,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;CAC3E;AAUD,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,cAAc,EAAE,cAAc,CAAA;IAElC,IAAI,uBAAuB,EAAE,OAAO,CAAA;CACrC"}
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { afterAll, beforeEach, it, describe, vi, beforeAll } from "vitest";
4
4
  import { getPaths, getPrismaSchemas } from "@cedarjs/project-config";
5
5
  import { defineScenario } from "@cedarjs/testing/api";
6
+ import { emptyTablesInWorkingOrder } from "./teardown.js";
6
7
  const mockContextStore = vi.hoisted(() => /* @__PURE__ */ new Map());
7
8
  const mockContext = vi.hoisted(
8
9
  () => new Proxy(
@@ -38,7 +39,6 @@ globalThis.mockCurrentUser = (currentUser) => {
38
39
  };
39
40
  globalThis.defineScenario = defineScenario;
40
41
  const cedarPaths = getPaths();
41
- const HANDLED_ERRORS = [1451, 1811, 23001, 23503];
42
42
  const TEARDOWN_CACHE_PATH = path.join(
43
43
  cedarPaths.generated.base,
44
44
  "scenarioTeardown.json"
@@ -132,23 +132,12 @@ async function teardown() {
132
132
  }
133
133
  const quoteStyle2 = await getQuoteStyle();
134
134
  const projectDb = await getProjectDb();
135
- for (const modelName of teardownOrder) {
136
- try {
137
- const query = `DELETE FROM ${quoteStyle2}${modelName}${quoteStyle2}`;
138
- await projectDb.$executeRawUnsafe(query);
139
- } catch (e) {
140
- console.error("teardown error\n", e);
141
- const match = isErrorWithMessage(e) && e.message.match(/Code: `(\d+)`/);
142
- if (match && HANDLED_ERRORS.includes(parseInt(match[1]))) {
143
- const index = teardownOrder.indexOf(modelName);
144
- teardownOrder[index] = null;
145
- teardownOrder.push(modelName);
146
- } else {
147
- throw e;
148
- }
149
- }
150
- }
151
- teardownOrder = teardownOrder.filter((val) => val);
135
+ teardownOrder = await emptyTablesInWorkingOrder(
136
+ teardownOrder,
137
+ (modelName) => projectDb.$executeRawUnsafe(
138
+ `DELETE FROM ${quoteStyle2}${modelName}${quoteStyle2}`
139
+ )
140
+ );
152
141
  if (!isIdenticalArray(teardownOrder, originalTeardownOrder)) {
153
142
  originalTeardownOrder = deepCopy(teardownOrder);
154
143
  fs.writeFileSync(TEARDOWN_CACHE_PATH, JSON.stringify(teardownOrder));
@@ -235,9 +224,6 @@ function isIdenticalArray(a, b) {
235
224
  function deepCopy(obj) {
236
225
  return JSON.parse(JSON.stringify(obj));
237
226
  }
238
- function isErrorWithMessage(e) {
239
- return !!e && typeof e === "object" && "message" in e && typeof e.message === "string";
240
- }
241
227
  function isErrorWithCode(e) {
242
228
  return !!e && typeof e === "object" && "code" in e && typeof e.code === "string";
243
229
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/testing",
3
- "version": "7.0.0-canary.3086",
3
+ "version": "7.0.0-canary.3088",
4
4
  "description": "Tools, wrappers and configuration for testing a Cedar project.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -54,9 +54,9 @@
54
54
  "test:watch": "vitest watch"
55
55
  },
56
56
  "dependencies": {
57
- "@cedarjs/context": "7.0.0-canary.3086",
58
- "@cedarjs/graphql-server": "7.0.0-canary.3086",
59
- "@cedarjs/project-config": "7.0.0-canary.3086",
57
+ "@cedarjs/context": "7.0.0-canary.3088",
58
+ "@cedarjs/graphql-server": "7.0.0-canary.3088",
59
+ "@cedarjs/project-config": "7.0.0-canary.3088",
60
60
  "@testing-library/dom": "10.4.1",
61
61
  "@testing-library/jest-dom": "6.9.1",
62
62
  "@testing-library/react": "16.3.3",
@@ -73,19 +73,19 @@
73
73
  },
74
74
  "devDependencies": {
75
75
  "@arethetypeswrong/cli": "0.18.5",
76
- "@cedarjs/auth": "7.0.0-canary.3086",
77
- "@cedarjs/framework-tools": "7.0.0-canary.3086",
78
- "@cedarjs/router": "7.0.0-canary.3086",
79
- "@cedarjs/web": "7.0.0-canary.3086",
76
+ "@cedarjs/auth": "7.0.0-canary.3088",
77
+ "@cedarjs/framework-tools": "7.0.0-canary.3088",
78
+ "@cedarjs/router": "7.0.0-canary.3088",
79
+ "@cedarjs/web": "7.0.0-canary.3088",
80
80
  "concurrently": "9.2.4",
81
81
  "publint": "0.3.24",
82
82
  "typescript": "5.9.3",
83
83
  "vitest": "4.1.11"
84
84
  },
85
85
  "peerDependencies": {
86
- "@cedarjs/auth": "7.0.0-canary.3086",
87
- "@cedarjs/router": "7.0.0-canary.3086",
88
- "@cedarjs/web": "7.0.0-canary.3086",
86
+ "@cedarjs/auth": "7.0.0-canary.3088",
87
+ "@cedarjs/router": "7.0.0-canary.3088",
88
+ "@cedarjs/web": "7.0.0-canary.3088",
89
89
  "vitest": "4.1.11"
90
90
  },
91
91
  "peerDependenciesMeta": {