jest.mock('../src/webshare', () => { const instances = []; class WebshareClient { constructor(username, password) { this.username = username; this.password = password; this.guest = !username || !password; this.ensureAuth = jest.fn(async () => {}); this.search = jest.fn(async () => []); this.getFileLink = jest.fn(async () => 'https://cdn.example/file'); instances.push(this); } } WebshareClient._instances = instances; return { WebshareClient }; }); const { WebshareClient } = require('../src/webshare'); const { formatSize, createWebshareMcpServer } = require('../src/mcp-server'); function lastClient() { return WebshareClient._instances[WebshareClient._instances.length - 1]; } describe('formatSize', () => { it('handles non-finite and large units', () => { expect(formatSize(NaN)).toBe('0 B'); expect(formatSize(-1)).toBe('0 B'); expect(formatSize(1024 ** 3)).toBe('1.0 GB'); expect(formatSize(1024 ** 4)).toBe('1.0 TB'); expect(formatSize(512)).toBe('512 B'); }); }); describe('MCP tool handlers', () => { beforeEach(() => { WebshareClient._instances.length = 0; }); it('webshare_search formats hits and empty results', async () => { const server = createWebshareMcpServer({ username: 'u', password: 'p' }); const handler = server._registeredTools.webshare_search.handler; const client = lastClient(); client.search.mockResolvedValueOnce([]); let out = await handler({ query: 'nope' }); expect(out.content[0].text).toMatch(/No results/); expect(out.structuredContent.count).toBe(0); client.search.mockResolvedValueOnce([ { name: 'Movie.mkv', ident: 'abc', size: 2048, votes: 3 }, ]); out = await handler({ query: 'movie', limit: 10, offset: 0, sort: 'recent', category: 'video' }); expect(out.content[0].text).toMatch(/Found 1 result/); expect(out.content[0].text).toMatch(/ident: abc/); expect(out.structuredContent.results[0].ident).toBe('abc'); }); it('webshare_search returns isError on failure', async () => { const server = createWebshareMcpServer({ username: 'u', password: 'p' }); const handler = server._registeredTools.webshare_search.handler; lastClient().ensureAuth.mockRejectedValueOnce(new Error('auth down')); const out = await handler({ query: 'x' }); expect(out.isError).toBe(true); expect(out.content[0].text).toMatch(/webshare_search failed/); }); it('webshare_get_link resolves and surfaces errors', async () => { const server = createWebshareMcpServer({ username: 'u', password: 'p' }); const handler = server._registeredTools.webshare_get_link.handler; const client = lastClient(); let out = await handler({ ident: 'id1' }); expect(out.structuredContent.link).toBe('https://cdn.example/file'); expect(out.content[0].text).toMatch(/Resolved link/); client.getFileLink.mockRejectedValueOnce(new Error('gone')); out = await handler({ ident: 'id2' }); expect(out.isError).toBe(true); expect(out.content[0].text).toMatch(/webshare_get_link failed/); }); it('webshare_login_check guest / auth / error paths', async () => { let server = createWebshareMcpServer({}); let handler = server._registeredTools.webshare_login_check.handler; let out = await handler({}); expect(out.structuredContent.guest).toBe(true); expect(out.content[0].text).toMatch(/guest mode/i); server = createWebshareMcpServer({ username: 'u', password: 'p' }); handler = server._registeredTools.webshare_login_check.handler; out = await handler({}); expect(out.structuredContent).toEqual({ ok: true, guest: false }); lastClient().ensureAuth.mockRejectedValueOnce(new Error('bad creds')); out = await handler({}); expect(out.isError).toBe(true); expect(out.structuredContent.ok).toBe(false); }); });