232 lines
8.2 KiB
JavaScript
232 lines
8.2 KiB
JavaScript
const request = require('supertest');
|
|
const app = require('../../app');
|
|
const { User, Notification, Task } = require('../../models');
|
|
const { createTestUser } = require('../helpers/testUtils');
|
|
|
|
describe('Notification Soft Delete', () => {
|
|
let user, agent, task;
|
|
|
|
beforeEach(async () => {
|
|
user = await createTestUser({
|
|
email: `test_${Date.now()}@example.com`,
|
|
});
|
|
|
|
// Create authenticated agent
|
|
agent = request.agent(app);
|
|
await agent.post('/api/login').send({
|
|
email: user.email,
|
|
password: 'password123',
|
|
});
|
|
|
|
// Create a test task directly in database
|
|
task = await Task.create({
|
|
name: 'Test Task',
|
|
user_id: user.id,
|
|
status: 0,
|
|
});
|
|
});
|
|
|
|
describe('DELETE /api/notifications/:id - Soft Delete', () => {
|
|
it('should soft delete (dismiss) a notification', async () => {
|
|
// Create a notification
|
|
const notification = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Test Notification',
|
|
message: 'This is a test',
|
|
sources: [],
|
|
data: { taskUid: task.uid },
|
|
});
|
|
|
|
// Delete (dismiss) the notification
|
|
const deleteResponse = await agent.delete(
|
|
`/api/notifications/${notification.id}`
|
|
);
|
|
|
|
expect(deleteResponse.status).toBe(200);
|
|
expect(deleteResponse.body.message).toBe(
|
|
'Notification dismissed successfully'
|
|
);
|
|
|
|
// Verify the notification still exists in database but is dismissed
|
|
const dismissedNotification = await Notification.findByPk(
|
|
notification.id
|
|
);
|
|
expect(dismissedNotification).not.toBeNull();
|
|
expect(dismissedNotification.dismissed_at).not.toBeNull();
|
|
expect(dismissedNotification.isDismissed()).toBe(true);
|
|
});
|
|
|
|
it('should not allow dismissing an already dismissed notification', async () => {
|
|
// Create and dismiss a notification
|
|
const notification = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Test Notification',
|
|
message: 'This is a test',
|
|
sources: [],
|
|
data: { taskUid: task.uid },
|
|
});
|
|
|
|
await notification.dismiss();
|
|
|
|
// Try to dismiss again
|
|
const deleteResponse = await agent.delete(
|
|
`/api/notifications/${notification.id}`
|
|
);
|
|
|
|
expect(deleteResponse.status).toBe(404);
|
|
expect(deleteResponse.body.error).toBe('Notification not found');
|
|
});
|
|
|
|
it('should hide dismissed notifications from GET /api/notifications', async () => {
|
|
// Create two notifications
|
|
const notification1 = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Notification 1',
|
|
message: 'This is test 1',
|
|
sources: [],
|
|
});
|
|
|
|
const notification2 = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_overdue',
|
|
title: 'Notification 2',
|
|
message: 'This is test 2',
|
|
sources: [],
|
|
});
|
|
|
|
// Dismiss the first notification
|
|
await agent.delete(`/api/notifications/${notification1.id}`);
|
|
|
|
// Get notifications
|
|
const getResponse = await agent.get('/api/notifications');
|
|
|
|
expect(getResponse.status).toBe(200);
|
|
expect(getResponse.body.total).toBe(1);
|
|
expect(getResponse.body.notifications.length).toBe(1);
|
|
expect(getResponse.body.notifications[0].id).toBe(notification2.id);
|
|
});
|
|
|
|
it('should exclude dismissed notifications from unread count', async () => {
|
|
// Create two unread notifications
|
|
const notification1 = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Notification 1',
|
|
message: 'This is test 1',
|
|
sources: [],
|
|
});
|
|
|
|
await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_overdue',
|
|
title: 'Notification 2',
|
|
message: 'This is test 2',
|
|
sources: [],
|
|
});
|
|
|
|
// Check unread count (should be 2)
|
|
let countResponse = await agent.get(
|
|
'/api/notifications/unread-count'
|
|
);
|
|
expect(countResponse.body.count).toBe(2);
|
|
|
|
// Dismiss one notification
|
|
await agent.delete(`/api/notifications/${notification1.id}`);
|
|
|
|
// Check unread count again (should be 1)
|
|
countResponse = await agent.get('/api/notifications/unread-count');
|
|
expect(countResponse.body.count).toBe(1);
|
|
});
|
|
|
|
it('should not recreate dismissed notifications in cron jobs', async () => {
|
|
// Update task with due date in the past
|
|
const dueDate = new Date(Date.now() - 1000 * 60 * 60); // 1 hour ago
|
|
await task.update({
|
|
due_date: dueDate,
|
|
});
|
|
|
|
// Run the due task service
|
|
const {
|
|
checkDueTasks,
|
|
} = require('../../modules/tasks/dueTaskService');
|
|
let result = await checkDueTasks();
|
|
|
|
// Should create 1 notification
|
|
expect(result.notificationsCreated).toBe(1);
|
|
|
|
// Get the notification
|
|
const notifications = await Notification.findAll({
|
|
where: { user_id: user.id },
|
|
});
|
|
expect(notifications.length).toBe(1);
|
|
|
|
const notification = notifications[0];
|
|
|
|
// Dismiss the notification
|
|
await notification.dismiss();
|
|
|
|
// Run the service again
|
|
result = await checkDueTasks();
|
|
|
|
// Should not create a new notification (dismissed one should be skipped)
|
|
expect(result.notificationsCreated).toBe(0);
|
|
|
|
// Verify only one notification exists (the dismissed one)
|
|
const allNotifications = await Notification.findAll({
|
|
where: { user_id: user.id },
|
|
});
|
|
expect(allNotifications.length).toBe(1);
|
|
expect(allNotifications[0].isDismissed()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Notification model - isDismissed and dismiss methods', () => {
|
|
it('should correctly identify dismissed notifications', async () => {
|
|
const notification = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Test',
|
|
message: 'Test',
|
|
sources: [],
|
|
});
|
|
|
|
// Reload from database to get actual values
|
|
await notification.reload();
|
|
|
|
expect(notification.dismissed_at).toBeNull();
|
|
expect(notification.isDismissed()).toBe(false);
|
|
|
|
await notification.dismiss();
|
|
|
|
expect(notification.isDismissed()).toBe(true);
|
|
expect(notification.dismissed_at).not.toBeNull();
|
|
});
|
|
|
|
it('should not change dismissed_at if already dismissed', async () => {
|
|
const notification = await Notification.createNotification({
|
|
userId: user.id,
|
|
type: 'task_due_soon',
|
|
title: 'Test',
|
|
message: 'Test',
|
|
sources: [],
|
|
});
|
|
|
|
await notification.dismiss();
|
|
const firstDismissedAt = notification.dismissed_at;
|
|
|
|
// Wait a bit
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
|
|
// Try to dismiss again
|
|
await notification.dismiss();
|
|
|
|
// dismissed_at should be the same
|
|
expect(notification.dismissed_at.getTime()).toBe(
|
|
firstDismissedAt.getTime()
|
|
);
|
|
});
|
|
});
|
|
});
|