Files
scrum-manager/server/tests/tasks.test.js
tusuii c604df281d feat: add more roles (tech_lead, scrum_master, product_owner, designer, qa)
- Registration form: added 5 new role options to dropdown
- Sidebar: new roles get proper nav access via ALL_ROLES/LEADER_ROLES
- Dashboard: isLeader check expanded to include new leadership roles
- Shared/Pages: role badge colors added for all new roles
- Invite modal: expanded role dropdown
2026-02-16 12:31:54 +05:30

121 lines
4.0 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import request from 'supertest';
import { app } from '../index.js';
import pool from '../db.js';
// Mock DB
const mockQuery = vi.fn();
const mockRelease = vi.fn();
const mockCommit = vi.fn();
const mockRollback = vi.fn();
const mockBeginTransaction = vi.fn();
vi.mock('../db.js', () => ({
default: {
query: vi.fn(),
getConnection: vi.fn()
},
initDB: vi.fn()
}));
describe('Task Routes', () => {
beforeEach(() => {
vi.clearAllMocks();
mockQuery.mockReset(); // Important to clear implementations
pool.query = mockQuery;
pool.getConnection.mockResolvedValue({
query: mockQuery,
release: mockRelease,
beginTransaction: mockBeginTransaction,
commit: mockCommit,
rollback: mockRollback
});
});
describe('GET /api/tasks', () => {
it('returns list of tasks', async () => {
// Mock fetching task IDs
mockQuery.mockResolvedValueOnce([[{ id: 't1' }]]);
// Mock getFullTask queries for 't1'
// 1. Task details
mockQuery.mockResolvedValueOnce([[{ id: 't1', title: 'Task 1', status: 'todo' }]]); // Task
// 2. Subtasks
mockQuery.mockResolvedValueOnce([[]]); // Subtasks
// 3. Comments
mockQuery.mockResolvedValueOnce([[]]); // Comments
// 4. Activities
mockQuery.mockResolvedValueOnce([[]]); // Activities
// 5. Tags
mockQuery.mockResolvedValueOnce([[]]); // Tags
// 6. Dependencies
mockQuery.mockResolvedValueOnce([[]]); // Dependencies
const res = await request(app).get('/api/tasks');
expect(res.status).toBe(200);
expect(res.body).toHaveLength(1);
expect(res.body[0].title).toBe('Task 1');
});
});
describe('POST /api/tasks', () => {
it('creates a new task', async () => {
// Mock INSERTs (1: Task, 2: Activities) -> Return {}
mockQuery.mockResolvedValueOnce({}); // Insert task
mockQuery.mockResolvedValueOnce({}); // Insert activity
// getFullTask queries (3-8)
mockQuery.mockResolvedValueOnce([[{ id: 'new-id', title: 'New Task', status: 'todo' }]]); // Task
mockQuery.mockResolvedValueOnce([[]]); // Subtasks
mockQuery.mockResolvedValueOnce([[]]); // Comments
mockQuery.mockResolvedValueOnce([[]]); // Activities
mockQuery.mockResolvedValueOnce([[]]); // Tags
mockQuery.mockResolvedValueOnce([[]]); // Deps
const newTask = {
// For getFullTask called at end
title: 'New Task',
description: 'Desc',
status: 'todo'
};
const res = await request(app)
.post('/api/tasks')
.send(newTask);
expect(res.status).toBe(201);
expect(mockBeginTransaction).toHaveBeenCalled();
expect(mockCommit).toHaveBeenCalled();
expect(mockRelease).toHaveBeenCalled();
});
it('rolls back on error', async () => {
mockQuery.mockRejectedValue(new Error('DB Error'));
const res = await request(app)
.post('/api/tasks')
.send({ title: 'Task' });
expect(res.status).toBe(500);
expect(mockRollback).toHaveBeenCalled();
expect(mockRelease).toHaveBeenCalled();
});
});
describe('DELETE /api/tasks/:id', () => {
it('deletes a task', async () => {
mockQuery.mockResolvedValue({});
const res = await request(app).delete('/api/tasks/t1');
expect(res.status).toBe(200);
expect(mockQuery).toHaveBeenCalledWith(
expect.stringContaining('DELETE FROM tasks'),
['t1']
);
});
});
});