@databricks/appkit 0.61.1 → 0.62.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/CLAUDE.md +1 -0
- package/dist/agents/databricks.d.ts.map +1 -1
- package/dist/agents/databricks.js.map +1 -1
- package/dist/agents/supervisor-api.d.ts.map +1 -1
- package/dist/agents/supervisor-api.js.map +1 -1
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/storage/memory.js.map +1 -1
- package/dist/cache/storage/persistent.js.map +1 -1
- package/dist/cli/commands/codemod/index.js.map +1 -1
- package/dist/cli/commands/codemod/on-plugins-ready.js.map +1 -1
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/doctor/bundle.js.map +1 -1
- package/dist/cli/commands/doctor/index.js.map +1 -1
- package/dist/cli/commands/doctor/report.js.map +1 -1
- package/dist/cli/commands/doctor/resolve-targets.js.map +1 -1
- package/dist/cli/commands/doctor/run.js.map +1 -1
- package/dist/cli/commands/generate-types.js.map +1 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/plugin/add-resource/add-resource.js.map +1 -1
- package/dist/cli/commands/plugin/create/create.js.map +1 -1
- package/dist/cli/commands/plugin/create/prompt-resource.js.map +1 -1
- package/dist/cli/commands/plugin/create/scaffold.js.map +1 -1
- package/dist/cli/commands/plugin/index.js.map +1 -1
- package/dist/cli/commands/plugin/list/list.js.map +1 -1
- package/dist/cli/commands/plugin/promote/promote.js.map +1 -1
- package/dist/cli/commands/plugin/sync/sync.js.map +1 -1
- package/dist/cli/commands/plugin/validate/validate-manifest.js.map +1 -1
- package/dist/cli/commands/plugin/validate/validate.js.map +1 -1
- package/dist/cli/commands/registry/add.js.map +1 -1
- package/dist/cli/commands/registry/client.js.map +1 -1
- package/dist/cli/commands/registry/config-writer.js.map +1 -1
- package/dist/cli/commands/registry/env-reconcile.js.map +1 -1
- package/dist/cli/commands/registry/env-writer.js.map +1 -1
- package/dist/cli/commands/registry/index.js.map +1 -1
- package/dist/cli/commands/registry/info.js.map +1 -1
- package/dist/cli/commands/registry/list.js.map +1 -1
- package/dist/cli/commands/registry/requirements.js.map +1 -1
- package/dist/cli/commands/registry/server-register.js.map +1 -1
- package/dist/cli/commands/registry/workspace-picker.js.map +1 -1
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/connectors/files/client.js.map +1 -1
- package/dist/connectors/lakebase/index.d.ts.map +1 -1
- package/dist/connectors/lakebase/index.js.map +1 -1
- package/dist/connectors/lakebase/pool-manager.d.ts.map +1 -1
- package/dist/connectors/lakebase/pool-manager.js.map +1 -1
- package/dist/connectors/lakebase/routing-pool.d.ts.map +1 -1
- package/dist/connectors/lakebase/routing-pool.js.map +1 -1
- package/dist/connectors/mcp/client.d.ts.map +1 -1
- package/dist/connectors/mcp/client.js.map +1 -1
- package/dist/connectors/sql-warehouse/client.js.map +1 -1
- package/dist/context/client-options.js.map +1 -1
- package/dist/context/execution-context.d.ts.map +1 -1
- package/dist/context/execution-context.js.map +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/service-context.d.ts +55 -3
- package/dist/context/service-context.d.ts.map +1 -1
- package/dist/context/service-context.js.map +1 -1
- package/dist/core/agent/build-toolkit.js.map +1 -1
- package/dist/core/agent/load-agents.d.ts.map +1 -1
- package/dist/core/agent/load-agents.js.map +1 -1
- package/dist/core/agent/run-agent.d.ts.map +1 -1
- package/dist/core/agent/run-agent.js.map +1 -1
- package/dist/core/agent/toolkit-resolver.js.map +1 -1
- package/dist/core/agent/tools/define-tool.d.ts.map +1 -1
- package/dist/core/agent/tools/define-tool.js.map +1 -1
- package/dist/core/agent/tools/tool.d.ts.map +1 -1
- package/dist/core/agent/tools/tool.js.map +1 -1
- package/dist/core/agent/types.d.ts.map +1 -1
- package/dist/core/agent/types.js.map +1 -1
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js.map +1 -1
- package/dist/core/lifecycle-manager.js.map +1 -1
- package/dist/core/plugin-context.d.ts +13 -0
- package/dist/core/plugin-context.d.ts.map +1 -1
- package/dist/core/plugin-context.js +12 -1
- package/dist/core/plugin-context.js.map +1 -1
- package/dist/errors/configuration.d.ts.map +1 -1
- package/dist/errors/configuration.js.map +1 -1
- package/dist/logging/logger.js.map +1 -1
- package/dist/logging/wide-event-emitter.js.map +1 -1
- package/dist/plugin/dev-reader.d.ts.map +1 -1
- package/dist/plugin/dev-reader.js.map +1 -1
- package/dist/plugin/interceptors/cache.js.map +1 -1
- package/dist/plugin/interceptors/retry.js.map +1 -1
- package/dist/plugin/interceptors/telemetry.js.map +1 -1
- package/dist/plugin/plugin.d.ts +2 -2
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/plugins/agents/agents.d.ts.map +1 -1
- package/dist/plugins/agents/agents.js.map +1 -1
- package/dist/plugins/agents/event-translator.js.map +1 -1
- package/dist/plugins/agents/thread-store.js.map +1 -1
- package/dist/plugins/ai-search/ai-search.d.ts.map +1 -1
- package/dist/plugins/ai-search/ai-search.js.map +1 -1
- package/dist/plugins/analytics/analytics.d.ts.map +1 -1
- package/dist/plugins/analytics/analytics.js.map +1 -1
- package/dist/plugins/analytics/mv/cache.js.map +1 -1
- package/dist/plugins/analytics/mv/constants.js.map +1 -1
- package/dist/plugins/analytics/mv/formatters.js.map +1 -1
- package/dist/plugins/analytics/mv/metadata.js.map +1 -1
- package/dist/plugins/analytics/mv/registry.js.map +1 -1
- package/dist/plugins/analytics/mv/schemas.js.map +1 -1
- package/dist/plugins/analytics/query.js.map +1 -1
- package/dist/plugins/analytics/result-delivery.js.map +1 -1
- package/dist/plugins/files/helpers.js.map +1 -1
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/files/types.d.ts.map +1 -1
- package/dist/plugins/genie/genie.d.ts.map +1 -1
- package/dist/plugins/genie/genie.js.map +1 -1
- package/dist/plugins/jobs/plugin.d.ts.map +1 -1
- package/dist/plugins/jobs/plugin.js.map +1 -1
- package/dist/plugins/jobs/types.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
- package/dist/plugins/lakebase/lakebase.js.map +1 -1
- package/dist/plugins/lakebase/types.d.ts.map +1 -1
- package/dist/plugins/server/base-server.js.map +1 -1
- package/dist/plugins/server/client-config-sanitizer.js.map +1 -1
- package/dist/plugins/server/index.d.ts.map +1 -1
- package/dist/plugins/server/index.js.map +1 -1
- package/dist/plugins/server/react-source-loc-vite-plugin.js.map +1 -1
- package/dist/plugins/server/remote-tunnel/remote-tunnel-controller.js.map +1 -1
- package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js.map +1 -1
- package/dist/plugins/server/static-server.js.map +1 -1
- package/dist/plugins/server/utils.js.map +1 -1
- package/dist/plugins/server/vite-dev-server.js.map +1 -1
- package/dist/plugins/serving/schema-filter.js.map +1 -1
- package/dist/plugins/serving/serving.d.ts.map +1 -1
- package/dist/plugins/serving/serving.js.map +1 -1
- package/dist/plugins/ui-variants/index.js.map +1 -1
- package/dist/registry/manifest-loader.d.ts.map +1 -1
- package/dist/registry/manifest-loader.js.map +1 -1
- package/dist/registry/resource-registry.d.ts.map +1 -1
- package/dist/registry/resource-registry.js.map +1 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/types.js.map +1 -1
- package/dist/schemas/manifest.d.ts.map +1 -1
- package/dist/schemas/manifest.js.map +1 -1
- package/dist/schemas/metric-fqn.js.map +1 -1
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/dist/shared/src/schemas/manifest.d.ts.map +1 -1
- package/dist/shared/src/schemas/metric-fqn.js.map +1 -1
- package/dist/shared/src/schemas/metric-metadata-bundle.js.map +1 -1
- package/dist/shared/src/schemas/metric-source.js.map +1 -1
- package/dist/shared/src/sse/analytics.js.map +1 -1
- package/dist/shared/src/workspace-client/legacy.js.map +1 -1
- package/dist/shared/src/workspace-client/types.d.ts.map +1 -1
- package/dist/stream/sse-writer.js.map +1 -1
- package/dist/stream/stream-manager.d.ts.map +1 -1
- package/dist/stream/stream-manager.js.map +1 -1
- package/dist/stream/types.js.map +1 -1
- package/dist/telemetry/instrumentations.js.map +1 -1
- package/dist/telemetry/telemetry-manager.js.map +1 -1
- package/dist/telemetry/telemetry-provider.js.map +1 -1
- package/dist/telemetry/trace-sampler.js.map +1 -1
- package/dist/testing/expect-stream.d.ts +111 -0
- package/dist/testing/expect-stream.d.ts.map +1 -0
- package/dist/testing/expect-stream.js +154 -0
- package/dist/testing/expect-stream.js.map +1 -0
- package/dist/testing/fixtures.d.ts +257 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +385 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/test-plugin-context.d.ts +158 -0
- package/dist/testing/test-plugin-context.d.ts.map +1 -0
- package/dist/testing/test-plugin-context.js +139 -0
- package/dist/testing/test-plugin-context.js.map +1 -0
- package/dist/type-generator/cache.js.map +1 -1
- package/dist/type-generator/index.js.map +1 -1
- package/dist/type-generator/migration.js.map +1 -1
- package/dist/type-generator/mv-registry/config.js.map +1 -1
- package/dist/type-generator/query-registry.js.map +1 -1
- package/dist/type-generator/serving/cache.js.map +1 -1
- package/dist/type-generator/serving/generator.js.map +1 -1
- package/dist/type-generator/serving/server-file-extractor.d.ts.map +1 -1
- package/dist/type-generator/serving/server-file-extractor.js.map +1 -1
- package/dist/type-generator/serving/vite-plugin.d.ts.map +1 -1
- package/dist/type-generator/serving/vite-plugin.js.map +1 -1
- package/dist/type-generator/vite-plugin.d.ts.map +1 -1
- package/dist/type-generator/vite-plugin.js.map +1 -1
- package/dist/workspace-client/legacy.js.map +1 -1
- package/dist/workspace-client/types.d.ts.map +1 -1
- package/docs/plugins/testing.md +245 -0
- package/llms.txt +1 -0
- package/package.json +15 -2
- package/sbom.cdx.json +1 -1
- package/skills/appkit-ui-variants/SKILL.md +1 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { IAppRouter } from "../shared/src/plugin.js";
|
|
2
|
+
import "../shared/src/index.js";
|
|
3
|
+
import { ITelemetry } from "../telemetry/types.js";
|
|
4
|
+
import { ServiceContext, ServiceContextState } from "../context/service-context.js";
|
|
5
|
+
import * as vitest from "vitest";
|
|
6
|
+
|
|
7
|
+
//#region src/testing/fixtures.d.ts
|
|
8
|
+
type Any = any;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a mock telemetry provider for testing. Every span/meter/logger is a
|
|
11
|
+
* `vi.fn()` no-op, so plugins that trace, count, or log run without a live
|
|
12
|
+
* OpenTelemetry pipeline. Passed into {@link createTestPluginContext} as the one
|
|
13
|
+
* injectable production seam.
|
|
14
|
+
*/
|
|
15
|
+
declare function createMockTelemetry(): ITelemetry;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a mock Express router that captures registered handlers so a test
|
|
18
|
+
* can pull a handler back out by method + path and invoke it directly.
|
|
19
|
+
*/
|
|
20
|
+
declare function createMockRouter(): {
|
|
21
|
+
router: IAppRouter;
|
|
22
|
+
handlers: Record<string, Any>;
|
|
23
|
+
getHandler: (method: string, path: string) => Any;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* On-behalf-of shorthand for {@link createMockRequest}. `true` uses the default
|
|
27
|
+
* test user; an object picks the identity. Sets the forwarded headers the real
|
|
28
|
+
* `Plugin.asUser` reads (`x-forwarded-access-token`, `x-forwarded-user`, and —
|
|
29
|
+
* when given — `x-forwarded-email`), so an OBO test is one flag instead of
|
|
30
|
+
* hand-rolled headers.
|
|
31
|
+
*/
|
|
32
|
+
type OboOption = boolean | {
|
|
33
|
+
/** `x-forwarded-user` — defaults to `"test-user"`. */userId?: string; /** `x-forwarded-access-token` — defaults to `"test-user-token"`. */
|
|
34
|
+
token?: string; /** `x-forwarded-email` — omitted unless provided. */
|
|
35
|
+
email?: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Creates a mock Express request. Pass `overrides` to set `params`, `query`,
|
|
39
|
+
* `body`, `headers`, etc.
|
|
40
|
+
*
|
|
41
|
+
* For on-behalf-of tests, pass `obo` instead of hand-adding forwarded headers —
|
|
42
|
+
* `createMockRequest({ obo: true })` sets the identity headers the real
|
|
43
|
+
* `asUser` requires. Any explicit `headers` you also pass win over the ones
|
|
44
|
+
* `obo` generates, so you can override a single field.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* createMockRequest({ obo: true }); // default test user + token
|
|
49
|
+
* createMockRequest({ obo: { userId: "alice" } }); // pick the user
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare function createMockRequest(overrides?: Any): any;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a mock Express response object. `write`/`send`/`setHeader` flip
|
|
55
|
+
* `headersSent`, `end` flips `writableEnded` and fires any `close` listener —
|
|
56
|
+
* enough for streaming handlers that branch on those flags.
|
|
57
|
+
*
|
|
58
|
+
* Every chunk passed to `write` (and a final chunk to `end`) is captured, so a
|
|
59
|
+
* streaming route's real SSE output can be replayed: pass the response straight
|
|
60
|
+
* to {@link expectStream}, or call `sseResponse()` for a real `Response`.
|
|
61
|
+
*
|
|
62
|
+
* @example Assert what a streaming route emitted
|
|
63
|
+
* ```ts
|
|
64
|
+
* const res = createMockResponse();
|
|
65
|
+
* await plugin._handleStream(req, res);
|
|
66
|
+
* await expectStream(res).toEmit("status", "result");
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function createMockResponse(): {
|
|
70
|
+
headersSent: boolean;
|
|
71
|
+
status: vitest.Mock<(...args: any[]) => any>;
|
|
72
|
+
json: vitest.Mock<(...args: any[]) => any>;
|
|
73
|
+
send: vitest.Mock<(this: Any) => any>;
|
|
74
|
+
sendStatus: vitest.Mock<(...args: any[]) => any>;
|
|
75
|
+
end: vitest.Mock<(this: Any, chunk?: unknown) => any>;
|
|
76
|
+
write: vitest.Mock<(this: Any, chunk?: unknown) => any>;
|
|
77
|
+
setHeader: vitest.Mock<(this: Any) => any>;
|
|
78
|
+
flushHeaders: vitest.Mock<(...args: any[]) => any>;
|
|
79
|
+
destroy: vitest.Mock<(...args: any[]) => any>;
|
|
80
|
+
on: vitest.Mock<(this: Any, event: string, handler: (...args: Any[]) => void) => any>;
|
|
81
|
+
off: vitest.Mock<(this: Any, event: string, handler: (...args: Any[]) => void) => any>;
|
|
82
|
+
writableEnded: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* The SSE body captured so far, as a real `Response` — the bridge from a
|
|
85
|
+
* `res.write`-based handler into {@link expectStream}. `expectStream`
|
|
86
|
+
* detects this method and calls it for you, so `expectStream(res)` and
|
|
87
|
+
* `expectStream(res.sseResponse())` are equivalent.
|
|
88
|
+
*/
|
|
89
|
+
sseResponse(): Response;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Sets up common environment variables for Databricks testing so code that
|
|
93
|
+
* reads `DATABRICKS_HOST` / `DATABRICKS_WAREHOUSE_ID` finds test values.
|
|
94
|
+
*/
|
|
95
|
+
declare function setupDatabricksEnv(overrides?: Record<string, string>): void;
|
|
96
|
+
/**
|
|
97
|
+
* Clears AppKit's process-wide cache singleton so cached values don't leak
|
|
98
|
+
* between tests in the same file.
|
|
99
|
+
*
|
|
100
|
+
* The cache `attach()` seeds is shared by every test in a file (Vitest isolates
|
|
101
|
+
* files, not tests within a file). Call this in `beforeEach` when one test's
|
|
102
|
+
* cached value must not be seen by the next, or mid-test to force a cache miss
|
|
103
|
+
* before asserting a subsequent hit.
|
|
104
|
+
*
|
|
105
|
+
* No-ops when the cache has not been initialized yet, so it is safe to call
|
|
106
|
+
* before any `attach()`.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* beforeEach(async () => {
|
|
111
|
+
* await resetTestCache();
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
declare function resetTestCache(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Context options for running tests with mocked service/user context
|
|
118
|
+
*/
|
|
119
|
+
interface TestContextOptions {
|
|
120
|
+
/** Mock WorkspaceClient for service principal operations */
|
|
121
|
+
serviceDatabricksClient?: Any;
|
|
122
|
+
/** Mock WorkspaceClient for user operations */
|
|
123
|
+
userDatabricksClient?: Any;
|
|
124
|
+
/** User ID for user context */
|
|
125
|
+
userId?: string;
|
|
126
|
+
/** Service user ID */
|
|
127
|
+
serviceUserId?: string;
|
|
128
|
+
/** Warehouse ID */
|
|
129
|
+
warehouseId?: string;
|
|
130
|
+
/** Workspace ID */
|
|
131
|
+
workspaceId?: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Creates a default mock WorkspaceClient for testing (SQL succeeds, warehouse
|
|
135
|
+
* RUNNING).
|
|
136
|
+
*/
|
|
137
|
+
declare function createMockWorkspaceClient(): {
|
|
138
|
+
statementExecution: {
|
|
139
|
+
executeStatement: vitest.Mock<(...args: any[]) => any>;
|
|
140
|
+
};
|
|
141
|
+
warehouses: {
|
|
142
|
+
get: vitest.Mock<(...args: any[]) => any>;
|
|
143
|
+
start: vitest.Mock<(...args: any[]) => any>;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Mocks the `ServiceContext` singleton for testing — spies `get`,
|
|
148
|
+
* `initialize`, `isInitialized`, and `createUserContext` so code that resolves
|
|
149
|
+
* the service principal or an on-behalf-of user context gets test doubles.
|
|
150
|
+
* Call in `beforeEach`; call the returned `restore()` in `afterEach`.
|
|
151
|
+
*
|
|
152
|
+
* @returns The mock context plus the spies and a `restore()` helper.
|
|
153
|
+
*/
|
|
154
|
+
declare function mockServiceContext(options?: TestContextOptions): {
|
|
155
|
+
serviceContext: ServiceContextState;
|
|
156
|
+
getSpy: vitest.MockInstance<typeof ServiceContext.get>;
|
|
157
|
+
initSpy: vitest.MockInstance<typeof ServiceContext.initialize>;
|
|
158
|
+
isInitializedSpy: vitest.MockInstance<typeof ServiceContext.isInitialized>;
|
|
159
|
+
createUserContextSpy: vitest.MockInstance<typeof ServiceContext.createUserContext>;
|
|
160
|
+
restore: () => void;
|
|
161
|
+
};
|
|
162
|
+
/** The handle {@link mockServiceContext} returns (spies + `restore`). */
|
|
163
|
+
type ServiceContextMock = ReturnType<typeof mockServiceContext>;
|
|
164
|
+
/**
|
|
165
|
+
* Registers a fresh {@link mockServiceContext} before each test and restores it
|
|
166
|
+
* after — the whole `beforeEach`/`afterEach` dance in one line.
|
|
167
|
+
*
|
|
168
|
+
* Call it at the top of a `describe` block (or module top-level), NOT inside a
|
|
169
|
+
* test: Vitest's `beforeEach`/`afterEach` only register during collection, so a
|
|
170
|
+
* call from within a test body registers nothing for that test.
|
|
171
|
+
*
|
|
172
|
+
* Returns a **live** accessor, not the handle: each `beforeEach` builds fresh
|
|
173
|
+
* spies, so reading `.current` inside a test always sees that test's mock. A
|
|
174
|
+
* handle captured once would go stale after the first hook runs.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* describe("my plugin", () => {
|
|
179
|
+
* const ctx = useServiceContextMock({ warehouseId: "wh-1" });
|
|
180
|
+
*
|
|
181
|
+
* test("resolves the warehouse", async () => {
|
|
182
|
+
* await myHandler(req, res);
|
|
183
|
+
* expect(ctx.current.getSpy).toHaveBeenCalled();
|
|
184
|
+
* });
|
|
185
|
+
* });
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @returns `{ current }` — the active {@link ServiceContextMock} for the test.
|
|
189
|
+
*/
|
|
190
|
+
declare function useServiceContextMock(options?: TestContextOptions): {
|
|
191
|
+
readonly current: ServiceContextMock;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Runs a test function within a mocked service context: installs the mock,
|
|
195
|
+
* runs `fn`, and restores the singleton afterward.
|
|
196
|
+
*/
|
|
197
|
+
declare function runWithRequestContext<T>(fn: () => T | Promise<T>, context?: TestContextOptions): Promise<T>;
|
|
198
|
+
/**
|
|
199
|
+
* Builds a SUCCEEDED SQL statement response with a synthetic statement id,
|
|
200
|
+
* `data_array` rows, and a manifest schema derived from `columns`.
|
|
201
|
+
*/
|
|
202
|
+
declare function createSuccessfulSQLResponse(data: Any[][], columns: Array<{
|
|
203
|
+
name: string;
|
|
204
|
+
type_name?: string;
|
|
205
|
+
}>): {
|
|
206
|
+
status: {
|
|
207
|
+
state: string;
|
|
208
|
+
};
|
|
209
|
+
statement_id: string;
|
|
210
|
+
result: {
|
|
211
|
+
data_array: any[][];
|
|
212
|
+
};
|
|
213
|
+
manifest: {
|
|
214
|
+
schema: {
|
|
215
|
+
columns: {
|
|
216
|
+
name: string;
|
|
217
|
+
type_name: string;
|
|
218
|
+
}[];
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
/** Builds a FAILED SQL statement response carrying `errorMessage`. */
|
|
223
|
+
declare function createFailedSQLResponse(errorMessage: string): {
|
|
224
|
+
status: {
|
|
225
|
+
state: string;
|
|
226
|
+
error: {
|
|
227
|
+
message: string;
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
statement_id: string;
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* A WorkspaceClient whose `executeStatement`/`getStatement` are bare `vi.fn()`s
|
|
234
|
+
* (no default resolution) so a test can script exactly what SQL returns.
|
|
235
|
+
* `warehouses.get` defaults to RUNNING.
|
|
236
|
+
*/
|
|
237
|
+
declare function createConfigurableMockWorkspaceClient(): {
|
|
238
|
+
client: {
|
|
239
|
+
statementExecution: {
|
|
240
|
+
executeStatement: vitest.Mock<(...args: any[]) => any>;
|
|
241
|
+
getStatement: vitest.Mock<(...args: any[]) => any>;
|
|
242
|
+
};
|
|
243
|
+
warehouses: {
|
|
244
|
+
get: vitest.Mock<(...args: any[]) => any>;
|
|
245
|
+
start: vitest.Mock<(...args: any[]) => any>;
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
mocks: {
|
|
249
|
+
executeStatement: vitest.Mock<(...args: any[]) => any>;
|
|
250
|
+
getStatement: vitest.Mock<(...args: any[]) => any>;
|
|
251
|
+
warehousesGet: vitest.Mock<(...args: any[]) => any>;
|
|
252
|
+
warehousesStart: vitest.Mock<(...args: any[]) => any>;
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
//#endregion
|
|
256
|
+
export { OboOption, ServiceContextMock, TestContextOptions, createConfigurableMockWorkspaceClient, createFailedSQLResponse, createMockRequest, createMockResponse, createMockRouter, createMockTelemetry, createMockWorkspaceClient, createSuccessfulSQLResponse, mockServiceContext, resetTestCache, runWithRequestContext, setupDatabricksEnv, useServiceContextMock };
|
|
257
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","names":[],"sources":["../../src/testing/fixtures.ts"],"mappings":";;;;;;;KAWK,GAAA;;;AAJkE;;;;iBAYvD,mBAAA,CAAA,GAAuB,UAAA;AAAvC;;;;AAAA,iBAqDgB,gBAAA,CAAA;EACd,MAAA,EAAQ,UAAA;EACR,QAAA,EAAU,MAAA,SAAe,GAAA;EACzB,UAAA,GAAa,MAAA,UAAgB,IAAA,aAAiB,GAAA;AAAA;;;;;;;;KAqCpC,SAAA;EAtCA,sDA0CN,MAAA,WAzCJ;EA2CI,KAAA,WA3CyB;EA6CzB,KAAA;AAAA;;AARN;;;;;;;;;AAqCA;;;;;iBAAgB,iBAAA,CAAkB,SAAA,GAAW,GAAA;;;;;;;;;;;;;;;;;iBA+C7B,kBAAA,CAAA;;UAAkB,MAAA,CAAA,IAAA;;QAWC,MAAA,CAAA,IAAA,QAAH,GAAA;;OAKE,MAAA,CAAA,IAAA,QAAH,GAAA,EAAG,KAAA;SAcE,MAAA,CAAA,IAAA,QAAH,GAAA,EAAG,KAAA;aAOI,MAAA,CAAA,IAAA,QAAH,GAAA;;;MAST,MAAA,CAAA,IAAA,QAFhB,GAAA,EAAG,KAAA,UACI,OAAA,MACA,IAAA,EAAM,GAAA;OAWG,MAAA,CAAA,IAAA,QAFhB,GAAA,EAAG,KAAA,UACI,OAAA,MACA,IAAA,EAAM,GAAA;;;;;;;;iBAgBN,QAAA;AAAA;;;;;iBAWH,kBAAA,CAAmB,SAAA,GAAW,MAAA;;;;;;;;;;;;;;;;;;;;iBAyBxB,cAAA,CAAA,GAAkB,OAAA;;;;UAcvB,kBAAA;;EAEf,uBAAA,GAA0B,GAAA;;EAE1B,oBAAA,GAAuB,GAAA;EAtEN;EAwEjB,MAAA;EAzEiB;EA2EjB,aAAA;;EAEA,WAAA;EA5DyB;EA8DzB,WAAA;AAAA;;;;;iBAOc,yBAAA,CAAA;;sBAAyB,MAAA,CAAA,IAAA;;;;;;;;;;;;;;;iBA2CzB,kBAAA,CAAmB,OAAA,GAAS,kBAAA;;;;;;;;;KA6ChC,kBAAA,GAAqB,UAAA,QAAkB,kBAAA;;;;;;;;;;;;;;AA7CnD;;;;;;;;;;;;;iBAyEgB,qBAAA,CAAsB,OAAA,GAAS,kBAAA;EAAA,SACpC,OAAA,EAAS,kBAAA;AAAA;;;;;iBA+BE,qBAAA,GAAA,CACpB,EAAA,QAAU,CAAA,GAAI,OAAA,CAAQ,CAAA,GACtB,OAAA,GAAU,kBAAA,GACT,OAAA,CAAQ,CAAA;;;;;iBAcK,2BAAA,CACd,IAAA,EAAM,GAAA,MACN,OAAA,EAAS,KAAA;EAAQ,IAAA;EAAc,SAAA;AAAA;;;;;;;;;;;;;;;;;;iBAoBjB,uBAAA,CAAwB,YAAA;;;;;;;;;;;;;;iBAiBxB,qCAAA,CAAA;;;wBAAqC,MAAA,CAAA,IAAA"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { ServiceContext } from "../context/service-context.js";
|
|
2
|
+
import { CacheManager } from "../cache/index.js";
|
|
3
|
+
import { afterEach, beforeEach, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
//#region src/testing/fixtures.ts
|
|
6
|
+
/**
|
|
7
|
+
* Creates a mock telemetry provider for testing. Every span/meter/logger is a
|
|
8
|
+
* `vi.fn()` no-op, so plugins that trace, count, or log run without a live
|
|
9
|
+
* OpenTelemetry pipeline. Passed into {@link createTestPluginContext} as the one
|
|
10
|
+
* injectable production seam.
|
|
11
|
+
*/
|
|
12
|
+
function createMockTelemetry() {
|
|
13
|
+
const mockSpan = {
|
|
14
|
+
addLink: vi.fn(),
|
|
15
|
+
addLinks: vi.fn(),
|
|
16
|
+
end: vi.fn(),
|
|
17
|
+
setAttribute: vi.fn(),
|
|
18
|
+
setAttributes: vi.fn(),
|
|
19
|
+
setStatus: vi.fn(),
|
|
20
|
+
recordException: vi.fn(),
|
|
21
|
+
updateName: vi.fn(),
|
|
22
|
+
addEvent: vi.fn(),
|
|
23
|
+
isRecording: vi.fn().mockReturnValue(false),
|
|
24
|
+
spanContext: vi.fn()
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
getTracer: vi.fn().mockReturnValue({ startActiveSpan: vi.fn().mockImplementation((...args) => {
|
|
28
|
+
const fn = args[args.length - 1];
|
|
29
|
+
if (typeof fn === "function") return fn(mockSpan);
|
|
30
|
+
}) }),
|
|
31
|
+
getMeter: vi.fn().mockReturnValue({
|
|
32
|
+
createCounter: vi.fn().mockReturnValue({ add: vi.fn() }),
|
|
33
|
+
createHistogram: vi.fn().mockReturnValue({ record: vi.fn() })
|
|
34
|
+
}),
|
|
35
|
+
getLogger: vi.fn().mockReturnValue({ emit: vi.fn() }),
|
|
36
|
+
emit: vi.fn(),
|
|
37
|
+
startActiveSpan: vi.fn().mockImplementation(async (_name, _options, fn, _tracerOptions) => {
|
|
38
|
+
return await fn(mockSpan);
|
|
39
|
+
}),
|
|
40
|
+
registerInstrumentations: vi.fn()
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates a mock Express router that captures registered handlers so a test
|
|
45
|
+
* can pull a handler back out by method + path and invoke it directly.
|
|
46
|
+
*/
|
|
47
|
+
function createMockRouter() {
|
|
48
|
+
const handlers = {};
|
|
49
|
+
return {
|
|
50
|
+
router: {
|
|
51
|
+
get: vi.fn((path, handler) => {
|
|
52
|
+
handlers[`GET:${path}`] = handler;
|
|
53
|
+
}),
|
|
54
|
+
post: vi.fn((path, handler) => {
|
|
55
|
+
handlers[`POST:${path}`] = handler;
|
|
56
|
+
}),
|
|
57
|
+
put: vi.fn((path, handler) => {
|
|
58
|
+
handlers[`PUT:${path}`] = handler;
|
|
59
|
+
}),
|
|
60
|
+
delete: vi.fn((path, handler) => {
|
|
61
|
+
handlers[`DELETE:${path}`] = handler;
|
|
62
|
+
}),
|
|
63
|
+
patch: vi.fn((path, handler) => {
|
|
64
|
+
handlers[`PATCH:${path}`] = handler;
|
|
65
|
+
})
|
|
66
|
+
},
|
|
67
|
+
handlers,
|
|
68
|
+
getHandler: (method, path) => handlers[`${method.toUpperCase()}:${path}`]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Build the forwarded identity headers an `obo` option implies. */
|
|
72
|
+
function oboHeaders(obo) {
|
|
73
|
+
const opts = obo === true ? {} : obo;
|
|
74
|
+
const headers = {
|
|
75
|
+
"x-forwarded-access-token": opts.token ?? "test-user-token",
|
|
76
|
+
"x-forwarded-user": opts.userId ?? "test-user"
|
|
77
|
+
};
|
|
78
|
+
if (opts.email) headers["x-forwarded-email"] = opts.email;
|
|
79
|
+
return headers;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a mock Express request. Pass `overrides` to set `params`, `query`,
|
|
83
|
+
* `body`, `headers`, etc.
|
|
84
|
+
*
|
|
85
|
+
* For on-behalf-of tests, pass `obo` instead of hand-adding forwarded headers —
|
|
86
|
+
* `createMockRequest({ obo: true })` sets the identity headers the real
|
|
87
|
+
* `asUser` requires. Any explicit `headers` you also pass win over the ones
|
|
88
|
+
* `obo` generates, so you can override a single field.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* createMockRequest({ obo: true }); // default test user + token
|
|
93
|
+
* createMockRequest({ obo: { userId: "alice" } }); // pick the user
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
function createMockRequest(overrides = {}) {
|
|
97
|
+
const { obo, headers: headerOverrides, ...rest } = overrides;
|
|
98
|
+
const headers = Object.fromEntries(Object.entries({
|
|
99
|
+
...obo ? oboHeaders(obo) : {},
|
|
100
|
+
...headerOverrides
|
|
101
|
+
}).map(([name, value]) => [name.toLowerCase(), value]));
|
|
102
|
+
return {
|
|
103
|
+
params: {},
|
|
104
|
+
query: {},
|
|
105
|
+
body: {},
|
|
106
|
+
header: function(name) {
|
|
107
|
+
return this.headers[name.toLowerCase()];
|
|
108
|
+
},
|
|
109
|
+
...rest,
|
|
110
|
+
headers
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Creates a mock Express response object. `write`/`send`/`setHeader` flip
|
|
115
|
+
* `headersSent`, `end` flips `writableEnded` and fires any `close` listener —
|
|
116
|
+
* enough for streaming handlers that branch on those flags.
|
|
117
|
+
*
|
|
118
|
+
* Every chunk passed to `write` (and a final chunk to `end`) is captured, so a
|
|
119
|
+
* streaming route's real SSE output can be replayed: pass the response straight
|
|
120
|
+
* to {@link expectStream}, or call `sseResponse()` for a real `Response`.
|
|
121
|
+
*
|
|
122
|
+
* @example Assert what a streaming route emitted
|
|
123
|
+
* ```ts
|
|
124
|
+
* const res = createMockResponse();
|
|
125
|
+
* await plugin._handleStream(req, res);
|
|
126
|
+
* await expectStream(res).toEmit("status", "result");
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
function createMockResponse() {
|
|
130
|
+
const eventListeners = {};
|
|
131
|
+
const chunks = [];
|
|
132
|
+
return {
|
|
133
|
+
headersSent: false,
|
|
134
|
+
status: vi.fn().mockReturnThis(),
|
|
135
|
+
json: vi.fn().mockReturnThis(),
|
|
136
|
+
send: vi.fn(function() {
|
|
137
|
+
this.headersSent = true;
|
|
138
|
+
return this;
|
|
139
|
+
}),
|
|
140
|
+
sendStatus: vi.fn().mockReturnThis(),
|
|
141
|
+
end: vi.fn(function(chunk) {
|
|
142
|
+
if (chunk != null && typeof chunk !== "function") chunks.push(String(chunk));
|
|
143
|
+
this.writableEnded = true;
|
|
144
|
+
if (eventListeners.close) for (const handler of eventListeners.close) handler();
|
|
145
|
+
return this;
|
|
146
|
+
}),
|
|
147
|
+
write: vi.fn(function(chunk) {
|
|
148
|
+
this.headersSent = true;
|
|
149
|
+
if (chunk != null) chunks.push(String(chunk));
|
|
150
|
+
return this;
|
|
151
|
+
}),
|
|
152
|
+
setHeader: vi.fn(function() {
|
|
153
|
+
this.headersSent = true;
|
|
154
|
+
return this;
|
|
155
|
+
}),
|
|
156
|
+
flushHeaders: vi.fn().mockReturnThis(),
|
|
157
|
+
destroy: vi.fn().mockReturnThis(),
|
|
158
|
+
on: vi.fn(function(event, handler) {
|
|
159
|
+
if (!eventListeners[event]) eventListeners[event] = [];
|
|
160
|
+
eventListeners[event].push(handler);
|
|
161
|
+
return this;
|
|
162
|
+
}),
|
|
163
|
+
off: vi.fn(function(event, handler) {
|
|
164
|
+
if (eventListeners[event]) eventListeners[event] = eventListeners[event].filter((h) => h !== handler);
|
|
165
|
+
return this;
|
|
166
|
+
}),
|
|
167
|
+
writableEnded: false,
|
|
168
|
+
sseResponse() {
|
|
169
|
+
return new Response(chunks.join(""));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Sets up common environment variables for Databricks testing so code that
|
|
175
|
+
* reads `DATABRICKS_HOST` / `DATABRICKS_WAREHOUSE_ID` finds test values.
|
|
176
|
+
*/
|
|
177
|
+
function setupDatabricksEnv(overrides = {}) {
|
|
178
|
+
process.env.DATABRICKS_HOST = "https://test.databricks.com";
|
|
179
|
+
process.env.DATABRICKS_WAREHOUSE_ID = "test-warehouse-id";
|
|
180
|
+
Object.assign(process.env, overrides);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Clears AppKit's process-wide cache singleton so cached values don't leak
|
|
184
|
+
* between tests in the same file.
|
|
185
|
+
*
|
|
186
|
+
* The cache `attach()` seeds is shared by every test in a file (Vitest isolates
|
|
187
|
+
* files, not tests within a file). Call this in `beforeEach` when one test's
|
|
188
|
+
* cached value must not be seen by the next, or mid-test to force a cache miss
|
|
189
|
+
* before asserting a subsequent hit.
|
|
190
|
+
*
|
|
191
|
+
* No-ops when the cache has not been initialized yet, so it is safe to call
|
|
192
|
+
* before any `attach()`.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* beforeEach(async () => {
|
|
197
|
+
* await resetTestCache();
|
|
198
|
+
* });
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
async function resetTestCache() {
|
|
202
|
+
let cache;
|
|
203
|
+
try {
|
|
204
|
+
cache = CacheManager.getInstanceSync();
|
|
205
|
+
} catch {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
await cache.clear();
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Creates a default mock WorkspaceClient for testing (SQL succeeds, warehouse
|
|
212
|
+
* RUNNING).
|
|
213
|
+
*/
|
|
214
|
+
function createMockWorkspaceClient() {
|
|
215
|
+
return {
|
|
216
|
+
statementExecution: { executeStatement: vi.fn().mockResolvedValue({
|
|
217
|
+
status: { state: "SUCCEEDED" },
|
|
218
|
+
result: { data: [] }
|
|
219
|
+
}) },
|
|
220
|
+
warehouses: {
|
|
221
|
+
get: vi.fn().mockResolvedValue({ state: "RUNNING" }),
|
|
222
|
+
start: vi.fn().mockResolvedValue(void 0)
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Builds a {@link ServiceContextState} value for testing without touching the
|
|
228
|
+
* singleton. Internal building block for {@link mockServiceContext}, which
|
|
229
|
+
* installs the state as spies — that installer is the public entry point.
|
|
230
|
+
*/
|
|
231
|
+
function buildServiceContextState(options = {}) {
|
|
232
|
+
return {
|
|
233
|
+
client: options.serviceDatabricksClient || createMockWorkspaceClient(),
|
|
234
|
+
serviceUserId: options.serviceUserId || "test-service-user",
|
|
235
|
+
warehouseId: Promise.resolve(options.warehouseId || "test-warehouse-id"),
|
|
236
|
+
workspaceId: Promise.resolve(options.workspaceId || "test-workspace-id")
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Mocks the `ServiceContext` singleton for testing — spies `get`,
|
|
241
|
+
* `initialize`, `isInitialized`, and `createUserContext` so code that resolves
|
|
242
|
+
* the service principal or an on-behalf-of user context gets test doubles.
|
|
243
|
+
* Call in `beforeEach`; call the returned `restore()` in `afterEach`.
|
|
244
|
+
*
|
|
245
|
+
* @returns The mock context plus the spies and a `restore()` helper.
|
|
246
|
+
*/
|
|
247
|
+
function mockServiceContext(options = {}) {
|
|
248
|
+
const serviceContext = buildServiceContextState(options);
|
|
249
|
+
const getSpy = vi.spyOn(ServiceContext, "get").mockReturnValue(serviceContext);
|
|
250
|
+
const initSpy = vi.spyOn(ServiceContext, "initialize").mockResolvedValue(serviceContext);
|
|
251
|
+
const isInitializedSpy = vi.spyOn(ServiceContext, "isInitialized").mockReturnValue(true);
|
|
252
|
+
const createUserContextSpy = vi.spyOn(ServiceContext, "createUserContext").mockImplementation((_token, userId, userName) => {
|
|
253
|
+
return {
|
|
254
|
+
client: options.userDatabricksClient || createMockWorkspaceClient(),
|
|
255
|
+
userId,
|
|
256
|
+
userName,
|
|
257
|
+
warehouseId: serviceContext.warehouseId,
|
|
258
|
+
workspaceId: serviceContext.workspaceId,
|
|
259
|
+
isUserContext: true
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
return {
|
|
263
|
+
serviceContext,
|
|
264
|
+
getSpy,
|
|
265
|
+
initSpy,
|
|
266
|
+
isInitializedSpy,
|
|
267
|
+
createUserContextSpy,
|
|
268
|
+
restore: () => {
|
|
269
|
+
getSpy.mockRestore();
|
|
270
|
+
initSpy.mockRestore();
|
|
271
|
+
isInitializedSpy.mockRestore();
|
|
272
|
+
createUserContextSpy.mockRestore();
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Registers a fresh {@link mockServiceContext} before each test and restores it
|
|
278
|
+
* after — the whole `beforeEach`/`afterEach` dance in one line.
|
|
279
|
+
*
|
|
280
|
+
* Call it at the top of a `describe` block (or module top-level), NOT inside a
|
|
281
|
+
* test: Vitest's `beforeEach`/`afterEach` only register during collection, so a
|
|
282
|
+
* call from within a test body registers nothing for that test.
|
|
283
|
+
*
|
|
284
|
+
* Returns a **live** accessor, not the handle: each `beforeEach` builds fresh
|
|
285
|
+
* spies, so reading `.current` inside a test always sees that test's mock. A
|
|
286
|
+
* handle captured once would go stale after the first hook runs.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* describe("my plugin", () => {
|
|
291
|
+
* const ctx = useServiceContextMock({ warehouseId: "wh-1" });
|
|
292
|
+
*
|
|
293
|
+
* test("resolves the warehouse", async () => {
|
|
294
|
+
* await myHandler(req, res);
|
|
295
|
+
* expect(ctx.current.getSpy).toHaveBeenCalled();
|
|
296
|
+
* });
|
|
297
|
+
* });
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* @returns `{ current }` — the active {@link ServiceContextMock} for the test.
|
|
301
|
+
*/
|
|
302
|
+
function useServiceContextMock(options = {}) {
|
|
303
|
+
let handle;
|
|
304
|
+
beforeEach(() => {
|
|
305
|
+
handle = mockServiceContext(options);
|
|
306
|
+
});
|
|
307
|
+
afterEach(() => {
|
|
308
|
+
handle?.restore();
|
|
309
|
+
handle = void 0;
|
|
310
|
+
});
|
|
311
|
+
return { get current() {
|
|
312
|
+
if (!handle) throw new Error("useServiceContextMock: no active mock. Call useServiceContextMock() at the top of a describe block (not inside a test), and read `.current` from within a test.");
|
|
313
|
+
return handle;
|
|
314
|
+
} };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Runs a test function within a mocked service context: installs the mock,
|
|
318
|
+
* runs `fn`, and restores the singleton afterward.
|
|
319
|
+
*/
|
|
320
|
+
async function runWithRequestContext(fn, context) {
|
|
321
|
+
const mocks = mockServiceContext(context);
|
|
322
|
+
try {
|
|
323
|
+
return await fn();
|
|
324
|
+
} finally {
|
|
325
|
+
mocks.restore();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Builds a SUCCEEDED SQL statement response with a synthetic statement id,
|
|
330
|
+
* `data_array` rows, and a manifest schema derived from `columns`.
|
|
331
|
+
*/
|
|
332
|
+
function createSuccessfulSQLResponse(data, columns) {
|
|
333
|
+
return {
|
|
334
|
+
status: { state: "SUCCEEDED" },
|
|
335
|
+
statement_id: `stmt-${Date.now()}`,
|
|
336
|
+
result: { data_array: data },
|
|
337
|
+
manifest: { schema: { columns: columns.map((col) => ({
|
|
338
|
+
name: col.name,
|
|
339
|
+
type_name: col.type_name ?? "STRING"
|
|
340
|
+
})) } }
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** Builds a FAILED SQL statement response carrying `errorMessage`. */
|
|
344
|
+
function createFailedSQLResponse(errorMessage) {
|
|
345
|
+
return {
|
|
346
|
+
status: {
|
|
347
|
+
state: "FAILED",
|
|
348
|
+
error: { message: errorMessage }
|
|
349
|
+
},
|
|
350
|
+
statement_id: `stmt-${Date.now()}`
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* A WorkspaceClient whose `executeStatement`/`getStatement` are bare `vi.fn()`s
|
|
355
|
+
* (no default resolution) so a test can script exactly what SQL returns.
|
|
356
|
+
* `warehouses.get` defaults to RUNNING.
|
|
357
|
+
*/
|
|
358
|
+
function createConfigurableMockWorkspaceClient() {
|
|
359
|
+
const executeStatement = vi.fn();
|
|
360
|
+
const getStatement = vi.fn();
|
|
361
|
+
const warehousesGet = vi.fn().mockResolvedValue({ state: "RUNNING" });
|
|
362
|
+
const warehousesStart = vi.fn().mockResolvedValue(void 0);
|
|
363
|
+
return {
|
|
364
|
+
client: {
|
|
365
|
+
statementExecution: {
|
|
366
|
+
executeStatement,
|
|
367
|
+
getStatement
|
|
368
|
+
},
|
|
369
|
+
warehouses: {
|
|
370
|
+
get: warehousesGet,
|
|
371
|
+
start: warehousesStart
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
mocks: {
|
|
375
|
+
executeStatement,
|
|
376
|
+
getStatement,
|
|
377
|
+
warehousesGet,
|
|
378
|
+
warehousesStart
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
//#endregion
|
|
384
|
+
export { createConfigurableMockWorkspaceClient, createFailedSQLResponse, createMockRequest, createMockResponse, createMockRouter, createMockTelemetry, createMockWorkspaceClient, createSuccessfulSQLResponse, mockServiceContext, resetTestCache, runWithRequestContext, setupDatabricksEnv, useServiceContextMock };
|
|
385
|
+
//# sourceMappingURL=fixtures.js.map
|