joist-codegen 2.4.0-next.26 → 2.4.0-next.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joist-codegen",
3
- "version": "2.4.0-next.26",
3
+ "version": "2.4.0-next.27",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -48,7 +48,7 @@
48
48
  "skills"
49
49
  ],
50
50
  "peerDependencies": {
51
- "joist-utils": "2.4.0-next.26",
51
+ "joist-utils": "2.4.0-next.27",
52
52
  "knex": "^3.1.0",
53
53
  "pg": "^8.23.0"
54
54
  },
@@ -30,7 +30,9 @@ Authoritative references:
30
30
  5. Use `run` or the project's `makeRun` wrapper when production code needs an
31
31
  isolated `EntityManager`; it flushes Given state and mirrors the callback's
32
32
  flushed Joist writes into the original test graph.
33
- 6. Assert entity state and relationships with `toMatchEntity`.
33
+ 6. Assert entity state and relationships with `toMatchEntity`. Prefer checking
34
+ side effects through retained entities and their relations instead of using
35
+ `em.getEntities` to discover what the action created or changed.
34
36
  7. Prefer focused tests for one behavior over a single scenario that exercises
35
37
  unrelated updates at several graph levels.
36
38
 
@@ -338,6 +340,39 @@ expect((await author.books.load()).map((book) => ({ id: book.id, title: book.tit
338
340
  ]);
339
341
  ```
340
342
 
343
+ ## Assert Side Effects Through the Domain Graph
344
+
345
+ Avoid `em.getEntities(Entity).filter(...)` or `.find(...)` to look up side
346
+ effects for assertions. `getEntities` inspects the `EntityManager`'s tracked
347
+ entities; finding a new child there does not prove that the action attached it
348
+ to the correct parent. Assert through the retained Given graph instead, so the
349
+ test describes the resulting domain state and checks relationship membership.
350
+
351
+ ```ts
352
+ // Less useful: finds a book without proving which author owns it.
353
+ const [createdBook] = ctx.em.getEntities(Book).filter((book) => book.title === "New book");
354
+ expect(createdBook).toMatchEntity({ title: "New book" });
355
+ ```
356
+
357
+ ```ts
358
+ it.withCtx("adds a book to the existing author", async (ctx) => {
359
+ // Given an author with an existing book
360
+ const author = newAuthor(ctx.em, { books: [{}] });
361
+ const [existingBook] = author.books.get;
362
+
363
+ // When we add another book to that author
364
+ await run(ctx, (ctx) => addBook(ctx, { authorId: author.id, title: "New book" }));
365
+
366
+ // Then the author keeps the existing book and owns the new book
367
+ expect(author).toMatchEntity({ books: [existingBook, { title: "New book" }] });
368
+ });
369
+ ```
370
+
371
+ Use the action result when a new entity has no natural path from the Given
372
+ graph. If neither a relation nor the result exposes it, use an intentional
373
+ domain query. Reserve `getEntities` assertions for tests whose behavior under
374
+ test is specifically which entities the `EntityManager` tracks.
375
+
341
376
  ## Keep Tests Focused
342
377
 
343
378
  One test should describe one coherent boundary. Split a large graph mutation
@@ -392,6 +427,8 @@ reuse decisions instead of replacing factories with manual setup.
392
427
  - Important entities have direct, role-based `const` names.
393
428
  - Separate production units of work use `run`/`makeRun` and flush normally.
394
429
  - Assertions reuse loaded factory entities with `toMatchEntity`.
430
+ - Side-effect assertions follow domain relations or action results instead of
431
+ scanning `em.getEntities` for created or changed entities.
395
432
  - No unnecessary reloads, `load()` calls, assertion awaits, or direct flushes
396
433
  remain.
397
434
  - Each test covers one coherent boundary.