@shivaedev/test-story 0.4.0 → 0.5.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/CHANGELOG.md +17 -0
- package/README.md +88 -0
- package/dist/server/internal/narration.d.ts +4 -1
- package/dist/server/internal/narration.d.ts.map +1 -1
- package/dist/server/internal/narration.js +11 -5
- package/dist/server/internal/narration.js.map +1 -1
- package/dist/server/internal/otlpProtobuf.d.ts +2 -0
- package/dist/server/internal/otlpProtobuf.d.ts.map +1 -0
- package/dist/server/internal/otlpProtobuf.js +107 -0
- package/dist/server/internal/otlpProtobuf.js.map +1 -0
- package/dist/server/internal/otlpReadout.d.ts +38 -0
- package/dist/server/internal/otlpReadout.d.ts.map +1 -0
- package/dist/server/internal/otlpReadout.js +45 -0
- package/dist/server/internal/otlpReadout.js.map +1 -0
- package/dist/server/internal/otlpValue.d.ts +22 -0
- package/dist/server/internal/otlpValue.d.ts.map +1 -0
- package/dist/server/internal/otlpValue.js +12 -0
- package/dist/server/internal/otlpValue.js.map +1 -0
- package/dist/server/internal/otlpWire.d.ts +7 -0
- package/dist/server/internal/otlpWire.d.ts.map +1 -0
- package/dist/server/internal/otlpWire.js +55 -0
- package/dist/server/internal/otlpWire.js.map +1 -0
- package/dist/server/internal/seed.d.ts +1 -0
- package/dist/server/internal/seed.d.ts.map +1 -1
- package/dist/server/internal/seed.js +2 -2
- package/dist/server/internal/seed.js.map +1 -1
- package/dist/server/internal/start.d.ts +2 -4
- package/dist/server/internal/start.d.ts.map +1 -1
- package/dist/server/internal/start.js +18 -16
- package/dist/server/internal/start.js.map +1 -1
- package/dist/server/internal/storyIt.d.ts.map +1 -1
- package/dist/server/internal/storyIt.js +10 -8
- package/dist/server/internal/storyIt.js.map +1 -1
- package/dist/server/otlpReceiver.d.ts +21 -0
- package/dist/server/otlpReceiver.d.ts.map +1 -0
- package/dist/server/otlpReceiver.js +50 -0
- package/dist/server/otlpReceiver.js.map +1 -0
- package/dist/server/storyKit.d.ts +1 -0
- package/dist/server/storyKit.d.ts.map +1 -1
- package/dist/server/storyKit.js.map +1 -1
- package/package.json +1 -1
- package/src/server/internal/narration.ts +11 -5
- package/src/server/internal/otlpProtobuf.ts +115 -0
- package/src/server/internal/otlpReadout.ts +59 -0
- package/src/server/internal/otlpValue.ts +24 -0
- package/src/server/internal/otlpWire.ts +57 -0
- package/src/server/internal/seed.ts +3 -2
- package/src/server/internal/start.ts +23 -16
- package/src/server/internal/storyIt.ts +10 -8
- package/src/server/otlpReceiver.ts +69 -0
- package/src/server/storyKit.ts +1 -0
|
@@ -30,8 +30,7 @@ function withTags(options: number | EffectTestOptions | undefined, tags: readonl
|
|
|
30
30
|
|
|
31
31
|
function storyOf(definition: LooseDefinition, given: readonly LooseTrait[], body: LooseBody | undefined) {
|
|
32
32
|
return function* story(_harness: unknown, context: TestContext) {
|
|
33
|
-
|
|
34
|
-
return yield* hooked(() => body?.(told, context));
|
|
33
|
+
return yield* start(definition, given, context, (told) => hooked(() => body?.(told, context)));
|
|
35
34
|
};
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -67,11 +66,14 @@ export function storyIt(definition: LooseDefinition): LooseIt {
|
|
|
67
66
|
layer: definition.layer ?? Layer.empty,
|
|
68
67
|
makeHarness: () => Effect.void,
|
|
69
68
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
function register(declare: EffectTest<unknown, unknown>) {
|
|
70
|
+
return declaring(definition, genre, definition.runIf === false ? effectApp.skip : declare);
|
|
71
|
+
}
|
|
72
|
+
return Object.assign(register(effectApp), {
|
|
73
|
+
fails: register(effectApp.fails),
|
|
74
|
+
only: register(effectApp.only),
|
|
75
|
+
runIf: (condition: unknown) => register(effectApp.runIf(condition)),
|
|
76
|
+
skip: register(effectApp.skip),
|
|
77
|
+
skipIf: (condition: unknown) => register(effectApp.skipIf(condition)),
|
|
76
78
|
});
|
|
77
79
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { otlpReadout } from "#internal/otlpReadout.ts";
|
|
4
|
+
|
|
5
|
+
export type OtlpSpan = ReturnType<typeof otlpReadout>[number];
|
|
6
|
+
export interface OtlpExport {
|
|
7
|
+
readonly body: Buffer;
|
|
8
|
+
readonly headers: IncomingHttpHeaders;
|
|
9
|
+
readonly path: string | undefined;
|
|
10
|
+
readonly rawHeaders: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export interface OtlpReceiverOptions {
|
|
13
|
+
readonly answer?: string;
|
|
14
|
+
readonly path?: string;
|
|
15
|
+
readonly status?: number | ((attempt: number) => number);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function receive(request: IncomingMessage, response: ServerResponse, requests: OtlpExport[], spans: OtlpSpan[], options: OtlpReceiverOptions) {
|
|
19
|
+
try {
|
|
20
|
+
const chunks: Buffer[] = [];
|
|
21
|
+
for await (const chunk of request) {
|
|
22
|
+
chunks.push(Buffer.from(chunk));
|
|
23
|
+
}
|
|
24
|
+
const body = Buffer.concat(chunks);
|
|
25
|
+
requests.push({ body, headers: request.headers, path: request.url, rawHeaders: request.rawHeaders });
|
|
26
|
+
if (request.method !== "POST" || request.url !== (options.path ?? "/v1/traces")) {
|
|
27
|
+
response.writeHead(404).end();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const contentType = request.headers["content-type"]?.split(";")[0]?.trim();
|
|
31
|
+
if (contentType !== "application/json" && contentType !== "application/x-protobuf") {
|
|
32
|
+
response.writeHead(415).end();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
spans.push(...otlpReadout(body, contentType));
|
|
36
|
+
response.writeHead(typeof options.status === "function" ? options.status(requests.length) : (options.status ?? 200)).end(options.answer ?? "{}");
|
|
37
|
+
} catch {
|
|
38
|
+
response.writeHead(400).end();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const otlpReceiver = Effect.fnUntraced(function* (options: OtlpReceiverOptions = {}) {
|
|
43
|
+
const requests: OtlpExport[] = [];
|
|
44
|
+
const spans: OtlpSpan[] = [];
|
|
45
|
+
const server = createServer((request, response) => receive(request, response, requests, spans, options));
|
|
46
|
+
yield* Effect.acquireRelease(
|
|
47
|
+
Effect.tryPromise(
|
|
48
|
+
() =>
|
|
49
|
+
new Promise<void>((resolve, reject) => {
|
|
50
|
+
server.once("error", reject);
|
|
51
|
+
server.listen(0, "127.0.0.1", () => {
|
|
52
|
+
server.off("error", reject);
|
|
53
|
+
resolve();
|
|
54
|
+
});
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
57
|
+
() => Effect.promise(() => new Promise<void>((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())))),
|
|
58
|
+
);
|
|
59
|
+
const address = server.address();
|
|
60
|
+
if (address === null || typeof address === "string") {
|
|
61
|
+
return yield* Effect.die("Missing OTLP receiver address");
|
|
62
|
+
}
|
|
63
|
+
const receiver: { readonly requests: readonly OtlpExport[]; readonly spans: readonly OtlpSpan[]; readonly url: string } = {
|
|
64
|
+
requests,
|
|
65
|
+
spans,
|
|
66
|
+
url: `http://127.0.0.1:${address.port}`,
|
|
67
|
+
};
|
|
68
|
+
return receiver;
|
|
69
|
+
});
|
package/src/server/storyKit.ts
CHANGED
|
@@ -54,6 +54,7 @@ export interface StoryKitDefinition<
|
|
|
54
54
|
readonly name: string;
|
|
55
55
|
readonly outbound?: Readonly<Record<string, string>>;
|
|
56
56
|
readonly run?: RunHooks<TEngine, TStep, TFailed, TDiagnose>;
|
|
57
|
+
readonly runIf?: boolean;
|
|
57
58
|
readonly stages: readonly [TStage, ...TStage[]];
|
|
58
59
|
readonly verbs: (engine: TEngine, story: Story<TEngine, TStep | TFailed | TDiagnose>) => TVerbs;
|
|
59
60
|
}
|