From d57f959e6c88591b8734847d007a16144a3e0235 Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Wed, 29 Nov 2023 10:13:06 +0100 Subject: [PATCH 1/6] quest 1.2 done --- .env | 6 + .env.sample | 7 +- .gitignore | 1 + database.js | 12 ++ index.js | 3 +- package-lock.json | 193 +++++++++++++++++++++++++++- package.json | 4 +- src/app.js | 4 + src/controllers/movieControllers.js | 58 ++++----- src/controllers/userControllers.js | 36 ++++++ tests/users.test.js | 3 + 11 files changed, 289 insertions(+), 38 deletions(-) create mode 100644 .env create mode 100644 database.js create mode 100644 src/controllers/userControllers.js diff --git a/.env b/.env new file mode 100644 index 000000000..8a34a3a3e --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=GEB8hfap8! +DB_NAME=express_quests +APP_PORT=5000 \ No newline at end of file diff --git a/.env.sample b/.env.sample index d5349ec8a..64811ac87 100644 --- a/.env.sample +++ b/.env.sample @@ -1 +1,6 @@ -APP_PORT=5000 +DB_HOST=localhost +DB_PORT=3306 +DB_USER=YOUR_USERNAME +DB_PASSWORD=YOUR_PASSWORD +DB_NAME=DB_NAME +APP_PORT=YOUR_APP_PORT \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c3629e64..fe1b8129c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.env/ diff --git a/database.js b/database.js new file mode 100644 index 000000000..65d50db3a --- /dev/null +++ b/database.js @@ -0,0 +1,12 @@ +require("dotenv").config(); +const mysql = require("mysql2/promise"); + +const database = mysql.createPool({ + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, +}); + +module.exports = database; diff --git a/index.js b/index.js index d6626f115..6a5c56b9e 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ +require("dotenv").config(); const app = require("./src/app"); -const port = 5000; +const port = process.env.APP_PORT; app .listen(port, () => { diff --git a/package-lock.json b/package-lock.json index d6aeb7259..a47f916d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "express": "^4.18.2" + "dotenv": "^16.3.1", + "express": "^4.18.2", + "mysql2": "^3.6.5" }, "devDependencies": { "jest": "^29.7.0", @@ -1809,6 +1811,14 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1854,6 +1864,17 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2169,6 +2190,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2493,6 +2522,11 @@ "node": ">=0.12.0" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -3306,6 +3340,11 @@ "node": ">=8" } }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3468,6 +3507,62 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/mysql2": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.5.tgz", + "integrity": "sha512-pS/KqIb0xlXmtmqEuTvBXTmLoQ5LmAz5NW/r8UyQ1ldvnprNEj3P9GbmuQQ2J0A4LO+ynotGi6TbscPa8OUb+w==", + "dependencies": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mysql2/node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "engines": { + "node": ">=16.14" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4044,6 +4139,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -4164,6 +4264,14 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -6048,6 +6156,11 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6080,6 +6193,11 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6324,6 +6442,14 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -6552,6 +6678,11 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -7171,6 +7302,11 @@ "p-locate": "^4.1.0" } }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7293,6 +7429,51 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "mysql2": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.5.tgz", + "integrity": "sha512-pS/KqIb0xlXmtmqEuTvBXTmLoQ5LmAz5NW/r8UyQ1ldvnprNEj3P9GbmuQQ2J0A4LO+ynotGi6TbscPa8OUb+w==", + "requires": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==" + } + } + }, + "named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "requires": { + "lru-cache": "^7.14.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7705,6 +7886,11 @@ } } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -7803,6 +7989,11 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" + }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", diff --git a/package.json b/package.json index 64b8ae6d8..081afd753 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ }, "homepage": "https://github.com/WildCodeSchool/Express-Quests#readme", "dependencies": { - "express": "^4.18.2" + "dotenv": "^16.3.1", + "express": "^4.18.2", + "mysql2": "^3.6.5" }, "devDependencies": { "jest": "^29.7.0", diff --git a/src/app.js b/src/app.js index 19f5d86d4..b03d9d7ee 100644 --- a/src/app.js +++ b/src/app.js @@ -3,8 +3,12 @@ const express = require("express"); const app = express(); const movieControllers = require("./controllers/movieControllers"); +const userControllers = require("./controllers/userControllers"); app.get("/api/movies", movieControllers.getMovies); app.get("/api/movies/:id", movieControllers.getMovieById); +app.get("/api/users", userControllers.getUsers); +app.get("/api/users/:id", userControllers.getUserById); + module.exports = app; diff --git a/src/controllers/movieControllers.js b/src/controllers/movieControllers.js index e3bb0053f..7552df27e 100644 --- a/src/controllers/movieControllers.js +++ b/src/controllers/movieControllers.js @@ -1,44 +1,34 @@ -const movies = [ - { - id: 1, - title: "Citizen Kane", - director: "Orson Wells", - year: "1941", - color: false, - duration: 120, - }, - { - id: 2, - title: "The Godfather", - director: "Francis Ford Coppola", - year: "1972", - color: true, - duration: 180, - }, - { - id: 3, - title: "Pulp Fiction", - director: "Quentin Tarantino", - year: "1994", - color: true, - duration: 180, - }, -]; + +const database = require("../../database.js"); const getMovies = (req, res) => { - res.json(movies); + database + .query("select * from movies") + .then(([movies]) => { + res.json(movies); + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); }; const getMovieById = (req, res) => { const id = parseInt(req.params.id); - const movie = movies.find((movie) => movie.id === id); - - if (movie != null) { - res.json(movie); - } else { - res.status(404).send("Not Found"); - } + database + .query("select * from movies where id = ?", [id]) + .then(([movies]) => { + if (movies[0] != null) { + res.json(movies[0]); + } else { + res.sendStatus(404); + } + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); }; module.exports = { diff --git a/src/controllers/userControllers.js b/src/controllers/userControllers.js new file mode 100644 index 000000000..6a762bc4f --- /dev/null +++ b/src/controllers/userControllers.js @@ -0,0 +1,36 @@ +const database = require("../../database.js"); + +const getUsers = (req, res) => { + database + .query("select * from users") + .then(([users]) => { + res.json(users); + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); +}; + +const getUserById = (req, res) => { + const id = parseInt(req.params.id); + + database + .query("select * from users where id = ?", [id]) + .then(([users]) => { + if (users[0] != null) { + res.json(users[0]); + } else { + res.sendStatus(404); + } + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); +}; + +module.exports = { + getUsers, + getUserById, +}; diff --git a/tests/users.test.js b/tests/users.test.js index f69d5e9e0..df5d232e5 100644 --- a/tests/users.test.js +++ b/tests/users.test.js @@ -1,6 +1,9 @@ const request = require("supertest"); const app = require("../src/app"); +const database = require("../database") + +afterAll(() => database.end()); describe("GET /api/users", () => { it("should return all users", async () => { From d024b5bb42858982d64b89bbf76887f24ce28980 Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Wed, 29 Nov 2023 11:24:07 +0100 Subject: [PATCH 2/6] add post feature on users --- src/app.js | 4 ++++ src/controllers/movieControllers.js | 20 +++++++++++++++++++- src/controllers/userControllers.js | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/app.js b/src/app.js index b03d9d7ee..eaaa34902 100644 --- a/src/app.js +++ b/src/app.js @@ -1,6 +1,7 @@ const express = require("express"); const app = express(); +app.use(express.json()); const movieControllers = require("./controllers/movieControllers"); const userControllers = require("./controllers/userControllers"); @@ -11,4 +12,7 @@ app.get("/api/movies/:id", movieControllers.getMovieById); app.get("/api/users", userControllers.getUsers); app.get("/api/users/:id", userControllers.getUserById); +app.post("/api/movies", movieControllers.postMovie); +app.post("/api/users", userControllers.postUser); + module.exports = app; diff --git a/src/controllers/movieControllers.js b/src/controllers/movieControllers.js index 7552df27e..de660630d 100644 --- a/src/controllers/movieControllers.js +++ b/src/controllers/movieControllers.js @@ -1,4 +1,3 @@ - const database = require("../../database.js"); const getMovies = (req, res) => { @@ -31,7 +30,26 @@ const getMovieById = (req, res) => { }); }; +const postMovie = (req, res) => { + const { title, director, year, color, duration } = req.body; + + database + .query( + "INSERT INTO movies(title, director, year, color, duration) VALUES (?, ?, ?, ?, ?)", + [title, director, year, color, duration] + ) + .then(([result]) => { + res.status(201).send({ id: result.insertId }); + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); +}; + module.exports = { getMovies, getMovieById, + postMovie, + }; diff --git a/src/controllers/userControllers.js b/src/controllers/userControllers.js index 6a762bc4f..caa0cc3b7 100644 --- a/src/controllers/userControllers.js +++ b/src/controllers/userControllers.js @@ -29,8 +29,25 @@ const getUserById = (req, res) => { res.sendStatus(500); }); }; +const postUser = (req, res) => { + const { firstname, lastname, email, city, language } = req.body; + + database + .query( + "INSERT INTO users(firstname, lastname, email, city, language) VALUES ( ?, ?, ?, ?, ?)", + [firstname, lastname, email, city, language] + ) + .then(([result]) => { + res.status(201).send({ id: result.insertId }); + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); + }; module.exports = { getUsers, getUserById, + postUser, }; From 01eacfff9268aa0342d7c2e2a7a4a39b524694dd Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Wed, 29 Nov 2023 11:44:46 +0100 Subject: [PATCH 3/6] add tests --- src/controllers/movieControllers.js | 1 + tests/movies.test.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/controllers/movieControllers.js b/src/controllers/movieControllers.js index 7552df27e..d66d8d067 100644 --- a/src/controllers/movieControllers.js +++ b/src/controllers/movieControllers.js @@ -34,4 +34,5 @@ const getMovieById = (req, res) => { module.exports = { getMovies, getMovieById, + postMovie, }; diff --git a/tests/movies.test.js b/tests/movies.test.js index 09621f56f..41d5bc4dc 100644 --- a/tests/movies.test.js +++ b/tests/movies.test.js @@ -27,3 +27,22 @@ describe("GET /api/movies/:id", () => { expect(response.status).toEqual(404); }); }); + +describe("POST /api/movies", () => { + it("should return created movie", async () => { + const newMovie = { + title: "Star Wars", + director: "George Lucas", + year: "1977", + color: "1", + duration: 120, + }; + + const response = await request(app).post("/api/movies").send(newMovie); + + expect(response.status).toEqual(201); + expect(response.body).toHaveProperty("id"); + expect(typeof response.body.id).toBe("number"); + + }); +}); From a5da32059e862813cd6e2c99211d2c18e5d38ce7 Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Wed, 29 Nov 2023 16:44:06 +0100 Subject: [PATCH 4/6] tests on users done --- src/controllers/movieControllers.js | 1 - tests/movies.test.js | 41 ++++++++++++++++++++++++++++ tests/users.test.js | 42 +++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/controllers/movieControllers.js b/src/controllers/movieControllers.js index de660630d..015fc4757 100644 --- a/src/controllers/movieControllers.js +++ b/src/controllers/movieControllers.js @@ -51,5 +51,4 @@ module.exports = { getMovies, getMovieById, postMovie, - }; diff --git a/tests/movies.test.js b/tests/movies.test.js index 09621f56f..74d1fc1dc 100644 --- a/tests/movies.test.js +++ b/tests/movies.test.js @@ -1,4 +1,5 @@ const request = require("supertest"); +const database = require("../database.js"); const app = require("../src/app"); @@ -27,3 +28,43 @@ describe("GET /api/movies/:id", () => { expect(response.status).toEqual(404); }); }); + +describe("POST /api/movies", () => { + it("should return created movie", async () => { + const newMovie = { + title: "Star Wars", + director: "George Lucas", + year: "1977", + color: "1", + duration: 120, + }; + + const response = await request(app).post("/api/movies").send(newMovie); + + expect(response.status).toEqual(201); + expect(response.body).toHaveProperty("id"); + expect(typeof response.body.id).toBe("number"); + + const [result] = await database.query( + "SELECT * FROM movies WHERE id=?", + response.body.id + ); + + const [movieInDatabase] = result; + + expect(movieInDatabase).toHaveProperty("id"); + + expect(movieInDatabase).toHaveProperty("title"); + expect(movieInDatabase.title).toStrictEqual(newMovie.title); + }); + + it("should return an error", async () => { + const movieWithMissingProps = { title: "Harry Potter" }; + + const response = await request(app) + .post("/api/movies") + .send(movieWithMissingProps); + + expect(response.status).toEqual(500); + }); +}); diff --git a/tests/users.test.js b/tests/users.test.js index df5d232e5..a1d618ca9 100644 --- a/tests/users.test.js +++ b/tests/users.test.js @@ -2,6 +2,7 @@ const request = require("supertest"); const app = require("../src/app"); const database = require("../database") +const crypto = require("node:crypto"); afterAll(() => database.end()); @@ -30,3 +31,44 @@ describe("GET /api/users/:id", () => { expect(response.status).toEqual(404); }); }); + +describe("POST /api/users", () => { + it("should return created user", async () => { + const newUser = { + firstname: "Marie", + lastname: "Martin", + email: `${crypto.randomUUID()}@wild.co`, + city: "Paris", + language: "French", + }; + + const response = await request(app).post("/api/users").send(newUser); + + expect(response.status).toEqual(201); + expect(response.body).toHaveProperty("id"); + expect(typeof response.body.id).toBe("number"); + + const [result] = await database.query( + "SELECT * FROM users WHERE id=?", + response.body.id + ); + + const [userInDatabase] = result; + + expect(userInDatabase).toHaveProperty("id"); + + expect(userInDatabase).toHaveProperty("firstname"); + expect(userInDatabase.firstname).toStrictEqual(newUser.firstname); + }); + + it("should return an error", async () => { + const userWithMissingProps = { firstname: "kijijij" }; + + const response = await request(app) + .post("/api/users") + .send(userWithMissingProps); + + expect(response.status).toEqual(500); + }); +}); + From c9a22c4d9b694519c1ebc74b59e021aa1728c27f Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Thu, 30 Nov 2023 13:48:30 +0100 Subject: [PATCH 5/6] add test users --- src/app.js | 3 +- src/controllers/userControllers.js | 53 +++++++++++++----- tests/movies.test.js | 89 +++++++++++++++++++++++++++++- tests/users.test.js | 85 +++++++++++++++++++++++++++- 4 files changed, 210 insertions(+), 20 deletions(-) diff --git a/src/app.js b/src/app.js index fe0bc7094..2aa1c9ffe 100644 --- a/src/app.js +++ b/src/app.js @@ -15,6 +15,7 @@ app.get("/api/users/:id", userControllers.getUserById); app.post("/api/movies", movieControllers.postMovie); app.post("/api/users", userControllers.postUser); -app.put("/api/movies/:id", movieControllers.edit ) +app.put("/api/movies/:id", movieControllers.edit); +app.put("/api/users/:id", userControllers.edit); module.exports = app; diff --git a/src/controllers/userControllers.js b/src/controllers/userControllers.js index caa0cc3b7..0b3ce29c9 100644 --- a/src/controllers/userControllers.js +++ b/src/controllers/userControllers.js @@ -30,24 +30,47 @@ const getUserById = (req, res) => { }); }; const postUser = (req, res) => { - const { firstname, lastname, email, city, language } = req.body; - - database - .query( - "INSERT INTO users(firstname, lastname, email, city, language) VALUES ( ?, ?, ?, ?, ?)", - [firstname, lastname, email, city, language] - ) - .then(([result]) => { - res.status(201).send({ id: result.insertId }); - }) - .catch((err) => { - console.error(err); - res.sendStatus(500); - }); - }; + const { firstname, lastname, email, city, language } = req.body; + + database + .query( + "INSERT INTO users(firstname, lastname, email, city, language) VALUES ( ?, ?, ?, ?, ?)", + [firstname, lastname, email, city, language] + ) + .then(([result]) => { + res.status(201).send({ id: result.insertId }); + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); +}; + +const edit = (req, res) => { + const id = parseInt(req.params.id); + const { firstname, lastname, email, city, language } = req.body; + + database + .query( + "update users set firstname = ?, lastname = ?, email = ?, city = ?, language = ? where id = ?", + [firstname, lastname, email, city, language, id] + ) + .then(([result]) => { + if (result.affectedRows === 0) { + res.sendStatus(404); + } else { + res.sendStatus(204); + } + }) + .catch((err) => { + console.error(err); + res.sendStatus(500); + }); +}; module.exports = { getUsers, getUserById, postUser, + edit, }; diff --git a/tests/movies.test.js b/tests/movies.test.js index 70b0f0d58..41344b564 100644 --- a/tests/movies.test.js +++ b/tests/movies.test.js @@ -45,8 +45,6 @@ describe("POST /api/movies", () => { expect(response.body).toHaveProperty("id"); expect(typeof response.body.id).toBe("number"); -<<<<<<< HEAD -======= const [result] = await database.query( "SELECT * FROM movies WHERE id=?", response.body.id @@ -68,6 +66,91 @@ describe("POST /api/movies", () => { .send(movieWithMissingProps); expect(response.status).toEqual(500); ->>>>>>> b14d3879a5e7ce017ecddb3ddc4e6f9c3b9da71d + }); +}); + +describe("PUT /api/movies/:id", () => { + it("should edit movie", async () => { + const newMovie = { + title: "Avatar", + director: "James Cameron", + year: "2009", + color: "1", + duration: 162, + }; + const [result] = await database.query( + "INSERT INTO movies(title, director, year, color, duration) VALUES (?, ?, ?, ?, ?)", + [ + newMovie.title, + newMovie.director, + newMovie.year, + newMovie.color, + newMovie.duration, + ] + ); + + const id = result.insertId; + + const updatedMovie = { + title: "Wild is life", + director: "Alan Smithee", + year: "2023", + color: "0", + duration: 120, + }; + + const response = await request(app) + .put(`/api/movies/${id}`) + .send(updatedMovie); + + expect(response.status).toEqual(204); + + const [movies] = await database.query( + "SELECT * FROM movies WHERE id=?", + id + ); + + const [movieInDatabase] = movies; + + expect(movieInDatabase).toHaveProperty("id"); + + expect(movieInDatabase).toHaveProperty("title"); + expect(movieInDatabase.title).toStrictEqual(updatedMovie.title); + + expect(movieInDatabase).toHaveProperty("director"); + expect(movieInDatabase.director).toStrictEqual(updatedMovie.director); + + expect(movieInDatabase).toHaveProperty("year"); + expect(movieInDatabase.year).toStrictEqual(updatedMovie.year); + + expect(movieInDatabase).toHaveProperty("color"); + expect(movieInDatabase.color).toStrictEqual(updatedMovie.color); + + expect(movieInDatabase).toHaveProperty("duration"); + expect(movieInDatabase.duration).toStrictEqual(updatedMovie.duration); + }); + + it("should return an error", async () => { + const movieWithMissingProps = { title: "Harry Potter" }; + + const response = await request(app) + .put(`/api/movies/1`) + .send(movieWithMissingProps); + + expect(response.status).toEqual(500); + }); + + it("should return no movie", async () => { + const newMovie = { + title: "Avatar", + director: "James Cameron", + year: "2009", + color: "1", + duration: 162, + }; + + const response = await request(app).put("/api/movies/0").send(newMovie); + + expect(response.status).toEqual(404); }); }); diff --git a/tests/users.test.js b/tests/users.test.js index a1d618ca9..05804eaa3 100644 --- a/tests/users.test.js +++ b/tests/users.test.js @@ -1,8 +1,9 @@ const request = require("supertest"); const app = require("../src/app"); -const database = require("../database") +const database = require("../database"); const crypto = require("node:crypto"); +const exp = require("node:constants"); afterAll(() => database.end()); @@ -72,3 +73,85 @@ describe("POST /api/users", () => { }); }); +describe("PUT /api/users/:id", () => { + it("should edit user", async () => { + const newUser = { + firstname: "Patrick", + lastname: "Bruel", + email: `${crypto.randomUUID()}@wild.com`, + city: "Lille", + language: "French", + }; + const [result] = await database.query( + "INSERT INTO users(firstname, lastname, email, city, language) VALUES ( ?, ?, ?, ?, ?)", + [ + newUser.firstname, + newUser.lastname, + newUser.email, + newUser.city, + newUser.language, + ] + ); + + const id = result.insertId; + + const updatedUser = { + firstname: "Paul", + lastname: "Mirabel", + email: `${crypto.randomUUID()}@wcs.com`, + city: "Lyon", + language: "Suisse", + }; + + const response = await request(app) + .put(`/api/users/${id}`) + .send(updatedUser); + + expect(response.status).toEqual(204); + + const [users] = await database.query("SELECT * FROM users WHERE id=?", id); + + const [usersInDatabase] = users; + + expect(usersInDatabase).toHaveProperty("id"); + + expect(usersInDatabase).toHaveProperty("firstname"); + expect(usersInDatabase.firstname).toStrictEqual(updatedUser.firstname); + + expect(usersInDatabase).toHaveProperty("lastname"); + expect(usersInDatabase.lastname).toStrictEqual(updatedUser.lastname); + + expect(usersInDatabase).toHaveProperty("email"); + expect(usersInDatabase.email).toStrictEqual(updatedUser.email); + + expect(usersInDatabase).toHaveProperty("city"); + expect(usersInDatabase.city).toStrictEqual(updatedUser.city); + + expect(usersInDatabase).toHaveProperty("language"); + expect(usersInDatabase.language).toStrictEqual(updatedUser.language); + }); + + it("should return an error", async () => { + const userWithMissingProps = { firstname: "Michel" }; + + const response = await request(app) + .put(`/api/users/1`) + .send(userWithMissingProps); + + expect(response.status).toEqual(500); + }); + + it("should return no user", async () => { + const newUser = { + firstname: "Patrick", + lastname: "Bruel", + email: `${crypto.randomUUID()}@wild.co`, + city: "Lille", + language: "French", + }; + + const response = await request(app).put("/api/users/0").send(newUser); + + expect(response.status).toEqual(404); + }); +}); From 3c37e275c8bc820c59b39701251c54929ba9cde0 Mon Sep 17 00:00:00 2001 From: TRISTAN ZVUNKA Date: Fri, 1 Dec 2023 10:04:01 +0100 Subject: [PATCH 6/6] add delete --- src/app.js | 3 +++ src/controllers/movieControllers.js | 19 +++++++++++++++++++ src/controllers/userControllers.js | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/app.js b/src/app.js index 2aa1c9ffe..dc8d6f403 100644 --- a/src/app.js +++ b/src/app.js @@ -18,4 +18,7 @@ app.post("/api/users", userControllers.postUser); app.put("/api/movies/:id", movieControllers.edit); app.put("/api/users/:id", userControllers.edit); +app.delete("/api/movies/:id", movieControllers.deleteMovie); +app.delete("/api/users/:id", userControllers.deleteUser); + module.exports = app; diff --git a/src/controllers/movieControllers.js b/src/controllers/movieControllers.js index 9cb19070a..bc0b8de13 100644 --- a/src/controllers/movieControllers.js +++ b/src/controllers/movieControllers.js @@ -69,9 +69,28 @@ const edit = (req, res) => { }); }; +const deleteMovie = (req, res) => { + const id = parseInt(req.params.id); + database + .query ( + "DELETE FROM movies WHERE id = ?", [id] + ).then (([result]) => { + if (result.affectedRows === 0){ + res.sendStatus(404); + }else { + res.sendStatus(204); + } + }) + .catch ((error) => { +console.error(error); +res.sendStatus(500); + }); +} + module.exports = { getMovies, getMovieById, postMovie, edit, + deleteMovie }; diff --git a/src/controllers/userControllers.js b/src/controllers/userControllers.js index 0b3ce29c9..52f1287ee 100644 --- a/src/controllers/userControllers.js +++ b/src/controllers/userControllers.js @@ -68,9 +68,28 @@ const edit = (req, res) => { }); }; +const deleteUser = (req, res) => { + const id = parseInt(req.params.id); + database + .query ( + "DELETE FROM users WHERE id = ?", [id] + ).then (([result]) => { + if (result.affectedRows === 0){ + res.sendStatus(404); + }else { + res.sendStatus(204); + } + }) + .catch ((error) => { +console.error(error); +res.sendStatus(500); + }); +} + module.exports = { getUsers, getUserById, postUser, edit, + deleteUser, };