@kronos-ts/test 0.1.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/dist/fixture.d.ts +78 -0
- package/dist/fixture.d.ts.map +1 -0
- package/dist/fixture.js +424 -0
- package/dist/fixture.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/recording-enhancer.d.ts +40 -0
- package/dist/recording-enhancer.d.ts.map +1 -0
- package/dist/recording-enhancer.js +82 -0
- package/dist/recording-enhancer.js.map +1 -0
- package/package.json +57 -0
- package/src/fixture.ts +535 -0
- package/src/index.ts +18 -0
- package/src/recording-enhancer.ts +113 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type Metadata } from "@kronos-ts/common";
|
|
2
|
+
import type { CommandDescriptor, EventDescriptor, EventMessage, CommandMessage } from "@kronos-ts/messaging";
|
|
3
|
+
import { type App, type RunningApp } from "@kronos-ts/app";
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
type EventPair = [EventDescriptor<any>, unknown];
|
|
6
|
+
type CommandPair = [CommandDescriptor<any>, unknown];
|
|
7
|
+
/**
|
|
8
|
+
* Creates a BDD test fixture that runs your REAL application code
|
|
9
|
+
* against an in-memory event store with recording decorators.
|
|
10
|
+
*
|
|
11
|
+
* Pass a configuration function that sets up the same domain
|
|
12
|
+
* as your production app via the kronos() App fluent surface.
|
|
13
|
+
*
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const fixture = await createTestFixture((app) => {
|
|
16
|
+
* app.states(Course)
|
|
17
|
+
* app.commands(createCourse, subscribeStudent)
|
|
18
|
+
* app.queries(getCourseView, getAllCourses)
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* await fixture
|
|
22
|
+
* .given()
|
|
23
|
+
* .events([CourseCreated, { courseId: "cs-101", name: "Intro", capacity: 30 }])
|
|
24
|
+
* .when()
|
|
25
|
+
* .command(SubscribeStudent, { courseId: "cs-101", studentId: "stu-001" })
|
|
26
|
+
* .then()
|
|
27
|
+
* .expectSuccess()
|
|
28
|
+
* .expectEvents([StudentSubscribed, { courseId: "cs-101", studentId: "stu-001" }])
|
|
29
|
+
*
|
|
30
|
+
* await fixture.stop()
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function createTestFixture(configureFn: (app: App) => void): Promise<TestFixture>;
|
|
34
|
+
export interface TestFixture {
|
|
35
|
+
given(): GivenPhase;
|
|
36
|
+
stop(): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
export interface GivenPhase {
|
|
39
|
+
events(...pairs: EventPair[]): GivenPhase;
|
|
40
|
+
commands(...pairs: CommandPair[]): GivenPhase;
|
|
41
|
+
execute(fn: (app: RunningApp) => void | Promise<void>): GivenPhase;
|
|
42
|
+
noPriorActivity(): GivenPhase;
|
|
43
|
+
when(): WhenPhase;
|
|
44
|
+
}
|
|
45
|
+
export interface WhenPhase {
|
|
46
|
+
command<P extends z.ZodType>(descriptor: CommandDescriptor<P>, payload: z.infer<P>, metadata?: Metadata): WhenResult;
|
|
47
|
+
event<P extends z.ZodType>(descriptor: EventDescriptor<P>, payload: z.infer<P>, metadata?: Metadata): WhenResult;
|
|
48
|
+
nothing(): WhenResult;
|
|
49
|
+
}
|
|
50
|
+
export interface WhenResult {
|
|
51
|
+
then(): ThenPhase;
|
|
52
|
+
}
|
|
53
|
+
export interface ThenPhase extends PromiseLike<void> {
|
|
54
|
+
expectEvents(...pairs: EventPair[]): ThenPhase;
|
|
55
|
+
expectNoEvents(): ThenPhase;
|
|
56
|
+
expectSuccess(): ThenPhase;
|
|
57
|
+
expectResult(expected: unknown): ThenPhase;
|
|
58
|
+
expectResultSatisfying(fn: (result: unknown) => void): ThenPhase;
|
|
59
|
+
expectResultPayloadSatisfying<T>(fn: (payload: T) => void): ThenPhase;
|
|
60
|
+
expectException(messageSubstring: string): ThenPhase;
|
|
61
|
+
expectExceptionType(errorName: string): ThenPhase;
|
|
62
|
+
expectExceptionSatisfying(fn: (error: unknown) => void): ThenPhase;
|
|
63
|
+
expectEventsSatisfying(fn: (events: ReadonlyArray<EventMessage>) => void): ThenPhase;
|
|
64
|
+
expectCommands(...pairs: CommandPair[]): ThenPhase;
|
|
65
|
+
expectNoCommands(): ThenPhase;
|
|
66
|
+
expectCommandsSatisfying(fn: (commands: ReadonlyArray<CommandMessage>) => void): ThenPhase;
|
|
67
|
+
expect(fn: (app: RunningApp) => void | Promise<void>): ThenPhase;
|
|
68
|
+
await(assertion: (app: RunningApp) => void | Promise<void>, timeoutMs?: number, intervalMs?: number): ThenPhase;
|
|
69
|
+
and(): TestFixture;
|
|
70
|
+
}
|
|
71
|
+
export declare class FixtureAssertionError extends Error {
|
|
72
|
+
constructor(message: string);
|
|
73
|
+
}
|
|
74
|
+
export type FieldFilter = (fieldName: string, owner: unknown) => boolean;
|
|
75
|
+
export declare const allFieldsFilter: FieldFilter;
|
|
76
|
+
export declare function ignoreFields(...fieldNames: string[]): FieldFilter;
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
|
package/dist/fixture.js
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { generateIdentifier, emptyMetadata, qualifiedNameToString, } from "@kronos-ts/common";
|
|
2
|
+
import { runInNewUoW } from "@kronos-ts/messaging";
|
|
3
|
+
import { kronos } from "@kronos-ts/app";
|
|
4
|
+
import { createRecordings, testRecordingExtension, } from "./recording-enhancer.js";
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Fixture entry point
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
/**
|
|
9
|
+
* Creates a BDD test fixture that runs your REAL application code
|
|
10
|
+
* against an in-memory event store with recording decorators.
|
|
11
|
+
*
|
|
12
|
+
* Pass a configuration function that sets up the same domain
|
|
13
|
+
* as your production app via the kronos() App fluent surface.
|
|
14
|
+
*
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const fixture = await createTestFixture((app) => {
|
|
17
|
+
* app.states(Course)
|
|
18
|
+
* app.commands(createCourse, subscribeStudent)
|
|
19
|
+
* app.queries(getCourseView, getAllCourses)
|
|
20
|
+
* })
|
|
21
|
+
*
|
|
22
|
+
* await fixture
|
|
23
|
+
* .given()
|
|
24
|
+
* .events([CourseCreated, { courseId: "cs-101", name: "Intro", capacity: 30 }])
|
|
25
|
+
* .when()
|
|
26
|
+
* .command(SubscribeStudent, { courseId: "cs-101", studentId: "stu-001" })
|
|
27
|
+
* .then()
|
|
28
|
+
* .expectSuccess()
|
|
29
|
+
* .expectEvents([StudentSubscribed, { courseId: "cs-101", studentId: "stu-001" }])
|
|
30
|
+
*
|
|
31
|
+
* await fixture.stop()
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export async function createTestFixture(configureFn) {
|
|
35
|
+
const recordings = createRecordings();
|
|
36
|
+
const app = kronos({ quiet: true });
|
|
37
|
+
// Apply testRecordingExtension synchronously BEFORE configureFn so its
|
|
38
|
+
// decorators land FIRST in the registration order — Phase 6 D-62: first
|
|
39
|
+
// registered = innermost wrap. Recording must be innermost so it captures
|
|
40
|
+
// messages AFTER all interceptors have enriched them.
|
|
41
|
+
testRecordingExtension(recordings)(app);
|
|
42
|
+
// Capture the eventStore reference via an identity decorator so the BDD
|
|
43
|
+
// given/when paths can append events directly. The decorator runs as
|
|
44
|
+
// part of the user-decorator pass at .start(), so it sees whatever
|
|
45
|
+
// (recording-wrapped) store the framework resolved.
|
|
46
|
+
let capturedEventStore;
|
|
47
|
+
app.decorate("eventStore", (inner) => {
|
|
48
|
+
capturedEventStore = inner;
|
|
49
|
+
return inner;
|
|
50
|
+
});
|
|
51
|
+
configureFn(app);
|
|
52
|
+
const running = await app.start();
|
|
53
|
+
if (!capturedEventStore) {
|
|
54
|
+
throw new Error("Test fixture: eventStore capture failed (start() did not run probe decorator).");
|
|
55
|
+
}
|
|
56
|
+
const eventStore = capturedEventStore;
|
|
57
|
+
return {
|
|
58
|
+
given() {
|
|
59
|
+
return new GivenPhaseImpl(running, recordings, eventStore);
|
|
60
|
+
},
|
|
61
|
+
async stop() {
|
|
62
|
+
await running.stop();
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
class GivenPhaseImpl {
|
|
67
|
+
app;
|
|
68
|
+
recordings;
|
|
69
|
+
eventStore;
|
|
70
|
+
givenEvents = [];
|
|
71
|
+
givenCommands = [];
|
|
72
|
+
givenSetupFns = [];
|
|
73
|
+
_prerequisite;
|
|
74
|
+
constructor(app, recordings, eventStore) {
|
|
75
|
+
this.app = app;
|
|
76
|
+
this.recordings = recordings;
|
|
77
|
+
this.eventStore = eventStore;
|
|
78
|
+
}
|
|
79
|
+
events(...pairs) {
|
|
80
|
+
this.givenEvents.push(...pairs);
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
commands(...pairs) {
|
|
84
|
+
this.givenCommands.push(...pairs);
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
execute(fn) {
|
|
88
|
+
this.givenSetupFns.push(fn);
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
noPriorActivity() {
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
when() {
|
|
95
|
+
return new WhenPhaseImpl(this.app, this.recordings, this.eventStore, this.givenEvents, this.givenCommands, this.givenSetupFns, this._prerequisite);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
class WhenPhaseImpl {
|
|
99
|
+
app;
|
|
100
|
+
recordings;
|
|
101
|
+
eventStore;
|
|
102
|
+
givenEvents;
|
|
103
|
+
givenCommands;
|
|
104
|
+
givenSetupFns;
|
|
105
|
+
prerequisite;
|
|
106
|
+
constructor(app, recordings, eventStore, givenEvents, givenCommands, givenSetupFns, prerequisite) {
|
|
107
|
+
this.app = app;
|
|
108
|
+
this.recordings = recordings;
|
|
109
|
+
this.eventStore = eventStore;
|
|
110
|
+
this.givenEvents = givenEvents;
|
|
111
|
+
this.givenCommands = givenCommands;
|
|
112
|
+
this.givenSetupFns = givenSetupFns;
|
|
113
|
+
this.prerequisite = prerequisite;
|
|
114
|
+
}
|
|
115
|
+
command(descriptor, payload, metadata) {
|
|
116
|
+
const thenPhase = new ThenPhaseImpl(this.app, this.recordings, this.eventStore, this.givenEvents, this.givenCommands, this.givenSetupFns, { kind: "command", descriptor, payload, metadata }, this.prerequisite);
|
|
117
|
+
return { then: () => thenPhase };
|
|
118
|
+
}
|
|
119
|
+
event(descriptor, payload, metadata) {
|
|
120
|
+
const thenPhase = new ThenPhaseImpl(this.app, this.recordings, this.eventStore, this.givenEvents, this.givenCommands, this.givenSetupFns, { kind: "event", descriptor, payload, metadata }, this.prerequisite);
|
|
121
|
+
return { then: () => thenPhase };
|
|
122
|
+
}
|
|
123
|
+
nothing() {
|
|
124
|
+
const thenPhase = new ThenPhaseImpl(this.app, this.recordings, this.eventStore, this.givenEvents, this.givenCommands, this.givenSetupFns, { kind: "nothing" }, this.prerequisite);
|
|
125
|
+
return { then: () => thenPhase };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
class ThenPhaseImpl {
|
|
129
|
+
app;
|
|
130
|
+
recordings;
|
|
131
|
+
eventStore;
|
|
132
|
+
givenEvents;
|
|
133
|
+
givenCommands;
|
|
134
|
+
givenSetupFns;
|
|
135
|
+
whenAction;
|
|
136
|
+
prerequisite;
|
|
137
|
+
assertions = [];
|
|
138
|
+
executionPromise = null;
|
|
139
|
+
constructor(app, recordings, eventStore, givenEvents, givenCommands, givenSetupFns, whenAction, prerequisite) {
|
|
140
|
+
this.app = app;
|
|
141
|
+
this.recordings = recordings;
|
|
142
|
+
this.eventStore = eventStore;
|
|
143
|
+
this.givenEvents = givenEvents;
|
|
144
|
+
this.givenCommands = givenCommands;
|
|
145
|
+
this.givenSetupFns = givenSetupFns;
|
|
146
|
+
this.whenAction = whenAction;
|
|
147
|
+
this.prerequisite = prerequisite;
|
|
148
|
+
}
|
|
149
|
+
expectEvents(...pairs) {
|
|
150
|
+
this.assertions.push((_result, _error, events) => {
|
|
151
|
+
if (events.length !== pairs.length) {
|
|
152
|
+
throw new FixtureAssertionError(`Expected ${pairs.length} event(s) but got ${events.length}.\n` +
|
|
153
|
+
` Expected: [${pairs.map(([d]) => qualifiedNameToString(d.name)).join(", ")}]\n` +
|
|
154
|
+
` Actual: [${events.map((e) => qualifiedNameToString(e.name)).join(", ")}]`);
|
|
155
|
+
}
|
|
156
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
157
|
+
const [desc, payload] = pairs[i];
|
|
158
|
+
const actual = events[i];
|
|
159
|
+
const expectedName = qualifiedNameToString(desc.name);
|
|
160
|
+
const actualName = qualifiedNameToString(actual.name);
|
|
161
|
+
if (actualName !== expectedName) {
|
|
162
|
+
throw new FixtureAssertionError(`Event ${i}: expected "${expectedName}" but got "${actualName}"`);
|
|
163
|
+
}
|
|
164
|
+
assertDeepEqual(payload, actual.payload, `Event ${i} (${expectedName}) payload`);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
169
|
+
expectNoEvents() {
|
|
170
|
+
this.assertions.push((_result, _error, events) => {
|
|
171
|
+
if (events.length !== 0) {
|
|
172
|
+
throw new FixtureAssertionError(`Expected no events but got ${events.length}: ` + events.map((e) => qualifiedNameToString(e.name)).join(", "));
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
expectSuccess() {
|
|
178
|
+
this.assertions.push((_result, error) => {
|
|
179
|
+
if (error)
|
|
180
|
+
throw new FixtureAssertionError(`Expected success but command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
181
|
+
});
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
expectResult(expected) {
|
|
185
|
+
this.assertions.push((result, error) => {
|
|
186
|
+
if (error)
|
|
187
|
+
throw new FixtureAssertionError(`Expected result but command failed: ${error}`);
|
|
188
|
+
assertDeepEqual(expected, result, "Command result");
|
|
189
|
+
});
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
expectResultSatisfying(fn) {
|
|
193
|
+
this.assertions.push((result, error) => {
|
|
194
|
+
if (error)
|
|
195
|
+
throw new FixtureAssertionError(`Expected result but command failed: ${error}`);
|
|
196
|
+
fn(result);
|
|
197
|
+
});
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
expectResultPayloadSatisfying(fn) {
|
|
201
|
+
this.assertions.push((result, error) => {
|
|
202
|
+
if (error)
|
|
203
|
+
throw new FixtureAssertionError(`Expected result but command failed: ${error}`);
|
|
204
|
+
fn(result);
|
|
205
|
+
});
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
expectException(messageSubstring) {
|
|
209
|
+
this.assertions.push((_result, error) => {
|
|
210
|
+
if (!error)
|
|
211
|
+
throw new FixtureAssertionError(`Expected exception containing "${messageSubstring}" but command succeeded`);
|
|
212
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
213
|
+
if (!msg.includes(messageSubstring)) {
|
|
214
|
+
throw new FixtureAssertionError(`Expected exception containing "${messageSubstring}" but got: "${msg}"`);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
expectExceptionType(errorName) {
|
|
220
|
+
this.assertions.push((_result, error) => {
|
|
221
|
+
if (!error)
|
|
222
|
+
throw new FixtureAssertionError(`Expected ${errorName} but command succeeded`);
|
|
223
|
+
const actualName = error instanceof Error ? error.name : "Error";
|
|
224
|
+
if (actualName !== errorName) {
|
|
225
|
+
throw new FixtureAssertionError(`Expected ${errorName} but got ${actualName}: ${error instanceof Error ? error.message : error}`);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
expectExceptionSatisfying(fn) {
|
|
231
|
+
this.assertions.push((_result, error) => {
|
|
232
|
+
if (!error)
|
|
233
|
+
throw new FixtureAssertionError("Expected exception but command succeeded");
|
|
234
|
+
fn(error);
|
|
235
|
+
});
|
|
236
|
+
return this;
|
|
237
|
+
}
|
|
238
|
+
expectEventsSatisfying(fn) {
|
|
239
|
+
this.assertions.push((_result, _error, events) => { fn(events); });
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
expectCommands(...pairs) {
|
|
243
|
+
this.assertions.push(() => {
|
|
244
|
+
const actual = this.recordings.commands();
|
|
245
|
+
const handlerCommands = actual.slice(1);
|
|
246
|
+
if (handlerCommands.length !== pairs.length) {
|
|
247
|
+
throw new FixtureAssertionError(`Expected ${pairs.length} dispatched command(s) but got ${handlerCommands.length}.`);
|
|
248
|
+
}
|
|
249
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
250
|
+
const [desc, payload] = pairs[i];
|
|
251
|
+
const actualCmd = handlerCommands[i];
|
|
252
|
+
const expectedName = qualifiedNameToString(desc.name);
|
|
253
|
+
const actualName = qualifiedNameToString(actualCmd.name);
|
|
254
|
+
if (actualName !== expectedName)
|
|
255
|
+
throw new FixtureAssertionError(`Command ${i}: expected "${expectedName}" but got "${actualName}"`);
|
|
256
|
+
assertDeepEqual(payload, actualCmd.payload, `Command ${i} (${expectedName}) payload`);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
expectNoCommands() {
|
|
262
|
+
this.assertions.push(() => {
|
|
263
|
+
const handlerCommands = this.recordings.commands().slice(1);
|
|
264
|
+
if (handlerCommands.length !== 0) {
|
|
265
|
+
throw new FixtureAssertionError(`Expected no dispatched commands but got ${handlerCommands.length}`);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
expectCommandsSatisfying(fn) {
|
|
271
|
+
this.assertions.push(() => { fn(this.recordings.commands().slice(1)); });
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
expect(fn) {
|
|
275
|
+
this.assertions.push(async () => { await fn(this.app); });
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
await(assertion, timeoutMs = 5000, intervalMs = 50) {
|
|
279
|
+
this.assertions.push(async () => {
|
|
280
|
+
const start = Date.now();
|
|
281
|
+
let lastError;
|
|
282
|
+
while (Date.now() - start < timeoutMs) {
|
|
283
|
+
try {
|
|
284
|
+
await assertion(this.app);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
lastError = err;
|
|
289
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
throw new FixtureAssertionError(`Assertion did not pass within ${timeoutMs}ms. Last error: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
293
|
+
});
|
|
294
|
+
return this;
|
|
295
|
+
}
|
|
296
|
+
and() {
|
|
297
|
+
const prerequisite = this.getExecutionPromise();
|
|
298
|
+
return {
|
|
299
|
+
given: () => {
|
|
300
|
+
const given = new GivenPhaseImpl(this.app, this.recordings, this.eventStore);
|
|
301
|
+
given._prerequisite = prerequisite;
|
|
302
|
+
return given;
|
|
303
|
+
},
|
|
304
|
+
stop: async () => { await this.app.stop(); },
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
then(onfulfilled, onrejected) {
|
|
308
|
+
return this.getExecutionPromise().then(onfulfilled, onrejected);
|
|
309
|
+
}
|
|
310
|
+
getExecutionPromise() {
|
|
311
|
+
if (!this.executionPromise)
|
|
312
|
+
this.executionPromise = this.execute();
|
|
313
|
+
return this.executionPromise;
|
|
314
|
+
}
|
|
315
|
+
async execute() {
|
|
316
|
+
if (this.prerequisite)
|
|
317
|
+
await this.prerequisite;
|
|
318
|
+
const eventStore = this.eventStore;
|
|
319
|
+
// 1. Given: publish events within a UnitOfWork
|
|
320
|
+
if (this.givenEvents.length > 0) {
|
|
321
|
+
await runInNewUoW(emptyMetadata(), async () => {
|
|
322
|
+
const events = this.givenEvents.map(([desc, payload]) => {
|
|
323
|
+
const tags = desc.tags ? desc.tags(payload) : [];
|
|
324
|
+
return { identifier: generateIdentifier(), name: desc.name, version: desc.version, payload, metadata: emptyMetadata(), timestamp: Date.now(), tags };
|
|
325
|
+
});
|
|
326
|
+
await eventStore.append(events);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
// 1b. Given: run custom setup
|
|
330
|
+
for (const fn of this.givenSetupFns) {
|
|
331
|
+
await fn(this.app);
|
|
332
|
+
}
|
|
333
|
+
// 1c. Given: dispatch commands via the gateway (matches user-facing semantics).
|
|
334
|
+
// The recording decorator on the bus captures messages whether they
|
|
335
|
+
// arrive via gateway or direct bus dispatch.
|
|
336
|
+
for (const [desc, payload] of this.givenCommands) {
|
|
337
|
+
await this.app.commandGateway.send(desc, payload, emptyMetadata());
|
|
338
|
+
}
|
|
339
|
+
// 2. Reset recordings
|
|
340
|
+
this.recordings.reset();
|
|
341
|
+
// 3. When
|
|
342
|
+
let result;
|
|
343
|
+
let error;
|
|
344
|
+
if (this.whenAction.kind === "command") {
|
|
345
|
+
try {
|
|
346
|
+
result = await this.app.commandGateway.send(this.whenAction.descriptor, this.whenAction.payload, this.whenAction.metadata ?? emptyMetadata());
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
error = err;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
else if (this.whenAction.kind === "event") {
|
|
353
|
+
const desc = this.whenAction.descriptor;
|
|
354
|
+
const payload = this.whenAction.payload;
|
|
355
|
+
const tags = desc.tags ? desc.tags(payload) : [];
|
|
356
|
+
try {
|
|
357
|
+
await eventStore.append([{ identifier: generateIdentifier(), name: desc.name, version: desc.version, payload, metadata: this.whenAction.metadata ?? emptyMetadata(), timestamp: Date.now(), tags }]);
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
error = err;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// 4. Then
|
|
364
|
+
const recordedEvents = this.recordings.events();
|
|
365
|
+
for (const assertion of this.assertions) {
|
|
366
|
+
await assertion(result, error, recordedEvents);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Helpers
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
export class FixtureAssertionError extends Error {
|
|
374
|
+
constructor(message) { super(message); this.name = "FixtureAssertionError"; }
|
|
375
|
+
}
|
|
376
|
+
export const allFieldsFilter = () => true;
|
|
377
|
+
export function ignoreFields(...fieldNames) {
|
|
378
|
+
const ignored = new Set(fieldNames);
|
|
379
|
+
return (name) => !ignored.has(name);
|
|
380
|
+
}
|
|
381
|
+
function assertDeepEqual(expected, actual, label, fieldFilter = allFieldsFilter) {
|
|
382
|
+
const differences = deepCompare(expected, actual, "", fieldFilter);
|
|
383
|
+
if (differences.length > 0)
|
|
384
|
+
throw new FixtureAssertionError(`${label} mismatch:\n${differences.map((d) => ` ${d}`).join("\n")}`);
|
|
385
|
+
}
|
|
386
|
+
function deepCompare(expected, actual, path, fieldFilter) {
|
|
387
|
+
if (expected === actual)
|
|
388
|
+
return [];
|
|
389
|
+
if (expected === null || actual === null)
|
|
390
|
+
return [`${path || "root"}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`];
|
|
391
|
+
if (typeof expected !== typeof actual)
|
|
392
|
+
return [`${path || "root"}: expected type ${typeof expected}, got type ${typeof actual}`];
|
|
393
|
+
if (typeof expected !== "object")
|
|
394
|
+
return [`${path || "root"}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`];
|
|
395
|
+
if (Array.isArray(expected) !== Array.isArray(actual))
|
|
396
|
+
return [`${path || "root"}: expected ${Array.isArray(expected) ? "array" : "object"}, got ${Array.isArray(actual) ? "array" : "object"}`];
|
|
397
|
+
if (Array.isArray(expected) && Array.isArray(actual)) {
|
|
398
|
+
const diffs = [];
|
|
399
|
+
for (let i = 0; i < Math.max(expected.length, actual.length); i++) {
|
|
400
|
+
if (i >= expected.length)
|
|
401
|
+
diffs.push(`${path}[${i}]: unexpected extra element`);
|
|
402
|
+
else if (i >= actual.length)
|
|
403
|
+
diffs.push(`${path}[${i}]: missing expected element`);
|
|
404
|
+
else
|
|
405
|
+
diffs.push(...deepCompare(expected[i], actual[i], `${path}[${i}]`, fieldFilter));
|
|
406
|
+
}
|
|
407
|
+
return diffs;
|
|
408
|
+
}
|
|
409
|
+
const diffs = [];
|
|
410
|
+
const allKeys = new Set([...Object.keys(expected), ...Object.keys(actual)]);
|
|
411
|
+
for (const key of allKeys) {
|
|
412
|
+
if (!fieldFilter(key, expected))
|
|
413
|
+
continue;
|
|
414
|
+
const fieldPath = path ? `${path}.${key}` : key;
|
|
415
|
+
if (!(key in expected))
|
|
416
|
+
diffs.push(`${fieldPath}: unexpected field`);
|
|
417
|
+
else if (!(key in actual))
|
|
418
|
+
diffs.push(`${fieldPath}: missing expected value`);
|
|
419
|
+
else
|
|
420
|
+
diffs.push(...deepCompare(expected[key], actual[key], fieldPath, fieldFilter));
|
|
421
|
+
}
|
|
422
|
+
return diffs;
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type TestFixture, type GivenPhase, type WhenPhase, type WhenResult, type ThenPhase, type FieldFilter, allFieldsFilter, ignoreFields, createTestFixture, FixtureAssertionError, } from "./fixture.js";
|
|
2
|
+
export { type Recordings, createRecordings, testRecordingExtension, } from "./recording-enhancer.js";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,KAAK,UAAU,EACf,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AAErB,OAAO,EAEL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Extension } from "@kronos-ts/app";
|
|
2
|
+
import type { CommandMessage, EventMessage } from "@kronos-ts/messaging";
|
|
3
|
+
/**
|
|
4
|
+
* Recorded state from the test fixture.
|
|
5
|
+
* Events and commands are captured by decorators installed at the
|
|
6
|
+
* INNERMOST position (after all interceptors have run).
|
|
7
|
+
*/
|
|
8
|
+
export interface Recordings {
|
|
9
|
+
/** Events recorded since the last reset. */
|
|
10
|
+
events(): ReadonlyArray<EventMessage>;
|
|
11
|
+
/** Commands dispatched since the last reset. */
|
|
12
|
+
commands(): ReadonlyArray<CommandMessage>;
|
|
13
|
+
/** Clear all recordings. Called between Given and When phases. */
|
|
14
|
+
reset(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a fresh Recordings handle. Pass it into {@link testRecordingExtension}
|
|
18
|
+
* so the fixture and the decorators share the same backing arrays.
|
|
19
|
+
*
|
|
20
|
+
* Replaces the legacy "register testRecordings as a component, retrieve via
|
|
21
|
+
* configuration.getComponent" pattern (removed in Phase 8).
|
|
22
|
+
*/
|
|
23
|
+
export declare function createRecordings(): Recordings;
|
|
24
|
+
/**
|
|
25
|
+
* Native Extension that decorates the eventStore and commandBus with
|
|
26
|
+
* recording wrappers.
|
|
27
|
+
*
|
|
28
|
+
* **Decoration order** (Phase 6 D-62): user decorators registered AFTER this
|
|
29
|
+
* extension's `app.use(...)` wrap OUTSIDE the recording decorators. To land
|
|
30
|
+
* the recording decorators at the INNERMOST position (capturing messages
|
|
31
|
+
* AFTER all interceptors have enriched them), call
|
|
32
|
+
* `app.use(testRecordingExtension(recordings))` BEFORE applying any user
|
|
33
|
+
* decorators / `configureFn(app)`.
|
|
34
|
+
*
|
|
35
|
+
* The legacy enhancer used `Number.MIN_SAFE_INTEGER` numeric priority for the
|
|
36
|
+
* same effect; Phase 6 dropped numeric priorities — innermost = first
|
|
37
|
+
* registered.
|
|
38
|
+
*/
|
|
39
|
+
export declare function testRecordingExtension(recordings: Recordings): Extension;
|
|
40
|
+
//# sourceMappingURL=recording-enhancer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recording-enhancer.d.ts","sourceRoot":"","sources":["../src/recording-enhancer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAO,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAc,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEpF;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,MAAM,IAAI,aAAa,CAAC,YAAY,CAAC,CAAA;IACrC,gDAAgD;IAChD,QAAQ,IAAI,aAAa,CAAC,cAAc,CAAC,CAAA;IACzC,kEAAkE;IAClE,KAAK,IAAI,IAAI,CAAA;CACd;AAcD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAwB7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAmCxE"}
|