@fougere/testing 0.5.0-alpha.1 → 0.7.0-alpha.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.
Files changed (71) hide show
  1. package/README.md +1 -1
  2. package/dist/all.d.ts +2 -17
  3. package/dist/all.d.ts.map +1 -1
  4. package/dist/all.js +2 -17
  5. package/dist/all.js.map +1 -1
  6. package/dist/app.d.ts +4 -35
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +2 -17
  9. package/dist/app.js.map +1 -1
  10. package/dist/comparison.d.ts +3 -20
  11. package/dist/comparison.d.ts.map +1 -1
  12. package/dist/comparison.js +29 -58
  13. package/dist/comparison.js.map +1 -1
  14. package/dist/derive.d.ts +3 -9
  15. package/dist/derive.d.ts.map +1 -1
  16. package/dist/derive.js +1 -7
  17. package/dist/derive.js.map +1 -1
  18. package/dist/doors.d.ts +4 -22
  19. package/dist/doors.d.ts.map +1 -1
  20. package/dist/doors.js +6 -24
  21. package/dist/doors.js.map +1 -1
  22. package/dist/gql.d.ts +5 -24
  23. package/dist/gql.d.ts.map +1 -1
  24. package/dist/gql.js +11 -37
  25. package/dist/gql.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/load.d.ts +3 -20
  30. package/dist/load.d.ts.map +1 -1
  31. package/dist/load.js +6 -23
  32. package/dist/load.js.map +1 -1
  33. package/dist/remotes.d.ts +1 -6
  34. package/dist/remotes.d.ts.map +1 -1
  35. package/dist/remotes.js +1 -6
  36. package/dist/remotes.js.map +1 -1
  37. package/dist/sample.d.ts +2 -14
  38. package/dist/sample.d.ts.map +1 -1
  39. package/dist/sample.js +8 -16
  40. package/dist/sample.js.map +1 -1
  41. package/dist/scope.d.ts +5 -38
  42. package/dist/scope.d.ts.map +1 -1
  43. package/dist/scope.js +4 -26
  44. package/dist/scope.js.map +1 -1
  45. package/dist/stub.d.ts +3 -32
  46. package/dist/stub.d.ts.map +1 -1
  47. package/dist/stub.js +3 -32
  48. package/dist/stub.js.map +1 -1
  49. package/dist/sync.d.ts +2 -19
  50. package/dist/sync.d.ts.map +1 -1
  51. package/dist/sync.js +5 -22
  52. package/dist/sync.js.map +1 -1
  53. package/dist/vitest.d.ts +1 -20
  54. package/dist/vitest.d.ts.map +1 -1
  55. package/dist/vitest.js +1 -20
  56. package/dist/vitest.js.map +1 -1
  57. package/package.json +9 -9
  58. package/src/all.ts +2 -17
  59. package/src/app.ts +5 -41
  60. package/src/comparison.ts +34 -63
  61. package/src/derive.ts +3 -9
  62. package/src/doors.ts +7 -25
  63. package/src/gql.ts +9 -35
  64. package/src/index.ts +1 -1
  65. package/src/load.ts +7 -24
  66. package/src/remotes.ts +1 -6
  67. package/src/sample.ts +10 -30
  68. package/src/scope.ts +5 -38
  69. package/src/stub.ts +3 -32
  70. package/src/sync.ts +5 -22
  71. package/src/vitest.ts +1 -20
package/src/stub.ts CHANGED
@@ -8,18 +8,7 @@ export type Port = abstract new (...args: never[]) => unknown;
8
8
  /** The double handed in place of a port — one spy per method the port declares. */
9
9
  export type Stub<T> = { [K in keyof T]: T[K] extends (...args: never[]) => unknown ? Mock : T[K] };
10
10
 
