Skip to content

Commit c6a8928

Browse files
authored
Merge pull request #245 from retran/test/visitor-coverage
test: add visitor tests for 20 untested source files
2 parents 59204a1 + a0e2a1c commit c6a8928

22 files changed

Lines changed: 1944 additions & 1 deletion

mdl/backend/mock/mock_page_mutator.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ var _ backend.PageMutator = (*MockPageMutator)(nil)
1212

1313
// MockPageMutator implements backend.PageMutator. Every interface method is
1414
// backed by a public function field. If the field is nil the method returns
15-
// zero values / nil error (never panics).
15+
// nil error (never panics). ContainerType defaults to ContainerPage when unset;
16+
// all other methods return zero values.
1617
type MockPageMutator struct {
1718
ContainerTypeFunc func() backend.ContainerKind
1819
SetWidgetPropertyFunc func(widgetRef string, prop string, value any) error
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestCreateModel(t *testing.T) {
12+
input := `CREATE MODEL MyModule.GPT4 (
13+
Provider: MxCloudGenAI,
14+
Key: MyModule.APIKey,
15+
DisplayName: 'GPT-4 Turbo'
16+
);`
17+
prog, errs := Build(input)
18+
if len(errs) > 0 {
19+
for _, e := range errs {
20+
t.Errorf("Parse error: %v", e)
21+
}
22+
return
23+
}
24+
stmt, ok := prog.Statements[0].(*ast.CreateModelStmt)
25+
if !ok {
26+
t.Fatalf("Expected CreateModelStmt, got %T", prog.Statements[0])
27+
}
28+
if stmt.Name.Module != "MyModule" || stmt.Name.Name != "GPT4" {
29+
t.Errorf("Expected MyModule.GPT4, got %s.%s", stmt.Name.Module, stmt.Name.Name)
30+
}
31+
if stmt.Provider != "MxCloudGenAI" {
32+
t.Errorf("Got Provider %q", stmt.Provider)
33+
}
34+
if stmt.Key == nil || stmt.Key.Name != "APIKey" {
35+
t.Error("Key mismatch")
36+
}
37+
if stmt.DisplayName != "GPT-4 Turbo" {
38+
t.Errorf("Got DisplayName %q", stmt.DisplayName)
39+
}
40+
}
41+
42+
func TestCreateConsumedMCPService(t *testing.T) {
43+
input := `CREATE CONSUMED MCP SERVICE MyModule.ToolService (
44+
ProtocolVersion: v2025_03_26,
45+
Version: '0.0.1',
46+
ConnectionTimeoutSeconds: 30,
47+
Documentation: 'MCP tool service'
48+
);`
49+
prog, errs := Build(input)
50+
if len(errs) > 0 {
51+
for _, e := range errs {
52+
t.Errorf("Parse error: %v", e)
53+
}
54+
return
55+
}
56+
stmt, ok := prog.Statements[0].(*ast.CreateConsumedMCPServiceStmt)
57+
if !ok {
58+
t.Fatalf("Expected CreateConsumedMCPServiceStmt, got %T", prog.Statements[0])
59+
}
60+
if stmt.ProtocolVersion != "v2025_03_26" {
61+
t.Errorf("Got ProtocolVersion %q", stmt.ProtocolVersion)
62+
}
63+
if stmt.Version != "0.0.1" {
64+
t.Errorf("Got Version %q", stmt.Version)
65+
}
66+
if stmt.ConnectionTimeoutSeconds != 30 {
67+
t.Errorf("Got ConnectionTimeoutSeconds %d", stmt.ConnectionTimeoutSeconds)
68+
}
69+
if stmt.InnerDocumentation != "MCP tool service" {
70+
t.Errorf("Got InnerDocumentation %q", stmt.InnerDocumentation)
71+
}
72+
}
73+
74+
func TestCreateKnowledgeBase(t *testing.T) {
75+
input := `CREATE KNOWLEDGE BASE MyModule.ProductKB (
76+
Provider: MxCloudGenAI,
77+
Key: MyModule.KBKey,
78+
ModelDisplayName: 'Product Knowledge',
79+
ModelName: 'product-embeddings'
80+
);`
81+
prog, errs := Build(input)
82+
if len(errs) > 0 {
83+
for _, e := range errs {
84+
t.Errorf("Parse error: %v", e)
85+
}
86+
return
87+
}
88+
stmt, ok := prog.Statements[0].(*ast.CreateKnowledgeBaseStmt)
89+
if !ok {
90+
t.Fatalf("Expected CreateKnowledgeBaseStmt, got %T", prog.Statements[0])
91+
}
92+
if stmt.Provider != "MxCloudGenAI" {
93+
t.Errorf("Got Provider %q", stmt.Provider)
94+
}
95+
if stmt.Key == nil || stmt.Key.Name != "KBKey" {
96+
t.Error("Key mismatch")
97+
}
98+
if stmt.ModelDisplayName != "Product Knowledge" {
99+
t.Errorf("Got ModelDisplayName %q", stmt.ModelDisplayName)
100+
}
101+
}
102+
103+
func TestCreateAgent_Basic(t *testing.T) {
104+
input := `CREATE AGENT MyModule.OrderAgent (
105+
UsageType: Task,
106+
Model: MyModule.GPT4,
107+
Entity: MyModule.OrderContext,
108+
SystemPrompt: 'You are an order processing assistant.',
109+
ToolChoice: auto,
110+
MaxTokens: 4096,
111+
Temperature: 0.7
112+
);`
113+
prog, errs := Build(input)
114+
if len(errs) > 0 {
115+
for _, e := range errs {
116+
t.Errorf("Parse error: %v", e)
117+
}
118+
return
119+
}
120+
stmt, ok := prog.Statements[0].(*ast.CreateAgentStmt)
121+
if !ok {
122+
t.Fatalf("Expected CreateAgentStmt, got %T", prog.Statements[0])
123+
}
124+
if stmt.UsageType != "Task" {
125+
t.Errorf("Got UsageType %q", stmt.UsageType)
126+
}
127+
if stmt.Model == nil || stmt.Model.Name != "GPT4" {
128+
t.Error("Model mismatch")
129+
}
130+
if stmt.Entity == nil || stmt.Entity.Name != "OrderContext" {
131+
t.Error("Entity mismatch")
132+
}
133+
if stmt.MaxTokens == nil || *stmt.MaxTokens != 4096 {
134+
t.Error("MaxTokens mismatch")
135+
}
136+
if stmt.Temperature == nil || *stmt.Temperature != 0.7 {
137+
t.Error("Temperature mismatch")
138+
}
139+
if stmt.ToolChoice != "auto" {
140+
t.Errorf("Got ToolChoice %q", stmt.ToolChoice)
141+
}
142+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestCreateAssociation(t *testing.T) {
12+
input := `CREATE ASSOCIATION MyModule.Order_Customer FROM MyModule.Order TO MyModule.Customer TYPE REFERENCE OWNER DEFAULT;`
13+
prog, errs := Build(input)
14+
if len(errs) > 0 {
15+
for _, e := range errs {
16+
t.Errorf("Parse error: %v", e)
17+
}
18+
return
19+
}
20+
stmt, ok := prog.Statements[0].(*ast.CreateAssociationStmt)
21+
if !ok {
22+
t.Fatalf("Expected CreateAssociationStmt, got %T", prog.Statements[0])
23+
}
24+
if stmt.Name.Module != "MyModule" || stmt.Name.Name != "Order_Customer" {
25+
t.Errorf("Got name %s.%s", stmt.Name.Module, stmt.Name.Name)
26+
}
27+
if stmt.Parent.Name != "Order" {
28+
t.Errorf("Got parent %s", stmt.Parent.Name)
29+
}
30+
if stmt.Child.Name != "Customer" {
31+
t.Errorf("Got child %s", stmt.Child.Name)
32+
}
33+
if stmt.Type != ast.AssocReference {
34+
t.Errorf("Expected Reference type, got %v", stmt.Type)
35+
}
36+
}
37+
38+
func TestCreateAssociation_ReferenceSet(t *testing.T) {
39+
input := `CREATE ASSOCIATION MyModule.Order_Product FROM MyModule.Order TO MyModule.Product TYPE REFERENCE_SET OWNER BOTH;`
40+
prog, errs := Build(input)
41+
if len(errs) > 0 {
42+
for _, e := range errs {
43+
t.Errorf("Parse error: %v", e)
44+
}
45+
return
46+
}
47+
stmt := prog.Statements[0].(*ast.CreateAssociationStmt)
48+
if stmt.Type != ast.AssocReferenceSet {
49+
t.Errorf("Expected ReferenceSet, got %v", stmt.Type)
50+
}
51+
if stmt.Owner != ast.OwnerBoth {
52+
t.Errorf("Expected OwnerBoth, got %v", stmt.Owner)
53+
}
54+
}
55+
56+
func TestAlterAssociation_SetOwner(t *testing.T) {
57+
input := `ALTER ASSOCIATION MyModule.Order_Customer SET OWNER BOTH;`
58+
prog, errs := Build(input)
59+
if len(errs) > 0 {
60+
for _, e := range errs {
61+
t.Errorf("Parse error: %v", e)
62+
}
63+
return
64+
}
65+
stmt, ok := prog.Statements[0].(*ast.AlterAssociationStmt)
66+
if !ok {
67+
t.Fatalf("Expected AlterAssociationStmt, got %T", prog.Statements[0])
68+
}
69+
if stmt.Name.Name != "Order_Customer" {
70+
t.Errorf("Got name %s", stmt.Name.Name)
71+
}
72+
if stmt.Owner != ast.OwnerBoth {
73+
t.Errorf("Expected OwnerBoth, got %v", stmt.Owner)
74+
}
75+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestCreateBusinessEventService(t *testing.T) {
12+
input := `CREATE BUSINESS EVENT SERVICE MyModule.OrderEvents (
13+
ServiceName: 'OrderService',
14+
EventNamePrefix: 'com.example.orders'
15+
) {
16+
MESSAGE OrderCreated (OrderId: Long) PUBLISH ENTITY MyModule.Order;
17+
};`
18+
prog, errs := Build(input)
19+
if len(errs) > 0 {
20+
for _, e := range errs {
21+
t.Errorf("Parse error: %v", e)
22+
}
23+
return
24+
}
25+
stmt, ok := prog.Statements[0].(*ast.CreateBusinessEventServiceStmt)
26+
if !ok {
27+
t.Fatalf("Expected CreateBusinessEventServiceStmt, got %T", prog.Statements[0])
28+
}
29+
if stmt.ServiceName != "OrderService" {
30+
t.Errorf("Got ServiceName %q", stmt.ServiceName)
31+
}
32+
if stmt.EventNamePrefix != "com.example.orders" {
33+
t.Errorf("Got EventNamePrefix %q", stmt.EventNamePrefix)
34+
}
35+
if len(stmt.Messages) != 1 {
36+
t.Fatalf("Expected 1 message, got %d", len(stmt.Messages))
37+
}
38+
if stmt.Messages[0].MessageName != "OrderCreated" {
39+
t.Errorf("Got MessageName %q", stmt.Messages[0].MessageName)
40+
}
41+
if stmt.Messages[0].Operation != "PUBLISH" {
42+
t.Errorf("Got Operation %q", stmt.Messages[0].Operation)
43+
}
44+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestConnect_Local(t *testing.T) {
12+
input := `CONNECT LOCAL '/path/to/project';`
13+
prog, errs := Build(input)
14+
if len(errs) > 0 {
15+
for _, e := range errs {
16+
t.Errorf("Parse error: %v", e)
17+
}
18+
return
19+
}
20+
stmt, ok := prog.Statements[0].(*ast.ConnectStmt)
21+
if !ok {
22+
t.Fatalf("Expected ConnectStmt, got %T", prog.Statements[0])
23+
}
24+
if stmt.Path != "/path/to/project" {
25+
t.Errorf("Expected /path/to/project, got %q", stmt.Path)
26+
}
27+
}
28+
29+
func TestDisconnect(t *testing.T) {
30+
input := `DISCONNECT;`
31+
prog, errs := Build(input)
32+
if len(errs) > 0 {
33+
for _, e := range errs {
34+
t.Errorf("Parse error: %v", e)
35+
}
36+
return
37+
}
38+
_, ok := prog.Statements[0].(*ast.DisconnectStmt)
39+
if !ok {
40+
t.Fatalf("Expected DisconnectStmt, got %T", prog.Statements[0])
41+
}
42+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestCreateDataTransformer(t *testing.T) {
12+
input := `CREATE DATA TRANSFORMER MyModule.LatExtract SOURCE JSON '{"lat": 51.9}' {
13+
JSLT '{ "latitude": .lat }';
14+
};`
15+
prog, errs := Build(input)
16+
if len(errs) > 0 {
17+
for _, e := range errs {
18+
t.Errorf("Parse error: %v", e)
19+
}
20+
return
21+
}
22+
stmt, ok := prog.Statements[0].(*ast.CreateDataTransformerStmt)
23+
if !ok {
24+
t.Fatalf("Expected CreateDataTransformerStmt, got %T", prog.Statements[0])
25+
}
26+
if stmt.Name.Name != "LatExtract" {
27+
t.Errorf("Got name %s", stmt.Name.Name)
28+
}
29+
if stmt.SourceType != "JSON" {
30+
t.Errorf("Got SourceType %q", stmt.SourceType)
31+
}
32+
if len(stmt.Steps) != 1 {
33+
t.Fatalf("Expected 1 step, got %d", len(stmt.Steps))
34+
}
35+
if stmt.Steps[0].Technology != "JSLT" {
36+
t.Errorf("Got Technology %q", stmt.Steps[0].Technology)
37+
}
38+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package visitor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
)
10+
11+
func TestCreateDatabaseConnection(t *testing.T) {
12+
input := `CREATE DATABASE CONNECTION MyModule.MyDB TYPE 'PostgreSQL' HOST 'localhost' PORT 5432 DATABASE 'mydb' USERNAME 'user' PASSWORD 'pass';`
13+
prog, errs := Build(input)
14+
if len(errs) > 0 {
15+
for _, e := range errs {
16+
t.Errorf("Parse error: %v", e)
17+
}
18+
return
19+
}
20+
stmt, ok := prog.Statements[0].(*ast.CreateDatabaseConnectionStmt)
21+
if !ok {
22+
t.Fatalf("Expected CreateDatabaseConnectionStmt, got %T", prog.Statements[0])
23+
}
24+
if stmt.Name.Name != "MyDB" {
25+
t.Errorf("Got name %s", stmt.Name.Name)
26+
}
27+
if stmt.DatabaseType != "PostgreSQL" {
28+
t.Errorf("Got DatabaseType %q", stmt.DatabaseType)
29+
}
30+
if stmt.Host != "localhost" {
31+
t.Errorf("Got Host %q", stmt.Host)
32+
}
33+
if stmt.Port != 5432 {
34+
t.Errorf("Got Port %d", stmt.Port)
35+
}
36+
if stmt.UserName != "user" {
37+
t.Errorf("Got UserName %q", stmt.UserName)
38+
}
39+
}

0 commit comments

Comments
 (0)