news-minimal.test.ts•6.27 kB
/**
* Minimal, isolated tests for News API routes
* This approach directly tests the route handlers without starting a server
*/
import { describe, test, expect, beforeEach, jest } from '@jest/globals';
import { Request, Response } from 'express';
import { cacheService } from '../../utils/cache';
// Mock article data for consistent testing
const MOCK_ARTICLES = [
{
id: 1,
uuid: 'test-uuid-1',
title: 'Test Article 1',
description: 'Test description 1',
content: 'Test content 1',
url: 'http://example.com/1',
image_url: 'http://example.com/image1.jpg',
source: 'Test Source',
categories: ['general'],
published_at: new Date().toISOString(),
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 2,
uuid: 'test-uuid-2',
title: 'Test Article 2',
description: 'Test description 2',
content: 'Test content 2',
url: 'http://example.com/2',
image_url: 'http://example.com/image2.jpg',
source: 'Test Source',
categories: ['technology'],
published_at: new Date().toISOString(),
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
];
// Mock database
jest.mock('../../utils/db', () => {
return {
prisma: {
article: {
findMany: jest.fn().mockResolvedValue(MOCK_ARTICLES),
findUnique: jest.fn().mockImplementation((args: any) => {
const uuid = args?.where?.uuid;
const article = MOCK_ARTICLES.find(a => a.uuid === uuid);
return Promise.resolve(article || null);
}),
count: jest.fn().mockResolvedValue(MOCK_ARTICLES.length)
}
}
};
});
// Import controller class
import { NewsController } from '../../controllers/news.controller';
describe('News Controllers', () => {
// Create a controller instance for each test
let newsController: NewsController;
beforeEach(() => {
cacheService.clear();
jest.clearAllMocks();
// Create a fresh controller instance for each test
newsController = new NewsController();
});
// Test getTopNews controller
test('getTopNews should return top news articles', async () => {
// Create mock request and response
const req = {
query: {}
} as unknown as Request;
const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;
// Call controller method
await newsController.getTopNews(req, res);
// Verify response
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith({
success: true,
data: expect.any(Array)
});
// Type assertion for the mock
const mockJson = res.json as jest.Mock;
// Verify articles in response
const call = mockJson.mock.calls[0][0];
expect(call.success).toBe(true);
expect(Array.isArray(call.data)).toBe(true);
expect(call.data.length).toBeGreaterThan(0);
});
// Test getTopNews with category
test('getTopNews should filter by category', async () => {
// Create mock request with category
const req = {
query: { categories: 'technology' }
} as unknown as Request;
const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;
// Call controller method
await newsController.getTopNews(req, res);
// Verify response
expect(res.status).toHaveBeenCalledWith(200);
// Type assertion for the mock
const mockJson = res.json as jest.Mock;
// Check basic structure
const call = mockJson.mock.calls[0][0];
expect(call.success).toBe(true);
expect(Array.isArray(call.data)).toBe(true);
});
// Test getAllNews with pagination
test('getAllNews should return paginated articles', async () => {
// Create mock request with pagination
const req = {
query: { page: '1', limit: '10' }
} as unknown as Request;
const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;
// Call controller method
await newsController.getAllNews(req, res);
// Verify response
expect(res.status).toHaveBeenCalledWith(200);
// Type assertion for the mock
const mockJson = res.json as jest.Mock;
// Check structure and pagination
const call = mockJson.mock.calls[0][0];
expect(call.success).toBe(true);
expect(Array.isArray(call.data)).toBe(true);
expect(call.meta).toBeDefined();
expect(call.meta.page).toBeDefined();
expect(call.meta.limit).toBeDefined();
expect(call.meta.total).toBeDefined();
});
// Test getNewsByUuid for existing article
test('getNewsByUuid should return a specific article', async () => {
// Create mock request with UUID
const req = {
params: { uuid: 'test-uuid-1' }
} as unknown as Request;
const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;
// Call controller method
await newsController.getNewsByUuid(req, res);
// Verify response
expect(res.status).toHaveBeenCalledWith(200);
// Type assertion for the mock
const mockJson = res.json as jest.Mock;
// Check article data
const call = mockJson.mock.calls[0][0];
expect(call.success).toBe(true);
expect(call.data).toBeDefined();
expect(call.data.uuid).toBe('test-uuid-1');
});
// Test getNewsByUuid for non-existent article
test('getNewsByUuid should return 404 for non-existent article', async () => {
// Create mock request with non-existent UUID
const req = {
params: { uuid: 'non-existent-uuid' }
} as unknown as Request;
const res = {
status: jest.fn().mockReturnThis(),
json: jest.fn()
} as unknown as Response;
// Call controller method
await newsController.getNewsByUuid(req, res);
// Verify 404 response
expect(res.status).toHaveBeenCalledWith(404);
// Type assertion for the mock
const mockJson = res.json as jest.Mock;
// Check error message
const call = mockJson.mock.calls[0][0];
expect(call.success).toBe(false);
expect(call.error).toBeDefined();
});
});