@typespec/emitter-framework 0.9.0-dev.7 → 0.9.0-dev.9
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/dist/src/csharp/components/class/declaration.test.js +100 -115
- package/dist/src/csharp/components/{enum-declaration.d.ts → enum/declaration.d.ts} +1 -1
- package/dist/src/csharp/components/enum/declaration.d.ts.map +1 -0
- package/dist/src/csharp/components/{enum-declaration.js → enum/declaration.js} +4 -4
- package/dist/src/csharp/components/enum/declaration.test.d.ts +2 -0
- package/dist/src/csharp/components/enum/declaration.test.d.ts.map +1 -0
- package/dist/src/csharp/components/enum/declaration.test.js +309 -0
- package/dist/src/csharp/components/index.d.ts +1 -1
- package/dist/src/csharp/components/index.js +1 -1
- package/dist/src/csharp/components/property/property.test.js +14 -14
- package/dist/src/testing/scenario-test/code-block-expectation.d.ts +33 -0
- package/dist/src/testing/scenario-test/code-block-expectation.d.ts.map +1 -0
- package/dist/src/testing/scenario-test/code-block-expectation.js +69 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts +2 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts.map +1 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.js +80 -0
- package/dist/src/testing/scenario-test/harness.d.ts +2 -2
- package/dist/src/testing/scenario-test/harness.d.ts.map +1 -1
- package/dist/src/testing/scenario-test/harness.js +69 -158
- package/dist/src/testing/scenario-test/index.d.ts +0 -1
- package/dist/src/testing/scenario-test/index.d.ts.map +1 -1
- package/dist/src/testing/scenario-test/index.js +1 -2
- package/dist/src/testing/scenario-test/snippet-extractor.d.ts +1 -1
- package/dist/src/testing/scenario-test/snippet-extractor.js +1 -1
- package/dist/test/testing/snippet-extractor-csharp.test.js +3 -3
- package/dist/test/testing/snippet-extractor-java.test.js +3 -3
- package/dist/test/testing/snippet-extractor-python.test.js +2 -2
- package/dist/test/testing/snippet-extractor-typescript.test.js +3 -3
- package/package.json +8 -6
- package/src/csharp/components/class/declaration.test.tsx +106 -168
- package/src/csharp/components/enum/declaration.test.tsx +267 -0
- package/src/csharp/components/{enum-declaration.tsx → enum/declaration.tsx} +4 -4
- package/src/csharp/components/index.ts +1 -1
- package/src/csharp/components/property/property.test.tsx +14 -14
- package/src/testing/scenario-test/code-block-expectation.test.ts +95 -0
- package/src/testing/scenario-test/code-block-expectation.ts +115 -0
- package/src/testing/scenario-test/harness.ts +91 -236
- package/src/testing/scenario-test/index.ts +0 -1
- package/src/testing/scenario-test/snippet-extractor.ts +1 -1
- package/test/testing/snippet-extractor-csharp.test.ts +3 -3
- package/test/testing/snippet-extractor-java.test.ts +3 -3
- package/test/testing/snippet-extractor-python.test.ts +2 -2
- package/test/testing/snippet-extractor-typescript.test.ts +3 -3
- package/dist/src/csharp/components/enum-declaration.d.ts.map +0 -1
- package/dist/src/testing/scenario-test/test-host.d.ts +0 -8
- package/dist/src/testing/scenario-test/test-host.d.ts.map +0 -1
- package/dist/src/testing/scenario-test/test-host.js +0 -49
- package/dist/test/csharp/components/enum-declaration.test.d.ts +0 -2
- package/dist/test/csharp/components/enum-declaration.test.d.ts.map +0 -1
- package/dist/test/csharp/components/enum-declaration.test.js +0 -403
- package/dist/test/csharp/test-host.d.ts +0 -11
- package/dist/test/csharp/test-host.d.ts.map +0 -1
- package/dist/test/csharp/test-host.js +0 -32
- package/dist/test/csharp/utils.d.ts +0 -3
- package/dist/test/csharp/utils.d.ts.map +0 -1
- package/dist/test/csharp/utils.js +0 -6
- package/src/testing/scenario-test/test-host.ts +0 -83
- package/test/csharp/components/enum-declaration.test.tsx +0 -337
- package/test/csharp/test-host.ts +0 -42
- package/test/csharp/utils.ts +0 -8
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { createComponent as _$createComponent, createIntrinsic as _$createIntrinsic } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { Tester } from "#test/test-host.js";
|
|
3
|
+
import { createCSharpNamePolicy, Namespace, SourceFile } from "@alloy-js/csharp";
|
|
4
|
+
import { t } from "@typespec/compiler/testing";
|
|
5
|
+
import { beforeEach, expect, it } from "vitest";
|
|
6
|
+
import { Output } from "../../../core/index.js";
|
|
7
|
+
import { EnumDeclaration } from "../../index.js";
|
|
8
|
+
let runner;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
runner = await Tester.createInstance();
|
|
11
|
+
});
|
|
12
|
+
function Wrapper(props) {
|
|
13
|
+
const policy = createCSharpNamePolicy();
|
|
14
|
+
return _$createComponent(Output, {
|
|
15
|
+
get program() {
|
|
16
|
+
return runner.program;
|
|
17
|
+
},
|
|
18
|
+
namePolicy: policy,
|
|
19
|
+
get children() {
|
|
20
|
+
return _$createComponent(Namespace, {
|
|
21
|
+
name: "TestNamespace",
|
|
22
|
+
get children() {
|
|
23
|
+
return _$createComponent(SourceFile, {
|
|
24
|
+
path: "test.cs",
|
|
25
|
+
get children() {
|
|
26
|
+
return props.children;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
it("renders a basic enum declaration", async () => {
|
|
35
|
+
const {
|
|
36
|
+
TestEnum
|
|
37
|
+
} = await runner.compile(t.code`
|
|
38
|
+
@test enum ${t.enum("TestEnum")} {
|
|
39
|
+
Value1;
|
|
40
|
+
Value2;
|
|
41
|
+
Value3;
|
|
42
|
+
}
|
|
43
|
+
`);
|
|
44
|
+
expect(_$createComponent(Wrapper, {
|
|
45
|
+
get children() {
|
|
46
|
+
return _$createComponent(EnumDeclaration, {
|
|
47
|
+
type: TestEnum
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
})).toRenderTo(`
|
|
51
|
+
namespace TestNamespace
|
|
52
|
+
{
|
|
53
|
+
enum TestEnum
|
|
54
|
+
{
|
|
55
|
+
Value1,
|
|
56
|
+
Value2,
|
|
57
|
+
Value3
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
it("renders an empty enum declaration", async () => {
|
|
63
|
+
const {
|
|
64
|
+
TestEnum
|
|
65
|
+
} = await runner.compile(t.code`
|
|
66
|
+
@test enum ${t.enum("TestEnum")} {}
|
|
67
|
+
`);
|
|
68
|
+
expect(_$createComponent(Wrapper, {
|
|
69
|
+
get children() {
|
|
70
|
+
return _$createComponent(EnumDeclaration, {
|
|
71
|
+
type: TestEnum
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
})).toRenderTo(`
|
|
75
|
+
namespace TestNamespace
|
|
76
|
+
{
|
|
77
|
+
enum TestEnum
|
|
78
|
+
{
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`);
|
|
83
|
+
});
|
|
84
|
+
it("can override enum name", async () => {
|
|
85
|
+
const {
|
|
86
|
+
TestEnum
|
|
87
|
+
} = await runner.compile(t.code`
|
|
88
|
+
@test enum ${t.enum("TestEnum")} {
|
|
89
|
+
Value1;
|
|
90
|
+
Value2;
|
|
91
|
+
}
|
|
92
|
+
`);
|
|
93
|
+
expect(_$createComponent(Wrapper, {
|
|
94
|
+
get children() {
|
|
95
|
+
return _$createComponent(EnumDeclaration, {
|
|
96
|
+
type: TestEnum,
|
|
97
|
+
name: "CustomEnumName"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
})).toRenderTo(`
|
|
101
|
+
namespace TestNamespace
|
|
102
|
+
{
|
|
103
|
+
enum CustomEnumName
|
|
104
|
+
{
|
|
105
|
+
Value1,
|
|
106
|
+
Value2
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`);
|
|
110
|
+
});
|
|
111
|
+
it("renders an enum with access modifiers", async () => {
|
|
112
|
+
const {
|
|
113
|
+
TestEnum
|
|
114
|
+
} = await runner.compile(t.code`
|
|
115
|
+
@test enum ${t.enum("TestEnum")} {
|
|
116
|
+
Value1;
|
|
117
|
+
Value2;
|
|
118
|
+
}
|
|
119
|
+
`);
|
|
120
|
+
expect(_$createComponent(Wrapper, {
|
|
121
|
+
get children() {
|
|
122
|
+
return _$createComponent(EnumDeclaration, {
|
|
123
|
+
type: TestEnum,
|
|
124
|
+
internal: true
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
})).toRenderTo(`
|
|
128
|
+
namespace TestNamespace
|
|
129
|
+
{
|
|
130
|
+
internal enum TestEnum
|
|
131
|
+
{
|
|
132
|
+
Value1,
|
|
133
|
+
Value2
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
`);
|
|
137
|
+
});
|
|
138
|
+
it("renders enum with C# naming conventions", async () => {
|
|
139
|
+
const {
|
|
140
|
+
TestEnum
|
|
141
|
+
} = await runner.compile(t.code`
|
|
142
|
+
@test enum ${t.enum("TestEnum")} {
|
|
143
|
+
value_one;
|
|
144
|
+
value_two;
|
|
145
|
+
value_three;
|
|
146
|
+
}
|
|
147
|
+
`);
|
|
148
|
+
expect(_$createComponent(Output, {
|
|
149
|
+
get program() {
|
|
150
|
+
return runner.program;
|
|
151
|
+
},
|
|
152
|
+
get namePolicy() {
|
|
153
|
+
return createCSharpNamePolicy();
|
|
154
|
+
},
|
|
155
|
+
get children() {
|
|
156
|
+
return _$createComponent(Namespace, {
|
|
157
|
+
name: "TestNamespace",
|
|
158
|
+
get children() {
|
|
159
|
+
return _$createComponent(SourceFile, {
|
|
160
|
+
path: "test.cs",
|
|
161
|
+
get children() {
|
|
162
|
+
return _$createComponent(EnumDeclaration, {
|
|
163
|
+
type: TestEnum
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
})).toRenderTo(`
|
|
171
|
+
namespace TestNamespace
|
|
172
|
+
{
|
|
173
|
+
enum TestEnum
|
|
174
|
+
{
|
|
175
|
+
ValueOne,
|
|
176
|
+
ValueTwo,
|
|
177
|
+
ValueThree
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
`);
|
|
181
|
+
});
|
|
182
|
+
it("renders enum with single value", async () => {
|
|
183
|
+
const {
|
|
184
|
+
TestEnum
|
|
185
|
+
} = await runner.compile(t.code`
|
|
186
|
+
@test enum ${t.enum("TestEnum")} {
|
|
187
|
+
OnlyValue;
|
|
188
|
+
}
|
|
189
|
+
`);
|
|
190
|
+
expect(_$createComponent(Wrapper, {
|
|
191
|
+
get children() {
|
|
192
|
+
return _$createComponent(EnumDeclaration, {
|
|
193
|
+
type: TestEnum
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
})).toRenderTo(`
|
|
197
|
+
namespace TestNamespace
|
|
198
|
+
{
|
|
199
|
+
enum TestEnum
|
|
200
|
+
{
|
|
201
|
+
OnlyValue
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
`);
|
|
205
|
+
});
|
|
206
|
+
it("renders enum with numeric-like member names", async () => {
|
|
207
|
+
const {
|
|
208
|
+
TestEnum
|
|
209
|
+
} = await runner.compile(t.code`
|
|
210
|
+
@test enum ${t.enum("TestEnum")} {
|
|
211
|
+
Value0;
|
|
212
|
+
Value1;
|
|
213
|
+
Value10;
|
|
214
|
+
Value100;
|
|
215
|
+
}
|
|
216
|
+
`);
|
|
217
|
+
expect(_$createComponent(Wrapper, {
|
|
218
|
+
get children() {
|
|
219
|
+
return _$createComponent(EnumDeclaration, {
|
|
220
|
+
type: TestEnum
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
})).toRenderTo(`
|
|
224
|
+
namespace TestNamespace
|
|
225
|
+
{
|
|
226
|
+
enum TestEnum
|
|
227
|
+
{
|
|
228
|
+
Value0,
|
|
229
|
+
Value1,
|
|
230
|
+
Value10,
|
|
231
|
+
Value100
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
`);
|
|
235
|
+
});
|
|
236
|
+
it("renders multiple enums in the same namespace", async () => {
|
|
237
|
+
const {
|
|
238
|
+
TestEnum1,
|
|
239
|
+
TestEnum2
|
|
240
|
+
} = await runner.compile(t.code`
|
|
241
|
+
@test enum ${t.enum("TestEnum1")} {
|
|
242
|
+
Value1;
|
|
243
|
+
Value2;
|
|
244
|
+
}
|
|
245
|
+
@test enum ${t.enum("TestEnum2")} {
|
|
246
|
+
OptionA;
|
|
247
|
+
OptionB;
|
|
248
|
+
OptionC;
|
|
249
|
+
}
|
|
250
|
+
`);
|
|
251
|
+
expect(_$createComponent(Wrapper, {
|
|
252
|
+
get children() {
|
|
253
|
+
return [_$createComponent(EnumDeclaration, {
|
|
254
|
+
type: TestEnum1
|
|
255
|
+
}), _$createIntrinsic("hbr", {}), _$createComponent(EnumDeclaration, {
|
|
256
|
+
type: TestEnum2
|
|
257
|
+
})];
|
|
258
|
+
}
|
|
259
|
+
})).toRenderTo(`
|
|
260
|
+
namespace TestNamespace
|
|
261
|
+
{
|
|
262
|
+
enum TestEnum1
|
|
263
|
+
{
|
|
264
|
+
Value1,
|
|
265
|
+
Value2
|
|
266
|
+
}
|
|
267
|
+
enum TestEnum2
|
|
268
|
+
{
|
|
269
|
+
OptionA,
|
|
270
|
+
OptionB,
|
|
271
|
+
OptionC
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
`);
|
|
275
|
+
});
|
|
276
|
+
it("renders an enum with doc comments", async () => {
|
|
277
|
+
const {
|
|
278
|
+
TestEnum
|
|
279
|
+
} = await runner.compile(t.code`
|
|
280
|
+
@test enum ${t.enum("TestEnum")} {
|
|
281
|
+
@doc("This is value one")
|
|
282
|
+
Value1;
|
|
283
|
+
/** This is value two */
|
|
284
|
+
Value2;
|
|
285
|
+
}
|
|
286
|
+
`);
|
|
287
|
+
expect(_$createComponent(Wrapper, {
|
|
288
|
+
get children() {
|
|
289
|
+
return _$createComponent(EnumDeclaration, {
|
|
290
|
+
type: TestEnum
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
})).toRenderTo(`
|
|
294
|
+
namespace TestNamespace
|
|
295
|
+
{
|
|
296
|
+
enum TestEnum
|
|
297
|
+
{
|
|
298
|
+
/// <summary>
|
|
299
|
+
/// This is value one
|
|
300
|
+
/// </summary>
|
|
301
|
+
Value1,
|
|
302
|
+
/// <summary>
|
|
303
|
+
/// This is value two
|
|
304
|
+
/// </summary>
|
|
305
|
+
Value2
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
`);
|
|
309
|
+
});
|
|
@@ -53,10 +53,10 @@ it("maps prop: string | null to nullable property", async () => {
|
|
|
53
53
|
})).toRenderTo(`
|
|
54
54
|
namespace TestNamespace
|
|
55
55
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
class Test
|
|
57
|
+
{
|
|
58
|
+
public required string? Prop1 { get; set; }
|
|
59
|
+
}
|
|
60
60
|
}
|
|
61
61
|
`);
|
|
62
62
|
});
|
|
@@ -79,11 +79,11 @@ describe("jsonAttributes", () => {
|
|
|
79
79
|
})).toRenderTo(`
|
|
80
80
|
namespace TestNamespace
|
|
81
81
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
class Test
|
|
83
|
+
{
|
|
84
|
+
[System.Text.Json.JsonPropertyName("prop1")]
|
|
85
|
+
public required string Prop1 { get; set; }
|
|
86
|
+
}
|
|
87
87
|
}
|
|
88
88
|
`);
|
|
89
89
|
});
|
|
@@ -106,11 +106,11 @@ describe("jsonAttributes", () => {
|
|
|
106
106
|
})).toRenderTo(`
|
|
107
107
|
namespace TestNamespace
|
|
108
108
|
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
class Test
|
|
110
|
+
{
|
|
111
|
+
[System.Text.Json.JsonPropertyName("prop_1")]
|
|
112
|
+
public required string Prop1 { get; set; }
|
|
113
|
+
}
|
|
114
114
|
}
|
|
115
115
|
`);
|
|
116
116
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SnippetExtractor } from "./snippet-extractor.js";
|
|
2
|
+
export interface ElementQuery {
|
|
3
|
+
/** Type to query */
|
|
4
|
+
type: string;
|
|
5
|
+
/** Name of the type to query */
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
export interface CodeBlockQuery {
|
|
9
|
+
/** Language */
|
|
10
|
+
lang: string;
|
|
11
|
+
/** File path */
|
|
12
|
+
file: string;
|
|
13
|
+
/** Query for content in the file */
|
|
14
|
+
query?: ElementQuery;
|
|
15
|
+
}
|
|
16
|
+
export interface CodeBlockExpectation extends CodeBlockQuery {
|
|
17
|
+
/** Expected content of the code block */
|
|
18
|
+
expected: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parse a markdown code block following the expectation syntax
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseCodeblockExpectation(heading: string, content: string): CodeBlockExpectation;
|
|
24
|
+
/**
|
|
25
|
+
* Parse the codeblock heading for what it should validate.
|
|
26
|
+
* Expected format
|
|
27
|
+
* ```
|
|
28
|
+
* ts path/to/file.ts {type} {name}
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseCodeBlockHeading(heading: string): CodeBlockQuery;
|
|
32
|
+
export declare function getExcerptForQuery(snippetExtractor: SnippetExtractor, expectation: CodeBlockQuery, outputs: Record<string, string>): string;
|
|
33
|
+
//# sourceMappingURL=code-block-expectation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-expectation.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/code-block-expectation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IAEb,oCAAoC;IACpC,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAMhG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAerE;AAED,wBAAgB,kBAAkB,CAChC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CAUR"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a markdown code block following the expectation syntax
|
|
3
|
+
*/
|
|
4
|
+
export function parseCodeblockExpectation(heading, content) {
|
|
5
|
+
const query = parseCodeBlockHeading(heading);
|
|
6
|
+
return {
|
|
7
|
+
...query,
|
|
8
|
+
expected: content
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse the codeblock heading for what it should validate.
|
|
14
|
+
* Expected format
|
|
15
|
+
* ```
|
|
16
|
+
* ts path/to/file.ts {type} {name}
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function parseCodeBlockHeading(heading) {
|
|
20
|
+
const [lang, file, type, name] = heading.split(" ");
|
|
21
|
+
if (!file) {
|
|
22
|
+
throw new Error(`Invalid code block heading: "${heading}". Missing file path. Expected format: "<lang> <path>"`);
|
|
23
|
+
}
|
|
24
|
+
if (type && !name) {
|
|
25
|
+
throw new Error(`Invalid code block heading: "${heading}". Missing name when using type. Expected format: "<lang> <path> [type] [name]"`);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
lang,
|
|
29
|
+
file,
|
|
30
|
+
query: type ? {
|
|
31
|
+
type,
|
|
32
|
+
name
|
|
33
|
+
} : undefined
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function getExcerptForQuery(snippetExtractor, expectation, outputs) {
|
|
37
|
+
const content = outputs[expectation.file];
|
|
38
|
+
if (!content) {
|
|
39
|
+
throw new Error(`File ${expectation.file} not found in emitted files:\n ${Object.keys(outputs).join("\n")}`);
|
|
40
|
+
}
|
|
41
|
+
return getExcerptInFile(snippetExtractor, expectation, content);
|
|
42
|
+
}
|
|
43
|
+
function getExcerptInFile(snippetExtractor, expectation, sourceFile) {
|
|
44
|
+
if (expectation.query) {
|
|
45
|
+
const excerpt = tryGetExcerptInFile(snippetExtractor, expectation.query, sourceFile);
|
|
46
|
+
if (!excerpt) {
|
|
47
|
+
throw new Error(`Could not find ${expectation.query.type} "${expectation.query.name}" in file "${expectation.file}".`);
|
|
48
|
+
}
|
|
49
|
+
return excerpt;
|
|
50
|
+
} else {
|
|
51
|
+
return sourceFile;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function tryGetExcerptInFile(snippetExtractor, query, sourceFile) {
|
|
55
|
+
switch (query.type) {
|
|
56
|
+
case "interface":
|
|
57
|
+
return snippetExtractor.getInterface(sourceFile, query.name);
|
|
58
|
+
case "type":
|
|
59
|
+
return snippetExtractor.getTypeAlias(sourceFile, query.name);
|
|
60
|
+
case "enum":
|
|
61
|
+
return snippetExtractor.getEnum(sourceFile, query.name);
|
|
62
|
+
case "function":
|
|
63
|
+
return snippetExtractor.getFunction(sourceFile, query.name);
|
|
64
|
+
case "class":
|
|
65
|
+
return snippetExtractor.getClass(sourceFile, query.name);
|
|
66
|
+
default:
|
|
67
|
+
throw new Error("Unsupported type in code block expectation: " + query.type);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-expectation.test.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/code-block-expectation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { d } from "@alloy-js/core/testing";
|
|
2
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
3
|
+
import { getExcerptForQuery, parseCodeBlockHeading } from "./code-block-expectation.js";
|
|
4
|
+
import { createSnippetExtractor, createTypeScriptExtractorConfig } from "./snippet-extractor.js";
|
|
5
|
+
describe("parseCodeBlockHeading", () => {
|
|
6
|
+
it("parse whole file expectation", () => {
|
|
7
|
+
expect(parseCodeBlockHeading("ts path/to/file.ts")).toEqual({
|
|
8
|
+
lang: "ts",
|
|
9
|
+
file: "path/to/file.ts"
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
it("throws error when no file is provided", () => {
|
|
13
|
+
expect(() => parseCodeBlockHeading("ts")).toThrow('Invalid code block heading: "ts". Missing file path. Expected format: "<lang> <path>"');
|
|
14
|
+
});
|
|
15
|
+
it("parse parse with type and name", () => {
|
|
16
|
+
expect(parseCodeBlockHeading("ts path/to/file.ts interface foo")).toEqual({
|
|
17
|
+
lang: "ts",
|
|
18
|
+
file: "path/to/file.ts",
|
|
19
|
+
query: {
|
|
20
|
+
type: "interface",
|
|
21
|
+
name: "foo"
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it("throws error when using type but no name is provided", () => {
|
|
26
|
+
expect(() => parseCodeBlockHeading("ts path/to/file.ts interface")).toThrow('Invalid code block heading: "ts path/to/file.ts interface". Missing name when using type. Expected format: "<lang> <path> [type] [name]"');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("getExcerptForQuery", () => {
|
|
30
|
+
let snippetExtractor;
|
|
31
|
+
beforeAll(async () => {
|
|
32
|
+
const tsExtractorConfig = await createTypeScriptExtractorConfig();
|
|
33
|
+
snippetExtractor = createSnippetExtractor(tsExtractorConfig);
|
|
34
|
+
});
|
|
35
|
+
it("gets a whole file", async () => {
|
|
36
|
+
const expectation = {
|
|
37
|
+
lang: "ts",
|
|
38
|
+
file: "file.ts"
|
|
39
|
+
};
|
|
40
|
+
const outputs = {
|
|
41
|
+
"file.ts": d`
|
|
42
|
+
interface bar {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
interface foo {
|
|
46
|
+
bar: string;
|
|
47
|
+
}
|
|
48
|
+
`
|
|
49
|
+
};
|
|
50
|
+
const excerpt = getExcerptForQuery(snippetExtractor, expectation, outputs);
|
|
51
|
+
expect(excerpt).toBe(outputs["file.ts"]);
|
|
52
|
+
});
|
|
53
|
+
it("gets an interface for typescript", async () => {
|
|
54
|
+
const expectation = {
|
|
55
|
+
lang: "ts",
|
|
56
|
+
file: "file.ts",
|
|
57
|
+
query: {
|
|
58
|
+
type: "interface",
|
|
59
|
+
name: "foo"
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const outputs = {
|
|
63
|
+
"file.ts": d`
|
|
64
|
+
interface bar {
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface foo {
|
|
69
|
+
bar: string;
|
|
70
|
+
}
|
|
71
|
+
`
|
|
72
|
+
};
|
|
73
|
+
const excerpt = getExcerptForQuery(snippetExtractor, expectation, outputs);
|
|
74
|
+
expect(excerpt).toBe(d`
|
|
75
|
+
interface foo {
|
|
76
|
+
bar: string;
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type EmitterTester } from "@typespec/compiler/testing";
|
|
2
2
|
import type { LanguageConfiguration, SnippetExtractor } from "./snippet-extractor.js";
|
|
3
|
-
export declare function executeScenarios(
|
|
3
|
+
export declare function executeScenarios(tester: EmitterTester, languageConfiguration: LanguageConfiguration, scenariosLocation: string, snippetExtractor: SnippetExtractor): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/harness.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/harness.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUvF,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAKtF,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EACrB,qBAAqB,EAAE,qBAAqB,EAC5C,iBAAiB,EAAE,MAAM,EACzB,gBAAgB,EAAE,gBAAgB,iBAKnC"}
|