Skip to main content
Glama

News Aggregator API

simple-news.test.ts6.23 kB
/** * Super simplified controller tests with minimal dependencies * * This file demonstrates best practices for testing controllers: * - Proper TypeScript type handling * - Consistent setup/teardown * - Focused unit testing of controller logic * - Simple, maintainable mocking approach */ import { describe, test, expect, jest, beforeEach, afterEach } from '@jest/globals'; import { Request, Response } from 'express'; // Define types for our mocks to avoid TypeScript errors type MockResponse = { status: jest.Mock; json: jest.Mock; }; // Create mock implementations that we'll use throughout the tests const mockGetTopNews = jest.fn(); const mockGetNewsByUuid = jest.fn(); // Mock the entire news service jest.mock('../../services/news.service', () => { return { NewsService: jest.fn().mockImplementation(() => ({ getTopNews: mockGetTopNews, getNewsByUuid: mockGetNewsByUuid })) }; }); // Mock the cache service to avoid side effects jest.mock('../../utils/cache', () => ({ cacheService: { get: jest.fn(), set: jest.fn(), clear: jest.fn(), getStats: jest.fn().mockReturnValue({ hits: 0, misses: 0, keys: 0 }) } })); // Import the controller after mocking import { NewsController } from '../../controllers/news.controller'; describe('NewsController - Minimal Tests', () => { // Test subjects let controller: NewsController; let req: Partial<Request>; let res: MockResponse; // Setup before each test beforeEach(() => { // Reset all mocks jest.clearAllMocks(); mockGetTopNews.mockReset(); mockGetNewsByUuid.mockReset(); // Create a fresh controller for each test controller = new NewsController(); // Setup basic mock request with all required query parameters req = { query: { // Initialize all query parameters expected by the NewsController.getTopNews method search: undefined, search_fields: undefined, locale: undefined, categories: undefined, exclude_categories: undefined, domains: undefined, exclude_domains: undefined, source_ids: undefined, exclude_source_ids: undefined, language: undefined, published_before: undefined, published_after: undefined, limit: undefined, page: undefined, sort: undefined }, params: {} }; // Setup response with properly typed mocks res = { status: jest.fn().mockReturnThis(), json: jest.fn() } as unknown as MockResponse; }); // Clean up after each test afterEach(() => { jest.clearAllMocks(); }); describe('getTopNews', () => { test('returns successful response with 200 status', async () => { // Arrange - Set up mock to return successful response const mockData = { data: [{ title: 'Test Article', uuid: 'test-123' }], meta: { found: 1, returned: 1 } }; mockGetTopNews.mockResolvedValue(mockData); // Act - Call the controller method await controller.getTopNews(req as Request, res as unknown as Response); // Assert - Verify correct response expect(mockGetTopNews).toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ success: true, data: expect.any(Array) })); }); test('handles API errors with 500 status', async () => { // Arrange - Force service error mockGetTopNews.mockRejectedValue(new Error('API error')); // Act - Call the controller method await controller.getTopNews(req as Request, res as unknown as Response); // Assert - Verify error handling expect(res.status).toHaveBeenCalledWith(500); expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ success: false, error: expect.any(String) })); }); test('passes query parameters to service', async () => { // Arrange - Set up request with query params req.query = { categories: 'technology', limit: '10' }; mockGetTopNews.mockResolvedValue({ data: [], meta: { found: 0, returned: 0 } }); // Act - Call the controller method await controller.getTopNews(req as Request, res as unknown as Response); // Assert - Verify params were passed // Note: the controller converts string values to appropriate types expect(mockGetTopNews).toHaveBeenCalledWith( expect.objectContaining({ categories: 'technology', limit: 10 // Number conversion }) ); }); }); describe('getNewsByUuid', () => { test('returns article with 200 status when found', async () => { // Arrange - Set up mock with UUID and data const uuid = 'test-uuid-123'; req.params = { uuid }; mockGetNewsByUuid.mockResolvedValue({ data: { uuid, title: 'Test Article' } }); // Act - Call the controller method await controller.getNewsByUuid(req as Request, res as unknown as Response); // Assert - Verify correct response expect(mockGetNewsByUuid).toHaveBeenCalledWith(uuid); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ success: true, data: expect.objectContaining({ uuid }) })); }); test('returns 404 status when article not found', async () => { // Arrange - Set up mock to simulate not found const uuid = 'not-found-uuid'; req.params = { uuid }; mockGetNewsByUuid.mockRejectedValue(new Error('Article not found')); // Act - Call the controller method await controller.getNewsByUuid(req as Request, res as unknown as Response); // Assert - Verify 404 response expect(mockGetNewsByUuid).toHaveBeenCalledWith(uuid); expect(res.status).toHaveBeenCalledWith(404); expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ success: false, error: expect.any(String) })); }); }); });

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