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