const request = require('supertest'); const app = require('../../app'); const { User } = require('../../models'); const { createTestUser } = require('../helpers/testUtils'); describe('Notification Preferences', () => { let user, agent; 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', }); }); describe('GET /api/profile - notification_preferences', () => { it('should include notification_preferences in profile response', async () => { const response = await agent.get('/api/profile'); expect(response.status).toBe(200); expect(response.body).toHaveProperty('notification_preferences'); }); it('should return default notification_preferences for new users', async () => { const response = await agent.get('/api/profile'); expect(response.status).toBe(200); expect(response.body.notification_preferences).toEqual({ dueTasks: { inApp: true, email: false, push: false, telegram: false, }, overdueTasks: { inApp: true, email: false, push: false, telegram: false, }, dueProjects: { inApp: true, email: false, push: false, telegram: false, }, overdueProjects: { inApp: true, email: false, push: false, telegram: false, }, deferUntil: { inApp: true, email: false, push: false, telegram: false, }, }); }); it('should return saved notification_preferences', async () => { const preferences = { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; await User.update( { notification_preferences: preferences }, { where: { id: user.id } } ); const response = await agent.get('/api/profile'); expect(response.status).toBe(200); expect(response.body.notification_preferences).toEqual(preferences); }); }); describe('PATCH /api/profile - notification_preferences', () => { it('should update notification preferences', async () => { const preferences = { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; const response = await agent .patch('/api/profile') .send({ notification_preferences: preferences }); expect(response.status).toBe(200); expect(response.body.notification_preferences).toEqual(preferences); // Verify it was saved to database const updatedUser = await User.findByPk(user.id); expect(updatedUser.notification_preferences).toEqual(preferences); }); it('should allow partial notification preference updates', async () => { // Set initial preferences const initialPreferences = { dueTasks: { inApp: true, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: true, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; await agent .patch('/api/profile') .send({ notification_preferences: initialPreferences }); // Update only some types const updatedPreferences = { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: false, email: false, push: false }, dueProjects: { inApp: true, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; const response = await agent .patch('/api/profile') .send({ notification_preferences: updatedPreferences }); expect(response.status).toBe(200); expect(response.body.notification_preferences).toEqual( updatedPreferences ); }); it('should allow setting preferences to null', async () => { // First set some preferences await agent.patch('/api/profile').send({ notification_preferences: { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }, }); // Then set to null const response = await agent .patch('/api/profile') .send({ notification_preferences: null }); expect(response.status).toBe(200); expect(response.body.notification_preferences).toBeNull(); }); it('should not affect other profile fields', async () => { const preferences = { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; const response = await agent .patch('/api/profile') .send({ notification_preferences: preferences }); expect(response.status).toBe(200); expect(response.body.email).toBe(user.email); expect(response.body.appearance).toBe(user.appearance); expect(response.body.language).toBe(user.language); }); it('should require authentication', async () => { const preferences = { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }; const response = await request(app) .patch('/api/profile') .send({ notification_preferences: preferences }); expect(response.status).toBe(401); expect(response.body.error).toBe('Authentication required'); }); it('should work with other profile updates in same request', async () => { const updateData = { appearance: 'dark', language: 'es', notification_preferences: { dueTasks: { inApp: false, email: false, push: false }, overdueTasks: { inApp: true, email: false, push: false }, dueProjects: { inApp: false, email: false, push: false }, overdueProjects: { inApp: true, email: false, push: false }, deferUntil: { inApp: true, email: false, push: false }, }, }; const response = await agent.patch('/api/profile').send(updateData); expect(response.status).toBe(200); expect(response.body.appearance).toBe('dark'); expect(response.body.language).toBe('es'); expect(response.body.notification_preferences).toEqual( updateData.notification_preferences ); }); }); });