Skip to main content
Glama

News Aggregator API

cache-controller.test.ts6.3 kB
/** * Cache Routes Controller Tests * * Testing the cache management routes with proper isolation and TypeScript type safety */ import { describe, test, expect, beforeEach, afterEach, jest } from '@jest/globals'; import { Request, Response, NextFunction } from 'express'; import * as cacheModule from '../../utils/cache'; // Create properly typed mock objects type MockRequest = Partial<Request>; type MockResponse = Partial<Response> & { status: jest.Mock; json: jest.Mock; }; // Mock the cache service jest.mock('../../utils/cache', () => ({ cacheService: { getStats: jest.fn(), clear: jest.fn(), deleteByPrefix: jest.fn() } })); // Import cache routes module import cacheRoutes from '../../routes/cache.routes'; describe('Cache Routes', () => { let req: MockRequest; let res: MockResponse; let next: jest.Mock; beforeEach(() => { // Reset mocks jest.clearAllMocks(); // Setup request, response, and next function req = { params: {}, query: {} }; res = { status: jest.fn().mockReturnThis(), json: jest.fn() }; next = jest.fn(); }); afterEach(() => { jest.clearAllMocks(); }); describe('GET /stats', () => { test('returns cache statistics', () => { // Arrange const mockStats = { hits: 10, misses: 5, keys: 15 }; (cacheModule.cacheService.getStats as jest.Mock).mockReturnValue(mockStats); // Extract the route handler const router = Router(); let routeHandler: Function = () => {}; // Capture the handler when registered router.get = jest.fn().mockImplementation((path: string, handler: Function) => { if (path === '/stats') { routeHandler = handler; } return router; }); // Apply routes to our mocked router cacheRoutes(router); // Act - call the handler directly routeHandler(req as Request, res as Response); // Assert expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ success: true, data: mockStats }); }); test('handles errors', () => { // Arrange (cacheModule.cacheService.getStats as jest.Mock).mockImplementation(() => { throw new Error('Cache error'); }); // Extract the route handler const router = Router(); let routeHandler: Function = () => {}; // Capture the handler when registered router.get = jest.fn().mockImplementation((path: string, handler: Function) => { if (path === '/stats') { routeHandler = handler; } return router; }); // Apply routes to our mocked router cacheRoutes(router); // Act - call the handler directly routeHandler(req as Request, res as Response); // Assert expect(res.status).toHaveBeenCalledWith(500); expect(res.json).toHaveBeenCalledWith({ success: false, error: expect.stringContaining('Cache error') }); }); }); describe('DELETE /clear', () => { test('clears all cache entries', () => { // Arrange (cacheModule.cacheService.clear as jest.Mock).mockReturnValue(15); // 15 entries cleared // Extract the route handler const router = Router(); let routeHandler: Function = () => {}; // Capture the handler when registered router.delete = jest.fn().mockImplementation((path: string, handler: Function) => { if (path === '/clear') { routeHandler = handler; } return router; }); // Apply routes to our mocked router cacheRoutes(router); // Act - call the handler directly routeHandler(req as Request, res as Response); // Assert expect(cacheModule.cacheService.clear).toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ success: true, message: expect.stringContaining('cleared'), count: 15 }); }); }); describe('DELETE /clear/:type', () => { test('clears cache entries by prefix', () => { // Arrange (cacheModule.cacheService.deleteByPrefix as jest.Mock).mockReturnValue(5); // 5 entries cleared req.params = { type: 'news' }; // Extract the route handler const router = Router(); let routeHandler: Function = () => {}; // Capture the handler when registered router.delete = jest.fn().mockImplementation((path: string, handler: Function) => { if (path === '/clear/:type') { routeHandler = handler; } return router; }); // Apply routes to our mocked router cacheRoutes(router); // Act - call the handler directly routeHandler(req as Request, res as Response); // Assert expect(cacheModule.cacheService.deleteByPrefix).toHaveBeenCalledWith('news'); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith({ success: true, message: expect.stringContaining('news'), count: 5 }); }); test('handles invalid cache type', () => { // Arrange req.params = { type: 'invalid#type' }; // Extract the route handler const router = Router(); let routeHandler: Function = () => {}; // Capture the handler when registered router.delete = jest.fn().mockImplementation((path: string, handler: Function) => { if (path === '/clear/:type') { routeHandler = handler; } return router; }); // Apply routes to our mocked router cacheRoutes(router); // Act - call the handler directly routeHandler(req as Request, res as Response); // Assert expect(cacheModule.cacheService.deleteByPrefix).not.toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(400); expect(res.json).toHaveBeenCalledWith({ success: false, error: expect.stringContaining('Invalid') }); }); }); });

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/Malachi-devel/the-news-api-mcp-server'

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