diff --git a/server/src/setupTests.ts b/server/src/setupTests.ts index 6418b7a9c033be3f8742384168d47541ac4bfc70..6fc5d068dc6ef76d189d6701b630c3e6e054ab06 100644 --- a/server/src/setupTests.ts +++ b/server/src/setupTests.ts @@ -177,7 +177,7 @@ async function loadTestData() { status: 'open', priority: 'urgent', created: Date.parse('2020-10-15'), - edited: Date.parse('2020-10-20'), + edited: Date.parse('2020-11-20'), } ]); await database('task_requirements') diff --git a/server/src/v1/auth.test.ts b/server/src/v1/auth.test.ts index cdcace98a8796143497c994536097a075758bbab..67aaf839c1e6cf02e2973e52532617fb416cd538 100644 --- a/server/src/v1/auth.test.ts +++ b/server/src/v1/auth.test.ts @@ -101,7 +101,7 @@ describe('successful user registration', () => { .delete() .where({ 'users.user_name': 'user2' }); }); -}) +}); describe('password can be changed', () => { let response: Response; diff --git a/server/src/v1/comment.test.ts b/server/src/v1/comment.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b763c1f766f02283091ceb762d3468c86253f761 --- /dev/null +++ b/server/src/v1/comment.test.ts @@ -0,0 +1,26 @@ + +import supertest from 'supertest'; + +import { api } from '../api'; +import { generateAuthToken } from './auth'; + +const request = supertest(api); + +describe('GET /comment/:uuid', () => { + test('returns information for the requested comments', async () => { + const resp = await request + .get('/v1/comment/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.comment).toEqual({ + id: '00000000-0000-4000-8000-000000000000', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + text: 'Comment0', + created: Date.parse('2020-10-10T00:00:00'), + edited: Date.parse('2020-10-10T01:00:00'), + }); + }); +}); + diff --git a/server/src/v1/project.test.ts b/server/src/v1/project.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3ee499bc2d98de7bb9fad87626936da33cea4652 --- /dev/null +++ b/server/src/v1/project.test.ts @@ -0,0 +1,324 @@ + +import supertest from 'supertest'; + +import { api } from '../api'; +import { generateAuthToken } from './auth'; + +const request = supertest(api); + +describe('GET /project', () => { + test('returns all projects the user can see', async () => { + const resp = await request + .get('/v1/project') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.projects.length).toEqual(3); + }); + + test('includes projects of team 0', async () => { + const resp = await request + .get('/v1/project') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.projects).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + name: 'Project0', + text: 'Project0 Text', + color: '#00f', + status: 'open', + deadline: '2020-10-10', + }); + expect(resp.body.projects).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + name: 'Project2', + text: 'Project2 Text', + color: '#f00', + status: 'suspended', + deadline: null, + }); + }); + + test('includes projects of team 2', async () => { + const resp = await request + .get('/v1/project') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.projects).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + name: 'Project1', + text: 'Project1 Text', + color: '#0f0', + status: 'closed', + deadline: null, + }); + }); +}); + +describe('GET /project/:uuid', () => { + test('returns information for the requested project', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.project).toEqual({ + id: '00000000-0000-4000-8000-000000000000', + name: 'Project0', + text: 'Project0 Text', + color: '#00f', + status: 'open', + deadline: '2020-10-10', + teams: [ '00000000-0000-4000-8000-000000000000' ], + }); + }); +}); + +describe('GET /project/:uuid/tasks', () => { + test('returns all the tasks in the project', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/tasks') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(4); + }); + + test('contains open tasks', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/tasks') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task2', + text: 'Task2 Text', + icon: '2', + status: 'open', + priority: 'low', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [], + dependencies: [ '00000000-0000-4000-8000-000000000005' ], + requirements: [], + }); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000005', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task5', + text: 'Task5 Text', + icon: '5', + status: 'open', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-11-20'), + assigned: [ { user: '00000000-0000-4000-8000-000000000000', time: 120, finished: false } ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 60 }, + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + }); + + test('contains closed tasks', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/tasks') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000003', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task3', + text: 'Task3 Text', + icon: '3', + status: 'closed', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + }); + + test('contains suspended tasks', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/tasks') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000004', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task4', + text: 'Task4 Text', + icon: '4', + status: 'suspended', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + }); +}); + +describe('GET /project/:uuid/assigned', () => { + test('returns all users that are assigned to one of the projects tasks', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/assigned') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.assigned.length).toEqual(1); + }); + + test('contains the user information', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/assigned') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.assigned).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + username: 'user0', + email: 'test0@example.com', + realname: 'Testing Tester', + time: 120, + }); + }); +}); + +describe('GET /project/:uuid/work', () => { + test('returns all the work items done for the projects tasks', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(3); + }); + + test('containt all finished work information', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T12:00:00'), + finished: Date.parse('2020-10-10T13:00:00'), + }); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T13:00:00'), + finished: Date.parse('2020-10-10T14:00:00'), + }); + }); + + test('containt all unfinished work information', async () => { + const resp = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-11T12:00:00'), + finished: null, + }); + }); + + test('can be limited in time with from date', async () => { + const resp = await request + .get(`/v1/project/00000000-0000-4000-8000-000000000002/work?since=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(1); + }); + + test('can be limited in time with to date', async () => { + const resp = await request + .get(`/v1/project/00000000-0000-4000-8000-000000000002/work?to=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(2); + }); +}); + +describe('GET /project/:uuid/activity', () => { + test('returns time worked for all days', async () => { + const response = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/activity') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity.length).toEqual(1); + }); + + test('returns the total amount of work for each day', async () => { + const response = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/activity') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity[0].day).toEqual('2020-10-10'); + expect(response.body.activity[0].time).toEqual(120 * 60 * 1000); + }); + + test('can be limited in time with from date', async () => { + const response = await request + .get(`/v1/project/00000000-0000-4000-8000-000000000002/activity?since=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity.length).toEqual(0); + }); +}); + +describe('GET /project/:uuid/completion', () => { + test('returns completion for all tasks of the project', async () => { + const response = await request + .get('/v1/project/00000000-0000-4000-8000-000000000002/completion') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.completion).toEqual({ + open: 1, + closed: 1, + suspended: 1, + overdue: 1, + }); + }); + + test('can be limited in time with from date', async () => { + const response = await request + .get(`/v1/project/00000000-0000-4000-8000-000000000002/completion?since=${Date.parse('2020-10-30T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.completion).toEqual({ + open: 0, + closed: 0, + suspended: 0, + overdue: 1, + }); + }); +}); + diff --git a/server/src/v1/project.ts b/server/src/v1/project.ts index 600a7170aa296854d32a92418ad5d1b39973ca1f..cf3422cddbc582a4ff98555b7e7377fe1e9a29ac 100644 --- a/server/src/v1/project.ts +++ b/server/src/v1/project.ts @@ -30,7 +30,10 @@ project.get('/', async (req, res) => { .groupBy('projects.id'); res.status(200).json({ status: 'success', - projects: projects, + projects: projects.map(project => ({ + ...project, + deadline: project.deadline && (new Date(project.deadline)).toISOString().substr(0, 10), + })), }); } catch (e) { res.status(400).json({ @@ -72,7 +75,7 @@ project.get('/:uuid', async (req, res) => { text: projects[0].text, status: projects[0].status, color: projects[0].color, - deadline: projects[0].deadline, + deadline: projects[0].deadline && (new Date(projects[0].deadline)).toISOString().substr(0, 10), teams: projects.map(task => task.team_id), } }); @@ -448,7 +451,7 @@ project.put('/:uuid', async (req, res) => { text: req.body.text, color: req.body.color, status: req.body.status, - deadline: req.body.deadline, + deadline: req.body.deadline ? (new Date(req.body.deadline)).toISOString().substr(0, 10) : null, }).where({ id: id, }); diff --git a/server/src/v1/task.test.ts b/server/src/v1/task.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7561db6b7627a1e951314dd08eafaeabd449e179 --- /dev/null +++ b/server/src/v1/task.test.ts @@ -0,0 +1,519 @@ + +import supertest from 'supertest'; + +import { api } from '../api'; +import { generateAuthToken } from './auth'; + +const request = supertest(api); + +describe('GET /task', () => { + test('returns all tasks the user can see', async () => { + const resp = await request + .get('/v1/task') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(6); + }); + + test('includes tasks of project 0', async () => { + const resp = await request + .get('/v1/task') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + project: '00000000-0000-4000-8000-000000000000', + name: 'Task0', + text: 'Task0 Text', + icon: '0', + status: 'open', + priority: 'medium', + created: Date.parse('2020-10-05'), + edited: Date.parse('2020-10-10'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 30 }, + ], + }); + }); + + test('includes tasks of project 1', async () => { + const resp = await request + .get('/v1/task') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + project: '00000000-0000-4000-8000-000000000001', + name: 'Task1', + text: 'Task1 Text', + icon: '1', + status: 'closed', + priority: 'high', + created: Date.parse('2020-10-10'), + edited: Date.parse('2020-10-15'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + }); + + test('includes tasks of project 2', async () => { + const resp = await request + .get('/v1/task') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task2', + text: 'Task2 Text', + icon: '2', + status: 'open', + priority: 'low', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [], + dependencies: [ '00000000-0000-4000-8000-000000000005' ], + requirements: [], + }); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000005', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task5', + text: 'Task5 Text', + icon: '5', + status: 'open', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-11-20'), + assigned: [ { user: '00000000-0000-4000-8000-000000000000', time: 120, finished: false } ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 60 }, + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000003', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task3', + text: 'Task3 Text', + icon: '3', + status: 'closed', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000004', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task4', + text: 'Task4 Text', + icon: '4', + status: 'suspended', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + }); +}); + +describe('GET /task/open', () => { + test('returns all open tasks the user can see', async () => { + const resp = await request + .get('/v1/task/open') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(3); + }); + + test('includes tasks of project 0', async () => { + const resp = await request + .get('/v1/task/open') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + project: '00000000-0000-4000-8000-000000000000', + name: 'Task0', + text: 'Task0 Text', + icon: '0', + status: 'open', + priority: 'medium', + created: Date.parse('2020-10-05'), + edited: Date.parse('2020-10-10'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 30 }, + ], + }); + }); + + test('includes tasks of project 2', async () => { + const resp = await request + .get('/v1/task/open') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task2', + text: 'Task2 Text', + icon: '2', + status: 'open', + priority: 'low', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [], + dependencies: [ '00000000-0000-4000-8000-000000000005' ], + requirements: [], + }); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000005', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task5', + text: 'Task5 Text', + icon: '5', + status: 'open', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-11-20'), + assigned: [ { user: '00000000-0000-4000-8000-000000000000', time: 120, finished: false } ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 60 }, + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + }); +}); + +describe('GET /task/closed', () => { + test('returns all closed tasks the user can see', async () => { + const resp = await request + .get('/v1/task/closed') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(2); + }); + + test('includes tasks of project 1', async () => { + const resp = await request + .get('/v1/task/closed') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + project: '00000000-0000-4000-8000-000000000001', + name: 'Task1', + text: 'Task1 Text', + icon: '1', + status: 'closed', + priority: 'high', + created: Date.parse('2020-10-10'), + edited: Date.parse('2020-10-15'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + }); + + test('includes tasks of project 2', async () => { + const resp = await request + .get('/v1/task/closed') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000003', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task3', + text: 'Task3 Text', + icon: '3', + status: 'closed', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + }); +}); + +describe('GET /task/suspended', () => { + test('returns all suspended tasks the user can see', async () => { + const resp = await request + .get('/v1/task/suspended') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(1); + }); + + test('includes tasks of project 2', async () => { + const resp = await request + .get('/v1/task/suspended') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000004', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task4', + text: 'Task4 Text', + icon: '4', + status: 'suspended', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-10-20'), + assigned: [ ], + dependencies: [ ], + requirements: [ ], + }); + }); +}); + +describe('GET /task/possible', () => { + test('returns all open tasks without dependencies the user can see', async () => { + const resp = await request + .get('/v1/task/possible') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks.length).toEqual(2); + }); + + test('includes tasks of project 0', async () => { + const resp = await request + .get('/v1/task/possible') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + project: '00000000-0000-4000-8000-000000000000', + name: 'Task0', + text: 'Task0 Text', + icon: '0', + status: 'open', + priority: 'medium', + created: Date.parse('2020-10-05'), + edited: Date.parse('2020-10-10'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 30 }, + ], + }); + }); + + test('includes tasks of project 2', async () => { + const resp = await request + .get('/v1/task/possible') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.tasks).toContainEqual({ + id: '00000000-0000-4000-8000-000000000005', + project: '00000000-0000-4000-8000-000000000002', + name: 'Task5', + text: 'Task5 Text', + icon: '5', + status: 'open', + priority: 'urgent', + created: Date.parse('2020-10-15'), + edited: Date.parse('2020-11-20'), + assigned: [ { user: '00000000-0000-4000-8000-000000000000', time: 120, finished: false } ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 60 }, + { role: '00000000-0000-4000-8000-000000000001', time: 30 }, + ], + }); + }); +}); + +describe('GET /task/:uuid', () => { + test('returns the information for a task', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.task).toEqual({ + id: '00000000-0000-4000-8000-000000000000', + project: '00000000-0000-4000-8000-000000000000', + name: 'Task0', + text: 'Task0 Text', + icon: '0', + status: 'open', + priority: 'medium', + created: Date.parse('2020-10-05'), + edited: Date.parse('2020-10-10'), + assigned: [ ], + dependencies: [ ], + requirements: [ + { role: '00000000-0000-4000-8000-000000000000', time: 30 }, + ], + }); + }); +}); + +describe('GET /task/:uuid/comments', () => { + test('returns all the comments for a task', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/comments') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.comments.length).toEqual(3); + }); + + test('contains the information for the comments', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/comments') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.comments).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + text: 'Comment0', + created: Date.parse('2020-10-10T00:00:00'), + edited: Date.parse('2020-10-10T01:00:00'), + }); + expect(resp.body.comments).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000001', + text: 'Comment1', + created: Date.parse('2020-10-10T03:00:00'), + edited: Date.parse('2020-10-10T04:00:00'), + }); + expect(resp.body.comments).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000001', + text: 'Comment2', + created: Date.parse('2020-10-10T05:00:00'), + edited: Date.parse('2020-10-10T05:00:00'), + }); + }); +}); + +describe('GET /task/:uuid/work', () => { + test('returns all the work items done for the tasks', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(3); + }); + + test('containt all finished work information', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T12:00:00'), + finished: Date.parse('2020-10-10T13:00:00'), + }); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T13:00:00'), + finished: Date.parse('2020-10-10T14:00:00'), + }); + }); + + test('containt all unfinished work information', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-11T12:00:00'), + finished: null, + }); + }); + + test('can be limited in time with from date', async () => { + const resp = await request + .get(`/v1/task/00000000-0000-4000-8000-000000000005/work?since=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(1); + }); + + test('can be limited in time with to date', async () => { + const resp = await request + .get(`/v1/task/00000000-0000-4000-8000-000000000005/work?to=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(2); + }); +}); + +describe('GET /task/:uuid/assigned', () => { + test('returns all users that are assigned to the tasks', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/assigned') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.assigned.length).toEqual(1); + }); + + test('contains the user information', async () => { + const resp = await request + .get('/v1/task/00000000-0000-4000-8000-000000000005/assigned') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.assigned).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + username: 'user0', + email: 'test0@example.com', + realname: 'Testing Tester', + time: 120, + }); + }); +}); + diff --git a/server/src/v1/task.ts b/server/src/v1/task.ts index 30aaa0d3f22067630b36ebb897d2b1d4d0e4a2f3..f452ad893a8764cff96b0fdbf74ca83ae9432b0d 100644 --- a/server/src/v1/task.ts +++ b/server/src/v1/task.ts @@ -69,7 +69,7 @@ export function generateFromFlatResult(results: any[]): Task[] { grouped_tasks[row.id].assigned.push({ user: row.assigned_user, time: row.assigned_time, - finished: row.assigned_finished, + finished: row.assigned_finished ? true : false, }); } } diff --git a/server/src/v1/team.test.ts b/server/src/v1/team.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a81e212c7f484c74248806fb5b9a488281c181d7 --- /dev/null +++ b/server/src/v1/team.test.ts @@ -0,0 +1,405 @@ + +import supertest, { Response } from 'supertest'; + +import database from '../database'; +import { api } from '../api'; +import { generateAuthToken } from './auth'; + +const request = supertest(api); + +describe('GET /team', () => { + test('returns all teams the user is a member of', async () => { + const resp = await request + .get('/v1/team') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.teams.length).toEqual(2); + }); + + test('includes teams with a single member', async () => { + const resp = await request + .get('/v1/team') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.teams).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + name: 'Team0', + role: '00000000-0000-4000-8000-000000000000', + }); + }); + + test('includes shared teams', async () => { + const resp = await request + .get('/v1/team') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.teams).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + name: 'Team2', + role: '00000000-0000-4000-8000-000000000002', + }); + }); +}); + +describe('GET /team/:uuid', () => { + test('returns the requested teams', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual('00000000-0000-4000-8000-000000000000'); + expect(resp.body.team.name).toEqual('Team0'); + expect(resp.body.team.role).toEqual('00000000-0000-4000-8000-000000000000'); + }); + + test('can request teams one is not part of', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000001') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual('00000000-0000-4000-8000-000000000001'); + expect(resp.body.team.name).toEqual('Team1'); + expect(resp.body.team.role).toBeNull(); + }); +}); + +describe('GET /team/:uuid', () => { + test('returns the requested teams', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual('00000000-0000-4000-8000-000000000000'); + expect(resp.body.team.name).toEqual('Team0'); + expect(resp.body.team.role).toEqual('00000000-0000-4000-8000-000000000000'); + }); + + test('can request teams one is not part of', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000001') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual('00000000-0000-4000-8000-000000000001'); + expect(resp.body.team.name).toEqual('Team1'); + expect(resp.body.team.role).toBeNull(); + }); +}); + +describe('GET /team/:uuid/members', () => { + test('returns all the members of the team', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/members') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.members.length).toEqual(2); + }); + + test('contains the user itself', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/members') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.members).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + username: 'user0', + realname: 'Testing Tester', + email: 'test0@example.com', + role: { id: '00000000-0000-4000-8000-000000000002', name: 'Role2' }, + }); + }); + + test('contains other members', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/members') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.members).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + username: 'user1', + realname: 'Tester Testing', + email: 'test1@example.com', + role: { id: '00000000-0000-4000-8000-000000000003', name: 'Role3' }, + }); + }); +}); + +describe('GET /team/:uuid/roles', () => { + test('returns all the roles of the team', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/roles') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.roles.length).toEqual(2); + }); + + test('contains the users own role', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/roles') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.roles).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + name: 'Role2', + }); + }); + + test('contains other members roles', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000002/roles') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.roles).toContainEqual({ + id: '00000000-0000-4000-8000-000000000003', + name: 'Role3', + }); + }); +}); + +describe('GET /team/:uuid/projects', () => { + test('returns all the projects of the team', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/projects') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.projects.length).toEqual(2); + }); + + test('containt all the projects information', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/projects') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.projects).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + name: 'Project0', + text: 'Project0 Text', + color: '#00f', + status: 'open', + deadline: '2020-10-10', + }); + expect(resp.body.projects).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + name: 'Project2', + text: 'Project2 Text', + color: '#f00', + status: 'suspended', + deadline: null, + }); + }); +}); + +describe('GET /team/:uuid/work', () => { + test('returns all the work items done by teams members', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(3); + }); + + test('containt all finished work information', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000000', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T12:00:00'), + finished: Date.parse('2020-10-10T13:00:00'), + }); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000001', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-10T13:00:00'), + finished: Date.parse('2020-10-10T14:00:00'), + }); + }); + + test('containt all unfinished work information', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toContainEqual({ + id: '00000000-0000-4000-8000-000000000002', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-11T12:00:00'), + finished: null, + }); + }); + + test('can be limited in time with from date', async () => { + const resp = await request + .get(`/v1/team/00000000-0000-4000-8000-000000000000/work?since=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(1); + }); + + test('can be limited in time with to date', async () => { + const resp = await request + .get(`/v1/team/00000000-0000-4000-8000-000000000000/work?to=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work.length).toEqual(2); + }); +}); + +describe('GET /team/:uuid/activity', () => { + test('returns time worked for all days', async () => { + const response = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/activity') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity.length).toEqual(1); + }); + + test('returns the total amount of work for each day', async () => { + const response = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/activity') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity[0].day).toEqual('2020-10-10'); + expect(response.body.activity[0].time).toEqual(120 * 60 * 1000); + }); + + test('can be limited in time with from date', async () => { + const response = await request + .get(`/v1/team/00000000-0000-4000-8000-000000000000/activity?since=${Date.parse('2020-10-10T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.activity.length).toEqual(0); + }); +}); + +describe('GET /team/:uuid/completion', () => { + test('returns completion for all tasks of all projects', async () => { + const response = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000/completion') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.completion).toEqual({ + open: 2, + closed: 1, + suspended: 1, + overdue: 1, + }); + }); + + test('can be limited in time with from date', async () => { + const response = await request + .get(`/v1/team/00000000-0000-4000-8000-000000000000/completion?since=${Date.parse('2020-10-30T20:00:00')}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.completion).toEqual({ + open: 0, + closed: 0, + suspended: 0, + overdue: 1, + }); + }); +}); + +describe('POST /team', () => { + let response: Response; + + beforeAll(async () => { + response = await request + .post('/v1/team') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`) + .send({ + name: 'Team20', + }); + }); + + test('returns the id of the new team', async () => { + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + expect(response.body.id).toBeTruthy(); + }); + + test('team can be requested afterwards', async () => { + const resp = await request + .get(`/v1/team/${response.body.id}`) + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual(response.body.id); + expect(resp.body.team.name).toEqual('Team20'); + expect(resp.body.team.role).toBeTruthy(); + }); + + afterAll(async () => { + await database('teams') + .delete() + .where({ 'teams.name': 'Team20' }); + }); +}); + +describe('PUT /team/:uuid', () => { + let response: Response; + + beforeAll(async () => { + response = await request + .put('/v1/team/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`) + .send({ + name: 'Team20', + }); + }); + + test('returns successfully', async () => { + expect(response.status).toEqual(200); + expect(response.body.status).toEqual('success'); + }); + + test('team has now the new name', async () => { + const resp = await request + .get('/v1/team/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.team.id).toEqual('00000000-0000-4000-8000-000000000000'); + expect(resp.body.team.name).toEqual('Team20'); + expect(resp.body.team.role).toEqual('00000000-0000-4000-8000-000000000000'); + }); + + afterAll(async () => { + await request + .put('/v1/team/00000000-0000-4000-8000-000000000000') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`) + .send({ + name: 'Team0', + }); + }); +}); + diff --git a/server/src/v1/team.ts b/server/src/v1/team.ts index 9090c106e41d46d693718703199b2f558c11e0a8..fe329decbb45bd6f0e06796bd276f5bfc0265c04 100644 --- a/server/src/v1/team.ts +++ b/server/src/v1/team.ts @@ -138,25 +138,23 @@ team.get('/:uuid/', async (req, res) => { try { const id = req.params.uuid; if (validate(id)) { - const team = await database('teams') + const teams = await database('teams') .leftJoin('team_members', 'teams.id', 'team_members.team_id') .select({ id: 'teams.id', name: 'teams.name', role: 'team_members.role_id', + user: 'team_members.user_id', }) .where({ - 'team_members.user_id': req.body.token.id, - 'teams.id': id, - }) - .orWhere({ - 'team_members.user_id': null, 'teams.id': id, }) - if (team.length >= 1) { + if (teams.length >= 1) { + const team = teams.find(team => team.user === req.body.token.id) ?? { ...teams[0], role: null }; + delete team.user; res.status(200).json({ status: 'success', - team: team[0], + team: team, }); } else { res.status(404).json({ @@ -294,7 +292,10 @@ team.get('/:uuid/projects', async (req, res) => { }); res.status(200).json({ status: 'success', - projects: projects, + projects: projects.map(project => ({ + ...project, + deadline: project.deadline && (new Date(project.deadline)).toISOString().substr(0, 10), + })), }); } else { res.status(400).json({ diff --git a/server/src/v1/user.test.ts b/server/src/v1/user.test.ts index 5652aa2e6ae7e2a83f76bd290c47bc2ed69dcfe0..4efa7f36d00a79edce97ced60ebb1c251e0e848a 100644 --- a/server/src/v1/user.test.ts +++ b/server/src/v1/user.test.ts @@ -26,7 +26,7 @@ describe('GET /user/name', () => { expect(response.body.status).toEqual('success'); expect(response.body.user.username).toEqual('user0'); }); -}) +}); describe('GET /user/:uuid/image', () => { test('returns 404 without body if no image is set', async () => { @@ -46,7 +46,7 @@ describe('GET /user/:uuid/image', () => { expect(response.status).toEqual(200); expect(response.body).toBeTruthy(); }); -}) +}); describe('GET /user', () => { test('returns the user that is authorized', async () => { @@ -195,7 +195,7 @@ describe('GET /user/completion', () => { open: 0, closed: 0, suspended: 0, - overdue: 0, + overdue: 1, }); }); }); diff --git a/server/src/v1/work.test.ts b/server/src/v1/work.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4021bcf27f7e61ce5096c420ae56109a6511c8cf --- /dev/null +++ b/server/src/v1/work.test.ts @@ -0,0 +1,33 @@ + +import supertest from 'supertest'; + +import { api } from '../api'; +import { generateAuthToken } from './auth'; + +const request = supertest(api); + +describe('GET /work', () => { + test('returns information for the unfinished work', async () => { + const resp = await request + .get('/v1/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000000')}`); + expect(resp.status).toEqual(200); + expect(resp.body.status).toEqual('success'); + expect(resp.body.work).toEqual({ + id: '00000000-0000-4000-8000-000000000002', + task: '00000000-0000-4000-8000-000000000005', + user: '00000000-0000-4000-8000-000000000000', + started: Date.parse('2020-10-11T12:00:00'), + finished: null, + }); + }); + + test('returns 404 if no work is unfinished', async () => { + const resp = await request + .get('/v1/work') + .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-4000-8000-000000000001')}`); + expect(resp.status).toEqual(404); + expect(resp.body.status).toEqual('error'); + }); +}); +