From eb26f00b4f47d43ec3c813f5a33be61f5381dc7f Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Mon, 1 Jul 2024 11:58:31 +0100 Subject: [PATCH 1/7] Inital endpoint creation --- .env.example | 6 --- src/controllers/customer.js | 77 ++++++++++++++++++------------------- src/controllers/movies.js | 75 ++++++++++++++++++++++++++++++++++++ src/controllers/screens.js | 20 ++++++++++ src/domains/customer.js | 35 +++++++++-------- src/domains/movies.js | 36 +++++++++++++++++ src/domains/screens.js | 10 +++++ src/index.js | 4 -- src/routers/customer.js | 16 +++----- src/routers/movies.js | 11 ++++++ src/routers/screens.js | 8 ++++ src/server.js | 28 ++++++++------ 12 files changed, 238 insertions(+), 88 deletions(-) delete mode 100644 .env.example create mode 100644 src/controllers/movies.js create mode 100644 src/controllers/screens.js create mode 100644 src/domains/movies.js create mode 100644 src/domains/screens.js create mode 100644 src/routers/movies.js create mode 100644 src/routers/screens.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/src/controllers/customer.js b/src/controllers/customer.js index 775cfb42..844848d7 100644 --- a/src/controllers/customer.js +++ b/src/controllers/customer.js @@ -1,48 +1,47 @@ -const { PrismaClientKnownRequestError } = require("@prisma/client") +const { PrismaClientKnownRequestError } = require('@prisma/client') const { createCustomerDb } = require('../domains/customer.js') const createCustomer = async (req, res) => { - const { - name, - phone, - email - } = req.body - - if (!name || !phone || !email) { - return res.status(400).json({ - error: "Missing fields in request body" - }) - } - - // Try-catch is a very common way to handle errors in JavaScript. - // It allows us to customise how we want errors that are thrown to be handled. - // Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch - - // Here, if Prisma throws an error in the process of trying to create a new customer, - // instead of the Prisma error being thrown (and the app potentially crashing) we exit the - // `try` block (bypassing the `res.status` code) and enter the `catch` block. - try { - const createdCustomer = await createCustomerDb(name, phone, email) - - res.status(201).json({ customer: createdCustomer }) - } catch (e) { - // In this catch block, we are able to specify how different Prisma errors are handled. - // Prisma throws errors with its own codes. P2002 is the error code for - // "Unique constraint failed on the {constraint}". In our case, the {constraint} is the - // email field which we have set as needing to be unique in the prisma.schema. - // To handle this, we return a custom 409 (conflict) error as a response to the client. - // Prisma error codes: https://www.prisma.io/docs/orm/reference/error-reference#common - // HTTP error codes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses - if (e instanceof PrismaClientKnownRequestError) { - if (e.code === "P2002") { - return res.status(409).json({ error: "A customer with the provided email already exists" }) - } + const { name, phone, email } = req.body + + if (!name || !phone || !email) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const createdCustomer = await createCustomerDb(name, phone, email) + + res.status(201).json({ customer: createdCustomer }) + } catch (e) { + if (e instanceof PrismaClientKnownRequestError) { + if (e.code === 'P2002') { + return res.status(409).json({ + error: 'A customer with the provided email already exists', + }) + } + } + + res.status(500).json({ error: e.message }) } +} + +const updateCustomer = async (req, res) => { + const { name } = req.body + + if (!name) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + const updatedCustomer = await createCustomerDb(name) - res.status(500).json({ error: e.message }) - } + return updatedCustomer } module.exports = { - createCustomer + createCustomer, + updateCustomer, } diff --git a/src/controllers/movies.js b/src/controllers/movies.js new file mode 100644 index 00000000..f7adc073 --- /dev/null +++ b/src/controllers/movies.js @@ -0,0 +1,75 @@ +const { run } = require('jest') +const { + createMovieDb, + getAllMoviesDb, + findMovieByIdDb, + updateMovieByIdDb, +} = require('../domains/movies.js') +const { NotFoundError, RecordNotFound } = require('@prisma/client') + +const getAllMovies = async (req, res) => { + const movies = await getAllMoviesDb() + + console.log(movies) + + return res.status(200).json(movies) +} + +const createMovie = async (req, res) => { + const { title, runtimeMins } = req.body + + if (!title || !runtimeMins) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const createdMovie = await createMovieDb(title, runtimeMins) + + res.status(201).json({ movie: createdMovie }) + } catch (e) { + res.status(500).json({ error: e.message }) + } +} + +const findMovieById = async (req, res) => { + const id = Number(req.params.id) + + try { + const searchedMovie = await findMovieByIdDb(id) + + res.status(200).json({ movie: searchedMovie }) + } catch (e) { + if (e instanceof NotFoundError) { + res.status(404).json({ error: e.message }) + } + + res.status(500).json({ error: e.message }) + } +} + +const updateMovieById = async (req, res) => { + const id = Number(req.params.id) + + const { title, runtimeMins } = req.body + + if (!title || !runtimeMins) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const updatedMovie = await updateMovieByIdDb(id, title, runtimeMins) + + res.status(201).json({ movie: updatedMovie }) + } catch (e) { + if (e instanceof RecordNotFound) { + res.status(404).json({ error: e.message }) + } + + res.status(500).json({ error: e.message }) + } +} +module.exports = { getAllMovies, createMovie, findMovieById , updateMovieById} diff --git a/src/controllers/screens.js b/src/controllers/screens.js new file mode 100644 index 00000000..f6d20af4 --- /dev/null +++ b/src/controllers/screens.js @@ -0,0 +1,20 @@ +const { createScreenDb } = require('../domains/screens.js') + +const createScreen = async (req, res) => { + const number = Number(req.body.number) + + if (!number) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const createdScreen = await createScreenDb(number) + + res.status(201).json({ screen: createdScreen }) + } catch (e) { + res.status(500).json({ error: e.message }) + } +} +module.exports = { createScreen } diff --git a/src/domains/customer.js b/src/domains/customer.js index c7f315fd..28822e59 100644 --- a/src/domains/customer.js +++ b/src/domains/customer.js @@ -4,23 +4,24 @@ const prisma = require('../utils/prisma') * This will create a Customer AND create a new Contact, then automatically relate them with each other * @tutorial https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record */ -const createCustomerDb = async (name, phone, email) => await prisma.customer.create({ - data: { - name, - contact: { - create: { - phone, - email - } - } - }, - // We add an `include` outside of the `data` object to make sure the new contact is returned in the result - // This is like doing RETURNING in SQL - include: { - contact: true - } -}) +const createCustomerDb = async (name, phone, email) => + await prisma.customer.create({ + data: { + name, + contact: { + create: { + phone, + email, + }, + }, + }, + // We add an `include` outside of the `data` object to make sure the new contact is returned in the result + // This is like doing RETURNING in SQL + include: { + contact: true, + }, + }) module.exports = { - createCustomerDb + createCustomerDb, } diff --git a/src/domains/movies.js b/src/domains/movies.js new file mode 100644 index 00000000..f958a684 --- /dev/null +++ b/src/domains/movies.js @@ -0,0 +1,36 @@ +const prisma = require('../utils/prisma') + +/** + * This will create a Customer AND create a new Contact, then automatically relate them with each other + * @tutorial https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record + */ +const createMovieDb = async (title, runtimeMins) => { + return await prisma.movie.create({ + data: { + title: title, + runtimeMins: runtimeMins, + }, + }) +} + +const getAllMoviesDb = async () => { + return await prisma.movie.findMany() +} + +const findMovieByIdDb = async (id) => { + return await prisma.movie.findUniqueOrThrow({ where: { id: id } }) +} + +const updateMovieByIdDb = async (id, title, runtimeMins) => { + return await prisma.movie.update({ + where: { + id: id, + }, + data: { + title: title, + runtimeMins: runtimeMins, + }, + }) +} + +module.exports = { createMovieDb, getAllMoviesDb, findMovieByIdDb , updateMovieByIdDb} diff --git a/src/domains/screens.js b/src/domains/screens.js new file mode 100644 index 00000000..88380868 --- /dev/null +++ b/src/domains/screens.js @@ -0,0 +1,10 @@ +const prisma = require('../utils/prisma') + +const createScreenDb = async (number) => + await prisma.screen.create({ + data: { + number: number, + }, + }) + +module.exports = { createScreenDb } diff --git a/src/index.js b/src/index.js index 52bef4e6..bc031f6f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,6 @@ -// Load our .env file require('dotenv').config(); -// Load app const app = require('./server.js') -// Set the port const port = process.env.PORT || 4040; -// Start our API server app.listen(port, () => { console.log(`\n Server is running on http://localhost:${port}\n`); }); diff --git a/src/routers/customer.js b/src/routers/customer.js index f14a87fc..9cacf844 100644 --- a/src/routers/customer.js +++ b/src/routers/customer.js @@ -1,13 +1,9 @@ -const express = require("express"); -const { - createCustomer -} = require('../controllers/customer'); +const express = require('express') +const { createCustomer , updateCustomer} = require('../controllers/customer') -const router = express.Router(); +const router = express.Router() -// In index.js, we told express that the /customer route should use this router file -// The below /register route extends that, so the end result will be a URL -// that looks like http://localhost:4040/customer/register -router.post("/register", createCustomer); +router.post('/register', createCustomer) +router.put('/:id', updateCustomer) -module.exports = router; +module.exports = router diff --git a/src/routers/movies.js b/src/routers/movies.js new file mode 100644 index 00000000..5d1a94c7 --- /dev/null +++ b/src/routers/movies.js @@ -0,0 +1,11 @@ +const express = require('express') +const {getAllMovies, createMovie, findMovieById, updateMovieById} = require('../controllers/movies') + +const router = express.Router() + +router.get('/', getAllMovies) +router.post('/', createMovie) +router.get('/:id', findMovieById) +router.put('/:id', updateMovieById) + +module.exports = router diff --git a/src/routers/screens.js b/src/routers/screens.js new file mode 100644 index 00000000..f602dd6c --- /dev/null +++ b/src/routers/screens.js @@ -0,0 +1,8 @@ +const express = require('express') +const { createScreen } = require('../controllers/screens') + +const router = express.Router() + +router.post('/', createScreen) + +module.exports = router \ No newline at end of file diff --git a/src/server.js b/src/server.js index 93d47a16..cc0f236e 100644 --- a/src/server.js +++ b/src/server.js @@ -1,21 +1,25 @@ -const express = require('express'); -const app = express(); +const express = require('express') +const app = express() -const cors = require('cors'); -const morgan = require('morgan'); +const cors = require('cors') +const morgan = require('morgan') -app.disable('x-powered-by'); +app.disable('x-powered-by') // Add middleware -app.use(cors()); -app.use(morgan('dev')); -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - +app.use(cors()) +app.use(morgan('dev')) +app.use(express.json()) +app.use(express.urlencoded({ extended: true })) // Tell express to use your routers here -const customerRouter = require('./routers/customer'); -app.use('/customers', customerRouter); +const customerRouter = require('./routers/customer') +app.use('/customers', customerRouter) + +const movieRouter = require('./routers/movies') +app.use('/movies', movieRouter) +const screenRouter = require('./routers/screens') +app.use('/screens', screenRouter) module.exports = app From 8b8ef5b23c13b0c4a289600d8666fd52dd2bfb6b Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Mon, 1 Jul 2024 14:43:11 +0100 Subject: [PATCH 2/7] Completed core critera --- src/controllers/customer.js | 13 +++++++++---- src/controllers/movies.js | 4 +--- src/domains/customer.js | 15 ++++++++++++++- src/domains/movies.js | 30 +++++++++++++++++++++++------- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/controllers/customer.js b/src/controllers/customer.js index 844848d7..fdc0311b 100644 --- a/src/controllers/customer.js +++ b/src/controllers/customer.js @@ -1,5 +1,5 @@ const { PrismaClientKnownRequestError } = require('@prisma/client') -const { createCustomerDb } = require('../domains/customer.js') +const { createCustomerDb, updateCustomerDb } = require('../domains/customer.js') const createCustomer = async (req, res) => { const { name, phone, email } = req.body @@ -30,15 +30,20 @@ const createCustomer = async (req, res) => { const updateCustomer = async (req, res) => { const { name } = req.body + const id = Number(req.params.id) + if (!name) { return res.status(400).json({ error: 'Missing fields in request body', }) } - const updatedCustomer = await createCustomerDb(name) - - return updatedCustomer + try { + const updatedCustomer = await updateCustomerDb(id, name) + res.status(201).json({ customer: updatedCustomer }) + } catch(e) { + res.status(500).json({ error: e.message }) + } } module.exports = { diff --git a/src/controllers/movies.js b/src/controllers/movies.js index f7adc073..883e48d8 100644 --- a/src/controllers/movies.js +++ b/src/controllers/movies.js @@ -10,9 +10,7 @@ const { NotFoundError, RecordNotFound } = require('@prisma/client') const getAllMovies = async (req, res) => { const movies = await getAllMoviesDb() - console.log(movies) - - return res.status(200).json(movies) + return res.status(200).json({movies: movies}) } const createMovie = async (req, res) => { diff --git a/src/domains/customer.js b/src/domains/customer.js index 28822e59..237816ee 100644 --- a/src/domains/customer.js +++ b/src/domains/customer.js @@ -22,6 +22,19 @@ const createCustomerDb = async (name, phone, email) => }, }) +const updateCustomerDb = async (id, name) => + await prisma.customer.update({ + where:{ + id:id + }, + data: { + name, + }, + include: { + contact: true, + }, + }) + module.exports = { - createCustomerDb, + createCustomerDb,updateCustomerDb } diff --git a/src/domains/movies.js b/src/domains/movies.js index f958a684..23910d94 100644 --- a/src/domains/movies.js +++ b/src/domains/movies.js @@ -1,24 +1,32 @@ const prisma = require('../utils/prisma') -/** - * This will create a Customer AND create a new Contact, then automatically relate them with each other - * @tutorial https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record - */ const createMovieDb = async (title, runtimeMins) => { return await prisma.movie.create({ data: { title: title, runtimeMins: runtimeMins, }, + include: { + screenings: true + } }) } const getAllMoviesDb = async () => { - return await prisma.movie.findMany() + return await prisma.movie.findMany({ + include: { + screenings: true, + }, + }) } const findMovieByIdDb = async (id) => { - return await prisma.movie.findUniqueOrThrow({ where: { id: id } }) + return await prisma.movie.findUniqueOrThrow({ + where: { id: id }, + include: { + screenings: true, + }, + }) } const updateMovieByIdDb = async (id, title, runtimeMins) => { @@ -30,7 +38,15 @@ const updateMovieByIdDb = async (id, title, runtimeMins) => { title: title, runtimeMins: runtimeMins, }, + include: { + screenings: true, + }, }) } -module.exports = { createMovieDb, getAllMoviesDb, findMovieByIdDb , updateMovieByIdDb} +module.exports = { + createMovieDb, + getAllMoviesDb, + findMovieByIdDb, + updateMovieByIdDb, +} From 98b473805c8fef5ec4c043218dba0e9e0a0626bc Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Mon, 1 Jul 2024 19:02:57 +0100 Subject: [PATCH 3/7] Start the creation of extension endpoints --- src/controllers/customer.js | 18 +++++++++----- src/controllers/screens.js | 3 ++- src/domains/customer.js | 35 ++++++++++++++++++++------ src/domains/movies.js | 49 ++++++++++++++++++++++++++++++++++--- src/domains/screens.js | 24 ++++++++++++++++-- 5 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/controllers/customer.js b/src/controllers/customer.js index fdc0311b..66c3637a 100644 --- a/src/controllers/customer.js +++ b/src/controllers/customer.js @@ -1,4 +1,7 @@ -const { PrismaClientKnownRequestError } = require('@prisma/client') +const { + PrismaClientKnownRequestError, + NotFoundError, +} = require('@prisma/client') const { createCustomerDb, updateCustomerDb } = require('../domains/customer.js') const createCustomer = async (req, res) => { @@ -28,7 +31,7 @@ const createCustomer = async (req, res) => { } const updateCustomer = async (req, res) => { - const { name } = req.body + const { name, contact } = req.body const id = Number(req.params.id) @@ -39,10 +42,13 @@ const updateCustomer = async (req, res) => { } try { - const updatedCustomer = await updateCustomerDb(id, name) - res.status(201).json({ customer: updatedCustomer }) - } catch(e) { - res.status(500).json({ error: e.message }) + const updatedCustomer = await updateCustomerDb(id, name, contact) + return res.status(201).json({ customer: updatedCustomer }) + } catch (e) { + if (e.code === 'P2025') { + return res.status(404).json({ error: e.message }) + } + return res.status(500).json({ error: e.message }) } } diff --git a/src/controllers/screens.js b/src/controllers/screens.js index f6d20af4..57da9d9a 100644 --- a/src/controllers/screens.js +++ b/src/controllers/screens.js @@ -2,6 +2,7 @@ const { createScreenDb } = require('../domains/screens.js') const createScreen = async (req, res) => { const number = Number(req.body.number) + const {screenings} = req.body if (!number) { return res.status(400).json({ @@ -10,7 +11,7 @@ const createScreen = async (req, res) => { } try { - const createdScreen = await createScreenDb(number) + const createdScreen = await createScreenDb(number, screenings) res.status(201).json({ screen: createdScreen }) } catch (e) { diff --git a/src/domains/customer.js b/src/domains/customer.js index 237816ee..dc590450 100644 --- a/src/domains/customer.js +++ b/src/domains/customer.js @@ -22,19 +22,40 @@ const createCustomerDb = async (name, phone, email) => }, }) -const updateCustomerDb = async (id, name) => - await prisma.customer.update({ - where:{ - id:id - }, - data: { +const updateCustomerDb = async (id, name, contact) => { + if (contact) { + return await prisma.customer.update({ + where: { + id: id, + }, + data: { + name, + contact: { + update: { + data: { email: contact.email, phone: contact.phone }, + }, + }, + }, + include: { + contact: true, + }, + }) + } + + return await prisma.customer.update({ + where: { + id: id, + }, + data: { name, }, include: { contact: true, }, }) +} module.exports = { - createCustomerDb,updateCustomerDb + createCustomerDb, + updateCustomerDb, } diff --git a/src/domains/movies.js b/src/domains/movies.js index 23910d94..502c561d 100644 --- a/src/domains/movies.js +++ b/src/domains/movies.js @@ -1,6 +1,23 @@ const prisma = require('../utils/prisma') -const createMovieDb = async (title, runtimeMins) => { +const createMovieDb = async (title, runtimeMins, screenings) => { + if(screenings) { + return await prisma.movie.create({ + data: { + title: title, + runtimeMins: runtimeMins, + screenings: { + createMany: { + data: screenings + } + } + }, + include: { + screenings: true + } + }) + } + return await prisma.movie.create({ data: { title: title, @@ -12,7 +29,18 @@ const createMovieDb = async (title, runtimeMins) => { }) } -const getAllMoviesDb = async () => { +const getAllMoviesDb = async (runtimeLt, runtimeGt) => { + const hasRuntimes = runtimeLt || runtimeGt + if(hasRuntimes) { + return await prisma.movie.findMany({ + include: { + screenings: true, + }, + where:{ + runtimeMins:{lt:runtimeLt, gt:runtimeGt} + } + }) + } return await prisma.movie.findMany({ include: { screenings: true, @@ -21,8 +49,23 @@ const getAllMoviesDb = async () => { } const findMovieByIdDb = async (id) => { + const parsedId = Number(id) + + if(isNaN(parsedId)) { + return findMovieByTitleDb(id) + } + return await prisma.movie.findUniqueOrThrow({ - where: { id: id }, + where: { id: parsedId }, + include: { + screenings: true, + }, + }) +} + +const findMovieByTitleDb = async (title) => { + return await prisma.movie.findUniqueOrThrow({ + where: { title:title }, include: { screenings: true, }, diff --git a/src/domains/screens.js b/src/domains/screens.js index 88380868..7169ac3f 100644 --- a/src/domains/screens.js +++ b/src/domains/screens.js @@ -1,10 +1,30 @@ const prisma = require('../utils/prisma') -const createScreenDb = async (number) => - await prisma.screen.create({ +const createScreenDb = async (number, screenings) => { + if (screenings) { + return await prisma.screen.create({ + data: { + number: number, + screenings: { + create: { + data: screenings, + }, + }, + }, + include: { + screenings: true, + }, + }) + } + + return await prisma.screen.create({ data: { number: number, }, + include: { + screenings: true, + }, }) +} module.exports = { createScreenDb } From 1b5c8e5ade2662430054c4d825a1f2f99bb89244 Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Tue, 2 Jul 2024 00:00:15 +0100 Subject: [PATCH 4/7] Add extension tests --- .../migration.sql | 12 ++ prisma/schema.prisma | 4 +- src/controllers/movies.js | 21 ++- src/controllers/screens.js | 10 +- src/controllers/tickets.js | 25 ++++ src/domains/screens.js | 2 +- src/domains/tickets.js | 49 ++++++ src/routers/customer.js | 2 +- src/routers/movies.js | 7 +- src/routers/screens.js | 2 +- src/routers/tickets.js | 8 + src/server.js | 3 + test/api/extensions/movies-ext.spec.js | 139 ++++++++++++++++++ test/api/extensions/tickets-ext.spec.js | 66 +++++++++ test/helpers/createScreening.js | 15 ++ 15 files changed, 347 insertions(+), 18 deletions(-) create mode 100644 prisma/migrations/20240701180956_unique_value_updates/migration.sql create mode 100644 src/controllers/tickets.js create mode 100644 src/domains/tickets.js create mode 100644 src/routers/tickets.js create mode 100644 test/api/extensions/movies-ext.spec.js create mode 100644 test/api/extensions/tickets-ext.spec.js create mode 100644 test/helpers/createScreening.js diff --git a/prisma/migrations/20240701180956_unique_value_updates/migration.sql b/prisma/migrations/20240701180956_unique_value_updates/migration.sql new file mode 100644 index 00000000..f8077248 --- /dev/null +++ b/prisma/migrations/20240701180956_unique_value_updates/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - A unique constraint covering the columns `[title]` on the table `Movie` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[number]` on the table `Screen` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "Movie_title_key" ON "Movie"("title"); + +-- CreateIndex +CREATE UNIQUE INDEX "Screen_number_key" ON "Screen"("number"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index dd9b27f1..7d1a3c7f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -33,7 +33,7 @@ model Contact { model Movie { id Int @id @default(autoincrement()) screenings Screening[] - title String + title String @unique runtimeMins Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -41,7 +41,7 @@ model Movie { model Screen { id Int @id @default(autoincrement()) - number Int + number Int @unique screenings Screening[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/src/controllers/movies.js b/src/controllers/movies.js index 883e48d8..e0612291 100644 --- a/src/controllers/movies.js +++ b/src/controllers/movies.js @@ -1,4 +1,3 @@ -const { run } = require('jest') const { createMovieDb, getAllMoviesDb, @@ -8,9 +7,11 @@ const { const { NotFoundError, RecordNotFound } = require('@prisma/client') const getAllMovies = async (req, res) => { - const movies = await getAllMoviesDb() + const { runtimeLt, runtimeGt } = req.query - return res.status(200).json({movies: movies}) + const movies = await getAllMoviesDb(runtimeLt, runtimeGt) + + return res.status(200).json({ movies: movies }) } const createMovie = async (req, res) => { @@ -27,20 +28,18 @@ const createMovie = async (req, res) => { res.status(201).json({ movie: createdMovie }) } catch (e) { - res.status(500).json({ error: e.message }) + return res.status(500).json({ error: e.message }) } } const findMovieById = async (req, res) => { - const id = Number(req.params.id) - try { - const searchedMovie = await findMovieByIdDb(id) + const searchedMovie = await findMovieByIdDb(req.params.id) res.status(200).json({ movie: searchedMovie }) } catch (e) { if (e instanceof NotFoundError) { - res.status(404).json({ error: e.message }) + return res.status(404).json({ error: e.message }) } res.status(500).json({ error: e.message }) @@ -63,11 +62,11 @@ const updateMovieById = async (req, res) => { res.status(201).json({ movie: updatedMovie }) } catch (e) { - if (e instanceof RecordNotFound) { - res.status(404).json({ error: e.message }) + if (e.code = 'P2015') { + return res.status(404).json({ error: e.message }) } res.status(500).json({ error: e.message }) } } -module.exports = { getAllMovies, createMovie, findMovieById , updateMovieById} +module.exports = { getAllMovies, createMovie, findMovieById, updateMovieById } diff --git a/src/controllers/screens.js b/src/controllers/screens.js index 57da9d9a..815cc714 100644 --- a/src/controllers/screens.js +++ b/src/controllers/screens.js @@ -2,7 +2,7 @@ const { createScreenDb } = require('../domains/screens.js') const createScreen = async (req, res) => { const number = Number(req.body.number) - const {screenings} = req.body + const { screenings } = req.body if (!number) { return res.status(400).json({ @@ -15,6 +15,14 @@ const createScreen = async (req, res) => { res.status(201).json({ screen: createdScreen }) } catch (e) { + if (e instanceof PrismaClientKnownRequestError) { + if (e.code === 'P2002') { + return res.status(409).json({ + error: 'A screen with the provided number already exists', + }) + } + } + res.status(500).json({ error: e.message }) } } diff --git a/src/controllers/tickets.js b/src/controllers/tickets.js new file mode 100644 index 00000000..8783ce9b --- /dev/null +++ b/src/controllers/tickets.js @@ -0,0 +1,25 @@ +const { createTicketDb } = require('../domains/tickets.js') + +const createTicket = async (req, res) => { + const { screeningId, customerId } = req.body + + if (!screeningId||!customerId) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const createdTicket = await createTicketDb(screeningId, customerId) + + res.status(201).json({ ticket: createdTicket }) + } catch (e) { + + if(e.message === 'P2015') { + return res.status(404).json({ error: "Matching customer or screening not found"}) + } + + res.status(500).json({ error: e.message }) + } +} +module.exports = { createTicket } diff --git a/src/domains/screens.js b/src/domains/screens.js index 7169ac3f..6dd50f2b 100644 --- a/src/domains/screens.js +++ b/src/domains/screens.js @@ -6,7 +6,7 @@ const createScreenDb = async (number, screenings) => { data: { number: number, screenings: { - create: { + createMany: { data: screenings, }, }, diff --git a/src/domains/tickets.js b/src/domains/tickets.js new file mode 100644 index 00000000..845ed26f --- /dev/null +++ b/src/domains/tickets.js @@ -0,0 +1,49 @@ +const prisma = require('../utils/prisma') +const { PrismaClientKnownRequestError } = require('@prisma/client') + +const createTicketDb = async (screeningId, customerId) => { + const screening = await prisma.screening.findUnique({ + where: { id: screeningId }, + include: { + movie: true, + screen: true, + }, + }) + + if (!screening) { + throw Error('P2015') + } + + const customer = await prisma.customer.findUnique({ + where: { id: customerId }, + include: { + contact: true, + }, + }) + + if (!customer) { + throw Error('P2015') + } + + return await prisma.ticket.create({ + data: { + screeningId: screeningId, + customerId: customerId, + }, + include: { + screening: { + include: { + movie: true, + screen: true, + }, + }, + customer: { + include: { + contact: true, + }, + }, + }, + }) +} + +module.exports = { createTicketDb } diff --git a/src/routers/customer.js b/src/routers/customer.js index 9cacf844..df01e09b 100644 --- a/src/routers/customer.js +++ b/src/routers/customer.js @@ -1,5 +1,5 @@ const express = require('express') -const { createCustomer , updateCustomer} = require('../controllers/customer') +const { createCustomer, updateCustomer } = require('../controllers/customer') const router = express.Router() diff --git a/src/routers/movies.js b/src/routers/movies.js index 5d1a94c7..158934f2 100644 --- a/src/routers/movies.js +++ b/src/routers/movies.js @@ -1,5 +1,10 @@ const express = require('express') -const {getAllMovies, createMovie, findMovieById, updateMovieById} = require('../controllers/movies') +const { + getAllMovies, + createMovie, + findMovieById, + updateMovieById, +} = require('../controllers/movies') const router = express.Router() diff --git a/src/routers/screens.js b/src/routers/screens.js index f602dd6c..5c73903a 100644 --- a/src/routers/screens.js +++ b/src/routers/screens.js @@ -5,4 +5,4 @@ const router = express.Router() router.post('/', createScreen) -module.exports = router \ No newline at end of file +module.exports = router diff --git a/src/routers/tickets.js b/src/routers/tickets.js new file mode 100644 index 00000000..3dba4f29 --- /dev/null +++ b/src/routers/tickets.js @@ -0,0 +1,8 @@ +const express = require('express') +const { createTicket } = require('../controllers/tickets') + +const router = express.Router() + +router.post('/', createTicket) + +module.exports = router diff --git a/src/server.js b/src/server.js index cc0f236e..4c955d3a 100644 --- a/src/server.js +++ b/src/server.js @@ -22,4 +22,7 @@ app.use('/movies', movieRouter) const screenRouter = require('./routers/screens') app.use('/screens', screenRouter) +const ticketRouter = require('./routers/tickets') +app.use('/tickets', ticketRouter) + module.exports = app diff --git a/test/api/extensions/movies-ext.spec.js b/test/api/extensions/movies-ext.spec.js new file mode 100644 index 00000000..dd127d95 --- /dev/null +++ b/test/api/extensions/movies-ext.spec.js @@ -0,0 +1,139 @@ +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) + }) + + it("will return 400 if fields are missing", async () => { + const request = { + title: "Top Gun" + } + + const response = await supertest(app) + .post("/movies") + .send(request) + + expect(response.status).toEqual(400) + expect(response.body.error).toEqual('Missing fields in request body') + }) + }) + + 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) + }) + + it("will return 404 if movie is not found", async () => { + const response = await supertest(app).get(`/movies/9999`) + + expect(response.status).toEqual(404) + expect(response.body.error).toContain('No Movie found') + }) + }) + + 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) + }) + + it("will return 400 if fields are missing", async () => { + const screen = await createScreen(1) + const created = await createMovie('Dodgeball', 120, screen) + + const request = { + title: 'Scream' + } + + const response = await supertest(app) + .put(`/movies/${created.id}`) + .send(request) + + expect(response.status).toEqual(400) + expect(response.body.error).toEqual('Missing fields in request body') + }) + + it("will return 404 if movie is not found", async () => { + const request = { + title: 'Scream', + runtimeMins: 113 + } + + const response = await supertest(app) + .put(`/movies/9999`) + .send(request) + + expect(response.status).toEqual(404) + }) + }) +}) diff --git a/test/api/extensions/tickets-ext.spec.js b/test/api/extensions/tickets-ext.spec.js new file mode 100644 index 00000000..fc6ceda3 --- /dev/null +++ b/test/api/extensions/tickets-ext.spec.js @@ -0,0 +1,66 @@ +const supertest = require('supertest') +const app = require('../../../src/server.js') +const { createMovie } = require('../../helpers/createMovie.js') +const { createScreen } = require('../../helpers/createScreen.js') +const { createCustomer } = require('../../helpers/createCustomer.js') +const { createScreening } = require('../../helpers/createScreening.js') + +describe('Tickets Endpoint', () => { + describe('POST /tickets', () => { + it('will create a ticket', async () => { + const screen = await createScreen(1) + const movie = await createMovie('Dodgeball', 120, screen) + + const screening = await createScreening( + screen.id, + movie.id, + new Date('2024-07-01T10:00:00Z') + ) + + const customer = await createCustomer( + 'John', + '077777777', + 'john.doe@example.com' + ) + + const request = { + screeningId: screening.id, + customerId: customer.id, + } + + const response = await supertest(app).post('/tickets').send(request) + + expect(response.status).toEqual(201) + expect(response.body.ticket).not.toEqual(undefined) + expect(response.body.ticket.screeningId).toEqual(screening.id) + expect(response.body.ticket.customerId).toEqual(customer.id) + }) + + it('will return 400 if fields are missing', async () => { + const request = { + screeningId: 1, + } + + const response = await supertest(app).post('/tickets').send(request) + + expect(response.status).toEqual(400) + expect(response.body.error).toEqual( + 'Missing fields in request body' + ) + }) + + it('will return 404 if matching customer or screening not found', async () => { + const request = { + screeningId: 9999, + customerId: 9999, + } + + const response = await supertest(app).post('/tickets').send(request) + + expect(response.status).toEqual(404) + expect(response.body.error).toEqual( + 'Matching customer or screening not found' + ) + }) + }) +}) diff --git a/test/helpers/createScreening.js b/test/helpers/createScreening.js new file mode 100644 index 00000000..3e52390f --- /dev/null +++ b/test/helpers/createScreening.js @@ -0,0 +1,15 @@ +const prisma = require("../../src/utils/prisma"); + +const createScreening = async (screenId,movieId,startsAt) => { + return await prisma.screening.create({ + data: { + screenId: screenId, + movieId: movieId, + startsAt: startsAt + } + }) +} + +module.exports = { + createScreening +} \ No newline at end of file From a67bc8b14d81dd8b5c10b00edc2ccddea2a0427a Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Tue, 2 Jul 2024 21:09:55 +0100 Subject: [PATCH 5/7] Extended extensions, update schema and seed --- .../20240702195852_reviews/migration.sql | 19 ++ prisma/schema.prisma | 12 ++ prisma/seed.js | 168 ++++++++++-------- src/controllers/movies.js | 2 +- src/domains/movies.js | 54 ++++-- test/api/extensions/movies-ext.spec.js | 89 +++++----- test/api/routes/movies.spec.js | 54 +++--- 7 files changed, 241 insertions(+), 157 deletions(-) create mode 100644 prisma/migrations/20240702195852_reviews/migration.sql diff --git a/prisma/migrations/20240702195852_reviews/migration.sql b/prisma/migrations/20240702195852_reviews/migration.sql new file mode 100644 index 00000000..e964e9cb --- /dev/null +++ b/prisma/migrations/20240702195852_reviews/migration.sql @@ -0,0 +1,19 @@ +-- CreateTable +CREATE TABLE "Review" ( + "id" SERIAL NOT NULL, + "movieId" INTEGER NOT NULL, + "customerId" INTEGER NOT NULL, + "rating" INTEGER NOT NULL, + "content" TEXT NOT NULL, + + CONSTRAINT "Review_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Review" ADD CONSTRAINT "Review_movieId_fkey" FOREIGN KEY ("movieId") REFERENCES "Movie"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Review" ADD CONSTRAINT "Review_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddCheckConstraint +ALTER TABLE "Review" ADD CONSTRAINT "Rating_check" CHECK ("rating" > 0 and "rating" <11) \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7d1a3c7f..dc8f9362 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -18,6 +18,7 @@ model Customer { tickets Ticket[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + reviews Review[] } model Contact { @@ -37,6 +38,17 @@ model Movie { runtimeMins Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + reviews Review[] +} + +model Review { + id Int @id @default(autoincrement()) + movieId Int + movie Movie? @relation(fields: [movieId], references: [id]) + customerId Int + customer Customer? @relation(fields: [customerId], references: [id]) + rating Int + content String } model Screen { diff --git a/prisma/seed.js b/prisma/seed.js index 31e28bfa..e1dfd517 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -1,105 +1,125 @@ -const { PrismaClient } = require('@prisma/client'); -const prisma = new PrismaClient(); +const { PrismaClient } = require('@prisma/client') +const prisma = new PrismaClient() async function seed() { - await createCustomer(); - const movies = await createMovies(); - const screens = await createScreens(); - await createScreenings(screens, movies); + const customer = await createCustomer() + const movies = await createMovies() + const screens = await createScreens() + await createScreenings(screens, movies) + await createReviews(customer, movies) - process.exit(0); + process.exit(0) } async function createCustomer() { - const customer = await prisma.customer.create({ - data: { - name: 'Alice', - contact: { - create: { - email: 'alice@boolean.co.uk', - phone: '1234567890' - } - } - }, - include: { - contact: true - } - }); - - console.log('Customer created', customer); - - return customer; + const customer = await prisma.customer.create({ + data: { + name: 'Alice', + contact: { + create: { + email: 'alice@boolean.co.uk', + phone: '1234567890', + }, + }, + }, + include: { + contact: true, + }, + }) + + console.log('Customer created', customer) + + return customer } async function createMovies() { - const rawMovies = [ - { title: 'The Matrix', runtimeMins: 120 }, - { title: 'Dodgeball', runtimeMins: 154 }, - ]; + const rawMovies = [ + { title: 'The Matrix', runtimeMins: 120 }, + { title: 'Dodgeball', runtimeMins: 154 }, + ] - const movies = []; + const movies = [] - for (const rawMovie of rawMovies) { - const movie = await prisma.movie.create({ data: rawMovie }); - movies.push(movie); - } + for (const rawMovie of rawMovies) { + const movie = await prisma.movie.create({ data: rawMovie }) + movies.push(movie) + } - console.log('Movies created', movies); + console.log('Movies created', movies) - return movies; + return movies } async function createScreens() { - const rawScreens = [ - { number: 1 }, { number: 2 } - ]; + const rawScreens = [{ number: 1 }, { number: 2 }] - const screens = []; + const screens = [] - for (const rawScreen of rawScreens) { - const screen = await prisma.screen.create({ - data: rawScreen - }); + for (const rawScreen of rawScreens) { + const screen = await prisma.screen.create({ + data: rawScreen, + }) - console.log('Screen created', screen); + console.log('Screen created', screen) - screens.push(screen); - } + screens.push(screen) + } - return screens; + return screens } async function createScreenings(screens, movies) { - const screeningDate = new Date(); + const screeningDate = new Date() + + for (const screen of screens) { + for (let i = 0; i < movies.length; i++) { + screeningDate.setDate(screeningDate.getDate() + i) + + const screening = await prisma.screening.create({ + data: { + startsAt: screeningDate, + movie: { + connect: { + id: movies[i].id, + }, + }, + screen: { + connect: { + id: screen.id, + }, + }, + }, + }) + + console.log('Screening created', screening) + } + } +} - for (const screen of screens) { - for (let i = 0; i < movies.length; i++) { - screeningDate.setDate(screeningDate.getDate() + i); +async function createReviews(customer, movies) { + const rawReviews = [ + { customerId: customer.id, movieId: movies[0].id, rating: 5 , content:"It was okay"}, + { customerId: customer.id, movieId: movies[1].id, rating: 9 , content:"I liked this"}, + ] - const screening = await prisma.screening.create({ - data: { - startsAt: screeningDate, - movie: { - connect: { - id: movies[i].id - } - }, - screen: { - connect: { - id: screen.id - } - } - } - }); + const reviews = [] - console.log('Screening created', screening); + for (const rawReview of rawReviews) { + const review = await prisma.review.create({ + data: rawReview, + }) + + console.log('Reviews created', review) + + reviews.push(review) } - } + + return reviews } seed() - .catch(async e => { - console.error(e); - await prisma.$disconnect(); - }) - .finally(() => process.exit(1)); + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + }) + .finally(() => process.exit(1)) diff --git a/src/controllers/movies.js b/src/controllers/movies.js index e0612291..fb8ef246 100644 --- a/src/controllers/movies.js +++ b/src/controllers/movies.js @@ -9,7 +9,7 @@ const { NotFoundError, RecordNotFound } = require('@prisma/client') const getAllMovies = async (req, res) => { const { runtimeLt, runtimeGt } = req.query - const movies = await getAllMoviesDb(runtimeLt, runtimeGt) + const movies = await getAllMoviesDb(Number(runtimeLt), Number(runtimeGt)) return res.status(200).json({ movies: movies }) } diff --git a/src/domains/movies.js b/src/domains/movies.js index 502c561d..03a1b78a 100644 --- a/src/domains/movies.js +++ b/src/domains/movies.js @@ -1,60 +1,76 @@ const prisma = require('../utils/prisma') const createMovieDb = async (title, runtimeMins, screenings) => { - if(screenings) { + if (screenings) { return await prisma.movie.create({ data: { title: title, runtimeMins: runtimeMins, screenings: { createMany: { - data: screenings - } - } + data: screenings, + }, + }, }, include: { - screenings: true - } + screenings: true, + }, }) } - + return await prisma.movie.create({ data: { title: title, runtimeMins: runtimeMins, }, include: { - screenings: true - } + screenings: true, + }, }) } const getAllMoviesDb = async (runtimeLt, runtimeGt) => { const hasRuntimes = runtimeLt || runtimeGt - if(hasRuntimes) { + if (hasRuntimes) { return await prisma.movie.findMany({ include: { - screenings: true, + screenings: { + where: { + startsAt: { gt: new Date(Date.now()).toISOString() }, + }, + }, + }, + where: { + runtimeMins: { lt: runtimeLt || 999999, gt: runtimeGt || 0 }, + screenings: { + some: { + startsAt: { gt: new Date(Date.now()).toISOString() }, + }, + }, }, - where:{ - runtimeMins:{lt:runtimeLt, gt:runtimeGt} - } }) } return await prisma.movie.findMany({ include: { - screenings: true, + screenings: { + where: { startsAt: { gt: new Date(Date.now()).toISOString() } }, + }, + }, + where: { + screenings: { + some: { startsAt: { gt: new Date(Date.now()).toISOString() } }, + }, }, }) } const findMovieByIdDb = async (id) => { const parsedId = Number(id) - - if(isNaN(parsedId)) { + + if (isNaN(parsedId)) { return findMovieByTitleDb(id) } - + return await prisma.movie.findUniqueOrThrow({ where: { id: parsedId }, include: { @@ -65,7 +81,7 @@ const findMovieByIdDb = async (id) => { const findMovieByTitleDb = async (title) => { return await prisma.movie.findUniqueOrThrow({ - where: { title:title }, + where: { title: title }, include: { screenings: true, }, diff --git a/test/api/extensions/movies-ext.spec.js b/test/api/extensions/movies-ext.spec.js index dd127d95..1aef34b5 100644 --- a/test/api/extensions/movies-ext.spec.js +++ b/test/api/extensions/movies-ext.spec.js @@ -1,44 +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 supertest = require('supertest') +const app = require('../../../src/server.js') +const { createMovie } = require('../../helpers/createMovie.js') +const { createScreen } = require('../../helpers/createScreen.js') +const { createScreening } = require('../../helpers/createScreening.js') + +describe('Movies Endpoint', () => { + describe('GET /movies', () => { + it('will retrieve a list of movies, but not include any without screenings in the future', async () => { const screen = await createScreen(1) - await createMovie('Dodgeball', 120, screen) - await createMovie('Scream', 113, screen) + const movie = await createMovie('Dodgeball', 120, screen) + const secondMovie = await createMovie('Scream', 113, screen) + + await createScreening( + screen.id, + movie.id, + new Date(Date.now() + 86400).toISOString() + ) + await createScreening( + screen.id, + secondMovie.id, + new Date(Date.now() - 86400).toISOString() + ) 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) + expect(response.body.movies.length).toEqual(1) - const [movie1, movie2] = response.body.movies + const [movie1] = 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 () => { + describe('POST /movies', () => { + it('will create a movie', async () => { const request = { - title: "Top Gun", - runtimeMins: 110 + title: 'Top Gun', + runtimeMins: 110, } - const response = await supertest(app) - .post("/movies") - .send(request) + const response = await supertest(app).post('/movies').send(request) expect(response.status).toEqual(201) expect(response.body.movie).not.toEqual(undefined) @@ -48,22 +53,22 @@ describe("Movies Endpoint", () => { expect(response.body.movie.screenings.length).toEqual(0) }) - it("will return 400 if fields are missing", async () => { + it('will return 400 if fields are missing', async () => { const request = { - title: "Top Gun" + title: 'Top Gun', } - const response = await supertest(app) - .post("/movies") - .send(request) + const response = await supertest(app).post('/movies').send(request) expect(response.status).toEqual(400) - expect(response.body.error).toEqual('Missing fields in request body') + expect(response.body.error).toEqual( + 'Missing fields in request body' + ) }) }) - describe("GET /movies/:id", () => { - it("will get a movie by id", async () => { + describe('GET /movies/:id', () => { + it('will get a movie by id', async () => { const screen = await createScreen(1) const created = await createMovie('Dodgeball', 120, screen) @@ -77,7 +82,7 @@ describe("Movies Endpoint", () => { expect(response.body.movie.screenings.length).toEqual(1) }) - it("will return 404 if movie is not found", async () => { + it('will return 404 if movie is not found', async () => { const response = await supertest(app).get(`/movies/9999`) expect(response.status).toEqual(404) @@ -85,14 +90,14 @@ describe("Movies Endpoint", () => { }) }) - describe("PUT /movies/:id", () => { - it("will update a movie by id", async () => { + 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 + runtimeMins: 113, } const response = await supertest(app) @@ -107,12 +112,12 @@ describe("Movies Endpoint", () => { expect(response.body.movie.screenings.length).toEqual(1) }) - it("will return 400 if fields are missing", async () => { + it('will return 400 if fields are missing', async () => { const screen = await createScreen(1) const created = await createMovie('Dodgeball', 120, screen) const request = { - title: 'Scream' + title: 'Scream', } const response = await supertest(app) @@ -120,13 +125,15 @@ describe("Movies Endpoint", () => { .send(request) expect(response.status).toEqual(400) - expect(response.body.error).toEqual('Missing fields in request body') + expect(response.body.error).toEqual( + 'Missing fields in request body' + ) }) - it("will return 404 if movie is not found", async () => { + it('will return 404 if movie is not found', async () => { const request = { title: 'Scream', - runtimeMins: 113 + runtimeMins: 113, } const response = await supertest(app) diff --git a/test/api/routes/movies.spec.js b/test/api/routes/movies.spec.js index 209c4bc3..862d8cb8 100644 --- a/test/api/routes/movies.spec.js +++ b/test/api/routes/movies.spec.js @@ -1,14 +1,26 @@ -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 supertest = require('supertest') +const app = require('../../../src/server.js') +const { createMovie } = require('../../helpers/createMovie.js') +const { createScreen } = require('../../helpers/createScreen.js') +const { createScreening } = require('../../helpers/createScreening.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 movie = await createMovie('Dodgeball', 120, screen) + const secondMovie = await createMovie('Scream', 113, screen) + + await createScreening( + screen.id, + movie.id, + new Date(Date.now() + 86400).toISOString() + ) + await createScreening( + screen.id, + secondMovie.id, + new Date(Date.now() + 86400).toISOString() + ) const response = await supertest(app).get('/movies') @@ -29,16 +41,14 @@ describe("Movies Endpoint", () => { }) }) - describe("POST /movies", () => { - it("will create a movie", async () => { + describe('POST /movies', () => { + it('will create a movie', async () => { const request = { - title: "Top Gun", - runtimeMins: 110 + title: 'Top Gun', + runtimeMins: 110, } - const response = await supertest(app) - .post("/movies") - .send(request) + const response = await supertest(app).post('/movies').send(request) expect(response.status).toEqual(201) expect(response.body.movie).not.toEqual(undefined) @@ -49,8 +59,8 @@ describe("Movies Endpoint", () => { }) }) - describe("GET /movies/:id", () => { - it("will get a movie by id", async () => { + describe('GET /movies/:id', () => { + it('will get a movie by id', async () => { const screen = await createScreen(1) const created = await createMovie('Dodgeball', 120, screen) @@ -65,14 +75,14 @@ describe("Movies Endpoint", () => { }) }) - describe("PUT /movies/:id", () => { - it("will update a movie by id", async () => { + 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 + runtimeMins: 113, } const response = await supertest(app) From f8033c40e3f7a4935e38780b1ccaafad33a9e806 Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Tue, 2 Jul 2024 22:26:02 +0100 Subject: [PATCH 6/7] Complete reviews endpoint and tests --- prisma/schema.prisma | 84 ++++++++++++------------ prisma/seed.js | 14 +++- src/controllers/customer.js | 5 +- src/controllers/movies.js | 2 +- src/controllers/reviews.js | 31 +++++++++ src/controllers/tickets.js | 9 +-- src/domains/movies.js | 2 + src/domains/reviews.js | 30 +++++++++ src/domains/tickets.js | 13 +--- src/routers/reviews.js | 8 +++ src/server.js | 3 + test/api/extensions/customer-ext.spec.js | 42 +++++++----- test/api/extensions/movies-ext.spec.js | 4 +- test/api/extensions/reviews-ext.spec.js | 53 +++++++++++++++ test/api/routes/movies.spec.js | 4 +- test/api/routes/screens.spec.js | 18 +++-- test/helpers/createScreening.js | 12 ++-- test/setupTests.js | 31 ++++----- 18 files changed, 250 insertions(+), 115 deletions(-) create mode 100644 src/controllers/reviews.js create mode 100644 src/domains/reviews.js create mode 100644 src/routers/reviews.js create mode 100644 test/api/extensions/reviews-ext.spec.js diff --git a/prisma/schema.prisma b/prisma/schema.prisma index dc8f9362..8869ada5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,23 +12,23 @@ datasource db { // https://www.prisma.io/docs/concepts/components/prisma-schema/data-model model Customer { - id Int @id @default(autoincrement()) - name String - contact Contact? - tickets Ticket[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - reviews Review[] + id Int @id @default(autoincrement()) + name String + contact Contact? + tickets Ticket[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + reviews Review[] } model Contact { - id Int @id @default(autoincrement()) - customer Customer @relation(fields: [customerId], references: [id]) - customerId Int @unique - phone String - email String @unique - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + customer Customer @relation(fields: [customerId], references: [id]) + customerId Int @unique + phone String + email String @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Movie { @@ -42,41 +42,41 @@ model Movie { } model Review { - id Int @id @default(autoincrement()) - movieId Int - movie Movie? @relation(fields: [movieId], references: [id]) - customerId Int - customer Customer? @relation(fields: [customerId], references: [id]) - rating Int - content String + id Int @id @default(autoincrement()) + movieId Int + movie Movie? @relation(fields: [movieId], references: [id]) + customerId Int + customer Customer? @relation(fields: [customerId], references: [id]) + rating Int + content String } model Screen { - id Int @id @default(autoincrement()) - number Int @unique - screenings Screening[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + number Int @unique + screenings Screening[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Screening { - id Int @id @default(autoincrement()) - tickets Ticket[] - movie Movie @relation(fields: [movieId], references: [id]) - movieId Int - screen Screen @relation(fields: [screenId], references: [id]) - screenId Int - startsAt DateTime - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + tickets Ticket[] + movie Movie @relation(fields: [movieId], references: [id]) + movieId Int + screen Screen @relation(fields: [screenId], references: [id]) + screenId Int + startsAt DateTime + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Ticket { - id Int @id @default(autoincrement()) - screening Screening @relation(fields: [screeningId], references: [id]) - screeningId Int - customer Customer @relation(fields: [customerId], references: [id]) - customerId Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + screening Screening @relation(fields: [screeningId], references: [id]) + screeningId Int + customer Customer @relation(fields: [customerId], references: [id]) + customerId Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } diff --git a/prisma/seed.js b/prisma/seed.js index e1dfd517..50222a8d 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -98,8 +98,18 @@ async function createScreenings(screens, movies) { async function createReviews(customer, movies) { const rawReviews = [ - { customerId: customer.id, movieId: movies[0].id, rating: 5 , content:"It was okay"}, - { customerId: customer.id, movieId: movies[1].id, rating: 9 , content:"I liked this"}, + { + customerId: customer.id, + movieId: movies[0].id, + rating: 5, + content: 'It was okay', + }, + { + customerId: customer.id, + movieId: movies[1].id, + rating: 9, + content: 'I liked this', + }, ] const reviews = [] diff --git a/src/controllers/customer.js b/src/controllers/customer.js index 66c3637a..4085ac71 100644 --- a/src/controllers/customer.js +++ b/src/controllers/customer.js @@ -1,7 +1,4 @@ -const { - PrismaClientKnownRequestError, - NotFoundError, -} = require('@prisma/client') +const { PrismaClientKnownRequestError } = require('@prisma/client') const { createCustomerDb, updateCustomerDb } = require('../domains/customer.js') const createCustomer = async (req, res) => { diff --git a/src/controllers/movies.js b/src/controllers/movies.js index fb8ef246..6d6ffb85 100644 --- a/src/controllers/movies.js +++ b/src/controllers/movies.js @@ -62,7 +62,7 @@ const updateMovieById = async (req, res) => { res.status(201).json({ movie: updatedMovie }) } catch (e) { - if (e.code = 'P2015') { + if ((e.code = 'P2015')) { return res.status(404).json({ error: e.message }) } diff --git a/src/controllers/reviews.js b/src/controllers/reviews.js new file mode 100644 index 00000000..db4fb06c --- /dev/null +++ b/src/controllers/reviews.js @@ -0,0 +1,31 @@ +const { createReviewDb } = require('../domains/reviews.js') + +const createReview = async (req, res) => { + const { customerId, movieId, rating, content } = req.body + + if (!customerId || !movieId || !rating || !content) { + return res.status(400).json({ + error: 'Missing fields in request body', + }) + } + + try { + const createdReview = await createReviewDb( + customerId, + movieId, + rating, + content + ) + + res.status(201).json({ review: createdReview }) + } catch (e) { + if (e.code === 'P2025') { + return res + .status(404) + .json({ error: 'Matching customer or movie not found' }) + } + + res.status(500).json({ error: e.message }) + } +} +module.exports = { createReview } diff --git a/src/controllers/tickets.js b/src/controllers/tickets.js index 8783ce9b..89bc241b 100644 --- a/src/controllers/tickets.js +++ b/src/controllers/tickets.js @@ -3,7 +3,7 @@ const { createTicketDb } = require('../domains/tickets.js') const createTicket = async (req, res) => { const { screeningId, customerId } = req.body - if (!screeningId||!customerId) { + if (!screeningId || !customerId) { return res.status(400).json({ error: 'Missing fields in request body', }) @@ -14,9 +14,10 @@ const createTicket = async (req, res) => { res.status(201).json({ ticket: createdTicket }) } catch (e) { - - if(e.message === 'P2015') { - return res.status(404).json({ error: "Matching customer or screening not found"}) + if (e.code === 'P2025') { + return res + .status(404) + .json({ error: 'Matching customer or screening not found' }) } res.status(500).json({ error: e.message }) diff --git a/src/domains/movies.js b/src/domains/movies.js index 03a1b78a..ee3a9761 100644 --- a/src/domains/movies.js +++ b/src/domains/movies.js @@ -39,6 +39,7 @@ const getAllMoviesDb = async (runtimeLt, runtimeGt) => { startsAt: { gt: new Date(Date.now()).toISOString() }, }, }, + reviews: true, }, where: { runtimeMins: { lt: runtimeLt || 999999, gt: runtimeGt || 0 }, @@ -55,6 +56,7 @@ const getAllMoviesDb = async (runtimeLt, runtimeGt) => { screenings: { where: { startsAt: { gt: new Date(Date.now()).toISOString() } }, }, + reviews: true, }, where: { screenings: { diff --git a/src/domains/reviews.js b/src/domains/reviews.js new file mode 100644 index 00000000..afe10d9c --- /dev/null +++ b/src/domains/reviews.js @@ -0,0 +1,30 @@ +const prisma = require('../utils/prisma') + +const createReviewDb = async (customerId, movieId, rating, content) => { + await prisma.movie.findUniqueOrThrow({ + where: { id: movieId }, + }) + + await prisma.customer.findUniqueOrThrow({ + where: { id: customerId }, + }) + + return await prisma.review.create({ + data: { + customerId: customerId, + movieId: movieId, + rating: rating, + content: content, + }, + include: { + movie: true, + customer: { + include: { + contact: true, + }, + }, + }, + }) +} + +module.exports = { createReviewDb } diff --git a/src/domains/tickets.js b/src/domains/tickets.js index 845ed26f..77070394 100644 --- a/src/domains/tickets.js +++ b/src/domains/tickets.js @@ -1,8 +1,7 @@ const prisma = require('../utils/prisma') -const { PrismaClientKnownRequestError } = require('@prisma/client') const createTicketDb = async (screeningId, customerId) => { - const screening = await prisma.screening.findUnique({ + await prisma.screening.findUniqueOrThrow({ where: { id: screeningId }, include: { movie: true, @@ -10,21 +9,13 @@ const createTicketDb = async (screeningId, customerId) => { }, }) - if (!screening) { - throw Error('P2015') - } - - const customer = await prisma.customer.findUnique({ + await prisma.customer.findUniqueOrThrow({ where: { id: customerId }, include: { contact: true, }, }) - if (!customer) { - throw Error('P2015') - } - return await prisma.ticket.create({ data: { screeningId: screeningId, diff --git a/src/routers/reviews.js b/src/routers/reviews.js new file mode 100644 index 00000000..368a9a70 --- /dev/null +++ b/src/routers/reviews.js @@ -0,0 +1,8 @@ +const express = require('express') +const { createReview } = require('../controllers/reviews') + +const router = express.Router() + +router.post('/', createReview) + +module.exports = router diff --git a/src/server.js b/src/server.js index 4c955d3a..ae71b78b 100644 --- a/src/server.js +++ b/src/server.js @@ -25,4 +25,7 @@ app.use('/screens', screenRouter) const ticketRouter = require('./routers/tickets') app.use('/tickets', ticketRouter) +const reviewRouter = require('./routers/reviews') +app.use('/reviews', reviewRouter) + module.exports = app diff --git a/test/api/extensions/customer-ext.spec.js b/test/api/extensions/customer-ext.spec.js index fee884bb..bb48e6ed 100644 --- a/test/api/extensions/customer-ext.spec.js +++ b/test/api/extensions/customer-ext.spec.js @@ -1,18 +1,22 @@ -const supertest = require("supertest") -const app = require("../../../src/server.js") -const { createCustomer } = require("../../helpers/createCustomer.js") +const supertest = require('supertest') +const app = require('../../../src/server.js') +const { createCustomer } = require('../../helpers/createCustomer.js') -describe("Customer Endpoint", () => { - describe("PUT /customers/:id", () => { - it("can update a customers contact info when a contact property exists on the request body", async () => { - const customer = await createCustomer("John", "123456", "john@test.com") +describe('Customer Endpoint', () => { + describe('PUT /customers/:id', () => { + it('can update a customers contact info when a contact property exists on the request body', async () => { + const customer = await createCustomer( + 'John', + '123456', + 'john@test.com' + ) const request = { - name: "Jane", + name: 'Jane', contact: { - phone: "789", - email: "jane@test.com" - } + phone: '789', + email: 'jane@test.com', + }, } const response = await supertest(app) @@ -23,13 +27,15 @@ describe("Customer Endpoint", () => { 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("789") - expect(response.body.customer.contact.email).toEqual("jane@test.com") + expect(response.body.customer.contact.phone).toEqual('789') + expect(response.body.customer.contact.email).toEqual( + 'jane@test.com' + ) }) it('will return 404 if the customer is not found', async () => { const request = { - name: "Jane", + name: 'Jane', } const response = await supertest(app) @@ -40,8 +46,12 @@ describe("Customer Endpoint", () => { expect(response.body).toHaveProperty('error') }) - it("will return 400 when there are missing fields in the request body", async () => { - const customer = await createCustomer("John", "123456", "john@test.com") + it('will return 400 when there are missing fields in the request body', async () => { + const customer = await createCustomer( + 'John', + '123456', + 'john@test.com' + ) const request = {} diff --git a/test/api/extensions/movies-ext.spec.js b/test/api/extensions/movies-ext.spec.js index 1aef34b5..842c7e93 100644 --- a/test/api/extensions/movies-ext.spec.js +++ b/test/api/extensions/movies-ext.spec.js @@ -8,8 +8,8 @@ describe('Movies Endpoint', () => { describe('GET /movies', () => { it('will retrieve a list of movies, but not include any without screenings in the future', async () => { const screen = await createScreen(1) - const movie = await createMovie('Dodgeball', 120, screen) - const secondMovie = await createMovie('Scream', 113, screen) + const movie = await createMovie('Dodgeball', 120) + const secondMovie = await createMovie('Scream', 113) await createScreening( screen.id, diff --git a/test/api/extensions/reviews-ext.spec.js b/test/api/extensions/reviews-ext.spec.js new file mode 100644 index 00000000..7a5d74cf --- /dev/null +++ b/test/api/extensions/reviews-ext.spec.js @@ -0,0 +1,53 @@ +const supertest = require('supertest') +const app = require('../../../src/server.js') +const { createCustomer } = require('../../helpers/createCustomer.js') +const { createMovie } = require('../../helpers/createMovie.js') + +describe('Reviews endpoint', () => { + describe('POST /reviews', () => { + it('will create a review', async () => { + const customer = await createCustomer( + 'John', + '077777777', + 'john.doe@example.com' + ) + + const movie = await createMovie('Dodgeball', 120) + + const request = { + customerId: customer.id, + movieId: movie.id, + rating: 9, + content: 'Movie reviewed', + } + + const response = await supertest(app).post('/reviews').send(request) + + expect(response.status).toEqual(201) + expect(response.body.review).not.toEqual(undefined) + expect(response.body.review.movieId).toEqual(movie.id) + expect(response.body.review.customerId).toEqual(customer.id) + expect(response.body.review.rating).toEqual(request.rating) + expect(response.body.review.content).toEqual(request.content) + }) + + it('will return 400 if one of the required fields is missing', async () => { + const response = await supertest(app).post('/reviews').send({}) + + expect(response.status).toEqual(400) + expect(response.body).toHaveProperty('error') + }) + + it('will return 404 if the id does not match a record', async () => { + const response = await supertest(app).post('/reviews').send({ + customerId: 999999, + movieId: 1, + rating: 9, + content: 'Movie reviewed', + }) + + expect(response.status).toEqual(404) + expect(response.body).toHaveProperty('error') + }) + }) +}) diff --git a/test/api/routes/movies.spec.js b/test/api/routes/movies.spec.js index 862d8cb8..56af877b 100644 --- a/test/api/routes/movies.spec.js +++ b/test/api/routes/movies.spec.js @@ -8,8 +8,8 @@ describe('Movies Endpoint', () => { describe('GET /movies', () => { it('will retrieve a list of movies', async () => { const screen = await createScreen(1) - const movie = await createMovie('Dodgeball', 120, screen) - const secondMovie = await createMovie('Scream', 113, screen) + const movie = await createMovie('Dodgeball', 120) + const secondMovie = await createMovie('Scream', 113) await createScreening( screen.id, diff --git a/test/api/routes/screens.spec.js b/test/api/routes/screens.spec.js index e6bc8da5..d66b3d42 100644 --- a/test/api/routes/screens.spec.js +++ b/test/api/routes/screens.spec.js @@ -1,20 +1,18 @@ -const supertest = require("supertest") -const app = require("../../../src/server.js") +const supertest = require('supertest') +const app = require('../../../src/server.js') -describe("Screens Endpoint", () => { - describe("POST /screens", () => { - it("will create a new screen", async () => { +describe('Screens Endpoint', () => { + describe('POST /screens', () => { + it('will create a new screen', async () => { const request = { - number: 10 + number: 10, } - const response = await supertest(app) - .post("/screens") - .send(request) + 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 +}) diff --git a/test/helpers/createScreening.js b/test/helpers/createScreening.js index 3e52390f..1dce382b 100644 --- a/test/helpers/createScreening.js +++ b/test/helpers/createScreening.js @@ -1,15 +1,15 @@ -const prisma = require("../../src/utils/prisma"); +const prisma = require('../../src/utils/prisma') -const createScreening = async (screenId,movieId,startsAt) => { +const createScreening = async (screenId, movieId, startsAt) => { return await prisma.screening.create({ data: { screenId: screenId, movieId: movieId, - startsAt: startsAt - } + startsAt: startsAt, + }, }) } module.exports = { - createScreening -} \ No newline at end of file + createScreening, +} diff --git a/test/setupTests.js b/test/setupTests.js index 2be95321..5acc78aa 100644 --- a/test/setupTests.js +++ b/test/setupTests.js @@ -1,28 +1,29 @@ -const prisma = require("../src/utils/prisma") +const prisma = require('../src/utils/prisma') const deleteTables = () => { - const deleteTables = [ - prisma.ticket.deleteMany(), - prisma.screening.deleteMany(), - prisma.movie.deleteMany(), - prisma.screen.deleteMany(), - prisma.contact.deleteMany(), - prisma.customer.deleteMany(), - ]; + const deleteTables = [ + prisma.ticket.deleteMany(), + prisma.screening.deleteMany(), + prisma.review.deleteMany(), + prisma.movie.deleteMany(), + prisma.screen.deleteMany(), + prisma.contact.deleteMany(), + prisma.customer.deleteMany(), + ] - // Conditionally delete this table as this will only exist if "Extensions to the Extensions" bullet 2 is implemented - prisma.reviews && deleteTables.push(prisma.reviews.deleteMany()) - return prisma.$transaction(deleteTables) + // Conditionally delete this table as this will only exist if "Extensions to the Extensions" bullet 2 is implemented + prisma.reviews && deleteTables.push(prisma.reviews.deleteMany()) + return prisma.$transaction(deleteTables) } global.beforeAll(() => { - return deleteTables() + return deleteTables() }) global.afterEach(() => { - return deleteTables() + return deleteTables() }) global.afterAll(() => { - return prisma.$disconnect() + return prisma.$disconnect() }) From d76fee11c3299a6cc6458c322a972fc66b5adcfd Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Wed, 3 Jul 2024 09:33:03 +0100 Subject: [PATCH 7/7] Remove unused imports --- src/controllers/movies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/movies.js b/src/controllers/movies.js index 6d6ffb85..c1ef02fd 100644 --- a/src/controllers/movies.js +++ b/src/controllers/movies.js @@ -4,7 +4,7 @@ const { findMovieByIdDb, updateMovieByIdDb, } = require('../domains/movies.js') -const { NotFoundError, RecordNotFound } = require('@prisma/client') +const { NotFoundError} = require('@prisma/client') const getAllMovies = async (req, res) => { const { runtimeLt, runtimeGt } = req.query