Skip to main content
Glama

Node Code Sandbox MCP

by mozicim
getDependencyTypes.test.ts6.5 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import type { Mock } from 'vitest'; import { z } from 'zod'; import getDependencyTypes, { argSchema, } from '../src/tools/getDependencyTypes.ts'; import type { McpContentText } from '../src/types.ts'; // Schema validation tests describe('argSchema', () => { it('should accept valid dependencies array with version', () => { const input = { dependencies: [{ name: 'foo', version: '1.2.3' }] }; const parsed = z.object(argSchema).parse(input); expect(parsed).toEqual(input); }); it('should accept valid dependencies array without version', () => { const input = { dependencies: [{ name: 'bar' }] }; const parsed = z.object(argSchema).parse(input); expect(parsed).toEqual({ dependencies: [{ name: 'bar', version: undefined }], }); }); it('should reject when dependencies is missing', () => { expect(() => z.object(argSchema).parse({} as any)).toThrow(); }); }); // Tool behavior tests describe('getDependencyTypes', () => { beforeEach(() => { // Stub global.fetch vi.stubGlobal('fetch', vi.fn()); }); afterEach(() => { vi.unstubAllGlobals(); }); it('should return in-package types when available', async () => { // Mock registry metadata fetch (fetch as Mock).mockImplementation((url: string) => { if (url === 'https://registry.npmjs.org/foo') { return Promise.resolve({ ok: true, json: async () => ({ 'dist-tags': { latest: '1.0.0' }, versions: { '1.0.0': { types: 'index.d.ts' } }, }), }); } if (url === 'https://unpkg.com/foo@1.0.0/index.d.ts') { return Promise.resolve({ ok: true, text: async () => '/* foo types */', }); } return Promise.resolve({ ok: false }); }); const response = await getDependencyTypes({ dependencies: [{ name: 'foo' }], }); // Verify structure expect(response.content).toHaveLength(1); const item = response.content[0] as McpContentText; expect(item.type).toBe('text'); const parsed = JSON.parse(item.text) as any[]; expect(parsed).toEqual([ { name: 'foo', hasTypes: true, types: '/* foo types */', version: '1.0.0', }, ]); }); it('should fallback to @types package when in-package types are missing', async () => { (fetch as Mock).mockImplementation((url: string) => { if (url === 'https://registry.npmjs.org/bar') { return Promise.resolve({ ok: true, json: async () => ({ 'dist-tags': { latest: '2.0.0' }, versions: { '2.0.0': {} }, }), }); } if (url === 'https://registry.npmjs.org/%40types%2Fbar') { return Promise.resolve({ ok: true, json: async () => ({ 'dist-tags': { latest: '3.1.4' }, versions: { '3.1.4': { typings: 'index.d.ts' } }, }), }); } if (url === 'https://unpkg.com/@types/bar@3.1.4/index.d.ts') { return Promise.resolve({ ok: true, text: async () => '/* bar external types */', }); } return Promise.resolve({ ok: false }); }); const response = await getDependencyTypes({ dependencies: [{ name: 'bar' }], }); expect(response.content).toHaveLength(1); const item = response.content[0] as McpContentText; expect(item.type).toBe('text'); const parsed = JSON.parse(item.text) as any[]; expect(parsed).toEqual([ { name: 'bar', hasTypes: true, types: '/* bar external types */', typesPackage: '@types/bar', version: '3.1.4', }, ]); }); it('should return hasTypes false when no types are available', async () => { (fetch as Mock).mockImplementation((url: string) => { if (url.startsWith('https://registry.npmjs.org/')) { return Promise.resolve({ ok: true, json: async () => ({ 'dist-tags': { latest: '0.1.0' }, versions: { '0.1.0': {} }, }), }); } // @types lookup fails return Promise.resolve({ ok: false }); }); const response = await getDependencyTypes({ dependencies: [{ name: 'baz' }], }); const item = response.content[0] as McpContentText; const parsed = JSON.parse(item.text) as any[]; expect(parsed).toEqual([{ name: 'baz', hasTypes: false }]); }); it('should handle fetch errors gracefully', async () => { (fetch as Mock).mockImplementation(() => { throw new Error('Network failure'); }); const response = await getDependencyTypes({ dependencies: [{ name: 'qux' }], }); const item = response.content[0] as McpContentText; const parsed = JSON.parse(item.text) as any[]; expect(parsed).toEqual([{ name: 'qux', hasTypes: false }]); }); }); describe('getDependencyTypes integration test', () => { it('should fetch real types for dayjs', async () => { // Restore real fetch to allow network requests vi.restoreAllMocks(); const response = await getDependencyTypes({ dependencies: [{ name: 'dayjs', version: '1.11.7' }], }); expect(response.content).toHaveLength(1); const item = response.content[0] as McpContentText; expect(item.type).toBe('text'); const parsed = JSON.parse(item.text) as any[]; expect(parsed[0].name).toBe('dayjs'); expect(parsed[0].hasTypes).toBe(true); expect(parsed[0].types).toBeDefined(); expect(parsed[0].types.length).toBeGreaterThan(0); expect(parsed[0].version).toBe('1.11.7'); }, 15_000); it('should fetch external types from @types for express', async () => { // Restore real fetch to allow network requests vi.restoreAllMocks(); const response = await getDependencyTypes({ dependencies: [{ name: 'express', version: '4.17.1' }], }); expect(response.content).toHaveLength(1); const item = response.content[0] as McpContentText; expect(item.type).toBe('text'); const parsed = JSON.parse(item.text) as any[]; expect(parsed[0].name).toBe('express'); expect(parsed[0].hasTypes).toBe(true); expect(parsed[0].typesPackage).toBe('@types/express'); expect(parsed[0].types).toBeDefined(); expect(parsed[0].types.length).toBeGreaterThan(0); expect(typeof parsed[0].version).toBe('string'); }, 15_000); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mozicim/node-code-sandbox-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server