tududi/backend/tests/integration/notes.test.js
Chris 3c1209a5a9
Express migration (#80)
* Initial migration

* Cleanup and create migration scripts

* Introduce test suite

* Fix test issues

* Correct CORS issue and update paths

* Update README
2025-06-16 21:50:44 +03:00

308 lines
No EOL
8.8 KiB
JavaScript

const request = require('supertest');
const app = require('../../app');
const { Note, User, Project } = require('../../models');
const { createTestUser } = require('../helpers/testUtils');
describe('Notes Routes', () => {
let user, project, agent;
beforeEach(async () => {
user = await createTestUser({
email: 'test@example.com'
});
project = await Project.create({
name: 'Test Project',
user_id: user.id
});
// Create authenticated agent
agent = request.agent(app);
await agent
.post('/api/login')
.send({
email: 'test@example.com',
password: 'password123'
});
});
describe('POST /api/note', () => {
it('should create a new note', async () => {
const noteData = {
title: 'Test Note',
content: 'This is a test note content',
project_id: project.id
};
const response = await agent
.post('/api/note')
.send(noteData);
expect(response.status).toBe(201);
expect(response.body.title).toBe(noteData.title);
expect(response.body.content).toBe(noteData.content);
expect(response.body.project_id).toBe(project.id);
expect(response.body.user_id).toBe(user.id);
});
it('should create note without project', async () => {
const noteData = {
title: 'Test Note',
content: 'This is a test note content'
};
const response = await agent
.post('/api/note')
.send(noteData);
expect(response.status).toBe(201);
expect(response.body.title).toBe(noteData.title);
expect(response.body.content).toBe(noteData.content);
expect(response.body.project_id).toBeNull();
expect(response.body.user_id).toBe(user.id);
});
it('should require authentication', async () => {
const noteData = {
title: 'Test Note',
content: 'Test content'
};
const response = await request(app)
.post('/api/note')
.send(noteData);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('GET /api/notes', () => {
let note1, note2;
beforeEach(async () => {
note1 = await Note.create({
title: 'Note 1',
content: 'First note content',
user_id: user.id,
project_id: project.id
});
note2 = await Note.create({
title: 'Note 2',
content: 'Second note content',
user_id: user.id
});
});
it('should get all user notes', async () => {
const response = await agent.get('/api/notes');
expect(response.status).toBe(200);
expect(Array.isArray(response.body)).toBe(true);
expect(response.body.length).toBe(2);
expect(response.body.map(n => n.id)).toContain(note1.id);
expect(response.body.map(n => n.id)).toContain(note2.id);
});
it('should include project information', async () => {
const response = await agent.get('/api/notes');
expect(response.status).toBe(200);
const noteWithProject = response.body.find(n => n.id === note1.id);
expect(noteWithProject.Project).toBeDefined();
expect(noteWithProject.Project.name).toBe(project.name);
});
it('should return all notes when no filter is applied', async () => {
const response = await agent.get('/api/notes');
expect(response.status).toBe(200);
expect(response.body.length).toBe(2);
expect(response.body.map(n => n.id)).toContain(note1.id);
expect(response.body.map(n => n.id)).toContain(note2.id);
});
it('should require authentication', async () => {
const response = await request(app).get('/api/notes');
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('GET /api/note/:id', () => {
let note;
beforeEach(async () => {
note = await Note.create({
title: 'Test Note',
content: 'Test content',
user_id: user.id,
project_id: project.id
});
});
it('should get note by id', async () => {
const response = await agent.get(`/api/note/${note.id}`);
expect(response.status).toBe(200);
expect(response.body.id).toBe(note.id);
expect(response.body.title).toBe(note.title);
expect(response.body.content).toBe(note.content);
});
it('should return 404 for non-existent note', async () => {
const response = await agent.get('/api/note/999999');
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should not allow access to other user\'s notes', async () => {
const bcrypt = require('bcrypt');
const otherUser = await User.create({
email: 'other@example.com',
password_digest: await bcrypt.hash('password123', 10)
});
const otherNote = await Note.create({
title: 'Other Note',
user_id: otherUser.id
});
const response = await agent.get(`/api/note/${otherNote.id}`);
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should require authentication', async () => {
const response = await request(app).get(`/api/note/${note.id}`);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('PATCH /api/note/:id', () => {
let note;
beforeEach(async () => {
note = await Note.create({
title: 'Test Note',
content: 'Test content',
user_id: user.id
});
});
it('should update note', async () => {
const updateData = {
title: 'Updated Note',
content: 'Updated content',
project_id: project.id
};
const response = await agent
.patch(`/api/note/${note.id}`)
.send(updateData);
expect(response.status).toBe(200);
expect(response.body.title).toBe(updateData.title);
expect(response.body.content).toBe(updateData.content);
expect(response.body.project_id).toBe(project.id);
});
it('should return 404 for non-existent note', async () => {
const response = await agent
.patch('/api/note/999999')
.send({ title: 'Updated' });
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should not allow updating other user\'s notes', async () => {
const bcrypt = require('bcrypt');
const otherUser = await User.create({
email: 'other@example.com',
password_digest: await bcrypt.hash('password123', 10)
});
const otherNote = await Note.create({
title: 'Other Note',
user_id: otherUser.id
});
const response = await agent
.patch(`/api/note/${otherNote.id}`)
.send({ title: 'Updated' });
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should require authentication', async () => {
const response = await request(app)
.patch(`/api/note/${note.id}`)
.send({ title: 'Updated' });
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('DELETE /api/note/:id', () => {
let note;
beforeEach(async () => {
note = await Note.create({
title: 'Test Note',
user_id: user.id
});
});
it('should delete note', async () => {
const response = await agent.delete(`/api/note/${note.id}`);
expect(response.status).toBe(200);
expect(response.body.message).toBe('Note deleted successfully.');
// Verify note is deleted
const deletedNote = await Note.findByPk(note.id);
expect(deletedNote).toBeNull();
});
it('should return 404 for non-existent note', async () => {
const response = await agent.delete('/api/note/999999');
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should not allow deleting other user\'s notes', async () => {
const bcrypt = require('bcrypt');
const otherUser = await User.create({
email: 'other@example.com',
password_digest: await bcrypt.hash('password123', 10)
});
const otherNote = await Note.create({
title: 'Other Note',
user_id: otherUser.id
});
const response = await agent.delete(`/api/note/${otherNote.id}`);
expect(response.status).toBe(404);
expect(response.body.error).toBe('Note not found.');
});
it('should require authentication', async () => {
const response = await request(app).delete(`/api/note/${note.id}`);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
});