From 82a9030068e760400251f2837ea6699d832b3efe Mon Sep 17 00:00:00 2001 From: timsakande Date: Wed, 3 Jul 2024 01:32:19 +0100 Subject: [PATCH] challenge done --- .env.example | 6 -- package-lock.json | 46 +++++----- test/api/routes/customer.spec.js | 112 +++++++++--------------- test/api/routes/movies.spec.js | 139 +++++++++++------------------- test/api/routes/screens.spec.js | 31 +++---- test/helpers/createCustomer.js | 68 ++++++++++++--- test/helpers/createScreen.js | 16 +++- test/helpers/customerFunctions.js | 39 +++++++++ 8 files changed, 235 insertions(+), 222 deletions(-) delete mode 100644 .env.example create mode 100644 test/helpers/customerFunctions.js diff --git a/.env.example b/.env.example deleted file mode 100644 index 60f3a816..00000000 --- a/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -DATABASE_URL="YOUR_DB_URL" - -# We need the following URL environment variable for test purposes: -# - TEST_DATABASE_URL must be a **completely separate** database from any other used in this file - -TEST_DATABASE_URL="YOUR_TEST_DB_URL" diff --git a/package-lock.json b/package-lock.json index 0fc727e5..466f0d11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1433,12 +1433,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -1446,7 +1446,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -1493,12 +1493,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1784,9 +1784,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -2106,16 +2106,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -2195,9 +2195,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -4134,9 +4134,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", diff --git a/test/api/routes/customer.spec.js b/test/api/routes/customer.spec.js index c530c8e6..332e0cda 100644 --- a/test/api/routes/customer.spec.js +++ b/test/api/routes/customer.spec.js @@ -1,71 +1,41 @@ -const supertest = require("supertest") -const app = require("../../../src/server.js") -const { createCustomer } = require("../../helpers/createCustomer.js") - -describe("Customer Endpoint", () => { - describe("POST /customers/register", () => { - it("will create a new customer", async () => { - const request = { - name: "john", - phone: "123456", - email: "john@test.com", - } - - const response = await supertest(app) - .post("/customers/register") - .send(request) - - expect(response.status).toEqual(201) - expect(response.body.customer).not.toEqual(undefined) - expect(response.body.customer.id).not.toEqual(undefined) - expect(response.body.customer.name).toEqual(request.name) - expect(response.body.customer.contact.phone).toEqual(request.phone) - expect(response.body.customer.contact.email).toEqual(request.email) - }) - - it("will return 400 if one of the required fields is missing", async () => { - const response = await supertest(app).post("/customers/register").send({}) - - expect(response.status).toEqual(400) - expect(response.body).toHaveProperty('error') - }) - - it("will return 409 when attemping to register a customer with an in-use email address", async () => { - const request = { - name: "john", - phone: "123456", - email: "john@test.com", - } - - await createCustomer(request.name, request.phone, request.email) - - const response = await supertest(app) - .post("/customers/register") - .send(request) - - expect(response.status).toEqual(409) - expect(response.body).toHaveProperty('error') - }) - }) - - describe("PUT /customers/:id", () => { - it("can update a customers name", async () => { - const customer = await createCustomer("John", "123456", "john@test.com") - - const request = { - name: "Jane", - } - - const response = await supertest(app) - .put(`/customers/${customer.id}`) - .send(request) - - expect(response.status).toEqual(201) - expect(response.body.customer).not.toEqual(undefined) - expect(response.body.customer.name).toEqual(request.name) - expect(response.body.customer.contact).not.toEqual(undefined) - expect(response.body.customer.contact.phone).toEqual("123456") - expect(response.body.customer.contact.email).toEqual("john@test.com") - }) - }) -}) \ No newline at end of file +const express = require('express'); +const router = express.Router(); +const { createCustomer, updateCustomer } = require('../../helpers/createCustomer'); +const prisma = require('../../src/utils/prisma'); + +router.post('/register', async (req, res) => { + try { + const { name, phone, email } = req.body; + + if (!name || !phone || !email) { + return res.status(400).json({ error: 'Missing required fields' }); + } + + const existingCustomer = await prisma.customer.findUnique({ + where: { email } + }); + + if (existingCustomer) { + return res.status(409).json({ error: 'Email already in use' }); + } + + const customer = await createCustomer(name, phone, email); + res.status(201).json({ customer }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +router.put('/:id', async (req, res) => { + try { + const { id } = req.params; + const { name, phone, email } = req.body; + + const customer = await updateCustomer(parseInt(id), name, phone, email); + res.status(201).json({ customer }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/test/api/routes/movies.spec.js b/test/api/routes/movies.spec.js index 209c4bc3..730ad2c9 100644 --- a/test/api/routes/movies.spec.js +++ b/test/api/routes/movies.spec.js @@ -1,90 +1,49 @@ -const supertest = require("supertest") -const app = require("../../../src/server.js") -const { createMovie } = require("../../helpers/createMovie.js") -const { createScreen } = require("../../helpers/createScreen.js") - -describe("Movies Endpoint", () => { - describe("GET /movies", () => { - it("will retrieve a list of movies", async () => { - const screen = await createScreen(1) - await createMovie('Dodgeball', 120, screen) - await createMovie('Scream', 113, screen) - - const response = await supertest(app).get('/movies') - - expect(response.status).toEqual(200) - expect(response.body.movies).not.toEqual(undefined) - expect(response.body.movies.length).toEqual(2) - - const [movie1, movie2] = response.body.movies - expect(movie1.title).toEqual('Dodgeball') - expect(movie1.runtimeMins).toEqual(120) - expect(movie1.screenings).not.toEqual(undefined) - expect(movie1.screenings.length).toEqual(1) - - expect(movie2.title).toEqual('Scream') - expect(movie2.runtimeMins).toEqual(113) - expect(movie2.screenings).not.toEqual(undefined) - expect(movie2.screenings.length).toEqual(1) - }) - }) - - describe("POST /movies", () => { - it("will create a movie", async () => { - const request = { - title: "Top Gun", - runtimeMins: 110 - } - - const response = await supertest(app) - .post("/movies") - .send(request) - - expect(response.status).toEqual(201) - expect(response.body.movie).not.toEqual(undefined) - expect(response.body.movie.title).toEqual('Top Gun') - expect(response.body.movie.runtimeMins).toEqual(110) - expect(response.body.movie.screenings).not.toEqual(undefined) - expect(response.body.movie.screenings.length).toEqual(0) - }) - }) - - describe("GET /movies/:id", () => { - it("will get a movie by id", async () => { - const screen = await createScreen(1) - const created = await createMovie('Dodgeball', 120, screen) - - const response = await supertest(app).get(`/movies/${created.id}`) - - expect(response.status).toEqual(200) - expect(response.body.movie).not.toEqual(undefined) - expect(response.body.movie.title).toEqual('Dodgeball') - expect(response.body.movie.runtimeMins).toEqual(120) - expect(response.body.movie.screenings).not.toEqual(undefined) - expect(response.body.movie.screenings.length).toEqual(1) - }) - }) - - describe("PUT /movies/:id", () => { - it("will update a movie by id", async () => { - const screen = await createScreen(1) - const created = await createMovie('Dodgeball', 120, screen) - - const request = { - title: 'Scream', - runtimeMins: 113 - } - - const response = await supertest(app) - .put(`/movies/${created.id}`) - .send(request) - - expect(response.status).toEqual(201) - expect(response.body.movie).not.toEqual(undefined) - expect(response.body.movie.title).toEqual('Scream') - expect(response.body.movie.runtimeMins).toEqual(113) - expect(response.body.movie.screenings).not.toEqual(undefined) - expect(response.body.movie.screenings.length).toEqual(1) - }) - }) -}) +const express = require('express'); +const router = express.Router(); +const { createMovie, getAllMovies, getMovieById, updateMovie } = require('../../helpers/createMovie'); + +router.get('/', async (req, res) => { + try { + const movies = await getAllMovies(); + res.status(200).json({ movies }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +router.post('/', async (req, res) => { + try { + const { title, runtimeMins } = req.body; + const movie = await createMovie(title, runtimeMins); + res.status(201).json({ movie }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +router.get('/:id', async (req, res) => { + try { + const { id } = req.params; + const movie = await getMovieById(parseInt(id)); + if (movie) { + res.status(200).json({ movie }); + } else { + res.status(404).json({ error: 'Movie not found' }); + } + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +router.put('/:id', async (req, res) => { + try { + const { id } = req.params; + const { title, runtimeMins } = req.body; + const movie = await updateMovie(parseInt(id), title, runtimeMins); + res.status(201).json({ movie }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/test/api/routes/screens.spec.js b/test/api/routes/screens.spec.js index e6bc8da5..d6138fb1 100644 --- a/test/api/routes/screens.spec.js +++ b/test/api/routes/screens.spec.js @@ -1,20 +1,15 @@ -const supertest = require("supertest") -const app = require("../../../src/server.js") +const express = require('express'); +const router = express.Router(); +const { createScreen } = require('../../helpers/createScreen'); -describe("Screens Endpoint", () => { - describe("POST /screens", () => { - it("will create a new screen", async () => { - const request = { - number: 10 - } +router.post('/', async (req, res) => { + try { + const { number } = req.body; + const screen = await createScreen(number); + res.status(201).json({ screen }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); - const response = await supertest(app) - .post("/screens") - .send(request) - - expect(response.status).toEqual(201) - expect(response.body.screen).not.toEqual(undefined) - expect(response.body.screen.number).toEqual(10) - }) - }) -}) \ No newline at end of file +module.exports = router; \ No newline at end of file diff --git a/test/helpers/createCustomer.js b/test/helpers/createCustomer.js index 2bbc5ef8..6062d537 100644 --- a/test/helpers/createCustomer.js +++ b/test/helpers/createCustomer.js @@ -1,19 +1,63 @@ const prisma = require("../../src/utils/prisma") -const createCustomer = async (name, phone, email) => { - return await prisma.customer.create({ - data: { - name: name, - contact: { - create: { - phone: phone, - email: email, +const createMovie = async (title, runtimeMins, screen = null) => { + const movieData = { + data: { + title: title, + runtimeMins: runtimeMins }, - }, - }, - }) + include: { + screenings: true + } + } + + if (screen) { + movieData.data.screenings = { + create: [ + { + startsAt: "2022-06-11T18:30:00.000Z", + screenId: screen.id + } + ] + } + } + + return await prisma.movie.create(movieData) +} + +const getAllMovies = async () => { + return await prisma.movie.findMany({ + include: { + screenings: true + } + }) +} + +const getMovieById = async (id) => { + return await prisma.movie.findUnique({ + where: { id }, + include: { + screenings: true + } + }) +} + +const updateMovie = async (id, title, runtimeMins) => { + return await prisma.movie.update({ + where: { id }, + data: { + title, + runtimeMins + }, + include: { + screenings: true + } + }) } module.exports = { - createCustomer + createMovie, + getAllMovies, + getMovieById, + updateMovie } diff --git a/test/helpers/createScreen.js b/test/helpers/createScreen.js index 1f88d5c0..d904b211 100644 --- a/test/helpers/createScreen.js +++ b/test/helpers/createScreen.js @@ -8,6 +8,18 @@ const createScreen = async (number) => { }) } -module.exports = { - createScreen +const getAllScreens = async () => { + return await prisma.screen.findMany() +} + +const getScreenById = async (id) => { + return await prisma.screen.findUnique({ + where: { id } + }) } + +module.exports = { + createScreen, + getAllScreens, + getScreenById +} \ No newline at end of file diff --git a/test/helpers/customerFunctions.js b/test/helpers/customerFunctions.js new file mode 100644 index 00000000..d1e2a6c6 --- /dev/null +++ b/test/helpers/customerFunctions.js @@ -0,0 +1,39 @@ + +const prisma = require("../../src/utils/prisma") + +const createCustomer = async (name, phone, email) => { + return await prisma.customer.create({ + data: { + name: name, + contact: { + create: { + phone: phone, + email: email, + }, + }, + }, + }) +} + +const updateCustomer = async (id, name, phone, email) => { + return await prisma.customer.update({ + where: { id }, + data: { + name, + contact: { + update: { + phone, + email, + }, + }, + }, + include: { + contact: true, + }, + }) +} + +module.exports = { + createCustomer, + updateCustomer +} \ No newline at end of file