279 lines
7.4 KiB
TypeScript
279 lines
7.4 KiB
TypeScript
import express from 'express';
|
|
import request from 'supertest';
|
|
|
|
import { getPrismaClient } from '../config/database.config';
|
|
import { createRouter } from '../routes';
|
|
|
|
// EN: Mock getPrismaClient to return the mocked prisma client
|
|
// VI: Mock getPrismaClient để trả về mocked prisma client
|
|
jest.mocked(getPrismaClient).mockReturnValue(prisma);
|
|
|
|
// EN: Mock external dependencies for E2E tests
|
|
// VI: Mock dependencies bên ngoài cho E2E tests
|
|
jest.mock('../config/database.config', () => ({
|
|
connectDatabase: jest.fn().mockResolvedValue(undefined),
|
|
getPrismaClient: jest.fn().mockReturnValue({
|
|
$queryRaw: jest.fn().mockResolvedValue([{ '1': 1 }]),
|
|
$disconnect: jest.fn().mockResolvedValue(undefined),
|
|
feature: {
|
|
create: jest.fn(),
|
|
findMany: jest.fn(),
|
|
findUnique: jest.fn(),
|
|
update: jest.fn(),
|
|
delete: jest.fn(),
|
|
},
|
|
}),
|
|
prisma: {
|
|
$queryRaw: jest.fn().mockResolvedValue([{ '1': 1 }]),
|
|
$disconnect: jest.fn().mockResolvedValue(undefined),
|
|
feature: {
|
|
create: jest.fn(),
|
|
findMany: jest.fn(),
|
|
findUnique: jest.fn(),
|
|
update: jest.fn(),
|
|
delete: jest.fn(),
|
|
},
|
|
},
|
|
}));
|
|
|
|
// EN: Set up mock implementations for E2E tests
|
|
// VI: Thiết lập implementations mock cho E2E tests
|
|
import { prisma } from '../config/database.config';
|
|
|
|
// EN: Use jest.mocked to properly type the mock
|
|
// VI: Sử dụng jest.mocked để type mock đúng cách
|
|
const mockPrisma = jest.mocked(prisma);
|
|
|
|
// EN: Mock successful feature creation for E2E
|
|
// VI: Mock việc tạo feature thành công cho E2E
|
|
mockPrisma.feature.create.mockResolvedValue({
|
|
id: 'e2e-test-feature-id',
|
|
name: 'test-feature',
|
|
title: 'Test Feature',
|
|
description: 'A test feature for E2E testing',
|
|
config: {},
|
|
enabled: true,
|
|
version: '1.0.0',
|
|
tags: [],
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
|
|
// EN: Mock other feature operations
|
|
// VI: Mock các operations feature khác
|
|
mockPrisma.feature.findMany.mockResolvedValue([]);
|
|
mockPrisma.feature.findUnique.mockResolvedValue(null);
|
|
mockPrisma.feature.update.mockResolvedValue({
|
|
id: 'e2e-test-feature-id',
|
|
name: 'test-feature',
|
|
title: 'Updated Feature',
|
|
description: 'Updated description',
|
|
config: {},
|
|
enabled: true,
|
|
version: '1.0.0',
|
|
tags: [],
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
mockPrisma.feature.delete.mockResolvedValue({
|
|
id: 'e2e-test-feature-id',
|
|
name: 'test-feature',
|
|
title: 'Test Feature',
|
|
description: 'A test feature for E2E testing',
|
|
config: {},
|
|
enabled: true,
|
|
version: '1.0.0',
|
|
tags: [],
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
|
|
jest.mock('../config/redis.config', () => ({
|
|
getRedisClient: jest.fn().mockReturnValue({
|
|
call: jest.fn(),
|
|
}),
|
|
}));
|
|
|
|
jest.mock('../config/app.config', () => ({
|
|
appConfig: {
|
|
port: 3001,
|
|
nodeEnv: 'test',
|
|
corsOrigin: '*',
|
|
},
|
|
}));
|
|
|
|
jest.mock('@goodgo/logger', () => ({
|
|
logger: {
|
|
info: jest.fn(),
|
|
error: jest.fn(),
|
|
warn: jest.fn(),
|
|
debug: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('@goodgo/auth-sdk', () => ({
|
|
verifyToken: jest.fn(),
|
|
decodeToken: jest.fn(),
|
|
createToken: jest.fn(),
|
|
extractTokenFromHeader: jest.fn(),
|
|
isTokenExpired: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('@goodgo/logger', () => ({
|
|
logger: {
|
|
info: jest.fn(),
|
|
error: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('@goodgo/tracing', () => ({
|
|
initTracing: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('prom-client', () => ({
|
|
register: {
|
|
getMetricsAsJSON: jest.fn().mockReturnValue({}),
|
|
metrics: jest.fn().mockReturnValue('# Test metrics'),
|
|
},
|
|
}));
|
|
|
|
describe('Feature Endpoints E2E', () => {
|
|
let app: express.Application;
|
|
|
|
beforeAll(() => {
|
|
// EN: Set up test environment
|
|
// VI: Thiết lập môi trường test
|
|
process.env.NODE_ENV = 'test';
|
|
process.env.API_VERSION = 'v1';
|
|
|
|
app = express();
|
|
app.use(express.json());
|
|
app.use(createRouter());
|
|
});
|
|
|
|
describe('POST /api/v1/features', () => {
|
|
it('should create a feature successfully', async () => {
|
|
// EN: Arrange
|
|
// VI: Chuẩn bị
|
|
const featureData = {
|
|
name: 'test-feature',
|
|
title: 'Test Feature',
|
|
description: 'A test feature for E2E testing'
|
|
};
|
|
|
|
// EN: Act
|
|
// VI: Thực hiện
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send(featureData)
|
|
.expect(201);
|
|
|
|
// EN: Assert
|
|
// VI: Kiểm tra
|
|
expect(response.body).toMatchObject({
|
|
success: true,
|
|
message: 'Feature created successfully / Feature đã được tạo thành công',
|
|
});
|
|
expect(response.body.timestamp).toBeDefined();
|
|
});
|
|
|
|
it('should handle minimal request body', async () => {
|
|
// EN: Arrange
|
|
// VI: Chuẩn bị
|
|
const minimalData = { name: 'minimal-feature' };
|
|
|
|
// EN: Act
|
|
// VI: Thực hiện
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send(minimalData)
|
|
.expect(201);
|
|
|
|
// EN: Assert
|
|
// VI: Kiểm tra
|
|
expect(response.body).toMatchObject({
|
|
success: true,
|
|
data: { name: 'minimal-feature' },
|
|
message: 'Feature created successfully / Feature đã được tạo thành công',
|
|
});
|
|
});
|
|
|
|
it('should handle complex feature data', async () => {
|
|
// EN: Arrange
|
|
// VI: Chuẩn bị
|
|
const complexFeatureData = {
|
|
name: 'advanced-feature',
|
|
title: 'Advanced Feature',
|
|
description: 'Feature with metadata',
|
|
config: {
|
|
version: '1.0.0',
|
|
enabled: true,
|
|
priority: 1,
|
|
settings: {
|
|
timeout: 5000,
|
|
retries: 3
|
|
}
|
|
},
|
|
tags: ['advanced', 'test']
|
|
};
|
|
|
|
// EN: Act
|
|
// VI: Thực hiện
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send(complexFeatureData)
|
|
.expect(201);
|
|
|
|
// EN: Assert
|
|
// VI: Kiểm tra
|
|
expect(response.body).toMatchObject({
|
|
success: true,
|
|
message: 'Feature created successfully / Feature đã được tạo thành công',
|
|
});
|
|
expect(response.body.timestamp).toBeDefined();
|
|
});
|
|
|
|
it('should handle missing content-type header', async () => {
|
|
// EN: Act - Send request without content-type
|
|
// VI: Thực hiện - Gửi request không có content-type
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send('not json data')
|
|
.expect(201);
|
|
|
|
// EN: Assert
|
|
// VI: Kiểm tra
|
|
expect(response.body).toMatchObject({
|
|
success: true,
|
|
message: 'Feature created successfully / Feature đã được tạo thành công',
|
|
});
|
|
});
|
|
|
|
it('should handle large request payloads', async () => {
|
|
// EN: Arrange - Create large payload
|
|
// VI: Chuẩn bị - Tạo payload lớn
|
|
const largeFeatureData = {
|
|
name: 'large-feature',
|
|
title: 'Large Feature',
|
|
description: 'A'.repeat(500), // Large description
|
|
config: {
|
|
largeData: 'B'.repeat(1000), // Large config data
|
|
}
|
|
};
|
|
|
|
// EN: Act
|
|
// VI: Thực hiện
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send(largeFeatureData)
|
|
.expect(201);
|
|
|
|
// EN: Assert
|
|
// VI: Kiểm tra
|
|
expect(response.body).toMatchObject({
|
|
success: true,
|
|
message: 'Feature created successfully / Feature đã được tạo thành công',
|
|
});
|
|
});
|
|
});
|
|
}); |