Skip to content

Commit e09da85

Browse files
committed
Centralize OpenAPI test spec rendering
1 parent 0d7e91d commit e09da85

6 files changed

Lines changed: 39 additions & 25 deletions

File tree

apps/cloud/src/services/sources-api.node.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import {
1515
makeGreetingGraphqlSchema,
1616
} from "@executor-js/plugin-graphql/testing";
1717
import { makeGreetingMcpServer, serveMcpServer } from "@executor-js/plugin-mcp/testing";
18-
import { serveOpenApiEchoTestServer } from "@executor-js/plugin-openapi/testing";
18+
import {
19+
makeOpenApiTestSpecJson,
20+
serveOpenApiEchoTestServer,
21+
} from "@executor-js/plugin-openapi/testing";
1922

2023
import { asOrg, asUser, testUserOrgScopeId } from "./__test-harness__/api-harness";
2124

@@ -30,7 +33,7 @@ const MinimalSourceApi = HttpApi.make("sourcesApiTest")
3033
.add(PingGroup)
3134
.annotateMerge(OpenApi.annotations({ title: "Sources API Test", version: "1.0.0" }));
3235

33-
const MINIMAL_OPENAPI_SPEC = JSON.stringify(OpenApi.fromApi(MinimalSourceApi));
36+
const MINIMAL_OPENAPI_SPEC = makeOpenApiTestSpecJson(MinimalSourceApi);
3437

3538
// The Cloudflare OpenAPI spec is the biggest real spec we care about:
3639
// 16MB, 2700+ operations, thousands of shared schemas. Exercising

apps/cloud/src/services/sources-refresh.node.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import { Effect, Schema } from "effect";
99
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
1010

1111
import { ScopeId } from "@executor-js/sdk";
12-
import { serveMutableOpenApiSpecTestServer } from "@executor-js/plugin-openapi/testing";
12+
import {
13+
makeOpenApiTestSpecJson,
14+
serveMutableOpenApiSpecTestServer,
15+
} from "@executor-js/plugin-openapi/testing";
1316

1417
import { asOrg } from "./__test-harness__/api-harness";
1518

@@ -26,7 +29,7 @@ const refreshApi = (version: "1.0.0" | "2.0.0") =>
2629
.add(version === "1.0.0" ? RefreshGroupV1 : RefreshGroupV2)
2730
.annotateMerge(OpenApi.annotations({ title: "Refresh Fixture", version }));
2831

29-
const specV1 = JSON.stringify(OpenApi.fromApi(refreshApi("1.0.0")));
32+
const specV1 = makeOpenApiTestSpecJson(refreshApi("1.0.0"));
3033

