Skip to content

Commit af5381b

Browse files
committed
DEV test update
1 parent 4fcc515 commit af5381b

File tree

2 files changed

+118
-89
lines changed

2 files changed

+118
-89
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`resolveExternalCreators should return a normalized module output with expected properties: normalized 1`] = `
4+
[
5+
"Tool1",
6+
{
7+
"description": "Tool 1",
8+
"inputSchema": "[object Object] isZod = true",
9+
},
10+
[MockFunction],
11+
]
12+
`;
Lines changed: 106 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,155 @@
1+
import { z } from 'zod';
12
import { resolveExternalCreators } from '../server.toolsHostCreator';
2-
import { type McpToolCreator } from '../server';
3+
import { isZodSchema } from '../server.schema';
34

4-
// Mock dependencies
5-
jest.mock('../logger', () => ({
6-
log: {
7-
warn: jest.fn(),
8-
error: jest.fn(),
9-
info: jest.fn(),
10-
debug: jest.fn()
11-
},
12-
formatUnknownError: jest.fn((error: unknown) => String(error))
13-
}));
14-
15-
// plugin-object support removed in streamlined implementation
16-
17-
// plugin-object adapters removed; tests eliminated
18-
19-
describe('resolveExternalCreators (streamlined)', () => {
5+
describe('resolveExternalCreators', () => {
206
it.each([
217
{
22-
description: 'function export returning a realized tuple (cached)',
23-
moduleExports: { default: () => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()] },
24-
expectedLength: 1
25-
},
26-
{
27-
description: 'tool creator as default export',
8+
description: 'valid format, default export with function, tuple',
289
moduleExports: {
2910
default: () => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()]
3011
},
31-
expectedLength: 1
12+
isValid: true
3213
},
3314
{
34-
description: 'array of tool creators',
35-
moduleExports: [
36-
() => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
37-
() => ['Tool2', { description: 'Tool 2', inputSchema: {} }, jest.fn()]
38-
],
39-
expectedLength: 2
15+
description: 'valid format, default export with function, array of functions with tuple return',
16+
moduleExports: {
17+
default: () => [
18+
() => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
19+
() => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()]
20+
]
21+
},
22+
isValid: true
4023
},
4124
{
42-
description: 'array of tool creators as default export',
25+
description: 'valid format, default export with array of functions with tuple return',
4326
moduleExports: {
4427
default: [
28+
() => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
4529
() => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()]
4630
]
4731
},
48-
expectedLength: 1
32+
isValid: true
33+
},
34+
{
35+
description: 'invalid format, default export with function, array of tuples',
36+
moduleExports: {
37+
default: () => [
38+
['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
39+
['Tool2', { description: 'Tool 2', inputSchema: {} }, jest.fn()]
40+
]
41+
},
42+
isValid: false
43+
},
44+
{
45+
description: 'invalid format, default export with tuple',
46+
moduleExports: {
47+
default: ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()]
48+
},
49+
isValid: false
50+
},
51+
{
52+
description: 'invalid format, default export with array of tuples',
53+
moduleExports: {
54+
default: [
55+
['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
56+
['Tool2', { description: 'Tool 2', inputSchema: {} }, jest.fn()]
57+
]
58+
},
59+
isValid: false
60+
},
61+
{
62+
description: 'invalid format, default export function that returns empty',
63+
moduleExports: {
64+
default: () => {}
65+
},
66+
isValid: false
4967
},
5068
{
51-
description: 'empty module',
69+
description: 'invalid format, empty module',
5270
moduleExports: {},
53-
expectedLength: 0
71+
isValid: false
5472
},
5573
{
56-
description: 'null',
74+
description: 'invalid format, default export function that returns null',
75+
moduleExports: {
76+
default: () => null
77+
},
78+
isValid: false
79+
},
80+
{
81+
description: 'invalid format, null',
5782
moduleExports: null,
58-
expectedLength: 0
83+
isValid: false
84+
},
85+
{
86+
description: 'invalid format, default export function that returns undefined',
87+
moduleExports: {
88+
default: () => undefined
89+
},
90+
isValid: false
5991
},
6092
{
61-
description: 'undefined',
93+
description: 'invalid format, undefined',
6294
moduleExports: undefined,
63-
expectedLength: 0
95+
isValid: false
6496
},
6597
{
66-
description: 'function that throws',
98+
description: 'invalid format, default export function that throws',
99+
moduleExports: {
100+
default: () => {
101+
throw new Error('Function error');
102+
}
103+
},
104+
isValid: false
105+
},
106+
{
107+
description: 'invalid format, function that throws',
67108
moduleExports: () => {
68109
throw new Error('Function error');
69110
},
70-
expectedLength: 0
111+
isValid: false
71112
},
72113
{
73-
description: 'function returning unsupported shape',
114+
description: 'invalid format, function returning unsupported shape',
74115
moduleExports: () => 'not a tool or creators[]',
75-
expectedLength: 0
116+
isValid: false
76117
},
77118
{
78-
description: 'array with non-function elements',
119+
description: 'invalid format, array with non-function elements',
79120
moduleExports: ['not a function', 123, {}],
80-
expectedLength: 0
121+
isValid: false
81122
},
82123
{
83-
description: 'function returning non-tuple array (should not pass)',
84-
moduleExports: () => ['not a tool tuple', 123],
85-
expectedLength: 0
124+
description: 'invalid format, named exports only',
125+
moduleExports: {
126+
named1: () => ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()],
127+
named2: () => ['Tool2', { description: 'Tool 2', inputSchema: {} }, jest.fn()]
128+
},
129+
isValid: false
86130
}
87-
])('should normalize module exports, $description', ({ moduleExports, expectedLength }) => {
131+
])('should normalize module exports with specific formats, $description', ({ moduleExports, isValid }) => {
88132
const result = resolveExternalCreators(moduleExports);
89133

90134
expect(Array.isArray(result)).toBe(true);
91-
expect(result.length).toBe(expectedLength);
92-
if (expectedLength > 0) {
93-
expect(typeof result[0]).toBe('function');
94-
}
95-
});
96-
97-
it('should handle multiple candidates (default and named)', () => {
98-
const defaultTuple = ['Tool1', { description: 'Tool 1', inputSchema: {} }, jest.fn()] as const;
99-
const moduleExports = {
100-
default: () => defaultTuple,
101-
named: 'not a creator'
102-
} as any;
103-
104-
const result = resolveExternalCreators(moduleExports);
105-
106-
// Should use default export and wrap cached tuple
107-
expect(result.length).toBe(1);
108-
expect(typeof result[0]).toBe('function');
109-
expect((result[0] as any).toolName).toBe('Tool1');
110-
expect(result[0]!()).toBe(defaultTuple);
111-
});
112-
113-
it('should prefer default export over named export', () => {
114-
const defaultTuple = ['DefaultTool', { description: 'Default', inputSchema: {} }, jest.fn()] as const;
115-
const namedCreator: McpToolCreator = () => ['NamedTool', { description: 'Named', inputSchema: {} }, jest.fn()];
116-
117-
const moduleExports = {
118-
default: () => defaultTuple,
119-
named: namedCreator
120-
} as any;
121-
122-
const result = resolveExternalCreators(moduleExports);
123-
124-
expect(result.length).toBe(1);
125-
expect(typeof result[0]).toBe('function');
126-
expect(result[0]!()).toBe(defaultTuple);
135+
expect(result.length > 0).toBe(isValid);
127136
});
128137

129-
it('should handle function export that throws during invocation', () => {
130-
const moduleExports = () => {
131-
throw new Error('Factory error');
138+
it('should return a normalized module output with expected properties', () => {
139+
const moduleExport = {
140+
default: () => ['Tool1', { description: 'Tool 1', inputSchema: z.any() }, jest.fn()]
132141
};
133142

134-
const result = resolveExternalCreators(moduleExports);
143+
const [result] = resolveExternalCreators(moduleExport);
144+
const [name, schema = {}, handler]: any[] = result?.() || [];
135145

136-
expect(result.length).toBe(0);
146+
expect([
147+
name,
148+
{
149+
description: schema.description,
150+
inputSchema: `${schema} isZod = ${isZodSchema(schema.inputSchema)}`
151+
},
152+
handler
153+
]).toMatchSnapshot('normalized');
137154
});
138155
});

0 commit comments

Comments
 (0)