Showing the changes to packages/plugins/apps/src/testing (1 of 9 files). Show all
Unified · Split
| @@ -0,0 +1,57 @@ | ||
| 1 | +import { Effect } from "effect"; | |
| 2 | + | |
| 3 | +import type { AppDescriptor } from "../pipeline/descriptor"; | |
| 4 | +import type { AppsStore } from "../plugin/store"; | |
| 5 | +import type { ClientResolver, BindingError } from "../plugin/bindings"; | |
| 6 | + | |
| 7 | +// --------------------------------------------------------------------------- | |
| 8 | +// Test helpers: an in-memory AppsStore and a canned ClientResolver, plus the | |
| 9 | +// daily-brief fixture set. Used by the runtime integration test and the e2e. | |
| 10 | +// --------------------------------------------------------------------------- | |
| 11 | + | |
| 12 | +export * from "./daily-brief"; | |
| 13 | + | |
| 14 | +/** In-memory AppsStore (descriptors + blobs in Maps). */ | |
| 15 | +export const makeInMemoryAppsStore = (): AppsStore & { | |
| 16 | + readonly blobs: Map<string, string>; | |
| 17 | + readonly descriptors: Map<string, AppDescriptor>; | |
| 18 | +} => { | |
| 19 | + const descriptors = new Map<string, AppDescriptor>(); | |
| 20 | + const blobs = new Map<string, string>(); | |
| 21 | + return { | |
| 22 | + descriptors, | |
| 23 | + blobs, | |
| 24 | + putDescriptor: (_owner, descriptor) => | |
| 25 | + Effect.sync(() => void descriptors.set(descriptor.scope, descriptor)), | |
| 26 | + getDescriptor: (scope) => Effect.sync(() => descriptors.get(scope) ?? null), | |
| 27 | + putBlob: (key, value) => Effect.sync(() => void blobs.set(key, value)), | |
| 28 | + getBlob: (key) => Effect.sync(() => blobs.get(key) ?? null), | |
| 29 | + }; | |
| 30 | +}; | |
| 31 | + | |
| 32 | +/** A resolver that dispatches integration method calls to supplied handlers. | |
| 33 | + * `handlers[integration][path.join(".")]` returns the JSON result. */ | |
| 34 | +export const makeTestResolver = ( | |
| 35 | + handlers: Record<string, Record<string, (args: readonly unknown[]) => unknown>>, | |
| 36 | +): ClientResolver & { | |
| 37 | + readonly calls: { integration: string; connection: string; method: string }[]; | |
| 38 | +} => { | |
| 39 | + const calls: { integration: string; connection: string; method: string }[] = []; | |
| 40 | + return { | |
| 41 | + calls, | |
| 42 | + call: ({ integration, connection, path, args }) => { | |
| 43 | + const method = path.join("."); | |
| 44 | + calls.push({ integration, connection, method }); | |
| 45 | + const handler = handlers[integration]?.[method]; | |
| 46 | + if (!handler) { | |
| 47 | + return Effect.fail({ | |
| 48 | + _tag: "BindingError", | |
| 49 | + message: `no test handler for ${integration}.${method}`, | |
| 50 | + role: integration, | |
| 51 | + surface: integration, | |
| 52 | + } as unknown as BindingError); | |
| 53 | + } | |
| 54 | + return Effect.sync(() => handler(args)); | |
| 55 | + }, | |
| 56 | + }; | |
| 57 | +}; | |