245 lines
7.1 KiB
JavaScript
245 lines
7.1 KiB
JavaScript
const request = require('supertest');
|
|
const express = require('express');
|
|
|
|
// Mock dependencies
|
|
jest.mock('../../../models', () => ({
|
|
Feedback: {
|
|
create: jest.fn(),
|
|
},
|
|
User: {
|
|
findByPk: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('../../../middleware/auth', () => ({
|
|
authenticateToken: (req, res, next) => {
|
|
req.user = { id: 'user-123', email: 'test@example.com' };
|
|
next();
|
|
},
|
|
}));
|
|
|
|
jest.mock('../../../middleware/validation', () => ({
|
|
validateFeedback: (req, res, next) => next(),
|
|
sanitizeInput: (req, res, next) => next(),
|
|
}));
|
|
|
|
jest.mock('../../../services/email', () => ({
|
|
feedback: {
|
|
sendFeedbackConfirmation: jest.fn(),
|
|
sendFeedbackNotificationToAdmin: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('../../../utils/logger', () => ({
|
|
info: jest.fn(),
|
|
error: jest.fn(),
|
|
warn: jest.fn(),
|
|
withRequestId: jest.fn(() => ({
|
|
info: jest.fn(),
|
|
error: jest.fn(),
|
|
warn: jest.fn(),
|
|
})),
|
|
}));
|
|
|
|
const { Feedback } = require('../../../models');
|
|
const emailServices = require('../../../services/email');
|
|
const feedbackRoutes = require('../../../routes/feedback');
|
|
|
|
describe('Feedback Routes', () => {
|
|
let app;
|
|
|
|
beforeEach(() => {
|
|
app = express();
|
|
app.use(express.json());
|
|
app.use('/feedback', feedbackRoutes);
|
|
|
|
// Add error handler
|
|
app.use((err, req, res, next) => {
|
|
res.status(500).json({ error: err.message });
|
|
});
|
|
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('POST /feedback', () => {
|
|
it('should create feedback successfully', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
userId: 'user-123',
|
|
feedbackText: 'Great app!',
|
|
url: 'https://example.com/page',
|
|
userAgent: 'Mozilla/5.0',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.set('User-Agent', 'Mozilla/5.0')
|
|
.send({
|
|
feedbackText: 'Great app!',
|
|
url: 'https://example.com/page',
|
|
});
|
|
|
|
expect(response.status).toBe(201);
|
|
expect(response.body.id).toBe('feedback-123');
|
|
expect(response.body.feedbackText).toBe('Great app!');
|
|
expect(Feedback.create).toHaveBeenCalledWith({
|
|
userId: 'user-123',
|
|
feedbackText: 'Great app!',
|
|
url: 'https://example.com/page',
|
|
userAgent: 'Mozilla/5.0',
|
|
});
|
|
});
|
|
|
|
it('should send confirmation email to user', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(emailServices.feedback.sendFeedbackConfirmation).toHaveBeenCalledWith(
|
|
{ id: 'user-123', email: 'test@example.com' },
|
|
mockFeedback
|
|
);
|
|
});
|
|
|
|
it('should send notification email to admin', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(emailServices.feedback.sendFeedbackNotificationToAdmin).toHaveBeenCalledWith(
|
|
{ id: 'user-123', email: 'test@example.com' },
|
|
mockFeedback
|
|
);
|
|
});
|
|
|
|
it('should succeed even if confirmation email fails', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockRejectedValue(new Error('Email failed'));
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(response.status).toBe(201);
|
|
});
|
|
|
|
it('should succeed even if admin notification email fails', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockRejectedValue(new Error('Email failed'));
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(response.status).toBe(201);
|
|
});
|
|
|
|
it('should handle feedback with null url', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
url: null,
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(response.status).toBe(201);
|
|
expect(Feedback.create).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
url: null,
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should capture user agent from headers', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
userAgent: 'CustomUserAgent/1.0',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
await request(app)
|
|
.post('/feedback')
|
|
.set('User-Agent', 'CustomUserAgent/1.0')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(Feedback.create).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
userAgent: 'CustomUserAgent/1.0',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should handle missing user agent', async () => {
|
|
const mockFeedback = {
|
|
id: 'feedback-123',
|
|
feedbackText: 'Great app!',
|
|
};
|
|
|
|
Feedback.create.mockResolvedValue(mockFeedback);
|
|
emailServices.feedback.sendFeedbackConfirmation.mockResolvedValue();
|
|
emailServices.feedback.sendFeedbackNotificationToAdmin.mockResolvedValue();
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(response.status).toBe(201);
|
|
});
|
|
|
|
it('should return 500 when database error occurs', async () => {
|
|
Feedback.create.mockRejectedValue(new Error('Database error'));
|
|
|
|
const response = await request(app)
|
|
.post('/feedback')
|
|
.send({ feedbackText: 'Great app!' });
|
|
|
|
expect(response.status).toBe(500);
|
|
});
|
|
});
|
|
});
|