@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.
Files changed (92) hide show
  1. package/dist/src/core/context/name-policy-context.js +1 -2
  2. package/dist/src/core/index.js +1 -2
  3. package/dist/src/core/transport-name-policy.js +1 -2
  4. package/dist/src/core/write-output.js +1 -2
  5. package/dist/src/lib.js +1 -2
  6. package/dist/src/testing/index.js +1 -2
  7. package/dist/src/testing/scenario-test/harness.js +1 -2
  8. package/dist/src/testing/scenario-test/index.js +1 -2
  9. package/dist/src/testing/scenario-test/snippet-extractor.js +1 -2
  10. package/dist/src/testing/scenario-test/test-host.js +1 -2
  11. package/dist/src/typescript/components/array-expression.js +1 -2
  12. package/dist/src/typescript/components/arrow-function.js +2 -5
  13. package/dist/src/typescript/components/class-method.js +2 -4
  14. package/dist/src/typescript/components/enum-declaration.js +2 -4
  15. package/dist/src/typescript/components/function-declaration.js +2 -4
  16. package/dist/src/typescript/components/function-expression.js +2 -5
  17. package/dist/src/typescript/components/function-type.js +2 -5
  18. package/dist/src/typescript/components/index.js +1 -2
  19. package/dist/src/typescript/components/interface-declaration.js +2 -5
  20. package/dist/src/typescript/components/interface-member.js +2 -4
  21. package/dist/src/typescript/components/interface-method.d.ts.map +1 -1
  22. package/dist/src/typescript/components/interface-method.js +5 -8
  23. package/dist/src/typescript/components/record-expression.js +1 -2
  24. package/dist/src/typescript/components/static-serializers.js +1 -2
  25. package/dist/src/typescript/components/type-alias-declaration.js +2 -5
  26. package/dist/src/typescript/components/type-declaration.js +2 -4
  27. package/dist/src/typescript/components/type-expression.js +2 -4
  28. package/dist/src/typescript/components/type-transform.js +2 -4
  29. package/dist/src/typescript/components/union-declaration.js +2 -4
  30. package/dist/src/typescript/components/union-expression.js +2 -4
  31. package/dist/src/typescript/components/value-expression.js +2 -4
  32. package/dist/src/typescript/index.js +1 -2
  33. package/dist/src/typescript/lib.js +1 -2
  34. package/dist/src/typescript/utils/operation.js +1 -2
  35. package/dist/test/testing/snippet-extractor-csharp.test.js +96 -0
  36. package/dist/test/testing/snippet-extractor-java.test.js +104 -0
  37. package/dist/test/testing/snippet-extractor-python.test.js +33 -0
  38. package/dist/test/testing/snippet-extractor-typescript.test.js +161 -0
  39. package/dist/test/typescript/components/arrow-function.test.js +88 -0
  40. package/dist/test/typescript/components/enum-declaration.test.js +118 -0
  41. package/dist/test/typescript/components/function-declaration.test.js +246 -0
  42. package/dist/test/typescript/components/function-expression.test.js +88 -0
  43. package/dist/test/typescript/components/function-type.test.js +85 -0
  44. package/dist/test/typescript/components/interface-declaration.test.js +775 -0
  45. package/dist/test/typescript/components/interface-method.test.js +272 -0
  46. package/dist/test/typescript/components/member-expression.test.js +155 -0
  47. package/dist/test/typescript/components/type-alias-declaration.test.js +155 -0
  48. package/dist/test/typescript/components/type-transform.test.js +682 -0
  49. package/dist/test/typescript/components/union-declaration.test.js +205 -0
  50. package/dist/test/typescript/components/value-expression.test.js +199 -0
  51. package/dist/test/typescript/test-host.js +40 -0
  52. package/dist/test/utils.js +18 -0
  53. package/package.json +5 -10
  54. package/src/typescript/components/interface-method.tsx +2 -4
  55. package/test/typescript/components/interface-method.test.tsx +167 -2
  56. package/vitest.config.ts +2 -9
  57. package/babel.config.js +0 -4
  58. package/dist/src/core/context/index.js.map +0 -1
  59. package/dist/src/core/context/name-policy-context.js.map +0 -1
  60. package/dist/src/core/index.js.map +0 -1
  61. package/dist/src/core/transport-name-policy.js.map +0 -1
  62. package/dist/src/core/write-output.js.map +0 -1
  63. package/dist/src/lib.js.map +0 -1
  64. package/dist/src/testing/index.js.map +0 -1
  65. package/dist/src/testing/scenario-test/harness.js.map +0 -1
  66. package/dist/src/testing/scenario-test/index.js.map +0 -1
  67. package/dist/src/testing/scenario-test/snippet-extractor.js.map +0 -1
  68. package/dist/src/testing/scenario-test/test-host.js.map +0 -1
  69. package/dist/src/typescript/components/array-expression.js.map +0 -1
  70. package/dist/src/typescript/components/arrow-function.js.map +0 -1
  71. package/dist/src/typescript/components/class-method.js.map +0 -1
  72. package/dist/src/typescript/components/enum-declaration.js.map +0 -1
  73. package/dist/src/typescript/components/function-declaration.js.map +0 -1
  74. package/dist/src/typescript/components/function-expression.js.map +0 -1
  75. package/dist/src/typescript/components/function-type.js.map +0 -1
  76. package/dist/src/typescript/components/index.js.map +0 -1
  77. package/dist/src/typescript/components/interface-declaration.js.map +0 -1
  78. package/dist/src/typescript/components/interface-member.js.map +0 -1
  79. package/dist/src/typescript/components/interface-method.js.map +0 -1
  80. package/dist/src/typescript/components/record-expression.js.map +0 -1
  81. package/dist/src/typescript/components/static-serializers.js.map +0 -1
  82. package/dist/src/typescript/components/type-alias-declaration.js.map +0 -1
  83. package/dist/src/typescript/components/type-declaration.js.map +0 -1
  84. package/dist/src/typescript/components/type-expression.js.map +0 -1
  85. package/dist/src/typescript/components/type-transform.js.map +0 -1
  86. package/dist/src/typescript/components/union-declaration.js.map +0 -1
  87. package/dist/src/typescript/components/union-expression.js.map +0 -1
  88. package/dist/src/typescript/components/value-expression.js.map +0 -1
  89. package/dist/src/typescript/index.js.map +0 -1
  90. package/dist/src/typescript/lib.js.map +0 -1
  91. package/dist/src/typescript/utils/index.js.map +0 -1
  92. package/dist/src/typescript/utils/operation.js.map +0 -1