11
- /**
12
- * The methods a port declares, read from the prototype chain at runtime.
13
- *
14
- * Not written by hand and not read from the AST: `ProviderEntry` keeps `ctor`, `deps` and
15
- * `filePath` and never the methods, while the prototype has them all along. So a double
16
- * carries exactly what the port carries and gains a method the day the port does — which
17
- * is the failure `ports.test.ts` records, a `charge is not a function` from a stand-in
18
- * that did not carry what its type promised.
19
- *
20
- * Walks the chain because a port may itself extend one; stops at `Object.prototype`,
21
- * whose members belong to no port.
22
- */
11
+ /** The methods a port declares, read from the prototype chain at runtime. */
23
12
  export function methodsOf(port: Port): string[] {
24
13
  const found = new Set<string>();
25
14
  let proto: object | null = port.prototype as object;
@@ -34,32 +23,14 @@ export function methodsOf(port: Port): string[] {
34
23
  return [...found];
35
24
  }
36
25
 
37
- /**
38
- * A double for a port: every method present, every call recorded, nothing returned.
39
- *
40
- * What it RETURNS is not derivable and the value is the caller's to state — a service's
41
- * return type is a bare TypeScript type, erased at runtime, with no declared fields for
42
- * anything to build from. The same line the whole package sits on: what Fougere's
43
- * vocabulary declares can be derived, arbitrary code cannot.
44
- */
26
+ /** A double for a port. */
45
27
  export function stubOf<T>(port: Port): Stub<T> {
46
28
  const double: Record<string, Mock> = {};
47
29
  for (const method of methodsOf(port)) double[method] = vi.fn();
48
30
  return double as Stub<T>;
49
31
  }
50
32
 
51
- /**
52
- * Put doubles in front of ports, in every frond scope that answers under their name.
53
- *
54
- * After the boot rather than through `ports:`, because the container resolves lazily: a
55
- * provider is built on first `resolve`, so a value registered before any call is the one
56
- * a handler receives. `registerValue` also marks it as not the container's to dispose,
57
- * which is right — the test made it.
58
- *
59
- * A port nobody answers under is REFUSED by name, for the reason `ports:` refuses a key
60
- * that matched nothing: a double that silently stands in front of no one reads as a test
61
- * that covered a case it never reached.
62
- */
33
+ /** Put doubles in front of ports, in every frond scope that answers under their name. */
63
34
  export function installStubs(app: App, ports: Port[]): Map<Port, Stub<unknown>> {
64
35
  const doubles = new Map<Port, Stub<unknown>>();
65
36
  const scopes = app.fronds.map((frond) => app.resolve<Container>(`frond:${frond.name}`));
package/src/sync.ts CHANGED
@@ -33,28 +33,18 @@ export async function syncedRemotes(root: string): Promise<SyncedRemote[]> {
33
33
  }
34
34
  }
35
35
 
36
- /**
37
- * The shapes a consumer holds for one remote frond.
38
- *
39
- * Rebuilt from the classes rather than read back: `fougere sync` writes entities and an
40
- * index and does NOT keep the card it received. So the consumer's copy of the OPERATIONS
41
- * has no local counterpart at all, and only the shapes can be compared — which is the
42
- * narrower half, and the one that breaks a caller silently.
43
- *
44
- * Closing that would mean `sync` writing the card beside the classes; it is a change to
45
- * the CLI, not to this file.
46
- */
36
+ /** The shapes a consumer holds for one remote frond. */
47
37
  export async function heldShapes(remote: SyncedRemote): Promise<Map<string, SchemaDescriptor>> {
48
- const held = new Map<string, SchemaDescriptor>();
38
+ const cards = new Map<string, SchemaDescriptor>();
49
39
  const index = pathToFileURL(join(remote.path, 'index.ts')).href;
50
40
  const module = await import(index) as Record<string, unknown>;
51
41
 
52
42
  for (const [name, exported] of Object.entries(module)) {
53
43
  const entity = exported as SchemaView | undefined;
54
44
  if (typeof entity !== 'function' || typeof (entity as SchemaView).getFields !== 'function') continue;
55
- held.set(name, Card.fromSchema(entity).descriptor);
45
+ cards.set(name, Card.fromSchema(entity).descriptor);
56
46
  }
57
- return held;
47
+ return cards;
58
48
  }
59
49
 
60
50
  /** The shapes a card announces, by the name a door carries. */
@@ -67,14 +57,7 @@ function servedShapes(card: IdentityCard, frond: string): Map<string, unknown> {
67
57
  return served;
68
58
  }
69
59
 
70
- /**
71
- * What the consumer's copy no longer matches.
72
- *
73
- * Compared by the shape's own `title` — the entity's name as the descriptor carries it —
74
- * rather than by the door's, because a door is addressed in lowercase (`post`) and a class
75
- * is not (`Post`), and matching those two by hand is where a name convention gets copied
76
- * a third time.
77
- */
60
+ /** What the consumer's copy no longer matches. */
78
61
  export function syncDriftOf(
79
62
  held: Map<string, SchemaDescriptor>,
80
63
  card: IdentityCard,
package/src/vitest.ts CHANGED
@@ -1,25 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
2
 
3
- /**
4
- * The vitest configuration a Fougere project needs, so nobody has to discover it.
5
- *
6
- * One thing to know, and it is not obvious: `graphql` guards its types with `instanceOf`,
7
- * so a schema built by one loaded copy is refused by another with *"from another module
8
- * or realm"*. Under vitest a module is either transformed by Vite or externalized and
9
- * loaded by node, and Pothos ending up on one side while `graphql()` sits on the other
10
- * makes two copies of the same file. The alias pins the path, and the inlining makes the
11
- * packages that touch it take that path — neither alone is enough, which is what made
12
- * this cost an afternoon.
13
- *
14
- * An app that serves no GraphQL pays nothing for this: the alias resolves to whatever
15
- * `graphql` the project has, and no `graphql` means the option is simply unused.
16
- *
17
- * ```ts
18
- * // vitest.config.ts
19
- * import { fougereTest } from '@fougere/testing/vitest';
20
- * export default fougereTest();
21
- * ```
22
- */
3
+ /** The vitest configuration a Fougere project needs, so nobody has to discover it. */
23
4
  export function fougereTest(overrides: Record<string, unknown> = {}): Record<string, unknown> {
24
5
  const require = createRequire(import.meta.url);
25
6
  let graphqlDir: string | undefined;