Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3ad8de9

Browse files
authored
Add Test wrapper with symbol definition utility plus TS and CSharp specific wrappers (#310)
**Summary** Introduces a `createCSharpTestWrapper` helper to simplify defining andreferencing C# symbols by name in test JSX without manual upfrontdeclarations.**Key Changes** - Added wrapper factory exposing `Wrapper` + `defkey(name)` API. - Lazy `Namekey` creation with idempotent caching by string name. **Rationale** Reduces boilerplate for symbol-based test cases, enforces consistentdeclaration emission, protects against premature symbol creation outsidea valid scope, and improves clarity and maintainability.
1 parentd99ca6c commit3ad8de9

File tree

15 files changed

+377
-1
lines changed

15 files changed

+377
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind:feature
3+
packages:
4+
-"@alloy-js/csharp"
5+
---
6+
7+
Add C# test wrapper with symbol definition utility
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
changeKind:feature
3+
packages:
4+
-"@alloy-js/core"
5+
-"@alloy-js/typescript"
6+
---
7+
8+
Add a general TestWrapper factory and TS specific factory
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import{
2+
Children,
3+
Declaration,
4+
For,
5+
Namekey,
6+
namekey,
7+
Output,
8+
OutputSymbol,
9+
shallowReactive,
10+
}from"@alloy-js/core";
11+
12+
exportinterfaceTestWrapper{
13+
Wrapper:(props:{children:Children})=>Children;
14+
defkey:(name:string)=>Namekey;
15+
}
16+
17+
/**
18+
* Generic test wrapper creator.
19+
*/
20+
exportfunctioncreateTestWrapper<
21+
SymbolTextendsOutputSymbol,
22+
ScopeTextends{spaces:any},
23+
>(opts:{
24+
filePath:string;
25+
useScope:()=>ScopeT|undefined;
26+
makeSymbol:(nk:Namekey,scope:ScopeT)=>SymbolT;
27+
SourceFile:(props:{path:string;children:Children})=>any;
28+
}):TestWrapper{
29+
constseen=shallowReactive(newMap<string,Namekey>());
30+
constcreated=newMap<Namekey,SymbolT>();
31+
32+
functiondefkey(name:string):Namekey{
33+
constexisting=seen.get(name);
34+
if(existing)returnexisting;
35+
constnk=namekey(name,{
36+
ignoreNamePolicy:true,
37+
ignoreNameConflict:true,
38+
});
39+
seen.set(name,nk);
40+
returnnk;
41+
}
42+
43+
functioncreateSymbol(nk:Namekey){
44+
constexisting=created.get(nk);
45+
if(existing)returnexisting;
46+
constscope=opts.useScope();
47+
if(!scope){
48+
thrownewError(`No SourceFile scope when declaring symbol:${nk.name}`);
49+
}
50+
constsym=opts.makeSymbol(nk,scope);
51+
created.set(nk,sym);
52+
returnsym;
53+
}
54+
55+
functionWrapper(props:{children:Children}){
56+
constSF=opts.SourceFile;
57+
return(
58+
<Output>
59+
<SFpath={opts.filePath}>
60+
<Foreach={[...seen.values()]}joiner="">
61+
{(nk)=><Declarationsymbol={createSymbol(nk)}/>}
62+
</For>
63+
{props.children}
64+
</SF>
65+
</Output>
66+
);
67+
}
68+
69+
return{ Wrapper, defkey}asconst;
70+
}

‎packages/core/testing/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
import"./extend-expect.js";
2+
export*from"./create-test-wrapper.jsx";
23
export*from"./render.js";

‎packages/core/tsconfig.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"test/**/*.ts",
1212
"test/**/*.tsx",
1313
"testing/**/*.ts",
14+
"testing/**/*.tsx",
1415
"testing/**/*.d.ts",
1516
"testing/extend-expect.test.tsx"
1617
],

