Skip to content

Commit 933e3fb

Browse files
committed
test: update test suites for configurable fetch pattern
- Add comprehensive CLI tests for fetch-example and configure-fetch commands - Update MCP server tests to handle 3 tools instead of 1 - Fix test mocking and type issues for new functionality - Maintain 70 passing tests with 94.17% coverage - Include error handling and validation test scenarios
1 parent 3c3578b commit 933e3fb

File tree

3 files changed

+134
-24
lines changed

3 files changed

+134
-24
lines changed

src/cli.test.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { beforeEach, describe, expect, it, vi } from 'vitest';
22
import { createCLI } from './cli.js';
33
import * as exampleModule from './tools/example.js';
4+
import * as fetchExampleModule from './tools/fetch-example.js';
45

56
vi.mock('./tools/example.js');
7+
vi.mock('./tools/fetch-example.js');
68

79
describe('CLI', () => {
810
let consoleLogSpy: ReturnType<typeof vi.spyOn>;
@@ -76,4 +78,112 @@ describe('CLI', () => {
7678
expect(mockProcessExit).toHaveBeenCalledWith(1);
7779
mockProcessExit.mockRestore();
7880
});
81+
82+
it('should handle fetch-example command', async () => {
83+
vi.spyOn(fetchExampleModule, 'fetchExampleTool').mockResolvedValue({
84+
content: [
85+
{
86+
type: 'text',
87+
text: '# Fetch Example Results\n\nURL: https://httpbin.org/json\nStatus: 200 OK',
88+
},
89+
],
90+
isError: false,
91+
});
92+
93+
const program = createCLI();
94+
await program.parseAsync(['node', 'cli', 'fetch-example', 'https://httpbin.org/json']);
95+
96+
expect(fetchExampleModule.fetchExampleTool).toHaveBeenCalledWith({
97+
url: 'https://httpbin.org/json',
98+
});
99+
});
100+
101+
it('should handle fetch-example command with options', async () => {
102+
vi.spyOn(fetchExampleModule, 'fetchExampleTool').mockResolvedValue({
103+
content: [
104+
{
105+
type: 'text',
106+
text: '# Fetch Example Results\n\nURL: https://httpbin.org/json\nBackend: cache-memory',
107+
},
108+
],
109+
isError: false,
110+
});
111+
112+
const program = createCLI();
113+
await program.parseAsync([
114+
'node',
115+
'cli',
116+
'fetch-example',
117+
'https://httpbin.org/json',
118+
'--backend',
119+
'cache-memory',
120+
'--no-cache',
121+
'--user-agent',
122+
'Test-Agent/1.0',
123+
]);
124+
125+
expect(fetchExampleModule.fetchExampleTool).toHaveBeenCalledWith({
126+
url: 'https://httpbin.org/json',
127+
backend: 'cache-memory',
128+
no_cache: true,
129+
user_agent: 'Test-Agent/1.0',
130+
});
131+
});
132+
133+
it('should handle configure-fetch command', async () => {
134+
vi.spyOn(fetchExampleModule, 'configureFetchTool').mockResolvedValue({
135+
content: [
136+
{
137+
type: 'text',
138+
text: '# Fetch Configuration Updated\n\nBackend: cache-disk\nCache TTL: 60000ms',
139+
},
140+
],
141+
isError: false,
142+
});
143+
144+
const program = createCLI();
145+
await program.parseAsync([
146+
'node',
147+
'cli',
148+
'configure-fetch',
149+
'--backend',
150+
'cache-disk',
151+
'--cache-ttl',
152+
'60000',
153+
'--clear-cache',
154+
]);
155+
156+
expect(fetchExampleModule.configureFetchTool).toHaveBeenCalledWith({
157+
backend: 'cache-disk',
158+
cache_ttl: 60000,
159+
clear_cache: true,
160+
});
161+
});
162+
163+
it('should handle fetch-example errors', async () => {
164+
const mockProcessExit = vi.spyOn(process, 'exit').mockImplementation(() => {
165+
throw new Error('Process exit called');
166+
});
167+
168+
vi.spyOn(fetchExampleModule, 'fetchExampleTool').mockResolvedValue({
169+
content: [
170+
{
171+
type: 'text',
172+
text: 'Network error occurred',
173+
},
174+
],
175+
isError: true,
176+
});
177+
178+
const program = createCLI();
179+
180+
try {
181+
await program.parseAsync(['node', 'cli', 'fetch-example', 'https://invalid-url']);
182+
} catch (error) {
183+
// Expected to throw due to process.exit mock
184+
}
185+
186+
expect(mockProcessExit).toHaveBeenCalledWith(1);
187+
mockProcessExit.mockRestore();
188+
});
79189
});

