forked from microsoft/typespec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest-host.ts
107 lines (97 loc) · 3 KB
/
test-host.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { Diagnostic } from "@typespec/compiler";
import {
BasicTestRunner,
createTestHost,
createTestWrapper,
expectDiagnosticEmpty,
TestHost,
} from "@typespec/compiler/testing";
import {
getAllHttpServices,
HttpOperation,
HttpOperationParameter,
HttpVerb,
RouteResolutionOptions,
} from "../src/index.js";
import { HttpTestLibrary } from "../src/testing/index.js";
export async function createHttpTestHost(): Promise<TestHost> {
return createTestHost({
libraries: [HttpTestLibrary],
});
}
export async function createHttpTestRunner(): Promise<BasicTestRunner> {
const host = await createHttpTestHost();
return createTestWrapper(host, { autoUsings: ["TypeSpec.Http"] });
}
export interface RouteDetails {
path: string;
verb: HttpVerb;
params: string[];
}
export async function getRoutesFor(
code: string,
routeOptions?: RouteResolutionOptions
): Promise<RouteDetails[]> {
const [routes, diagnostics] = await compileOperations(code, routeOptions);
expectDiagnosticEmpty(diagnostics);
return routes.map((route) => ({
...route,
params: route.params.params
.map(({ type, name }) => (type === "path" ? name : undefined))
.filter((p) => p !== undefined) as string[],
}));
}
export interface SimpleOperationDetails {
verb: HttpVerb;
path: string;
params: {
params: Array<{ name: string; type: HttpOperationParameter["type"] }>;
/**
* name of explicit `@body` parameter or array of unannotated parameter names that make up the body.
*/
body?: string | string[];
};
}
export async function compileOperations(
code: string,
routeOptions?: RouteResolutionOptions
): Promise<[SimpleOperationDetails[], readonly Diagnostic[]]> {
const [routes, diagnostics] = await getOperationsWithServiceNamespace(code, routeOptions);
const details = routes.map((r) => {
return {
verb: r.verb,
path: r.path,
params: {
params: r.parameters.parameters.map(({ type, name }) => ({ type, name })),
body:
r.parameters.body?.parameter?.name ??
(r.parameters.body?.type?.kind === "Model"
? Array.from(r.parameters.body.type.properties.keys())
: undefined),
},
};
});
return [details, diagnostics];
}
export async function getOperationsWithServiceNamespace(
code: string,
routeOptions?: RouteResolutionOptions
): Promise<[HttpOperation[], readonly Diagnostic[]]> {
const runner = await createHttpTestRunner();
await runner.compileAndDiagnose(
`@service({title: "Test Service"}) namespace TestService;
${code}`,
{
noEmit: true,
}
);
const [services] = getAllHttpServices(runner.program, routeOptions);
return [services[0].operations, runner.program.diagnostics];
}
export async function getOperations(code: string): Promise<HttpOperation[]> {
const runner = await createHttpTestRunner();
await runner.compile(code);
const [services, diagnostics] = getAllHttpServices(runner.program);
expectDiagnosticEmpty(diagnostics);
return services[0].operations;
}