3134
describe("sources.refresh (HTTP)", () => {
3235
it.effect("addSpec from URL → canRefresh:true; refresh re-fetches and updates tools", () =>

apps/cloud/src/services/tenant-isolation.node.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Effect, Result, Schema } from "effect";
77
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
88

99
import { ConnectionId, ScopeId, SecretId } from "@executor-js/sdk";
10+
import { makeOpenApiTestSpecJson } from "@executor-js/plugin-openapi/testing";
1011

1112
import { asOrg } from "./__test-harness__/api-harness";
1213

@@ -18,7 +19,7 @@ const TenantIsolationApi = HttpApi.make("tenantIsolationTest")
1819
.add(PingGroup)
1920
.annotateMerge(OpenApi.annotations({ title: "Tenant Test API", version: "1.0.0" }));
2021

21-
const MINIMAL_OPENAPI_SPEC = JSON.stringify(OpenApi.fromApi(TenantIsolationApi));
22+
const MINIMAL_OPENAPI_SPEC = makeOpenApiTestSpecJson(TenantIsolationApi);
2223

2324
describe("tenant isolation (HTTP)", () => {
2425
it.effect("write requests cannot target another org scope", () =>

packages/plugins/openapi/src/sdk/plugin.test.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import { describe, expect, it } from "@effect/vitest";
22
import { Effect, Predicate, Schema } from "effect";
3-
import {
4-
HttpApi,
5-
HttpApiBuilder,
6-
HttpApiEndpoint,
7-
HttpApiGroup,
8-
OpenApi,
9-
} from "effect/unstable/httpapi";
3+
import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
104
import { FetchHttpClient, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
115

126
import {
@@ -27,7 +21,11 @@ import type { ConfigFileSink } from "@executor-js/config";
2721
const TEST_SCOPE = "test-scope";
2822
import { openApiPlugin } from "./plugin";
2923
import { ConfiguredHeaderBinding, OAuth2SourceConfig, OpenApiSourceBindingInput } from "./types";
30-
import { addOpenApiTestSource, serveOpenApiHttpApiTestServer } from "../testing";
24+
import {
25+
addOpenApiTestSource,
26+
makeOpenApiTestSpecJson,
27+
serveOpenApiHttpApiTestServer,
28+
} from "../testing";
3129

3230
const autoApprove: InvokeOptions = { onElicitation: "accept-all" };
3331

@@ -94,8 +92,7 @@ const ItemsGroup = HttpApiGroup.make("items")
9492

9593
const TestApi = HttpApi.make("testApi").add(ItemsGroup);
9694

97-
const spec = OpenApi.fromApi(TestApi);
98-
const specJson = JSON.stringify(spec);
95+
const specJson = makeOpenApiTestSpecJson(TestApi);
9996

10097
// ---------------------------------------------------------------------------
10198
// Implement handlers

packages/plugins/openapi/src/sdk/upstream-failures.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
import { makeTestConfig } from "@executor-js/sdk/testing";
3535
import {
3636
makeOpenApiTestSourceConfig,
37+
makeOpenApiTestSpecJson,
3738
type OpenApiTestServerShape,
3839
serveOpenApiHttpApiTestServer,
3940
} from "../testing";
@@ -126,7 +127,7 @@ const FailureApi = HttpApi.make("failuresTest")
126127
.add(ThingsGroup)
127128
.annotateMerge(OpenApi.annotations({ title: "FailuresTest", version: "1.0.0" }));
128129

129-
const makeSpec = () => JSON.stringify(OpenApi.fromApi(FailureApi));
130+
const makeSpec = () => makeOpenApiTestSpecJson(FailureApi);
130131

131132
const buildExecutor = (baseUrl: string) =>
132133
Effect.gen(function* () {

packages/plugins/openapi/src/testing/index.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ export type OpenApiTestSourceExecutor = {
8787
readonly openapi: Pick<OpenApiPluginExtension, "addSpec">;
8888
};
8989

90+
export interface OpenApiTestSpecOptions {
91+
readonly baseUrl?: string;
92+
readonly transformSpec?: (spec: Record<string, unknown>) => Record<string, unknown>;
93+
}
94+
95+
export const makeOpenApiTestSpecJson = (
96+
api: HttpApi.Any,
97+
options: OpenApiTestSpecOptions = {},
98+
): string => {
99+
const annotations = OpenApi.annotations({
100+
...(options.baseUrl !== undefined ? { servers: [{ url: options.baseUrl }] } : {}),
101+
transform: options.transformSpec,
102+
});
103+
const annotated = (api as HttpApi.AnyWithProps).annotateMerge(annotations);
104+
return JSON.stringify(OpenApi.fromApi(annotated));
105+
};
106+
90107
export const makeOpenApiTestSourceConfig = (
91108
server: OpenApiTestServerShape,
92109
options: OpenApiTestSourceOptions,
@@ -152,15 +169,7 @@ const openApiSpecJsonFromHttpApi = (
152169
transformSpec?: (spec: Record<string, unknown>) => Record<string, unknown>,
153170
): Effect.Effect<string, OpenApiTestServerSpecError> =>
154171
Effect.try({
155-
try: () => {
156-
const annotated = (api as HttpApi.AnyWithProps).annotateMerge(
157-
OpenApi.annotations({
158-
servers: [{ url: baseUrl }],
159-
transform: transformSpec,
160-
}),
161-
);
162-
return JSON.stringify(OpenApi.fromApi(annotated));
163-
},
172+
try: () => makeOpenApiTestSpecJson(api, { baseUrl, transformSpec }),
164173
catch: (cause) => new OpenApiTestServerSpecError({ cause }),
165174
});
166175

0 commit comments

Comments
 (0)