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 | }; | ||