@ddd-ts-kit/testing 0.2.0 → 0.3.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/README.md CHANGED
@@ -161,7 +161,7 @@ it('records the payment of a placed order', () => {
161
161
  it('refuses to pay an order twice', () => {
162
162
  given(anOrder().paid())
163
163
  .when((order) => order.pay())
164
- .thenError(OrderAlreadyPaid, 'ORDER_ALREADY_PAID')
164
+ .thenError('ORDER_ALREADY_PAID')
165
165
  .thenState((order) => expect(order.status).toBe('paid'));
166
166
  });
167
167
  ```
@@ -175,7 +175,8 @@ the same with the arrangement as a function, replayed from a fresh aggregate at
175
175
  | `thenEvents([...])` | exactly these events, in order; each described by its name, its class, or the properties that matter |
176
176
  | `thenEventNames([...])` | exactly these names, in order |
177
177
  | `thenNoEvent()` | nothing was recorded |
178
- | `thenError(ErrorClass, code?)`, `thenError(code)` | the action threw that error |
178
+ | `thenError(code)`, `thenError(code, facts)` | the action refused with that code, whatever the class of the error, carrying these facts when given (it may carry others) |
179
+ | `thenError(ErrorClass, code?)` | the action threw an instance of that class: for an error that is one class, as 0.2 wrote them |
179
180
  | `thenState((aggregate) => ...)` | your own assertions on the aggregate pass |
180
181
 
181
182
  Failures are `AssertionError`s of `node:assert` with the expected and recorded events side by
@@ -183,6 +184,25 @@ side, so they read well under any runner. An error raised by `when` is never swa
183
184
  assertion but `thenError` fails on it. When `when` (or the arrangement) is asynchronous, the
184
185
  chain is a promise: `await given(order).when(async (o) => ...).thenEventNames([...])`.
185
186
 
187
+ ## Refusals
188
+
189
+ A business refusal is known by its code, and carries its facts as data: a test asserts both,
190
+ never a message and never the class of one refusal.
191
+
192
+ ```ts
193
+ import { expectRefusal } from '@ddd-ts-kit/testing';
194
+
195
+ expectRefusal(() => calendar.slotFor('consultation', startsAt, now), 'BOOKING_TOO_LATE', { notice: 120 });
196
+ expectRefusal(Email.create('ada@'), 'INVALID_EMAIL');
197
+ await expectRefusal(() => commands.execute(command), 'SLOT_TAKEN', { calendarId: 'calendar-1' });
198
+ ```
199
+
200
+ `expectRefusal(subject, code, facts?)` reads an action, which it runs, a `Result`, or an error
201
+ already caught. An action that returns a promise gives a promise to await. It answers the
202
+ error, and fails with an `AssertionError` that names what was refused instead, or the facts
203
+ that differ, one line each. The facts given must be carried with those values; the refusal may
204
+ carry others.
205
+
186
206
  ## Handlers
187
207
 
188
208
  ```ts
@@ -292,7 +312,7 @@ afterAll(() => server.close());
292
312
  | `client.get / post / put / patch / delete` | JSON in, `{ status, headers, body }` out; `body` is parsed when the content type is JSON, text otherwise; a 4xx or 5xx is a response, not an exception |
293
313
  | `client.post(path, body, { headers })`, `client.withHeaders(headers)` | headers for one call, or a client for another caller |
294
314
  | `expectStatus(response, 201)` | hands the response back, or fails showing the body, where the API says why |
295
- | `expectProblem(response, { status, code })` | asserts an RFC 9457 `application/problem+json` answer and returns the document |
315
+ | `expectProblem(response, { status, code, facts })` | asserts an RFC 9457 `application/problem+json` answer and returns the document; `code` and `facts` are optional, and `facts` names the facts the document must expose, as JSON writes them (a date is its ISO text) |
296
316
  | `eventually(assertion, { timeoutMs = 2000, intervalMs = 20 })` | retries until the assertion passes; when the time is up, fails quoting the last error |
297
317
  | `collectEvents(subscriber, types)` | records published integration events: `received(type?)`, `waitFor(type, predicate?, options?)`, `stop()` |
298
318
 
@@ -349,7 +369,7 @@ levels of `docs/ARCHITECTURE.md` (the adapter level is the contract suites, belo
349
369
  it('refuses to pay an order twice', () => {
350
370
  given(anOrder().paid())
351
371
  .when((order) => order.pay(at))
352
- .thenError(OrderAlreadyPaid, 'ORDER_ALREADY_PAID');
372
+ .thenError('ORDER_ALREADY_PAID');
353
373
  });
354
374
 
355
375
  // 2. Application: the real handler through the bus, fakes for the ports.
@@ -3,11 +3,14 @@ export interface ExpectedProblem {
3
3
  readonly status: number;
4
4
  /** The stable error code, when the answer must carry this one. */
5
5
  readonly code?: string;
6
+ /** The facts the document must expose under `facts`, by name, as JSON writes them. It may expose others. */
7
+ readonly facts?: Readonly<Record<string, unknown>>;
6
8
  }
7
9
  export type ProblemDetails = Readonly<Record<string, unknown>>;
8
10
  /**
9
11
  * Asserts an RFC 9457 answer: the status, on the response and in the document, the
10
- * `application/problem+json` content type and the `code` member. Returns the document.
12
+ * `application/problem+json` content type, the `code` member and, when given, the exposed
13
+ * `facts`. Returns the document.
11
14
  */
12
15
  export declare function expectProblem(response: HttpResponse, expected: ExpectedProblem): ProblemDetails;
13
16
  //# sourceMappingURL=expect-problem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expect-problem.d.ts","sourceRoot":"","sources":["../../src/e2e/expect-problem.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI/D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,eAAe,GAAG,cAAc,CAkB/F"}
1
+ {"version":3,"file":"expect-problem.d.ts","sourceRoot":"","sources":["../../src/e2e/expect-problem.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,4GAA4G;IAC5G,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI/D;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,eAAe,GAAG,cAAc,CAoB/F"}
@@ -2,22 +2,29 @@ import { deepStrictEqual } from 'node:assert';
2
2
  const PROBLEM_JSON = 'application/problem+json';
3
3
  /**
4
4
  * Asserts an RFC 9457 answer: the status, on the response and in the document, the
5
- * `application/problem+json` content type and the `code` member. Returns the document.
5
+ * `application/problem+json` content type, the `code` member and, when given, the exposed
6
+ * `facts`. Returns the document.
6
7
  */
7
8
  export function expectProblem(response, expected) {
8
9
  const problem = isRecord(response.body) ? response.body : {};
9
10
  const code = (value) => (expected.code === undefined ? {} : { code: value });
11
+ const exposed = isRecord(problem.facts) ? problem.facts : {};
12
+ const names = Object.keys(expected.facts ?? {});
10
13
  deepStrictEqual({
11
14
  status: response.status,
12
15
  contentType: mediaTypeOf(response),
13
- problem: { status: problem.status, ...code(problem.code) },
16
+ problem: { status: problem.status, ...code(problem.code), ...facts(names, exposed) },
14
17
  }, {
15
18
  status: expected.status,
16
19
  contentType: PROBLEM_JSON,
17
- problem: { status: expected.status, ...code(expected.code) },
20
+ problem: { status: expected.status, ...code(expected.code), ...facts(names, expected.facts ?? {}) },
18
21
  });
19
22
  return problem;
20
23
  }
24
+ /** The named facts alone, so that the comparison shows the ones that differ and no other. */
25
+ function facts(names, source) {
26
+ return names.length === 0 ? {} : { facts: Object.fromEntries(names.map((name) => [name, source[name]])) };
27
+ }
21
28
  function isRecord(value) {
22
29
  return typeof value === 'object' && value !== null && !Array.isArray(value);
23
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"expect-problem.js","sourceRoot":"","sources":["../../src/e2e/expect-problem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAW9C,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAsB,EAAE,QAAyB;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE9F,eAAe,CACb;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC;QAClC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;KAC3D,EACD;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,WAAW,EAAE,YAAY;QACzB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;KAC7D,CACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,QAAsB;IACzC,OAAO,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"expect-problem.js","sourceRoot":"","sources":["../../src/e2e/expect-problem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAa9C,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAsB,EAAE,QAAyB;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9F,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAEhD,eAAe,CACb;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC;QAClC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;KACrF,EACD;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,WAAW,EAAE,YAAY;QACzB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;KACpG,CACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6FAA6F;AAC7F,SAAS,KAAK,CAAC,KAAwB,EAAE,MAAyC;IAChF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5G,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,QAAsB;IACzC,OAAO,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAC/E,CAAC"}
package/dist/index.d.ts CHANGED
@@ -14,6 +14,8 @@ export { ExecutionContextBuilder } from './execution/execution-context-builder.j
14
14
  export { scoped } from './execution/scoped.js';
15
15
  export { SessionBuilder } from './execution/session-builder.js';
16
16
  export { createTestBuses, type TestBuses, type TestBusesOptions } from './harness/create-test-buses.js';
17
+ export { expectRefusal } from './refusals/expect-refusal.js';
18
+ export type { ExpectedFacts } from './refusals/expected-facts.js';
17
19
  export { InMemoryRepository, type InMemoryRepositoryOptions } from './repositories/in-memory-repository.js';
18
20
  export { snapshots } from './repositories/snapshots.js';
19
21
  export { expectNoSecret } from './secrecy/expect-no-secret.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ export { ExecutionContextBuilder } from './execution/execution-context-builder.j
11
11
  export { scoped } from './execution/scoped.js';
12
12
  export { SessionBuilder } from './execution/session-builder.js';
13
13
  export { createTestBuses } from './harness/create-test-buses.js';
14
+ export { expectRefusal } from './refusals/expect-refusal.js';
14
15
  export { InMemoryRepository } from './repositories/in-memory-repository.js';
15
16
  export { snapshots } from './repositories/snapshots.js';
16
17
  export { expectNoSecret } from './secrecy/expect-no-secret.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAyC,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,kBAAkB,EAAkC,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAiB,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAyC,MAAM,gCAAgC,CAAC;AACxG,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAkC,MAAM,wCAAwC,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAiB,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ExpectedFacts } from './expected-facts.js';
2
+ /**
3
+ * Asserts a business refusal by its code, and by its facts when given: on an error that was
4
+ * caught, on a `Result`, or on an action, which is run. The class of the error is not looked
5
+ * at. Returns the error; an action that returns a promise gives a promise to await.
6
+ *
7
+ * expectRefusal(() => appointment.cancel(at), 'APPOINTMENT_ENDED', { status: 'cancelled' });
8
+ * expectRefusal(Email.create('nope'), 'INVALID_EMAIL');
9
+ * await expectRefusal(() => bus.execute(command), 'SLOT_TAKEN');
10
+ */
11
+ export declare function expectRefusal(subject: () => PromiseLike<unknown>, code: string, facts?: ExpectedFacts): Promise<unknown>;
12
+ export declare function expectRefusal(subject: unknown, code: string, facts?: ExpectedFacts): unknown;
13
+ //# sourceMappingURL=expect-refusal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect-refusal.d.ts","sourceRoot":"","sources":["../../src/refusals/expect-refusal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQzD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,EACnC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,aAAa,GACpB,OAAO,CAAC,OAAO,CAAC,CAAC;AACpB,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { AssertionError } from 'node:assert';
2
+ import { isPromiseLike } from '../scenarios/is-promise-like.js';
3
+ import { show } from '../scenarios/show.js';
4
+ import { factMismatches } from './fact-mismatches.js';
5
+ export function expectRefusal(subject, code, facts = {}) {
6
+ const attempt = attempted(subject);
7
+ if (isPromiseLike(attempt)) {
8
+ return Promise.resolve(attempt).then(() => refusalOf({ refused: false }, code, facts), (error) => refusalOf({ refused: true, error }, code, facts));
9
+ }
10
+ return refusalOf(attempt, code, facts);
11
+ }
12
+ function attempted(subject) {
13
+ if (!isAction(subject)) {
14
+ return outcomeOf(subject);
15
+ }
16
+ try {
17
+ const answer = subject();
18
+ return isPromiseLike(answer) ? answer : outcomeOf(answer, { ran: true });
19
+ }
20
+ catch (error) {
21
+ return { refused: true, error };
22
+ }
23
+ }
24
+ function isAction(subject) {
25
+ return typeof subject === 'function';
26
+ }
27
+ /** A `Result` says by itself whether it refuses; anything else an action returned is a success. */
28
+ function outcomeOf(value, { ran = false } = {}) {
29
+ if (typeof value === 'object' && value !== null && 'ok' in value && typeof value.ok === 'boolean') {
30
+ return value.ok || !('error' in value) ? { refused: false } : { refused: true, error: value.error };
31
+ }
32
+ return ran ? { refused: false } : { refused: true, error: value };
33
+ }
34
+ function refusalOf(attempt, code, facts) {
35
+ if (!attempt.refused) {
36
+ throw failure(`Expected a refusal with code ${code}, but nothing was refused.`, undefined, code);
37
+ }
38
+ const { error } = attempt;
39
+ const actual = codeOf(error);
40
+ if (actual !== code) {
41
+ throw failure(`Expected a refusal with code ${code}, but got ${described(error)}.`, actual, code);
42
+ }
43
+ const mismatches = factMismatches(error, facts);
44
+ if (mismatches.length > 0) {
45
+ throw failure([`The refusal ${code} does not carry the expected facts.`, ...mismatches].join('\n '), error, facts);
46
+ }
47
+ return error;
48
+ }
49
+ function failure(message, actual, expected) {
50
+ return new AssertionError({ message, actual, expected, operator: 'expectRefusal' });
51
+ }
52
+ function codeOf(error) {
53
+ return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'
54
+ ? error.code
55
+ : undefined;
56
+ }
57
+ function described(error) {
58
+ if (!(error instanceof Error)) {
59
+ return show(error);
60
+ }
61
+ const code = codeOf(error);
62
+ return `${error.constructor.name}${code === undefined ? '' : ` (code ${code})`}: ${error.message}`;
63
+ }
64
+ //# sourceMappingURL=expect-refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect-refusal.js","sourceRoot":"","sources":["../../src/refusals/expect-refusal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** The facts a refusal must carry, by name. A refusal may carry others. */
2
+ export type ExpectedFacts = Readonly<Record<string, unknown>>;
3
+ //# sourceMappingURL=expected-facts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expected-facts.d.ts","sourceRoot":"","sources":["../../src/refusals/expected-facts.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=expected-facts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expected-facts.js","sourceRoot":"","sources":["../../src/refusals/expected-facts.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { ExpectedFacts } from './expected-facts.js';
2
+ /** One sentence per expected fact the error does not carry with that value. */
3
+ export declare function factMismatches(error: unknown, expected: ExpectedFacts): string[];
4
+ //# sourceMappingURL=fact-mismatches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-mismatches.d.ts","sourceRoot":"","sources":["../../src/refusals/fact-mismatches.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE,CAYhF"}
@@ -0,0 +1,22 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { show } from '../scenarios/show.js';
3
+ /** One sentence per expected fact the error does not carry with that value. */
4
+ export function factMismatches(error, expected) {
5
+ const facts = factsOf(error);
6
+ return Object.entries(expected).flatMap(([name, value]) => {
7
+ if (!(name in facts)) {
8
+ return [`fact ${name}: expected ${show(value)}, the refusal carries no such fact`];
9
+ }
10
+ return isDeepStrictEqual(facts[name], value)
11
+ ? []
12
+ : [`fact ${name}: expected ${show(value)}, got ${show(facts[name])}`];
13
+ });
14
+ }
15
+ function factsOf(error) {
16
+ if (typeof error !== 'object' || error === null || !('facts' in error)) {
17
+ return {};
18
+ }
19
+ const { facts } = error;
20
+ return typeof facts === 'object' && facts !== null ? { ...facts } : {};
21
+ }
22
+ //# sourceMappingURL=fact-mismatches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-mismatches.js","sourceRoot":"","sources":["../../src/refusals/fact-mismatches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAG5C,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,QAAuB;IACpE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7B,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QACxD,IAAI,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,QAAQ,IAAI,cAAc,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACrF,CAAC;QAED,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;YAC1C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,QAAQ,IAAI,cAAc,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QACvE,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAExB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzE,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { AsyncOutcome } from './async-outcome.js';
2
+ import type { ExpectedFacts } from '../refusals/expected-facts.js';
2
3
  import type { ErrorClass } from './error-class.js';
3
4
  import type { EventMatcher } from './event-matcher.js';
4
5
  import type { Recorded } from './recorded.js';
@@ -10,7 +11,7 @@ export declare class DeferredOutcome<A> implements AsyncOutcome<A> {
10
11
  thenEvents(expected: readonly EventMatcher[]): this;
11
12
  thenEventNames(expected: readonly string[]): this;
12
13
  thenNoEvent(): this;
13
- thenError(typeOrCode: ErrorClass | string, code?: string): this;
14
+ thenError(typeOrCode: ErrorClass | string, detail?: string | ExpectedFacts): this;
14
15
  thenState(inspectState: (aggregate: A) => void): this;
15
16
  then<Fulfilled = void, Rejected = never>(onFulfilled?: ((value: undefined) => Fulfilled | PromiseLike<Fulfilled>) | null, onRejected?: ((reason: unknown) => Rejected | PromiseLike<Rejected>) | null): PromiseLike<Fulfilled | Rejected>;
16
17
  private after;
@@ -1 +1 @@
1
- {"version":3,"file":"deferred-outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/deferred-outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,uGAAuG;AACvG,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAKpC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ5C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAE/D;IAED,OAAO,eAAuE;IAE9E,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAElD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEhD;IAED,WAAW,IAAI,IAAI,CAElB;IAED,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAI9D;IAED,SAAS,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAEpD;IAED,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EACrC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,EAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,GAC1E,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,CAEnC;IAED,OAAO,CAAC,KAAK;CAId"}
1
+ {"version":3,"file":"deferred-outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/deferred-outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,uGAAuG;AACvG,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAKpC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ5C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAE/D;IAED,OAAO,eAAuE;IAE9E,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAElD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEhD;IAED,WAAW,IAAI,IAAI,CAElB;IAED,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAEhF;IAED,SAAS,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAEpD;IAED,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EACrC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,EAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,GAC1E,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,CAEnC;IAED,OAAO,CAAC,KAAK;CAId"}
@@ -17,8 +17,8 @@ export class DeferredOutcome {
17
17
  thenNoEvent() {
18
18
  return this.after((outcome) => outcome.thenNoEvent());
19
19
  }
20
- thenError(typeOrCode, code) {
21
- return this.after((outcome) => typeof typeOrCode === 'string' ? outcome.thenError(typeOrCode) : outcome.thenError(typeOrCode, code));
20
+ thenError(typeOrCode, detail) {
21
+ return this.after((outcome) => outcome.thenError(typeOrCode, detail));
22
22
  }
23
23
  thenState(inspectState) {
24
24
  return this.after((outcome) => outcome.thenState(inspectState));
@@ -1 +1 @@
1
- {"version":3,"file":"deferred-outcome.js","sourceRoot":"","sources":["../../src/scenarios/deferred-outcome.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,uGAAuG;AACvG,MAAM,OAAO,eAAe;IAKW,OAAO;IAJ5C,MAAM,CAAC,EAAE,CAAI,QAA8B;QACzC,OAAO,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,YAAqC,OAAqC;uBAArC,OAAO;IAAiC,CAAC;IAE9E,UAAU,CAAC,QAAiC;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,cAAc,CAAC,QAA2B;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,UAA+B,EAAE,IAAa;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAC5B,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CACrG,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,YAAoC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CACF,WAA+E,EAC/E,UAA2E;QAE3E,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;IAEO,KAAK,CAAC,MAA6D;QACzE,yKAAyK;QACzK,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAS,CAAC;IAChE,CAAC;CACF"}
1
+ {"version":3,"file":"deferred-outcome.js","sourceRoot":"","sources":["../../src/scenarios/deferred-outcome.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,uGAAuG;AACvG,MAAM,OAAO,eAAe;IAKW,OAAO;IAJ5C,MAAM,CAAC,EAAE,CAAI,QAA8B;QACzC,OAAO,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,YAAqC,OAAqC;uBAArC,OAAO;IAAiC,CAAC;IAE9E,UAAU,CAAC,QAAiC;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,cAAc,CAAC,QAA2B;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,UAA+B,EAAE,MAA+B;QACxE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,SAAS,CAAC,YAAoC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CACF,WAA+E,EAC/E,UAA2E;QAE3E,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;IAEO,KAAK,CAAC,MAA6D;QACzE,yKAAyK;QACzK,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAS,CAAC;IAChE,CAAC;CACF"}
@@ -1,3 +1,4 @@
1
+ import type { ExpectedFacts } from '../refusals/expected-facts.js';
1
2
  import type { ErrorClass } from './error-class.js';
2
3
  import type { EventMatcher } from './event-matcher.js';
3
4
  import type { Outcome } from './outcome.js';
@@ -10,7 +11,7 @@ export declare class ImmediateOutcome<A> implements Outcome<A> {
10
11
  thenEvents(expected: readonly EventMatcher[]): this;
11
12
  thenEventNames(expected: readonly string[]): this;
12
13
  thenNoEvent(): this;
13
- thenError(typeOrCode: ErrorClass | string, code?: string): this;
14
+ thenError(typeOrCode: ErrorClass | string, detail?: string | ExpectedFacts): this;
14
15
  thenState(inspectState: (aggregate: A) => void): this;
15
16
  private thrownInsteadOf;
16
17
  private assertDidNotThrow;
@@ -1 +1 @@
1
- {"version":3,"file":"immediate-outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/immediate-outcome.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,gFAAgF;AAChF,qBAAa,gBAAgB,CAAC,CAAC,CAAE,YAAW,OAAO,CAAC,CAAC,CAAC;IAIxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,OAAO,CAAC,aAAa,CAAS;IAE9B,YAA6B,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAI;IAEtD,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CA6BlD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAkBhD;IAED,WAAW,IAAI,IAAI,CAclB;IAED,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAwB9D;IAED,SAAS,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAQpD;IAED,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,iBAAiB;CAY1B"}
1
+ {"version":3,"file":"immediate-outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/immediate-outcome.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,gFAAgF;AAChF,qBAAa,gBAAgB,CAAC,CAAC,CAAE,YAAW,OAAO,CAAC,CAAC,CAAC;IAIxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,OAAO,CAAC,aAAa,CAAS;IAE9B,YAA6B,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAI;IAEtD,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CA6BlD;IAED,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAkBhD;IAED,WAAW,IAAI,IAAI,CAclB;IAED,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAyBhF;IAED,SAAS,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAQpD;IAED,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,iBAAiB;CAY1B"}
@@ -1,5 +1,6 @@
1
1
  import { AssertionError } from 'node:assert';
2
2
  import { isDeepStrictEqual } from 'node:util';
3
+ import { factMismatches } from '../refusals/fact-mismatches.js';
3
4
  import { describeEvent } from './describe-event.js';
4
5
  import { eventMismatches } from './event-mismatches.js';
5
6
  import { show } from './show.js';
@@ -66,9 +67,9 @@ export class ImmediateOutcome {
66
67
  }
67
68
  return this;
68
69
  }
69
- thenError(typeOrCode, code) {
70
+ thenError(typeOrCode, detail) {
70
71
  const type = typeof typeOrCode === 'string' ? undefined : typeOrCode;
71
- const expectedCode = typeof typeOrCode === 'string' ? typeOrCode : code;
72
+ const expectedCode = typeof typeOrCode === 'string' ? typeOrCode : codeIn(detail);
72
73
  const expected = [type?.name, expectedCode === undefined ? undefined : `code ${expectedCode}`]
73
74
  .filter((part) => part !== undefined)
74
75
  .join(' with ');
@@ -83,6 +84,7 @@ export class ImmediateOutcome {
83
84
  operator: 'thenError',
84
85
  });
85
86
  }
87
+ assertFacts(error, typeof detail === 'object' ? detail : {});
86
88
  this.errorAsserted = true;
87
89
  return this;
88
90
  }
@@ -132,6 +134,20 @@ function describeMatcher(matcher) {
132
134
  }
133
135
  return typeof matcher === 'function' ? `instance of ${matcher.name}` : show(matcher);
134
136
  }
137
+ function codeIn(detail) {
138
+ return typeof detail === 'string' ? detail : undefined;
139
+ }
140
+ function assertFacts(error, expected) {
141
+ const mismatches = factMismatches(error, expected);
142
+ if (mismatches.length > 0) {
143
+ throw new AssertionError({
144
+ message: ['The error does not carry the expected facts.', ...section('Difference', mismatches)].join('\n'),
145
+ actual: error,
146
+ expected,
147
+ operator: 'thenError',
148
+ });
149
+ }
150
+ }
135
151
  function codeOf(error) {
136
152
  return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'
137
153
  ? error.code
@@ -1 +1 @@
1
- {"version":3,"file":"immediate-outcome.js","sourceRoot":"","sources":["../../src/scenarios/immediate-outcome.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"immediate-outcome.js","sourceRoot":"","sources":["../../src/scenarios/immediate-outcome.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ExpectedFacts } from '../refusals/expected-facts.js';
1
2
  import type { ErrorClass } from './error-class.js';
2
3
  import type { EventMatcher } from './event-matcher.js';
3
4
  /** The assertions available once `when` ran. Each returns the outcome, so they chain. */
@@ -9,8 +10,8 @@ export interface Outcome<A> {
9
10
  thenNoEvent(): this;
10
11
  /** The action threw an instance of `type` (and, when given, with this `code`). */
11
12
  thenError(type: ErrorClass, code?: string): this;
12
- /** The action threw an error carrying this `code`, whatever its class. */
13
- thenError(code: string): this;
13
+ /** The action threw an error carrying this `code`, whatever its class, and these facts when given. */
14
+ thenError(code: string, facts?: ExpectedFacts): this;
14
15
  /** Inspects the aggregate after the action; `inspect` asserts with the runner's own tools. */
15
16
  thenState(inspect: (aggregate: A) => void): this;
16
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,yFAAyF;AACzF,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,2CAA2C;IAC3C,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAC;IACpD,gDAAgD;IAChD,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAClD,WAAW,IAAI,IAAI,CAAC;IACpB,kFAAkF;IAClF,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,0EAA0E;IAC1E,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8FAA8F;IAC9F,SAAS,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;CAClD"}
1
+ {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../src/scenarios/outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,yFAAyF;AACzF,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,2CAA2C;IAC3C,UAAU,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAC;IACpD,gDAAgD;IAChD,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAClD,WAAW,IAAI,IAAI,CAAC;IACpB,kFAAkF;IAClF,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,sGAAsG;IACtG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrD,8FAA8F;IAC9F,SAAS,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;CAClD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/testing",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Readable tests without mocks: test data builders, given/when/then scenarios and contract suites shared by fakes and real adapters.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,11 +46,11 @@
46
46
  "dist"
47
47
  ],
48
48
  "dependencies": {
49
- "@ddd-ts-kit/kernel": "0.2.0"
49
+ "@ddd-ts-kit/kernel": "0.3.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@ddd-ts-kit/aspects": "0.2.0",
53
- "@ddd-ts-kit/events": "0.2.0",
52
+ "@ddd-ts-kit/aspects": "0.3.0",
53
+ "@ddd-ts-kit/events": "0.3.0",
54
54
  "@faker-js/faker": "^10.6.0"
55
55
  },
56
56
  "peerDependencies": {