Skip to content

Commit 6e6f5cc

Browse files
authored
Merge pull request #232 from retran/feature/mock-handler-tests
feat: add comprehensive mock-based handler tests (189 tests)
2 parents b84500f + 02db813 commit 6e6f5cc

38 files changed

+3904
-132
lines changed

internal/marketplace/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var BaseURL = "https://marketplace-api.mendix.com"
1818
type Content struct {
1919
ContentID int `json:"contentId"`
2020
Publisher string `json:"publisher"`
21-
Type string `json:"type"` // "Module", "Widget", "Theme", "Starter App", ...
21+
Type string `json:"type"` // "Module", "Widget", "Theme", "Starter App", ...
2222
Categories []Category `json:"categories"`
2323
SupportCategory string `json:"supportCategory"` // "Platform", "Community", "Deprecated", ...
2424
LicenseURL string `json:"licenseUrl,omitempty"`

mdl/backend/mock/backend.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,16 @@ type MockBackend struct {
260260
FindAllCustomWidgetTypesFunc func(widgetID string) ([]*mpr.RawCustomWidgetType, error)
261261

262262
// AgentEditorBackend
263-
ListAgentEditorModelsFunc func() ([]*agenteditor.Model, error)
264-
ListAgentEditorKnowledgeBasesFunc func() ([]*agenteditor.KnowledgeBase, error)
265-
ListAgentEditorConsumedMCPServicesFunc func() ([]*agenteditor.ConsumedMCPService, error)
266-
ListAgentEditorAgentsFunc func() ([]*agenteditor.Agent, error)
263+
ListAgentEditorModelsFunc func() ([]*agenteditor.Model, error)
264+
ListAgentEditorKnowledgeBasesFunc func() ([]*agenteditor.KnowledgeBase, error)
265+
ListAgentEditorConsumedMCPServicesFunc func() ([]*agenteditor.ConsumedMCPService, error)
266+
ListAgentEditorAgentsFunc func() ([]*agenteditor.Agent, error)
267+
CreateAgentEditorModelFunc func(m *agenteditor.Model) error
268+
DeleteAgentEditorModelFunc func(id string) error
269+
CreateAgentEditorKnowledgeBaseFunc func(kb *agenteditor.KnowledgeBase) error
270+
DeleteAgentEditorKnowledgeBaseFunc func(id string) error
271+
CreateAgentEditorConsumedMCPServiceFunc func(svc *agenteditor.ConsumedMCPService) error
272+
DeleteAgentEditorConsumedMCPServiceFunc func(id string) error
273+
CreateAgentEditorAgentFunc func(a *agenteditor.Agent) error
274+
DeleteAgentEditorAgentFunc func(id string) error
267275
}

mdl/backend/mock/mock_infrastructure.go

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,58 @@ func (m *MockBackend) ListAgentEditorAgents() ([]*agenteditor.Agent, error) {
188188
return nil, nil
189189
}
190190

191-
func (m *MockBackend) CreateAgentEditorModel(_ *agenteditor.Model) error { return nil }
192-
func (m *MockBackend) DeleteAgentEditorModel(_ string) error { return nil }
193-
func (m *MockBackend) CreateAgentEditorKnowledgeBase(_ *agenteditor.KnowledgeBase) error { return nil }
194-
func (m *MockBackend) DeleteAgentEditorKnowledgeBase(_ string) error { return nil }
195-
func (m *MockBackend) CreateAgentEditorConsumedMCPService(_ *agenteditor.ConsumedMCPService) error {
191+
func (m *MockBackend) CreateAgentEditorModel(model *agenteditor.Model) error {
192+
if m.CreateAgentEditorModelFunc != nil {
193+
return m.CreateAgentEditorModelFunc(model)
194+
}
195+
return nil
196+
}
197+
198+
func (m *MockBackend) DeleteAgentEditorModel(id string) error {
199+
if m.DeleteAgentEditorModelFunc != nil {
200+
return m.DeleteAgentEditorModelFunc(id)
201+
}
202+
return nil
203+
}
204+
205+
func (m *MockBackend) CreateAgentEditorKnowledgeBase(kb *agenteditor.KnowledgeBase) error {
206+
if m.CreateAgentEditorKnowledgeBaseFunc != nil {
207+
return m.CreateAgentEditorKnowledgeBaseFunc(kb)
208+
}
209+
return nil
210+
}
211+
212+
func (m *MockBackend) DeleteAgentEditorKnowledgeBase(id string) error {
213+
if m.DeleteAgentEditorKnowledgeBaseFunc != nil {
214+
return m.DeleteAgentEditorKnowledgeBaseFunc(id)
215+
}
216+
return nil
217+
}
218+
219+
func (m *MockBackend) CreateAgentEditorConsumedMCPService(svc *agenteditor.ConsumedMCPService) error {
220+
if m.CreateAgentEditorConsumedMCPServiceFunc != nil {
221+
return m.CreateAgentEditorConsumedMCPServiceFunc(svc)
222+
}
223+
return nil
224+
}
225+
226+
func (m *MockBackend) DeleteAgentEditorConsumedMCPService(id string) error {
227+
if m.DeleteAgentEditorConsumedMCPServiceFunc != nil {
228+
return m.DeleteAgentEditorConsumedMCPServiceFunc(id)
229+
}
230+
return nil
231+
}
232+
233+
func (m *MockBackend) CreateAgentEditorAgent(a *agenteditor.Agent) error {
234+
if m.CreateAgentEditorAgentFunc != nil {
235+
return m.CreateAgentEditorAgentFunc(a)
236+
}
237+
return nil
238+
}
239+
240+
func (m *MockBackend) DeleteAgentEditorAgent(id string) error {
241+
if m.DeleteAgentEditorAgentFunc != nil {
242+
return m.DeleteAgentEditorAgentFunc(id)
243+
}
196244
return nil
197245
}
198-
func (m *MockBackend) DeleteAgentEditorConsumedMCPService(_ string) error { return nil }
199-
func (m *MockBackend) CreateAgentEditorAgent(_ *agenteditor.Agent) error { return nil }
200-
func (m *MockBackend) DeleteAgentEditorAgent(_ string) error { return nil }
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package executor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
"github.com/mendixlabs/mxcli/mdl/backend/mock"
10+
"github.com/mendixlabs/mxcli/model"
11+
"github.com/mendixlabs/mxcli/sdk/agenteditor"
12+
)
13+
14+
func TestShowAgentEditorModels_Mock(t *testing.T) {
15+
mod := mkModule("M")
16+
m1 := &agenteditor.Model{
17+
BaseElement: model.BaseElement{ID: nextID("aem")},
18+
ContainerID: mod.ID,
19+
Name: "GPT4",
20+
Provider: "MxCloudGenAI",
21+
DisplayName: "GPT-4 Turbo",
22+
Key: &agenteditor.ConstantRef{QualifiedName: "M.APIKey"},
23+
}
24+
25+
h := mkHierarchy(mod)
26+
withContainer(h, m1.ContainerID, mod.ID)
27+
28+
mb := &mock.MockBackend{
29+
IsConnectedFunc: func() bool { return true },
30+
ListAgentEditorModelsFunc: func() ([]*agenteditor.Model, error) { return []*agenteditor.Model{m1}, nil },
31+
}
32+
33+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
34+
assertNoError(t, showAgentEditorModels(ctx, ""))
35+
36+
out := buf.String()
37+
assertContainsStr(t, out, "Qualified Name")
38+
assertContainsStr(t, out, "Module")
39+
assertContainsStr(t, out, "Provider")
40+
assertContainsStr(t, out, "Key Constant")
41+
assertContainsStr(t, out, "Display Name")
42+
assertContainsStr(t, out, "M.GPT4")
43+
assertContainsStr(t, out, "MxCloudGenAI")
44+
assertContainsStr(t, out, "M.APIKey")
45+
assertContainsStr(t, out, "GPT-4 Turbo")
46+
}
47+
48+
func TestDescribeAgentEditorModel_Mock(t *testing.T) {
49+
mod := mkModule("M")
50+
m1 := &agenteditor.Model{
51+
BaseElement: model.BaseElement{ID: nextID("aem")},
52+
ContainerID: mod.ID,
53+
Name: "GPT4",
54+
Provider: "MxCloudGenAI",
55+
Key: &agenteditor.ConstantRef{QualifiedName: "M.APIKey"},
56+
}
57+
58+
h := mkHierarchy(mod)
59+
withContainer(h, m1.ContainerID, mod.ID)
60+
61+
mb := &mock.MockBackend{
62+
IsConnectedFunc: func() bool { return true },
63+
ListAgentEditorModelsFunc: func() ([]*agenteditor.Model, error) { return []*agenteditor.Model{m1}, nil },
64+
}
65+
66+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
67+
assertNoError(t, describeAgentEditorModel(ctx, ast.QualifiedName{Module: "M", Name: "GPT4"}))
68+
69+
out := buf.String()
70+
assertContainsStr(t, out, "CREATE MODEL")
71+
assertContainsStr(t, out, "Provider")
72+
assertContainsStr(t, out, "Key")
73+
}
74+
75+
func TestShowAgentEditorAgents_Mock(t *testing.T) {
76+
mod := mkModule("M")
77+
a1 := &agenteditor.Agent{
78+
BaseElement: model.BaseElement{ID: nextID("aea")},
79+
ContainerID: mod.ID,
80+
Name: "MyAgent",
81+
UsageType: "Chat",
82+
Model: &agenteditor.DocRef{QualifiedName: "M.GPT4"},
83+
Tools: []agenteditor.AgentTool{{ID: "t1", Enabled: true}},
84+
KBTools: []agenteditor.AgentKBTool{{ID: "kb1", Enabled: true}},
85+
}
86+
87+
h := mkHierarchy(mod)
88+
withContainer(h, a1.ContainerID, mod.ID)
89+
90+
mb := &mock.MockBackend{
91+
IsConnectedFunc: func() bool { return true },
92+
ListAgentEditorAgentsFunc: func() ([]*agenteditor.Agent, error) { return []*agenteditor.Agent{a1}, nil },
93+
}
94+
95+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
96+
assertNoError(t, showAgentEditorAgents(ctx, ""))
97+
98+
out := buf.String()
99+
assertContainsStr(t, out, "Qualified Name")
100+
assertContainsStr(t, out, "Usage")
101+
assertContainsStr(t, out, "Model")
102+
assertContainsStr(t, out, "Tools")
103+
assertContainsStr(t, out, "KBs")
104+
assertContainsStr(t, out, "M.MyAgent")
105+
assertContainsStr(t, out, "Chat")
106+
assertContainsStr(t, out, "M.GPT4")
107+
}
108+
109+
func TestDescribeAgentEditorAgent_Mock(t *testing.T) {
110+
mod := mkModule("M")
111+
a1 := &agenteditor.Agent{
112+
BaseElement: model.BaseElement{ID: nextID("aea")},
113+
ContainerID: mod.ID,
114+
Name: "MyAgent",
115+
UsageType: "Chat",
116+
Model: &agenteditor.DocRef{QualifiedName: "M.GPT4"},
117+
}
118+
119+
h := mkHierarchy(mod)
120+
withContainer(h, a1.ContainerID, mod.ID)
121+
122+
mb := &mock.MockBackend{
123+
IsConnectedFunc: func() bool { return true },
124+
ListAgentEditorAgentsFunc: func() ([]*agenteditor.Agent, error) { return []*agenteditor.Agent{a1}, nil },
125+
}
126+
127+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
128+
assertNoError(t, describeAgentEditorAgent(ctx, ast.QualifiedName{Module: "M", Name: "MyAgent"}))
129+
130+
out := buf.String()
131+
assertContainsStr(t, out, "CREATE AGENT")
132+
assertContainsStr(t, out, "UsageType")
133+
assertContainsStr(t, out, "Model")
134+
}
135+
136+
func TestShowAgentEditorKnowledgeBases_Mock(t *testing.T) {
137+
mod := mkModule("M")
138+
kb := &agenteditor.KnowledgeBase{
139+
BaseElement: model.BaseElement{ID: nextID("aekb")},
140+
ContainerID: mod.ID,
141+
Name: "MyKB",
142+
Provider: "MxCloudGenAI",
143+
Key: &agenteditor.ConstantRef{QualifiedName: "M.KBKey"},
144+
ModelDisplayName: "text-embedding-ada-002",
145+
}
146+
147+
h := mkHierarchy(mod)
148+
withContainer(h, kb.ContainerID, mod.ID)
149+
150+
mb := &mock.MockBackend{
151+
IsConnectedFunc: func() bool { return true },
152+
ListAgentEditorKnowledgeBasesFunc: func() ([]*agenteditor.KnowledgeBase, error) { return []*agenteditor.KnowledgeBase{kb}, nil },
153+
}
154+
155+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
156+
assertNoError(t, showAgentEditorKnowledgeBases(ctx, ""))
157+
158+
out := buf.String()
159+
assertContainsStr(t, out, "Qualified Name")
160+
assertContainsStr(t, out, "Provider")
161+
assertContainsStr(t, out, "Key Constant")
162+
assertContainsStr(t, out, "Embedding Model")
163+
assertContainsStr(t, out, "M.MyKB")
164+
assertContainsStr(t, out, "MxCloudGenAI")
165+
assertContainsStr(t, out, "M.KBKey")
166+
assertContainsStr(t, out, "text-embedding-ada-002")
167+
}
168+
169+
func TestDescribeAgentEditorKnowledgeBase_Mock(t *testing.T) {
170+
mod := mkModule("M")
171+
kb := &agenteditor.KnowledgeBase{
172+
BaseElement: model.BaseElement{ID: nextID("aekb")},
173+
ContainerID: mod.ID,
174+
Name: "MyKB",
175+
Provider: "MxCloudGenAI",
176+
Key: &agenteditor.ConstantRef{QualifiedName: "M.KBKey"},
177+
}
178+
179+
h := mkHierarchy(mod)
180+
withContainer(h, kb.ContainerID, mod.ID)
181+
182+
mb := &mock.MockBackend{
183+
IsConnectedFunc: func() bool { return true },
184+
ListAgentEditorKnowledgeBasesFunc: func() ([]*agenteditor.KnowledgeBase, error) { return []*agenteditor.KnowledgeBase{kb}, nil },
185+
}
186+
187+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
188+
assertNoError(t, describeAgentEditorKnowledgeBase(ctx, ast.QualifiedName{Module: "M", Name: "MyKB"}))
189+
190+
out := buf.String()
191+
assertContainsStr(t, out, "CREATE KNOWLEDGE BASE")
192+
assertContainsStr(t, out, "Provider")
193+
}
194+
195+
func TestShowAgentEditorConsumedMCPServices_Mock(t *testing.T) {
196+
mod := mkModule("M")
197+
svc := &agenteditor.ConsumedMCPService{
198+
BaseElement: model.BaseElement{ID: nextID("aemcp")},
199+
ContainerID: mod.ID,
200+
Name: "MySvc",
201+
ProtocolVersion: "2025-03-26",
202+
Version: "1.0.0",
203+
ConnectionTimeoutSeconds: 30,
204+
}
205+
206+
h := mkHierarchy(mod)
207+
withContainer(h, svc.ContainerID, mod.ID)
208+
209+
mb := &mock.MockBackend{
210+
IsConnectedFunc: func() bool { return true },
211+
ListAgentEditorConsumedMCPServicesFunc: func() ([]*agenteditor.ConsumedMCPService, error) { return []*agenteditor.ConsumedMCPService{svc}, nil },
212+
}
213+
214+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
215+
assertNoError(t, showAgentEditorConsumedMCPServices(ctx, ""))
216+
217+
out := buf.String()
218+
assertContainsStr(t, out, "Qualified Name")
219+
assertContainsStr(t, out, "Protocol")
220+
assertContainsStr(t, out, "Version")
221+
assertContainsStr(t, out, "Timeout")
222+
assertContainsStr(t, out, "M.MySvc")
223+
assertContainsStr(t, out, "2025-03-26")
224+
assertContainsStr(t, out, "1.0.0")
225+
}
226+
227+
func TestDescribeAgentEditorConsumedMCPService_Mock(t *testing.T) {
228+
mod := mkModule("M")
229+
svc := &agenteditor.ConsumedMCPService{
230+
BaseElement: model.BaseElement{ID: nextID("aemcp")},
231+
ContainerID: mod.ID,
232+
Name: "MySvc",
233+
ProtocolVersion: "2025-03-26",
234+
Version: "1.0.0",
235+
ConnectionTimeoutSeconds: 30,
236+
}
237+
238+
h := mkHierarchy(mod)
239+
withContainer(h, svc.ContainerID, mod.ID)
240+
241+
mb := &mock.MockBackend{
242+
IsConnectedFunc: func() bool { return true },
243+
ListAgentEditorConsumedMCPServicesFunc: func() ([]*agenteditor.ConsumedMCPService, error) { return []*agenteditor.ConsumedMCPService{svc}, nil },
244+
}
245+
246+
ctx, buf := newMockCtx(t, withBackend(mb), withHierarchy(h))
247+
assertNoError(t, describeAgentEditorConsumedMCPService(ctx, ast.QualifiedName{Module: "M", Name: "MySvc"}))
248+
249+
out := buf.String()
250+
assertContainsStr(t, out, "CREATE CONSUMED MCP SERVICE")
251+
assertContainsStr(t, out, "ProtocolVersion")
252+
}

mdl/executor/cmd_agenteditor_models.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,17 @@ func execCreateAgentEditorModel(ctx *ExecContext, s *ast.CreateModelStmt) error
159159
}
160160

161161
m := &agenteditor.Model{
162-
ContainerID: module.ID,
163-
Name: s.Name.Name,
162+
ContainerID: module.ID,
163+
Name: s.Name.Name,
164164
Documentation: s.Documentation,
165-
Provider: provider,
166-
Key: keyRef,
167-
DisplayName: s.DisplayName,
168-
KeyName: s.KeyName,
169-
KeyID: s.KeyID,
170-
Environment: s.Environment,
171-
ResourceName: s.ResourceName,
172-
DeepLinkURL: s.DeepLinkURL,
165+
Provider: provider,
166+
Key: keyRef,
167+
DisplayName: s.DisplayName,
168+
KeyName: s.KeyName,
169+
KeyID: s.KeyID,
170+
Environment: s.Environment,
171+
ResourceName: s.ResourceName,
172+
DeepLinkURL: s.DeepLinkURL,
173173
}
174174

175175
if err := ctx.Backend.CreateAgentEditorModel(m); err != nil {

0 commit comments

Comments
 (0)