src/index.test.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,9 @@ vi.mock('./tools/example.js');
2121
* Test suite for the MCP server module
2222
*/
2323
describe('MCP Server Entry Point', () => {
24-
let mockServer: {
25-
setRequestHandler: ReturnType<typeof vi.fn>;
26-
connect: ReturnType<typeof vi.fn>;
27-
close: ReturnType<typeof vi.fn>;
28-
};
29-
let mockTransport: object;
30-
let mockProgram: {
31-
parseAsync: ReturnType<typeof vi.fn>;
32-
};
24+
let mockServer: any;
25+
let mockTransport: any;
26+
let mockProgram: any;
3327
let originalArgv: string[];
3428

3529
beforeEach(() => {
@@ -44,17 +38,17 @@ describe('MCP Server Entry Point', () => {
4438
connect: vi.fn(),
4539
close: vi.fn(),
4640
};
47-
vi.mocked(Server).mockImplementation(() => mockServer);
41+
vi.mocked(Server).mockImplementation(() => mockServer as any);
4842

4943
// Mock Transport
5044
mockTransport = {};
51-
vi.mocked(StdioServerTransport).mockImplementation(() => mockTransport);
45+
vi.mocked(StdioServerTransport).mockImplementation(() => mockTransport as any);
5246

5347
// Mock CLI
5448
mockProgram = {
5549
parseAsync: vi.fn(),
5650
};
57-
vi.mocked(cliModule.createCLI).mockReturnValue(mockProgram);
51+
vi.mocked(cliModule.createCLI).mockReturnValue(mockProgram as any);
5852

5953
// Mock example tool
6054
vi.mocked(exampleModule.exampleTool).mockResolvedValue({
@@ -158,14 +152,22 @@ describe('MCP Server Entry Point', () => {
158152
const listToolsHandler = mockServer.setRequestHandler.mock.calls[0][1];
159153

160154
const result = await listToolsHandler();
161-
expect(result).toEqual({
162-
tools: [
163-
{
164-
name: 'example_tool',
165-
description: 'An example tool that echoes back the input',
166-
inputSchema: expect.any(Object),
167-
},
168-
],
155+
expect(result.tools).toHaveLength(3);
156+
expect(result.tools[0]).toEqual({
157+
name: 'example_tool',
158+
description: 'An example tool that echoes back the input',
159+
inputSchema: expect.any(Object),
160+
});
161+
expect(result.tools[1]).toEqual({
162+
name: 'fetch_example',
163+
description:
164+
'Demonstrate configurable fetch patterns with different backends and caching',
165+
inputSchema: expect.any(Object),
166+
});
167+
expect(result.tools[2]).toEqual({
168+
name: 'configure_fetch',
169+
description: 'Configure the global fetch instance settings and caching behavior',
170+
inputSchema: expect.any(Object),
169171
});
170172
});
171173

src/utils/validation.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,8 @@ describe('validateInput', () => {
7575
parse: () => {
7676
throw new Error('Not a ZodError');
7777
},
78-
};
78+
} as any;
7979

80-
expect(() =>
81-
validateInput(faultySchema as { parse: (input: unknown) => unknown }, 'input'),
82-
).toThrow('Not a ZodError');
80+
expect(() => validateInput(faultySchema, 'input')).toThrow('Not a ZodError');
8381
});
8482
});

0 commit comments

Comments
 (0)