@@ -0,0 +1,161 @@
1
+ import { d } from "@alloy-js/core/testing";
2
+ import { beforeEach, describe, expect, it } from "vitest";
3
+ import { createSnipperExtractor, createTypeScriptExtractorConfig } from "../../src/testing/index.js";
4
+ describe("TypeScript Snippet Extractor", () => {
5
+ let extractor;
6
+ beforeEach(() => {
7
+ extractor = createSnipperExtractor(createTypeScriptExtractorConfig());
8
+ });
9
+ it("should extract a class", async () => {
10
+ const content = d`
11
+ function bar(): number {
12
+ return 1;
13
+ }
14
+ class Foo {
15
+ constructor() {
16
+ console.log("Hello");
17
+ }
18
+ }
19
+ `;
20
+ const snippet = extractor.getClass(content, "Foo");
21
+ expect(snippet).toBe(d`
22
+ class Foo {
23
+ constructor() {
24
+ console.log("Hello");
25
+ }
26
+ }
27
+ `);
28
+ });
29
+ it("should extract an exported class", async () => {
30
+ const content = d`
31
+ function bar(): number {
32
+ return 1;
33
+ }
34
+ export class Foo {
35
+ constructor() {
36
+ console.log("Hello");
37
+ }
38
+ }
39
+ `;
40
+ const snippet = extractor.getClass(content, "Foo");
41
+ expect(snippet).toBe(d`
42
+ export class Foo {
43
+ constructor() {
44
+ console.log("Hello");
45
+ }
46
+ }
47
+ `);
48
+ });
49
+ it("should extract a class that extends another", async () => {
50
+ const content = d`
51
+ export class Bar {
52
+ constructor() {
53
+ console.log("Hello");
54
+ }
55
+ }
56
+ export class Foo extends Bar {
57
+ constructor() {
58
+ console.log("Hello");
59
+ }
60
+ }
61
+ `;
62
+ const snippet = extractor.getClass(content, "Foo");
63
+ expect(snippet).toBe(d`
64
+ export class Foo extends Bar {
65
+ constructor() {
66
+ console.log("Hello");
67
+ }
68
+ }
69
+ `);
70
+ });
71
+ it("should extract a class that implements an interface", async () => {
72
+ const content = d`
73
+ export interface MyFoo {
74
+ bar(): number;
75
+ }
76
+ export class Foo implements MyFoo {
77
+ constructor() {
78
+ console.log("Hello");
79
+ }
80
+
81
+ bar() {
82
+ return 1;
83
+ }
84
+ }
85
+ `;
86
+ const snippet = extractor.getClass(content, "Foo");
87
+ expect(snippet).toBe(d`
88
+ export class Foo implements MyFoo {
89
+ constructor() {
90
+ console.log("Hello");
91
+ }
92
+
93
+ bar() {
94
+ return 1;
95
+ }
96
+ }
97
+ `);
98
+ });
99
+ it("should extract a generic class", async () => {
100
+ const content = d`
101
+ export interface MyFoo {
102
+ bar(): number;
103
+ }
104
+ class Box<Type> {
105
+ contents: Type;
106
+ constructor(value: Type) {
107
+ this.contents = value;
108
+ }
109
+ }
110
+ `;
111
+ const snippet = extractor.getClass(content, "Box");
112
+ expect(snippet).toBe(d`
113
+ class Box<Type> {
114
+ contents: Type;
115
+ constructor(value: Type) {
116
+ this.contents = value;
117
+ }
118
+ }
119
+ `);
120
+ });
121
+ });
122
+ describe("TypeScript Snippet Extractor - Enums", () => {
123
+ let extractor;
124
+ beforeEach(() => {
125
+ extractor = createSnipperExtractor(createTypeScriptExtractorConfig());
126
+ });
127
+ it("should extract a basic enum", async () => {
128
+ const content = d`
129
+ enum Direction {
130
+ Up,
131
+ Down,
132
+ Left,
133
+ Right
134
+ }
135
+ `;
136
+ const snippet = extractor.getEnum(content, "Direction");
137
+ expect(snippet).toBe(d`
138
+ enum Direction {
139
+ Up,
140
+ Down,
141
+ Left,
142
+ Right
143
+ }
144
+ `);
145
+ });
146
+ it("should extract an exported enum", async () => {
147
+ const content = d`
148
+ export enum Status {
149
+ Active,
150
+ Inactive
151
+ }
152
+ `;
153
+ const snippet = extractor.getEnum(content, "Status");
154
+ expect(snippet).toBe(d`
155
+ export enum Status {
156
+ Active,
157
+ Inactive
158
+ }
159
+ `);
160
+ });
161
+ });
@@ -0,0 +1,88 @@
1
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
+ import { Output, render } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import { SourceFile } from "@alloy-js/typescript";
5
+ import { beforeEach, describe, it } from "vitest";
6
+ import { ArrowFunction } from "../../../src/typescript/components/arrow-function.js";
7
+ import { assertFileContents } from "../../utils.js";
8
+ import { createEmitterFrameworkTestRunner } from "../test-host.js";
9
+ describe("arrow functions with a `type` prop", () => {
10
+ let runner;
11
+ beforeEach(async () => {
12
+ runner = await createEmitterFrameworkTestRunner();
13
+ });
14
+ it("creates a function", async () => {
15
+ const {
16
+ getName
17
+ } = await runner.compile(`
18
+ @test op getName(id: string): string;
19
+ `);
20
+ const res = render(_$createComponent(Output, {
21
+ get children() {
22
+ return _$createComponent(SourceFile, {
23
+ path: "test.ts",
24
+ get children() {
25
+ return _$createComponent(ArrowFunction, {
26
+ type: getName,
27
+ children: "console.log(\"Hello!\");"
28
+ });
29
+ }
30
+ });
31
+ }
32
+ }));
33
+ assertFileContents(res, d`
34
+ (id: string): string => {
35
+ console.log("Hello!");
36
+ }
37
+ `);
38
+ });
39
+ it("creates an async function", async () => {
40
+ const {
41
+ getName
42
+ } = await runner.compile(`
43
+ @test op getName(id: string): string;
44
+ `);
45
+ const res = render(_$createComponent(Output, {
46
+ get children() {
47
+ return _$createComponent(SourceFile, {
48
+ path: "test.ts",
49
+ get children() {
50
+ return _$createComponent(ArrowFunction, {
51
+ async: true,
52
+ type: getName
53
+ });
54
+ }
55
+ });
56
+ }
57
+ }));
58
+ assertFileContents(res, d`
59
+ async (id: string): Promise<string> => {}
60
+ `);
61
+ });
62
+ it("can append extra parameters with raw params provided", async () => {
63
+ const {
64
+ getName
65
+ } = await runner.compile(`
66
+ @test op getName(id: string): string;
67
+ `);
68
+ const res = render(_$createComponent(Output, {
69
+ get children() {
70
+ return _$createComponent(SourceFile, {
71
+ path: "test.ts",
72
+ get children() {
73
+ return _$createComponent(ArrowFunction, {
74
+ type: getName,
75
+ parameters: [{
76
+ name: "additionalParam",
77
+ type: "number"
78
+ }]
79
+ });
80
+ }
81
+ });
82
+ }
83
+ }));
84
+ assertFileContents(res, d`
85
+ (additionalParam: number, id: string): string => {}
86
+ `);
87
+ });
88
+ });
@@ -0,0 +1,118 @@
1
+ import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
2
+ import { List, refkey, StatementList } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import { describe, expect, it } from "vitest";
5
+ import { EnumDeclaration } from "../../../src/typescript/components/enum-declaration.js";
6
+ import { getEmitOutput } from "../../utils.js";
7
+ describe("Typescript Enum Declaration", () => {
8
+ it("takes an enum type parameter", async () => {
9
+ const code = `
10
+ enum Foo {
11
+ one: 1,
12
+ two: 2,
13
+ three: 3
14
+ }
15
+ `;
16
+ const output = await getEmitOutput(code, program => {
17
+ const Foo = program.resolveTypeReference("Foo")[0];
18
+ return _$createComponent(EnumDeclaration, {
19
+ type: Foo
20
+ });
21
+ });
22
+ expect(output).toBe(d`
23
+ enum Foo {
24
+ one = 1,
25
+ two = 2,
26
+ three = 3
27
+ }
28
+ `);
29
+ });
30
+ it("takes a union type parameter", async () => {
31
+ const code = `
32
+ union Foo {
33
+ one: 1,
34
+ two: 2,
35
+ three: 3
36
+ }
37
+ `;
38
+ const output = await getEmitOutput(code, program => {
39
+ const Foo = program.resolveTypeReference("Foo")[0];
40
+ return _$createComponent(EnumDeclaration, {
41
+ type: Foo
42
+ });
43
+ });
44
+ expect(output).toBe(d`
45
+ enum Foo {
46
+ one = 1,
47
+ two = 2,
48
+ three = 3
49
+ }
50
+ `);
51
+ });
52
+ it("can be referenced", async () => {
53
+ const code = `
54
+ enum Foo {
55
+ one: 1,
56
+ two: 2,
57
+ three: 3
58
+ }
59
+ `;
60
+ const output = await getEmitOutput(code, program => {
61
+ const Foo = program.resolveTypeReference("Foo")[0];
62
+ return _$createComponent(List, {
63
+ hardline: true,
64
+ get children() {
65
+ return [_$createComponent(EnumDeclaration, {
66
+ type: Foo
67
+ }), _$createComponent(StatementList, {
68
+ get children() {
69
+ return [_$memo(() => refkey(Foo)), _$memo(() => refkey(Foo.members.get("one")))];
70
+ }
71
+ })];
72
+ }
73
+ });
74
+ });
75
+ expect(output).toBe(d`
76
+ enum Foo {
77
+ one = 1,
78
+ two = 2,
79
+ three = 3
80
+ }
81
+ Foo;
82
+ Foo.one;
83
+ `);
84
+ });
85
+ it("can be referenced using union", async () => {
86
+ const code = `
87
+ union Foo {
88
+ one: 1,
89
+ two: 2,
90
+ three: 3
91
+ }
92
+ `;
93
+ const output = await getEmitOutput(code, program => {
94
+ const Foo = program.resolveTypeReference("Foo")[0];
95
+ return _$createComponent(List, {
96
+ hardline: true,
97
+ get children() {
98
+ return [_$createComponent(EnumDeclaration, {
99
+ type: Foo
100
+ }), _$createComponent(StatementList, {
101
+ get children() {
102
+ return [_$memo(() => refkey(Foo)), _$memo(() => refkey(Foo.variants.get("one")))];
103
+ }
104
+ })];
105
+ }
106
+ });
107
+ });
108
+ expect(output).toBe(d`
109
+ enum Foo {
110
+ one = 1,
111
+ two = 2,
112
+ three = 3
113
+ }
114
+ Foo;
115
+ Foo.one;
116
+ `);
117
+ });
118
+ });
@@ -0,0 +1,246 @@
1
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
+ import { Output, render } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import { SourceFile } from "@alloy-js/typescript";
5
+ import { format } from "prettier";
6
+ import { assert, describe, expect, it } from "vitest";
7
+ import { FunctionDeclaration } from "../../../src/typescript/components/function-declaration.js";
8
+ import { getProgram } from "../test-host.js";
9
+ describe("Typescript Function Declaration", () => {
10
+ describe("Function bound to Typespec Types", () => {
11
+ describe("Bound to Operation", () => {
12
+ it("creates a function", async () => {
13
+ const program = await getProgram(`
14
+ namespace DemoService;
15
+ op getName(id: string): string;
16
+ `);
17
+ const [namespace] = program.resolveTypeReference("DemoService");
18
+ const operation = Array.from(namespace.operations.values())[0];
19
+ const res = render(_$createComponent(Output, {
20
+ get children() {
21
+ return _$createComponent(SourceFile, {
22
+ path: "test.ts",
23
+ get children() {
24
+ return _$createComponent(FunctionDeclaration, {
25
+ type: operation
26
+ });
27
+ }
28
+ });
29
+ }
30
+ }));
31
+ const testFile = res.contents.find(file => file.path === "test.ts");
32
+ assert(testFile, "test.ts file not rendered");
33
+ const actualContent = await format(testFile.contents, {
34
+ parser: "typescript"
35
+ });
36
+ const expectedContent = await format(`function getName(id: string): string{}`, {
37
+ parser: "typescript"
38
+ });
39
+ expect(actualContent).toBe(expectedContent);
40
+ });
41
+ it("creates an async function", async () => {
42
+ const program = await getProgram(`
43
+ namespace DemoService;
44
+ op getName(id: string): string;
45
+ `);
46
+ const [namespace] = program.resolveTypeReference("DemoService");
47
+ const operation = Array.from(namespace.operations.values())[0];
48
+ const res = render(_$createComponent(Output, {
49
+ get children() {
50
+ return _$createComponent(SourceFile, {
51
+ path: "test.ts",
52
+ get children() {
53
+ return _$createComponent(FunctionDeclaration, {
54
+ async: true,
55
+ type: operation
56
+ });
57
+ }
58
+ });
59
+ }
60
+ }));
61
+ const testFile = res.contents.find(file => file.path === "test.ts");
62
+ assert(testFile, "test.ts file not rendered");
63
+ const actualContent = await format(testFile.contents, {
64
+ parser: "typescript"
65
+ });
66
+ const expectedContent = await format(d`async function getName(id: string): Promise<string> {
67
+
68
+
69
+ }`, {
70
+ parser: "typescript"
71
+ });
72
+ expect(actualContent).toBe(expectedContent);
73
+ });
74
+ it("exports a function", async () => {
75
+ const program = await getProgram(`
76
+ namespace DemoService;
77
+ op getName(id: string): string;
78
+ `);
79
+ const [namespace] = program.resolveTypeReference("DemoService");
80
+ const operation = Array.from(namespace.operations.values())[0];
81
+ const res = render(_$createComponent(Output, {
82
+ get children() {
83
+ return _$createComponent(SourceFile, {
84
+ path: "test.ts",
85
+ get children() {
86
+ return _$createComponent(FunctionDeclaration, {
87
+ "export": true,
88
+ type: operation
89
+ });
90
+ }
91
+ });
92
+ }
93
+ }));
94
+ const testFile = res.contents.find(file => file.path === "test.ts");
95
+ assert(testFile, "test.ts file not rendered");
96
+ const actualContent = await format(testFile.contents, {
97
+ parser: "typescript"
98
+ });
99
+ const expectedContent = await format(`export function getName(id: string): string{}`, {
100
+ parser: "typescript"
101
+ });
102
+ expect(actualContent).toBe(expectedContent);
103
+ });
104
+ it("can override name", async () => {
105
+ const program = await getProgram(`
106
+ namespace DemoService;
107
+ op getName(id: string): string;
108
+ `);
109
+ const [namespace] = program.resolveTypeReference("DemoService");
110
+ const operation = Array.from(namespace.operations.values())[0];
111
+ const res = render(_$createComponent(Output, {
112
+ get children() {
113
+ return _$createComponent(SourceFile, {
114
+ path: "test.ts",
115
+ get children() {
116
+ return _$createComponent(FunctionDeclaration, {
117
+ name: "newName",
118
+ type: operation
119
+ });
120
+ }
121
+ });
122
+ }
123
+ }));
124
+ const testFile = res.contents.find(file => file.path === "test.ts");
125
+ assert(testFile, "test.ts file not rendered");
126
+ const actualContent = await format(testFile.contents, {
127
+ parser: "typescript"
128
+ });
129
+ const expectedContent = await format(`function newName(id: string): string{}`, {
130
+ parser: "typescript"
131
+ });
132
+ expect(actualContent).toBe(expectedContent);
133
+ });
134
+ it("can append extra parameters with raw params provided", async () => {
135
+ const program = await getProgram(`
136
+ namespace DemoService;
137
+ op createPerson(id: string): string;
138
+ `);
139
+ const [namespace] = program.resolveTypeReference("DemoService");
140
+ const operation = Array.from(namespace.operations.values())[0];
141
+ const res = render(_$createComponent(Output, {
142
+ get children() {
143
+ return _$createComponent(SourceFile, {
144
+ path: "test.ts",
145
+ get children() {
146
+ return _$createComponent(FunctionDeclaration, {
147
+ type: operation,
148
+ parameters: [{
149
+ name: "name",
150
+ type: "string"
151
+ }, {
152
+ name: "age",
153
+ type: "number"
154
+ }]
155
+ });
156
+ }
157
+ });
158
+ }
159
+ }));
160
+ const testFile = res.contents.find(file => file.path === "test.ts");
161
+ assert(testFile, "test.ts file not rendered");
162
+ const actualContent = await format(testFile.contents, {
163
+ parser: "typescript"
164
+ });
165
+ const expectedContent = await format(`function createPerson(name: string, age: number, id: string): string{}`, {
166
+ parser: "typescript"
167
+ });
168
+ expect(actualContent).toBe(expectedContent);
169
+ });
170
+ it.skip("can override parameters with an array of ModelProperties", async () => {
171
+ const program = await getProgram(`
172
+ namespace DemoService;
173
+ op createPerson(id: string): string;
174
+
175
+ model Foo {
176
+ name: string;
177
+ age: int32;
178
+ }
179
+ `);
180
+ const [namespace] = program.resolveTypeReference("DemoService");
181
+ const operation = Array.from(namespace.operations.values())[0];
182
+ const model = Array.from(namespace.models.values())[0];
183
+ const res = render(_$createComponent(Output, {
184
+ get children() {
185
+ return _$createComponent(SourceFile, {
186
+ path: "test.ts",
187
+ get children() {
188
+ return _$createComponent(FunctionDeclaration, {
189
+ type: operation,
190
+ get children() {
191
+ return _$createComponent(FunctionDeclaration.Parameters, {
192
+ type: model
193
+ });
194
+ }
195
+ });
196
+ }
197
+ });
198
+ }
199
+ }));
200
+ const testFile = res.contents.find(file => file.path === "test.ts");
201
+ assert(testFile, "test.ts file not rendered");
202
+ const actualContent = await format(testFile.contents, {
203
+ parser: "typescript"
204
+ });
205
+ const expectedContent = await format(`function createPerson(name: string, age: number): string{}`, {
206
+ parser: "typescript"
207
+ });
208
+ expect(actualContent).toBe(expectedContent);
209
+ });
210
+ it("can render function body", async () => {
211
+ const program = await getProgram(`
212
+ namespace DemoService;
213
+ op createPerson(id: string): string;
214
+ `);
215
+ const [namespace] = program.resolveTypeReference("DemoService");
216
+ const operation = Array.from(namespace.operations.values())[0];
217
+ const res = render(_$createComponent(Output, {
218
+ get children() {
219
+ return _$createComponent(SourceFile, {
220
+ path: "test.ts",
221
+ get children() {
222
+ return _$createComponent(FunctionDeclaration, {
223
+ "export": true,
224
+ type: operation,
225
+ children: "const message = \"Hello World!\"; console.log(message);"
226
+ });
227
+ }
228
+ });
229
+ }
230
+ }));
231
+ const testFile = res.contents.find(file => file.path === "test.ts");
232
+ assert(testFile, "test.ts file not rendered");
233
+ const actualContent = await format(testFile.contents, {
234
+ parser: "typescript"
235
+ });
236
+ const expectedContent = await format(`export function createPerson(id: string): string {
237
+ const message = "Hello World!";
238
+ console.log(message);
239
+ }`, {
240
+ parser: "typescript"
241
+ });
242
+ expect(actualContent).toBe(expectedContent);
243
+ });
244
+ });
245
+ });
246
+ });
@@ -0,0 +1,88 @@
1
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
+ import { Output, render } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import { SourceFile } from "@alloy-js/typescript";
5
+ import { beforeEach, describe, it } from "vitest";
6
+ import { FunctionExpression } from "../../../src/typescript/components/function-expression.js";
7
+ import { assertFileContents } from "../../utils.js";
8
+ import { createEmitterFrameworkTestRunner } from "../test-host.js";
9
+ describe("function expressions with a `type` prop", () => {
10
+ let runner;
11
+ beforeEach(async () => {
12
+ runner = await createEmitterFrameworkTestRunner();
13
+ });
14
+ it("creates a function", async () => {
15
+ const {
16
+ getName
17
+ } = await runner.compile(`
18
+ @test op getName(id: string): string;
19
+ `);
20
+ const res = render(_$createComponent(Output, {
21
+ get children() {
22
+ return _$createComponent(SourceFile, {
23
+ path: "test.ts",
24
+ get children() {
25
+ return _$createComponent(FunctionExpression, {
26
+ type: getName,
27
+ children: "console.log(\"Hello!\");"
28
+ });
29
+ }
30
+ });
31
+ }
32
+ }));
33
+ assertFileContents(res, d`
34
+ function (id: string): string {
35
+ console.log("Hello!");
36
+ }
37
+ `);
38
+ });
39
+ it("creates an async function", async () => {
40
+ const {
41
+ getName
42
+ } = await runner.compile(`
43
+ @test op getName(id: string): string;
44
+ `);
45
+ const res = render(_$createComponent(Output, {
46
+ get children() {
47
+ return _$createComponent(SourceFile, {
48
+ path: "test.ts",
49
+ get children() {
50
+ return _$createComponent(FunctionExpression, {
51
+ async: true,
52
+ type: getName
53
+ });
54
+ }
55
+ });
56
+ }
57
+ }));
58
+ assertFileContents(res, d`
59
+ async function (id: string): Promise<string> {}
60
+ `);
61
+ });
62
+ it("can append extra parameters with raw params provided", async () => {
63
+ const {
64
+ getName
65
+ } = await runner.compile(`
66
+ @test op getName(id: string): string;
67
+ `);
68
+ const res = render(_$createComponent(Output, {
69
+ get children() {
70
+ return _$createComponent(SourceFile, {
71
+ path: "test.ts",
72
+ get children() {
73
+ return _$createComponent(FunctionExpression, {
74
+ type: getName,
75
+ parameters: [{
76
+ name: "additionalParam",
77
+ type: "number"
78
+ }]
79
+ });
80
+ }
81
+ });
82
+ }
83
+ }));
84
+ assertFileContents(res, d`
85
+ function (additionalParam: number, id: string): string {}
86
+ `);
87
+ });
88
+ });