Files
rentall-app/backend/tests/unit/routes/feedback.test.js
2026-01-18 19:18:35 -05:00

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);
});
});
});