From 46fa00a83a34ae4f524bb9c4450f16180b410cb8 Mon Sep 17 00:00:00 2001 From: abouchtita <abouchtita@devops-tp.local> Date: Fri, 14 Mar 2025 17:15:50 +0100 Subject: [PATCH 1/5] =?UTF-8?q?R=C3=A9cup=C3=A9ration=20d'une=20t=C3=A2che?= =?UTF-8?q?=20par=20ID=20&=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FETCH_HEAD | 0 src/index.js | 11 +++++++++++ src/taskService.js | 8 +++++++- tests/integration/app.test.js | 19 +++++++++++++++++++ tests/unit/todoService.test.js | 10 +++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 FETCH_HEAD diff --git a/FETCH_HEAD b/FETCH_HEAD new file mode 100644 index 0000000..e69de29 diff --git a/src/index.js b/src/index.js index 441d6f9..d2ff431 100644 --- a/src/index.js +++ b/src/index.js @@ -21,6 +21,17 @@ app.get('/api/tasks', (req, res) => { res.json(tasks); }); +// +app.get('/api/tasks/:id', (req, res) => { + const id = req.params.id; + const task = taskService.getTaskById(id); + if (task) { + res.json(task); + } else { + res.status(404).json({ error: 'Tâche non trouvée' }); + } +}); + // Fonction pour démarrer le serveur const startServer = () => { const server = app.listen(port, () => { diff --git a/src/taskService.js b/src/taskService.js index aad0b48..19298d6 100644 --- a/src/taskService.js +++ b/src/taskService.js @@ -4,6 +4,11 @@ const tasks = require('../tasks.json'); +function getTaskById(id) { + const taskId = parseInt(id, 10); + return tasks.find(task => task.id === taskId); +} + //fonction de récupération de toutes les tâches function getAllTasks() { return tasks; @@ -11,5 +16,6 @@ function getAllTasks() { //export des fonctions module.exports = { - getAllTasks + getAllTasks, + getTaskById }; diff --git a/tests/integration/app.test.js b/tests/integration/app.test.js index 04c94c8..dd7eb43 100644 --- a/tests/integration/app.test.js +++ b/tests/integration/app.test.js @@ -24,3 +24,22 @@ describe('Endpoints de base', () => { }); }); + + +describe('GET /api/tasks/:id', () => { + + // Test pour un ID existant (par exemple, ID = 1) + test('devrait retourner la tâche correspondante pour un ID existant', async () => { + const res = await request(app).get('/api/tasks/1'); + expect(res.statusCode).toEqual(200); + expect(res.body).toEqual({ id: 1, description: 'Apprendre Git', done: false }); + }); + + // Test pour un ID inexistant (par exemple, ID = 999) + test('devrait retourner 404 pour un ID inexistant', async () => { + const res = await request(app).get('/api/tasks/999'); + expect(res.statusCode).toEqual(404); + expect(res.body).toEqual({ error: 'Tâche non trouvée' }); + }); + +}); \ No newline at end of file diff --git a/tests/unit/todoService.test.js b/tests/unit/todoService.test.js index 503dafd..9c0157a 100644 --- a/tests/unit/todoService.test.js +++ b/tests/unit/todoService.test.js @@ -1,7 +1,7 @@ //test unitaire des fonctions de service // Import de la fonction à tester -const { getAllTasks } = require('../../src/taskService'); +const { getAllTasks , getTaskById} = require('../../src/taskService'); //Test de la fonction de récupération de toutes les tâches. test('should return all tasks', () => { @@ -10,3 +10,11 @@ test('should return all tasks', () => { expect(tasks.length).toBeGreaterThan(0); }); +test('should return the correct task for a given id', () => { + const task = getTaskById(1); + expect(task).toEqual({ id: 1, description: 'Apprendre Git', done: false }); +}); + +test('should return undefined for a non-existent task id', () => { + const task = getTaskById(999); + expect(task).toBeUndefined();}); \ No newline at end of file -- GitLab From ab75819427b6c9b9d8455ab12cc2d0169f2ad54a Mon Sep 17 00:00:00 2001 From: abouchtita <abouchtita@devops-tp.local> Date: Fri, 14 Mar 2025 17:25:31 +0100 Subject: [PATCH 2/5] Ajout de la configuration GitLab CI/CD avec artifacts --- .gitlab-ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..24d099b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +image: node:16 + +stages: + - install + - lint + - test + +cache: + paths: + - node_modules/ + +before_script: + - npm install + +lint: + stage: lint + script: + - npm run lint + only: + - develop + - main + +test: + stage: test + script: + - npm run test + only: + - develop + - main \ No newline at end of file -- GitLab From 5c5cc39acb1c4dd3f4f762b30fde40376b2ff4ea Mon Sep 17 00:00:00 2001 From: abouchtita <abouchtita@devops-tp.local> Date: Fri, 14 Mar 2025 17:33:53 +0100 Subject: [PATCH 3/5] Ajout de l'endpoint POST /api/tasks et de la fonction addTask --- src/index.js | 13 +++++++++++++ src/taskService.js | 17 ++++++++++++++++- tests/integration/app.test.js | 22 ++++++++++++++++++++++ tests/unit/todoService.test.js | 19 +++++++++++++++++-- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index d2ff431..94fa182 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,19 @@ app.get('/api/tasks/:id', (req, res) => { } }); +app.post('/api/tasks', (req, res) => { + const { description } = req.body; + if (!description) { + return res.status(400).json({ error: 'La description est requise' }); + } + try { + const newTask = taskService.addTask(description); + res.status(201).json(newTask); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + // Fonction pour démarrer le serveur const startServer = () => { const server = app.listen(port, () => { diff --git a/src/taskService.js b/src/taskService.js index 19298d6..d9eaefc 100644 --- a/src/taskService.js +++ b/src/taskService.js @@ -14,8 +14,23 @@ function getAllTasks() { return tasks; } +function addTask(description) { + if (!description) { + throw new Error("La description est requise"); + } + const newId = tasks.reduce((max, task) => task.id > max ? task.id : max, 0) + 1; + const newTask = { + id: newId, + description: description, + done: false + }; + tasks.push(newTask); + return newTask; +} + //export des fonctions module.exports = { getAllTasks, - getTaskById + getTaskById, + addTask }; diff --git a/tests/integration/app.test.js b/tests/integration/app.test.js index dd7eb43..79bdebe 100644 --- a/tests/integration/app.test.js +++ b/tests/integration/app.test.js @@ -42,4 +42,26 @@ describe('GET /api/tasks/:id', () => { expect(res.body).toEqual({ error: 'Tâche non trouvée' }); }); +}); + +describe('POST /api/tasks', () => { + + test('should create a new task and return it', async () => { + const response = await request(app) + .post('/api/tasks') + .send({ description: "Nouvelle tâche" }); + expect(response.statusCode).toBe(201); + expect(response.body).toHaveProperty('id'); + expect(response.body.description).toBe("Nouvelle tâche"); + expect(response.body.done).toBe(false); + }); + + test('should return 400 if description is missing', async () => { + const response = await request(app) + .post('/api/tasks') + .send({}); + expect(response.statusCode).toBe(400); + expect(response.body).toHaveProperty('error', 'La description est requise'); + }); + }); \ No newline at end of file diff --git a/tests/unit/todoService.test.js b/tests/unit/todoService.test.js index 9c0157a..a5409b4 100644 --- a/tests/unit/todoService.test.js +++ b/tests/unit/todoService.test.js @@ -1,7 +1,7 @@ //test unitaire des fonctions de service // Import de la fonction à tester -const { getAllTasks , getTaskById} = require('../../src/taskService'); +const { getAllTasks, getTaskById, addTask } = require('../../src/taskService'); //Test de la fonction de récupération de toutes les tâches. test('should return all tasks', () => { @@ -17,4 +17,19 @@ test('should return the correct task for a given id', () => { test('should return undefined for a non-existent task id', () => { const task = getTaskById(999); - expect(task).toBeUndefined();}); \ No newline at end of file + expect(task).toBeUndefined(); +}); + +test('should add a new task with provided description', () => { + const initialLength = getAllTasks().length; + const description = "Nouvelle tâche"; + const newTask = addTask(description); + expect(newTask).toHaveProperty('id'); + expect(newTask.description).toBe(description); + expect(newTask.done).toBe(false); + expect(getAllTasks().length).toBe(initialLength + 1); +}); + +test('should throw an error if description is missing', () => { + expect(() => addTask()).toThrow("La description est requise"); +}); \ No newline at end of file -- GitLab From a76df305e630e3b037867a05c60a0fb4f0914b3e Mon Sep 17 00:00:00 2001 From: abouchtita <abouchtita@devops-tp.local> Date: Fri, 14 Mar 2025 17:36:39 +0100 Subject: [PATCH 4/5] Ajout de l'endpoint POST /api/tasks et de la fonction addTask --- src/taskService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/taskService.js b/src/taskService.js index d9eaefc..1ec2dd4 100644 --- a/src/taskService.js +++ b/src/taskService.js @@ -16,7 +16,7 @@ function getAllTasks() { function addTask(description) { if (!description) { - throw new Error("La description est requise"); + throw new Error('La description est requise'); } const newId = tasks.reduce((max, task) => task.id > max ? task.id : max, 0) + 1; const newTask = { -- GitLab From f33d6e20b05da28ee0c27e3a39c2429fabc65722 Mon Sep 17 00:00:00 2001 From: abouchtita <abouchtita@devops-tp.local> Date: Fri, 14 Mar 2025 17:40:59 +0100 Subject: [PATCH 5/5] =?UTF-8?q?Ajout=20de=20la=20suppression=20d'une=20t?= =?UTF-8?q?=C3=A2che=20(endpoint=20DELETE=20/api/tasks/:id)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 10 ++++++++++ src/taskService.js | 13 ++++++++++++- tests/integration/app.test.js | 25 +++++++++++++++++++++++++ tests/unit/todoService.test.js | 19 ++++++++++++++++++- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 94fa182..7c815b6 100644 --- a/src/index.js +++ b/src/index.js @@ -45,6 +45,16 @@ app.post('/api/tasks', (req, res) => { } }); +app.delete('/api/tasks/:id', (req, res) => { + const id = req.params.id; + const result = taskService.deleteTask(id); + if (result) { + res.status(204).send(); + } else { + res.status(404).json({ error: 'Tâche non trouvée' }); + } +}); + // Fonction pour démarrer le serveur const startServer = () => { const server = app.listen(port, () => { diff --git a/src/taskService.js b/src/taskService.js index 1ec2dd4..e564d91 100644 --- a/src/taskService.js +++ b/src/taskService.js @@ -28,9 +28,20 @@ function addTask(description) { return newTask; } +function deleteTask(id) { + const taskId = parseInt(id, 10); + const index = tasks.findIndex(task => task.id === taskId); + if (index === -1) { + return false; + } + tasks.splice(index, 1); + return true; +} + //export des fonctions module.exports = { getAllTasks, getTaskById, - addTask + addTask, + deleteTask }; diff --git a/tests/integration/app.test.js b/tests/integration/app.test.js index 79bdebe..c83e546 100644 --- a/tests/integration/app.test.js +++ b/tests/integration/app.test.js @@ -64,4 +64,29 @@ describe('POST /api/tasks', () => { expect(response.body).toHaveProperty('error', 'La description est requise'); }); +}); + + +describe('DELETE /api/tasks/:id', () => { + + test('should delete an existing task and return 204', async () => { + const addResponse = await request(app) + .post('/api/tasks') + .send({ description: "Task to delete via DELETE endpoint" }); + expect(addResponse.statusCode).toBe(201); + const taskId = addResponse.body.id; + + const deleteResponse = await request(app).delete(`/api/tasks/${taskId}`); + expect(deleteResponse.statusCode).toBe(204); + + const getResponse = await request(app).get(`/api/tasks/${taskId}`); + expect(getResponse.statusCode).toBe(404); + }); + + test('should return 404 when trying to delete a non-existent task', async () => { + const response = await request(app).delete('/api/tasks/99999'); + expect(response.statusCode).toBe(404); + expect(response.body).toEqual({ error: 'Tâche non trouvée' }); + }); + }); \ No newline at end of file diff --git a/tests/unit/todoService.test.js b/tests/unit/todoService.test.js index a5409b4..a252acc 100644 --- a/tests/unit/todoService.test.js +++ b/tests/unit/todoService.test.js @@ -1,7 +1,7 @@ //test unitaire des fonctions de service // Import de la fonction à tester -const { getAllTasks, getTaskById, addTask } = require('../../src/taskService'); +const { getAllTasks, getTaskById, addTask, deleteTask } = require('../../src/taskService'); //Test de la fonction de récupération de toutes les tâches. test('should return all tasks', () => { @@ -32,4 +32,21 @@ test('should add a new task with provided description', () => { test('should throw an error if description is missing', () => { expect(() => addTask()).toThrow("La description est requise"); +}); + +test('should delete a task with a valid id', () => { + const initialLength = getAllTasks().length; + + const newTask = addTask("Task to delete"); + expect(getAllTasks().length).toBe(initialLength + 1); + + const result = deleteTask(newTask.id); + expect(result).toBe(true); + + expect(getAllTasks().length).toBe(initialLength); +}); + +test('should return false when deleting a non-existent task', () => { + const result = deleteTask(999); + expect(result).toBe(false); }); \ No newline at end of file -- GitLab