‎packages/csharp/package.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
"./global/*": {
1515
"development":"./src/builtins/*/index.ts",
1616
"import":"./dist/src/builtins/*/index.js"
17+
},
18+
"./testing/*": {
19+
"development":"./testing/index.ts",
20+
"import":"./dist/testing/index.js"
1721
}
1822
},
1923
"imports": {

‎packages/csharp/src/components/attributes/attributes.test.tsx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { TestNamespace } from "#test/utils.jsx";
44
import{List,namekey}from"@alloy-js/core";
55
import{describe,expect,it}from"vitest";
66
import{Attribute,AttributeList}from"./attributes.jsx";
7-
87
it("define attribute",()=>{
98
expect(<Attributename="Test"/>).toRenderTo(`
109
[Test]
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import{
2+
ClassDeclaration,
3+
Method,
4+
Property,
5+
StructDeclaration,
6+
}from"#components/index.js";
7+
import{List,Refkey}from"@alloy-js/core";
8+
import{d}from"@alloy-js/core/testing";
9+
import{expect,it}from"vitest";
10+
import{createCSharpTestWrapper}from"./create-wrapper.jsx";
11+
12+
it("should render defkey inline",async()=>{
13+
const{ Wrapper, defkey}=createCSharpTestWrapper();
14+
15+
expect(<Wrapper>return{defkey("myResult")};</Wrapper>).toRenderTo(
16+
`return myResult;`,
17+
);
18+
});
19+
20+
it("emits a single declaration per unique name",()=>{
21+
const{ Wrapper, defkey}=createCSharpTestWrapper();
22+
consta=defkey("MyType");
23+
constb=defkey("MyType");
24+
expect(a).toBe(b);
25+
26+
expect(
27+
<Wrapper>
28+
return{a}{b};
29+
</Wrapper>,
30+
).toRenderTo(`return MyType MyType;`);// Ensure only one 'class/struct/interface' (whatever default is) declaration appears above if that's the behavior.
31+
});
32+
33+
it("reuses declarations across multiple usage sites",()=>{
34+
const{ Wrapper, defkey}=createCSharpTestWrapper();
35+
constT=defkey("Thing");
36+
constR=defkey("Result");
37+
38+
expect(
39+
<Wrapper>
40+
<ClassDeclarationabstractname="A">
41+
<List>
42+
<Method
43+
abstract
44+
name="a"
45+
returns={R}
46+
parameters={[{name:"x",type:T}]}
47+
/>
48+
<Method
49+
abstract
50+
name="b"
51+
returns={R}
52+
parameters={[{name:"y",type:T}]}
53+
/>
54+
</List>
55+
</ClassDeclaration>
56+
</Wrapper>,
57+
).toRenderTo(d`
58+
abstract class A
59+
{
60+
abstract Result a(Thing x);
61+
abstract Result b(Thing y);
62+
}`);
63+
});
64+
65+
it("reuses declarations across multiple defkeys",()=>{
66+
const{ Wrapper, defkey}=createCSharpTestWrapper();
67+
68+
expect(
69+
<Wrapper>
70+
<ClassDeclarationabstractname="A">
71+
<List>
72+
<Method
73+
abstract
74+
name="a"
75+
returns={defkey("Result")}
76+
parameters={[{name:"x",type:defkey("Thing")}]}
77+
/>
78+
<Method
79+
abstract
80+
name="b"
81+
returns={defkey("Result")}
82+
parameters={[{name:"y",type:defkey("Thing")}]}
83+
/>
84+
</List>
85+
</ClassDeclaration>
86+
</Wrapper>,
87+
).toRenderTo(d`
88+
abstract class A
89+
{
90+
abstract Result a(Thing x);
91+
abstract Result b(Thing y);
92+
}`);
93+
});
94+
95+
it("should render defkey in nested component",async()=>{
96+
functionTestComponent(props:{returnTypeRef:Refkey}){
97+
return<Methodname="foo"returns={props.returnTypeRef}/>;
98+
}
99+
100+
const{ Wrapper, defkey}=createCSharpTestWrapper();
101+
102+
expect(
103+
<Wrapper>
104+
<ClassDeclarationname="MyClass">
105+
<TestComponentreturnTypeRef={defkey("MyType")}/>
106+
</ClassDeclaration>
107+
</Wrapper>,
108+
).toRenderTo(d`
109+
class MyClass
110+
{
111+
MyType foo() {}
112+
}`);
113+
});
114+
115+
it("should render defkey in class property",async()=>{
116+
const{ Wrapper, defkey}=createCSharpTestWrapper();
117+
118+
expect(
119+
<Wrapper>
120+
<ClassDeclarationname="TestClass">
121+
<Propertyname="MyProperty"type={defkey("MyType")}getset/>
122+
</ClassDeclaration>
123+
</Wrapper>,
124+
).toRenderTo(d`
125+
class TestClass
126+
{
127+
MyType MyProperty { get; set; }
128+
}`);
129+
});
130+
131+
it("should render defkey in struct property",async()=>{
132+
const{ Wrapper, defkey}=createCSharpTestWrapper();
133+
134+
expect(
135+
<Wrapper>
136+
<StructDeclarationname="TestStruct">
137+
<Propertyname="MyProperty"type={defkey("MyType")}getset/>
138+
</StructDeclaration>
139+
</Wrapper>,
140+
).toRenderTo(d`
141+
struct TestStruct
142+
{
143+
MyType MyProperty { get; set; }
144+
}`);
145+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import{SourceFile}from"#components/index.js";
2+
import{createTestWrapper,typeTestWrapper}from"@alloy-js/core/testing";
3+
import{CSharpSymbol,useSourceFileScope}from"../src/index.js";
4+
5+
exportfunctioncreateCSharpTestWrapper():TestWrapper{
6+
returncreateTestWrapper({
7+
filePath:"test.cs",
8+
useScope:useSourceFileScope,
9+
makeSymbol:(nk,scope)=>newCSharpSymbol(nk,scope.spaces),
10+
SourceFile,
11+
});
12+
}

‎packages/csharp/testing/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export*from"./create-wrapper.jsx";

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp