@typespec/emitter-framework 0.6.0-dev.4 → 0.6.0-dev.6
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/core/context/name-policy-context.js +1 -2
- package/dist/src/core/index.js +1 -2
- package/dist/src/core/transport-name-policy.js +1 -2
- package/dist/src/core/write-output.js +1 -2
- package/dist/src/lib.js +1 -2
- package/dist/src/testing/index.js +1 -2
- package/dist/src/testing/scenario-test/harness.js +1 -2
- package/dist/src/testing/scenario-test/index.js +1 -2
- package/dist/src/testing/scenario-test/snippet-extractor.js +1 -2
- package/dist/src/testing/scenario-test/test-host.js +1 -2
- package/dist/src/typescript/components/array-expression.js +1 -2
- package/dist/src/typescript/components/arrow-function.js +2 -5
- package/dist/src/typescript/components/class-method.js +2 -4
- package/dist/src/typescript/components/enum-declaration.js +2 -4
- package/dist/src/typescript/components/function-declaration.js +2 -4
- package/dist/src/typescript/components/function-expression.js +2 -5
- package/dist/src/typescript/components/function-type.js +2 -5
- package/dist/src/typescript/components/index.js +1 -2
- package/dist/src/typescript/components/interface-declaration.js +2 -5
- package/dist/src/typescript/components/interface-member.js +2 -4
- package/dist/src/typescript/components/interface-method.d.ts.map +1 -1
- package/dist/src/typescript/components/interface-method.js +5 -8
- package/dist/src/typescript/components/record-expression.js +1 -2
- package/dist/src/typescript/components/static-serializers.js +1 -2
- package/dist/src/typescript/components/type-alias-declaration.js +2 -5
- package/dist/src/typescript/components/type-declaration.js +2 -4
- package/dist/src/typescript/components/type-expression.js +2 -4
- package/dist/src/typescript/components/type-transform.js +2 -4
- package/dist/src/typescript/components/union-declaration.js +2 -4
- package/dist/src/typescript/components/union-expression.js +2 -4
- package/dist/src/typescript/components/value-expression.js +2 -4
- package/dist/src/typescript/index.js +1 -2
- package/dist/src/typescript/lib.js +1 -2
- package/dist/src/typescript/utils/operation.js +1 -2
- package/dist/test/testing/snippet-extractor-csharp.test.js +96 -0
- package/dist/test/testing/snippet-extractor-java.test.js +104 -0
- package/dist/test/testing/snippet-extractor-python.test.js +33 -0
- package/dist/test/testing/snippet-extractor-typescript.test.js +161 -0
- package/dist/test/typescript/components/arrow-function.test.js +88 -0
- package/dist/test/typescript/components/enum-declaration.test.js +118 -0
- package/dist/test/typescript/components/function-declaration.test.js +246 -0
- package/dist/test/typescript/components/function-expression.test.js +88 -0
- package/dist/test/typescript/components/function-type.test.js +85 -0
- package/dist/test/typescript/components/interface-declaration.test.js +775 -0
- package/dist/test/typescript/components/interface-method.test.js +272 -0
- package/dist/test/typescript/components/member-expression.test.js +155 -0
- package/dist/test/typescript/components/type-alias-declaration.test.js +155 -0
- package/dist/test/typescript/components/type-transform.test.js +682 -0
- package/dist/test/typescript/components/union-declaration.test.js +205 -0
- package/dist/test/typescript/components/value-expression.test.js +199 -0
- package/dist/test/typescript/test-host.js +40 -0
- package/dist/test/utils.js +18 -0
- package/package.json +5 -10
- package/src/typescript/components/interface-method.tsx +2 -4
- package/test/typescript/components/interface-method.test.tsx +167 -2
- package/vitest.config.ts +2 -9
- package/babel.config.js +0 -4
- package/dist/src/core/context/index.js.map +0 -1
- package/dist/src/core/context/name-policy-context.js.map +0 -1
- package/dist/src/core/index.js.map +0 -1
- package/dist/src/core/transport-name-policy.js.map +0 -1
- package/dist/src/core/write-output.js.map +0 -1
- package/dist/src/lib.js.map +0 -1
- package/dist/src/testing/index.js.map +0 -1
- package/dist/src/testing/scenario-test/harness.js.map +0 -1
- package/dist/src/testing/scenario-test/index.js.map +0 -1
- package/dist/src/testing/scenario-test/snippet-extractor.js.map +0 -1
- package/dist/src/testing/scenario-test/test-host.js.map +0 -1
- package/dist/src/typescript/components/array-expression.js.map +0 -1
- package/dist/src/typescript/components/arrow-function.js.map +0 -1
- package/dist/src/typescript/components/class-method.js.map +0 -1
- package/dist/src/typescript/components/enum-declaration.js.map +0 -1
- package/dist/src/typescript/components/function-declaration.js.map +0 -1
- package/dist/src/typescript/components/function-expression.js.map +0 -1
- package/dist/src/typescript/components/function-type.js.map +0 -1
- package/dist/src/typescript/components/index.js.map +0 -1
- package/dist/src/typescript/components/interface-declaration.js.map +0 -1
- package/dist/src/typescript/components/interface-member.js.map +0 -1
- package/dist/src/typescript/components/interface-method.js.map +0 -1
- package/dist/src/typescript/components/record-expression.js.map +0 -1
- package/dist/src/typescript/components/static-serializers.js.map +0 -1
- package/dist/src/typescript/components/type-alias-declaration.js.map +0 -1
- package/dist/src/typescript/components/type-declaration.js.map +0 -1
- package/dist/src/typescript/components/type-expression.js.map +0 -1
- package/dist/src/typescript/components/type-transform.js.map +0 -1
- package/dist/src/typescript/components/union-declaration.js.map +0 -1
- package/dist/src/typescript/components/union-expression.js.map +0 -1
- package/dist/src/typescript/components/value-expression.js.map +0 -1
- package/dist/src/typescript/index.js.map +0 -1
- package/dist/src/typescript/lib.js.map +0 -1
- package/dist/src/typescript/utils/index.js.map +0 -1
- package/dist/src/typescript/utils/operation.js.map +0 -1
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
import { memo as _$memo, createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { InterfaceDeclaration } from "../../../src/typescript/components/interface-declaration.js";
|
|
3
|
+
import { For, List, Output, render } from "@alloy-js/core";
|
|
4
|
+
import { SourceFile } from "@alloy-js/typescript";
|
|
5
|
+
import { format } from "prettier";
|
|
6
|
+
import { assert, describe, expect, it } from "vitest";
|
|
7
|
+
import { getProgram } from "../test-host.js";
|
|
8
|
+
describe("Typescript Interface", () => {
|
|
9
|
+
describe("Interface bound to Typespec Types", () => {
|
|
10
|
+
describe("Bound to Model", () => {
|
|
11
|
+
it("creates an interface that extends a model for Record spread", async () => {
|
|
12
|
+
const program = await getProgram(`
|
|
13
|
+
namespace DemoService;
|
|
14
|
+
|
|
15
|
+
model DifferentSpreadModelRecord {
|
|
16
|
+
knownProp: string;
|
|
17
|
+
...Record<unknown>;
|
|
18
|
+
}
|
|
19
|
+
`);
|
|
20
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
21
|
+
const models = Array.from(namespace.models.values());
|
|
22
|
+
const res = render(_$createComponent(Output, {
|
|
23
|
+
get children() {
|
|
24
|
+
return _$createComponent(SourceFile, {
|
|
25
|
+
path: "test.ts",
|
|
26
|
+
get children() {
|
|
27
|
+
return _$createComponent(List, {
|
|
28
|
+
hardline: true,
|
|
29
|
+
get children() {
|
|
30
|
+
return models.map(model => _$createComponent(InterfaceDeclaration, {
|
|
31
|
+
"export": true,
|
|
32
|
+
type: model
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
41
|
+
assert(testFile, "test.ts file not rendered");
|
|
42
|
+
const actualContent = await format(testFile.contents, {
|
|
43
|
+
parser: "typescript"
|
|
44
|
+
});
|
|
45
|
+
const expectedContent = await format(`
|
|
46
|
+
export interface DifferentSpreadModelRecord {
|
|
47
|
+
knownProp: string;
|
|
48
|
+
additionalProperties?: Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
`, {
|
|
51
|
+
parser: "typescript"
|
|
52
|
+
});
|
|
53
|
+
expect(actualContent).toBe(expectedContent);
|
|
54
|
+
});
|
|
55
|
+
it("creates an interface for a model that 'is' an array ", async () => {
|
|
56
|
+
const program = await getProgram(`
|
|
57
|
+
namespace DemoService;
|
|
58
|
+
|
|
59
|
+
model Foo is Array<string>;
|
|
60
|
+
`);
|
|
61
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
62
|
+
const models = namespace.models;
|
|
63
|
+
const res = render(_$createComponent(Output, {
|
|
64
|
+
get children() {
|
|
65
|
+
return _$createComponent(SourceFile, {
|
|
66
|
+
path: "test.ts",
|
|
67
|
+
get children() {
|
|
68
|
+
return _$createComponent(For, {
|
|
69
|
+
get each() {
|
|
70
|
+
return Array.from(models.values());
|
|
71
|
+
},
|
|
72
|
+
hardline: true,
|
|
73
|
+
children: model => _$createComponent(InterfaceDeclaration, {
|
|
74
|
+
"export": true,
|
|
75
|
+
type: model
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
82
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
83
|
+
assert(testFile, "test.ts file not rendered");
|
|
84
|
+
const actualContent = await format(testFile.contents, {
|
|
85
|
+
parser: "typescript"
|
|
86
|
+
});
|
|
87
|
+
const expectedContent = await format(`export interface Foo extends Array<string> { }
|
|
88
|
+
`, {
|
|
89
|
+
parser: "typescript"
|
|
90
|
+
});
|
|
91
|
+
expect(actualContent).toBe(expectedContent);
|
|
92
|
+
});
|
|
93
|
+
it("creates an interface for a model that 'is' a record ", async () => {
|
|
94
|
+
const program = await getProgram(`
|
|
95
|
+
namespace DemoService;
|
|
96
|
+
|
|
97
|
+
model Foo is Record<string>;
|
|
98
|
+
`);
|
|
99
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
100
|
+
const models = namespace.models;
|
|
101
|
+
const res = render(_$createComponent(Output, {
|
|
102
|
+
get children() {
|
|
103
|
+
return _$createComponent(SourceFile, {
|
|
104
|
+
path: "test.ts",
|
|
105
|
+
get children() {
|
|
106
|
+
return _$createComponent(For, {
|
|
107
|
+
get each() {
|
|
108
|
+
return Array.from(models.values());
|
|
109
|
+
},
|
|
110
|
+
hardline: true,
|
|
111
|
+
children: model => _$createComponent(InterfaceDeclaration, {
|
|
112
|
+
"export": true,
|
|
113
|
+
type: model
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}));
|
|
120
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
121
|
+
assert(testFile, "test.ts file not rendered");
|
|
122
|
+
const actualContent = await format(testFile.contents, {
|
|
123
|
+
parser: "typescript"
|
|
124
|
+
});
|
|
125
|
+
const expectedContent = await format(`export interface Foo {
|
|
126
|
+
additionalProperties?: Record<string, string>;
|
|
127
|
+
}
|
|
128
|
+
`, {
|
|
129
|
+
parser: "typescript"
|
|
130
|
+
});
|
|
131
|
+
expect(actualContent).toBe(expectedContent);
|
|
132
|
+
});
|
|
133
|
+
it("creates an interface of a model that spreads a Record", async () => {
|
|
134
|
+
const program = await getProgram(`
|
|
135
|
+
namespace DemoService;
|
|
136
|
+
|
|
137
|
+
model Foo {
|
|
138
|
+
...Record<string>
|
|
139
|
+
}
|
|
140
|
+
`);
|
|
141
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
142
|
+
const models = namespace.models;
|
|
143
|
+
const res = render(_$createComponent(Output, {
|
|
144
|
+
get children() {
|
|
145
|
+
return _$createComponent(SourceFile, {
|
|
146
|
+
path: "test.ts",
|
|
147
|
+
get children() {
|
|
148
|
+
return _$createComponent(For, {
|
|
149
|
+
get each() {
|
|
150
|
+
return Array.from(models.values());
|
|
151
|
+
},
|
|
152
|
+
hardline: true,
|
|
153
|
+
children: model => _$createComponent(InterfaceDeclaration, {
|
|
154
|
+
"export": true,
|
|
155
|
+
type: model
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
163
|
+
assert(testFile, "test.ts file not rendered");
|
|
164
|
+
const actualContent = await format(testFile.contents, {
|
|
165
|
+
parser: "typescript"
|
|
166
|
+
});
|
|
167
|
+
const expectedContent = await format(`
|
|
168
|
+
export interface Foo {
|
|
169
|
+
additionalProperties?: Record<string, string>;
|
|
170
|
+
}
|
|
171
|
+
`, {
|
|
172
|
+
parser: "typescript"
|
|
173
|
+
});
|
|
174
|
+
expect(actualContent).toBe(expectedContent);
|
|
175
|
+
});
|
|
176
|
+
it("creates an interface that extends an spread model", async () => {
|
|
177
|
+
const program = await getProgram(`
|
|
178
|
+
namespace DemoService;
|
|
179
|
+
|
|
180
|
+
model ModelForRecord {
|
|
181
|
+
state: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
model DifferentSpreadModelRecord {
|
|
185
|
+
knownProp: string;
|
|
186
|
+
...Record<ModelForRecord>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
model DifferentSpreadModelDerived extends DifferentSpreadModelRecord {
|
|
190
|
+
derivedProp: ModelForRecord;
|
|
191
|
+
}
|
|
192
|
+
`);
|
|
193
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
194
|
+
const models = namespace.models;
|
|
195
|
+
const res = render(_$createComponent(Output, {
|
|
196
|
+
get children() {
|
|
197
|
+
return _$createComponent(SourceFile, {
|
|
198
|
+
path: "test.ts",
|
|
199
|
+
get children() {
|
|
200
|
+
return _$createComponent(For, {
|
|
201
|
+
get each() {
|
|
202
|
+
return Array.from(models.values());
|
|
203
|
+
},
|
|
204
|
+
hardline: true,
|
|
205
|
+
children: model => _$createComponent(InterfaceDeclaration, {
|
|
206
|
+
"export": true,
|
|
207
|
+
type: model
|
|
208
|
+
})
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}));
|
|
214
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
215
|
+
assert(testFile, "test.ts file not rendered");
|
|
216
|
+
const actualContent = await format(testFile.contents, {
|
|
217
|
+
parser: "typescript"
|
|
218
|
+
});
|
|
219
|
+
const expectedContent = await format(`export interface ModelForRecord {
|
|
220
|
+
state: string;
|
|
221
|
+
}
|
|
222
|
+
export interface DifferentSpreadModelRecord {
|
|
223
|
+
knownProp: string;
|
|
224
|
+
additionalProperties?: Record<string, ModelForRecord>;
|
|
225
|
+
}
|
|
226
|
+
export interface DifferentSpreadModelDerived extends DifferentSpreadModelRecord {
|
|
227
|
+
derivedProp: ModelForRecord;
|
|
228
|
+
additionalProperties?: Record<string, ModelForRecord>;
|
|
229
|
+
}
|
|
230
|
+
`, {
|
|
231
|
+
parser: "typescript"
|
|
232
|
+
});
|
|
233
|
+
expect(actualContent).toBe(expectedContent);
|
|
234
|
+
});
|
|
235
|
+
it("creates an interface that has additional properties", async () => {
|
|
236
|
+
const program = await getProgram(`
|
|
237
|
+
namespace DemoService;
|
|
238
|
+
model Widget extends Record<unknown> {
|
|
239
|
+
id: string;
|
|
240
|
+
weight: int32;
|
|
241
|
+
color: "blue" | "red";
|
|
242
|
+
}
|
|
243
|
+
`);
|
|
244
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
245
|
+
const models = Array.from(namespace.models.values());
|
|
246
|
+
const res = render(_$createComponent(Output, {
|
|
247
|
+
get children() {
|
|
248
|
+
return _$createComponent(SourceFile, {
|
|
249
|
+
path: "test.ts",
|
|
250
|
+
get children() {
|
|
251
|
+
return models.map(model => _$createComponent(InterfaceDeclaration, {
|
|
252
|
+
"export": true,
|
|
253
|
+
type: model
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}));
|
|
259
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
260
|
+
assert(testFile, "test.ts file not rendered");
|
|
261
|
+
const actualContent = await format(testFile.contents, {
|
|
262
|
+
parser: "typescript"
|
|
263
|
+
});
|
|
264
|
+
const expectedContent = await format(`export interface Widget {
|
|
265
|
+
id: string;
|
|
266
|
+
weight: number;
|
|
267
|
+
color: "blue" | "red";
|
|
268
|
+
additionalProperties?: Record<string, unknown>;
|
|
269
|
+
}`, {
|
|
270
|
+
parser: "typescript"
|
|
271
|
+
});
|
|
272
|
+
expect(actualContent).toBe(expectedContent);
|
|
273
|
+
});
|
|
274
|
+
it("handles a type reference to a union variant", async () => {
|
|
275
|
+
const program = await getProgram(`
|
|
276
|
+
namespace DemoService;
|
|
277
|
+
|
|
278
|
+
union Color {
|
|
279
|
+
red: "RED",
|
|
280
|
+
blue: "BLUE"
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
model Widget{
|
|
284
|
+
id: string;
|
|
285
|
+
weight: int32;
|
|
286
|
+
color: Color.blue
|
|
287
|
+
}
|
|
288
|
+
`);
|
|
289
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
290
|
+
const models = Array.from(namespace.models.values());
|
|
291
|
+
const res = render(_$createComponent(Output, {
|
|
292
|
+
get children() {
|
|
293
|
+
return _$createComponent(SourceFile, {
|
|
294
|
+
path: "test.ts",
|
|
295
|
+
get children() {
|
|
296
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
297
|
+
get type() {
|
|
298
|
+
return models[0];
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}));
|
|
305
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
306
|
+
assert(testFile, "test.ts file not rendered");
|
|
307
|
+
const actualContent = await format(testFile.contents, {
|
|
308
|
+
parser: "typescript"
|
|
309
|
+
});
|
|
310
|
+
const expectedContent = await format(`interface Widget {
|
|
311
|
+
id: string;
|
|
312
|
+
weight: number;
|
|
313
|
+
color: "BLUE";
|
|
314
|
+
}`, {
|
|
315
|
+
parser: "typescript"
|
|
316
|
+
});
|
|
317
|
+
expect(actualContent).toBe(expectedContent);
|
|
318
|
+
});
|
|
319
|
+
it("creates an interface", async () => {
|
|
320
|
+
const program = await getProgram(`
|
|
321
|
+
namespace DemoService;
|
|
322
|
+
|
|
323
|
+
model Widget{
|
|
324
|
+
id: string;
|
|
325
|
+
weight: int32;
|
|
326
|
+
color: "blue" | "red";
|
|
327
|
+
}
|
|
328
|
+
`);
|
|
329
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
330
|
+
const models = Array.from(namespace.models.values());
|
|
331
|
+
const res = render(_$createComponent(Output, {
|
|
332
|
+
get children() {
|
|
333
|
+
return _$createComponent(SourceFile, {
|
|
334
|
+
path: "test.ts",
|
|
335
|
+
get children() {
|
|
336
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
337
|
+
get type() {
|
|
338
|
+
return models[0];
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}));
|
|
345
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
346
|
+
assert(testFile, "test.ts file not rendered");
|
|
347
|
+
const actualContent = await format(testFile.contents, {
|
|
348
|
+
parser: "typescript"
|
|
349
|
+
});
|
|
350
|
+
const expectedContent = await format(`interface Widget {
|
|
351
|
+
id: string;
|
|
352
|
+
weight: number;
|
|
353
|
+
color: "blue" | "red";
|
|
354
|
+
}`, {
|
|
355
|
+
parser: "typescript"
|
|
356
|
+
});
|
|
357
|
+
expect(actualContent).toBe(expectedContent);
|
|
358
|
+
});
|
|
359
|
+
it("renders an empty interface with a never-typed member", async () => {
|
|
360
|
+
const program = await getProgram(`
|
|
361
|
+
namespace DemoService;
|
|
362
|
+
|
|
363
|
+
model Widget{
|
|
364
|
+
property: never;
|
|
365
|
+
}
|
|
366
|
+
`);
|
|
367
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
368
|
+
const models = Array.from(namespace.models.values());
|
|
369
|
+
const res = render(_$createComponent(Output, {
|
|
370
|
+
get children() {
|
|
371
|
+
return _$createComponent(SourceFile, {
|
|
372
|
+
path: "test.ts",
|
|
373
|
+
get children() {
|
|
374
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
375
|
+
"export": true,
|
|
376
|
+
get type() {
|
|
377
|
+
return models[0];
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}));
|
|
384
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
385
|
+
assert(testFile, "test.ts file not rendered");
|
|
386
|
+
const actualContent = await format(testFile.contents, {
|
|
387
|
+
parser: "typescript"
|
|
388
|
+
});
|
|
389
|
+
const expectedContent = await format(`export interface Widget {
|
|
390
|
+
}`, {
|
|
391
|
+
parser: "typescript"
|
|
392
|
+
});
|
|
393
|
+
expect(actualContent).toBe(expectedContent);
|
|
394
|
+
});
|
|
395
|
+
it("can override interface name", async () => {
|
|
396
|
+
const program = await getProgram(`
|
|
397
|
+
namespace DemoService;
|
|
398
|
+
|
|
399
|
+
model Widget{
|
|
400
|
+
id: string;
|
|
401
|
+
weight: int32;
|
|
402
|
+
color: "blue" | "red";
|
|
403
|
+
}
|
|
404
|
+
`);
|
|
405
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
406
|
+
const models = Array.from(namespace.models.values());
|
|
407
|
+
const res = render(_$createComponent(Output, {
|
|
408
|
+
get children() {
|
|
409
|
+
return _$createComponent(SourceFile, {
|
|
410
|
+
path: "test.ts",
|
|
411
|
+
get children() {
|
|
412
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
413
|
+
"export": true,
|
|
414
|
+
name: "MyOperations",
|
|
415
|
+
get type() {
|
|
416
|
+
return models[0];
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
}));
|
|
423
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
424
|
+
assert(testFile, "test.ts file not rendered");
|
|
425
|
+
const actualContent = await format(testFile.contents, {
|
|
426
|
+
parser: "typescript"
|
|
427
|
+
});
|
|
428
|
+
const expectedContent = await format(`export interface MyOperations {
|
|
429
|
+
id: string;
|
|
430
|
+
weight: number;
|
|
431
|
+
color: "blue" | "red";
|
|
432
|
+
}`, {
|
|
433
|
+
parser: "typescript"
|
|
434
|
+
});
|
|
435
|
+
expect(actualContent).toBe(expectedContent);
|
|
436
|
+
});
|
|
437
|
+
it("can add a members to the interface", async () => {
|
|
438
|
+
const program = await getProgram(`
|
|
439
|
+
namespace DemoService;
|
|
440
|
+
|
|
441
|
+
model Widget{
|
|
442
|
+
id: string;
|
|
443
|
+
weight: int32;
|
|
444
|
+
color: "blue" | "red";
|
|
445
|
+
}
|
|
446
|
+
`);
|
|
447
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
448
|
+
const models = Array.from(namespace.models.values());
|
|
449
|
+
const res = render(_$createComponent(Output, {
|
|
450
|
+
get children() {
|
|
451
|
+
return _$createComponent(SourceFile, {
|
|
452
|
+
path: "test.ts",
|
|
453
|
+
get children() {
|
|
454
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
455
|
+
"export": true,
|
|
456
|
+
name: "MyOperations",
|
|
457
|
+
get type() {
|
|
458
|
+
return models[0];
|
|
459
|
+
},
|
|
460
|
+
children: "customProperty: string; customMethod(): void;"
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
}));
|
|
466
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
467
|
+
assert(testFile, "test.ts file not rendered");
|
|
468
|
+
const actualContent = await format(testFile.contents, {
|
|
469
|
+
parser: "typescript"
|
|
470
|
+
});
|
|
471
|
+
const expectedContent = await format(`export interface MyOperations {
|
|
472
|
+
id: string;
|
|
473
|
+
weight: number;
|
|
474
|
+
color: "blue" | "red";
|
|
475
|
+
customProperty: string;
|
|
476
|
+
customMethod(): void;
|
|
477
|
+
}`, {
|
|
478
|
+
parser: "typescript"
|
|
479
|
+
});
|
|
480
|
+
expect(actualContent).toBe(expectedContent);
|
|
481
|
+
});
|
|
482
|
+
it("interface name can be customized", async () => {
|
|
483
|
+
const program = await getProgram(`
|
|
484
|
+
namespace DemoService;
|
|
485
|
+
|
|
486
|
+
model Widget{
|
|
487
|
+
id: string;
|
|
488
|
+
weight: int32;
|
|
489
|
+
color: "blue" | "red";
|
|
490
|
+
}
|
|
491
|
+
`);
|
|
492
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
493
|
+
const models = Array.from(namespace.models.values());
|
|
494
|
+
const res = render(_$createComponent(Output, {
|
|
495
|
+
get children() {
|
|
496
|
+
return _$createComponent(SourceFile, {
|
|
497
|
+
path: "test.ts",
|
|
498
|
+
get children() {
|
|
499
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
500
|
+
"export": true,
|
|
501
|
+
name: "MyModel",
|
|
502
|
+
get type() {
|
|
503
|
+
return models[0];
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}));
|
|
510
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
511
|
+
assert(testFile, "test.ts file not rendered");
|
|
512
|
+
const actualContent = await format(testFile.contents, {
|
|
513
|
+
parser: "typescript"
|
|
514
|
+
});
|
|
515
|
+
const expectedContent = await format(`export interface MyModel {
|
|
516
|
+
id: string;
|
|
517
|
+
weight: number;
|
|
518
|
+
color: "blue" | "red";
|
|
519
|
+
}`, {
|
|
520
|
+
parser: "typescript"
|
|
521
|
+
});
|
|
522
|
+
expect(actualContent).toBe(expectedContent);
|
|
523
|
+
});
|
|
524
|
+
it("interface with extends", async () => {
|
|
525
|
+
const program = await getProgram(`
|
|
526
|
+
namespace DemoService;
|
|
527
|
+
|
|
528
|
+
model Widget{
|
|
529
|
+
id: string;
|
|
530
|
+
weight: int32;
|
|
531
|
+
color: "blue" | "red";
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
model ErrorWidget extends Widget {
|
|
535
|
+
code: int32;
|
|
536
|
+
message: string;
|
|
537
|
+
}
|
|
538
|
+
`);
|
|
539
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
540
|
+
const models = Array.from(namespace.models.values());
|
|
541
|
+
const res = render(_$createComponent(Output, {
|
|
542
|
+
get children() {
|
|
543
|
+
return _$createComponent(SourceFile, {
|
|
544
|
+
path: "test.ts",
|
|
545
|
+
get children() {
|
|
546
|
+
return models.map(model => _$createComponent(InterfaceDeclaration, {
|
|
547
|
+
"export": true,
|
|
548
|
+
type: model
|
|
549
|
+
}));
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}));
|
|
554
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
555
|
+
assert(testFile, "test.ts file not rendered");
|
|
556
|
+
const actualContent = await format(testFile.contents, {
|
|
557
|
+
parser: "typescript"
|
|
558
|
+
});
|
|
559
|
+
const expectedContent = await format(`export interface Widget {
|
|
560
|
+
id: string;
|
|
561
|
+
weight: number;
|
|
562
|
+
color: "blue" | "red";
|
|
563
|
+
}
|
|
564
|
+
export interface ErrorWidget extends Widget {
|
|
565
|
+
code: number;
|
|
566
|
+
message: string;
|
|
567
|
+
}`, {
|
|
568
|
+
parser: "typescript"
|
|
569
|
+
});
|
|
570
|
+
expect(actualContent).toBe(expectedContent);
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
describe("Bound to Interface", () => {
|
|
574
|
+
it("creates an interface", async () => {
|
|
575
|
+
const program = await getProgram(`
|
|
576
|
+
namespace DemoService;
|
|
577
|
+
|
|
578
|
+
interface WidgetOperations {
|
|
579
|
+
op getName(id: string): string;
|
|
580
|
+
}
|
|
581
|
+
`);
|
|
582
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
583
|
+
const interfaces = Array.from(namespace.interfaces.values());
|
|
584
|
+
const res = render(_$createComponent(Output, {
|
|
585
|
+
get children() {
|
|
586
|
+
return _$createComponent(SourceFile, {
|
|
587
|
+
path: "test.ts",
|
|
588
|
+
get children() {
|
|
589
|
+
return _$createComponent(InterfaceDeclaration, {
|
|
590
|
+
"export": true,
|
|
591
|
+
get type() {
|
|
592
|
+
return interfaces[0];
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
}));
|
|
599
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
600
|
+
assert(testFile, "test.ts file not rendered");
|
|
601
|
+
const actualContent = await format(testFile.contents, {
|
|
602
|
+
parser: "typescript"
|
|
603
|
+
});
|
|
604
|
+
const expectedContent = await format(`export interface WidgetOperations {
|
|
605
|
+
getName(id: string): string;
|
|
606
|
+
}`, {
|
|
607
|
+
parser: "typescript"
|
|
608
|
+
});
|
|
609
|
+
expect(actualContent).toBe(expectedContent);
|
|
610
|
+
});
|
|
611
|
+
it("should handle spread and non spread model parameters", async () => {
|
|
612
|
+
const program = await getProgram(`
|
|
613
|
+
namespace DemoService;
|
|
614
|
+
|
|
615
|
+
model Foo {
|
|
616
|
+
name: string
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
interface WidgetOperations {
|
|
620
|
+
op getName(foo: Foo): string;
|
|
621
|
+
op getOtherName(...Foo): string
|
|
622
|
+
}
|
|
623
|
+
`);
|
|
624
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
625
|
+
const interfaces = Array.from(namespace.interfaces.values());
|
|
626
|
+
const models = Array.from(namespace.models.values());
|
|
627
|
+
const res = render(_$createComponent(Output, {
|
|
628
|
+
get children() {
|
|
629
|
+
return _$createComponent(SourceFile, {
|
|
630
|
+
path: "test.ts",
|
|
631
|
+
get children() {
|
|
632
|
+
return [_$createComponent(InterfaceDeclaration, {
|
|
633
|
+
"export": true,
|
|
634
|
+
get type() {
|
|
635
|
+
return interfaces[0];
|
|
636
|
+
}
|
|
637
|
+
}), _$createComponent(InterfaceDeclaration, {
|
|
638
|
+
"export": true,
|
|
639
|
+
get type() {
|
|
640
|
+
return models[0];
|
|
641
|
+
}
|
|
642
|
+
})];
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
}));
|
|
647
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
648
|
+
assert(testFile, "test.ts file not rendered");
|
|
649
|
+
const actualContent = await format(testFile.contents, {
|
|
650
|
+
parser: "typescript"
|
|
651
|
+
});
|
|
652
|
+
const expectedContent = await format(`export interface WidgetOperations {
|
|
653
|
+
getName(foo: Foo): string;
|
|
654
|
+
getOtherName(name: string): string
|
|
655
|
+
}
|
|
656
|
+
export interface Foo {
|
|
657
|
+
name: string;
|
|
658
|
+
}
|
|
659
|
+
`, {
|
|
660
|
+
parser: "typescript"
|
|
661
|
+
});
|
|
662
|
+
expect(actualContent).toBe(expectedContent);
|
|
663
|
+
});
|
|
664
|
+
it("creates an interface with Model references", async () => {
|
|
665
|
+
const program = await getProgram(`
|
|
666
|
+
namespace DemoService;
|
|
667
|
+
|
|
668
|
+
interface WidgetOperations {
|
|
669
|
+
op getName(id: string): Widget;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
model Widget {
|
|
673
|
+
id: string;
|
|
674
|
+
weight: int32;
|
|
675
|
+
color: "blue" | "red";
|
|
676
|
+
}
|
|
677
|
+
`);
|
|
678
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
679
|
+
const interfaces = Array.from(namespace.interfaces.values());
|
|
680
|
+
const models = Array.from(namespace.models.values());
|
|
681
|
+
const res = render(_$createComponent(Output, {
|
|
682
|
+
get children() {
|
|
683
|
+
return _$createComponent(SourceFile, {
|
|
684
|
+
path: "test.ts",
|
|
685
|
+
get children() {
|
|
686
|
+
return [_$createComponent(InterfaceDeclaration, {
|
|
687
|
+
"export": true,
|
|
688
|
+
get type() {
|
|
689
|
+
return interfaces[0];
|
|
690
|
+
}
|
|
691
|
+
}), _$memo(() => models.map(model => _$createComponent(InterfaceDeclaration, {
|
|
692
|
+
"export": true,
|
|
693
|
+
type: model
|
|
694
|
+
})))];
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}));
|
|
699
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
700
|
+
assert(testFile, "test.ts file not rendered");
|
|
701
|
+
const actualContent = await format(testFile.contents, {
|
|
702
|
+
parser: "typescript"
|
|
703
|
+
});
|
|
704
|
+
const expectedContent = await format(`export interface WidgetOperations {
|
|
705
|
+
getName(id: string): Widget;
|
|
706
|
+
}
|
|
707
|
+
export interface Widget {
|
|
708
|
+
id: string;
|
|
709
|
+
weight: number;
|
|
710
|
+
color: "blue" | "red";
|
|
711
|
+
}`, {
|
|
712
|
+
parser: "typescript"
|
|
713
|
+
});
|
|
714
|
+
expect(actualContent).toBe(expectedContent);
|
|
715
|
+
});
|
|
716
|
+
it("creates an interface that extends another", async () => {
|
|
717
|
+
const program = await getProgram(`
|
|
718
|
+
namespace DemoService;
|
|
719
|
+
|
|
720
|
+
interface WidgetOperations {
|
|
721
|
+
op getName(id: string): Widget;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
interface WidgetOperationsExtended extends WidgetOperations{
|
|
725
|
+
op delete(id: string): void;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
model Widget {
|
|
729
|
+
id: string;
|
|
730
|
+
weight: int32;
|
|
731
|
+
color: "blue" | "red";
|
|
732
|
+
}
|
|
733
|
+
`);
|
|
734
|
+
const [namespace] = program.resolveTypeReference("DemoService");
|
|
735
|
+
const interfaces = Array.from(namespace.interfaces.values());
|
|
736
|
+
const models = Array.from(namespace.models.values());
|
|
737
|
+
const res = render(_$createComponent(Output, {
|
|
738
|
+
get children() {
|
|
739
|
+
return _$createComponent(SourceFile, {
|
|
740
|
+
path: "test.ts",
|
|
741
|
+
get children() {
|
|
742
|
+
return [_$createComponent(InterfaceDeclaration, {
|
|
743
|
+
"export": true,
|
|
744
|
+
get type() {
|
|
745
|
+
return interfaces[1];
|
|
746
|
+
}
|
|
747
|
+
}), _$memo(() => models.map(model => _$createComponent(InterfaceDeclaration, {
|
|
748
|
+
"export": true,
|
|
749
|
+
type: model
|
|
750
|
+
})))];
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}));
|
|
755
|
+
const testFile = res.contents.find(file => file.path === "test.ts");
|
|
756
|
+
assert(testFile, "test.ts file not rendered");
|
|
757
|
+
const actualContent = await format(testFile.contents, {
|
|
758
|
+
parser: "typescript"
|
|
759
|
+
});
|
|
760
|
+
const expectedContent = await format(`export interface WidgetOperationsExtended {
|
|
761
|
+
getName(id: string): Widget;
|
|
762
|
+
delete(id: string): void;
|
|
763
|
+
}
|
|
764
|
+
export interface Widget {
|
|
765
|
+
id: string;
|
|
766
|
+
weight: number;
|
|
767
|
+
color: "blue" | "red";
|
|
768
|
+
}`, {
|
|
769
|
+
parser: "typescript"
|
|
770
|
+
});
|
|
771
|
+
expect(actualContent).toBe(expectedContent);
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
});
|