From f9a08b212b9cf1dfef710fe5b6667ad0996494bc Mon Sep 17 00:00:00 2001 From: Chloe Date: Sat, 18 Apr 2020 16:22:07 +0100 Subject: [PATCH] refactor and prettify all files Relates #54 --- .prettierrc | 12 + README.md | 118 ++++---- db/build.js | 16 +- db/connection.js | 7 +- db/init.sql | 35 +-- handlers/examples-handlers.js | 71 +++++ handlers/examples.js | 71 ----- handlers/users-handlers.js | 83 ++++++ handlers/users.js | 82 ------ middleware/auth.js | 55 ++-- middleware/error.js | 8 +- model/examples-model.js | 90 +++++++ model/examples.js | 102 ------- model/users-model.js | 32 +++ model/users.js | 36 --- package-lock.json | 6 + package.json | 68 ++--- server.js | 12 +- tests/model.test.js | 149 +++++----- tests/routes.test.js | 495 ++++++++++++++++------------------ tests/zzz.test.js | 2 +- 21 files changed, 756 insertions(+), 794 deletions(-) create mode 100644 .prettierrc create mode 100644 handlers/examples-handlers.js delete mode 100644 handlers/examples.js create mode 100644 handlers/users-handlers.js delete mode 100644 handlers/users.js create mode 100644 model/examples-model.js delete mode 100644 model/examples.js create mode 100644 model/users-model.js delete mode 100644 model/users.js diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..c08bd90 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 4, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "none", + "bracketSpacing": false, + "jsxBracketSameLine": false, + "arrowParens": "avoid", + "proseWrap": "never" +} \ No newline at end of file diff --git a/README.md b/README.md index 0eb041d..a7af9d4 100644 --- a/README.md +++ b/README.md @@ -25,19 +25,19 @@ Project build as a part of Founders and Coders FAC19. ### Stack -- JavaScript -- Node -- Express -- PostgreSQL +- JavaScript +- Node +- Express +- PostgreSQL ### User Stories -- As an API user, I want to: get a list of all available resources -- As an API user, I want to: get all the information on a specific resource -- As an API user, I want to: create a new resource -- As an API user, I want to: update an existing resource -- As an API user, I want to: delete an existing resource -- As an API user, I want to: only be able to change an existing resource if I am authenticated to do so +- As an API user, I want to: get a list of all available resources +- As an API user, I want to: get all the information on a specific resource +- As an API user, I want to: create a new resource +- As an API user, I want to: update an existing resource +- As an API user, I want to: delete an existing resource +- As an API user, I want to: only be able to change an existing resource if I am authenticated to do so ### Database Schema @@ -69,28 +69,23 @@ CREATE TABLE examples 1. Clone repo 2. cd into folder 3. Run NPM install -4. If you already have an existing SUPERUSER -create a local production psql data base and assign it to that user. - ```sql - CREATE DATABASE local_production_database_name WITH OWNER your_user; - ``` - - OTHERWISE change your user to a superuser - ```sql ALTER USER your_user WITH SUPERUSER ``` - - +4. If you already have an existing SUPERUSER create a local production psql data base and assign it to that user. + ```sql + CREATE DATABASE local_production_database_name WITH OWNER your_user; + ``` + +OTHERWISE change your user to a superuser `sql ALTER USER your_user WITH SUPERUSER` + 5. Create a test database called localtest with the same owner/user - ```sql - CREATE DATABASE localtest WITH OWNER your_user; - ``` + ```sql + CREATE DATABASE localtest WITH OWNER your_user; + ``` 6. Create an .env file in the project's root folder - - PGDATABASE=local_production_database_name - - PGUSER=your_user - - PGPASSWORD=your_password - - SECRET=JWTSECRET - You can choose a secret of your choice. -7. npm run setupdb - Alternatively import db/init.sql in your preferred db admin tool + - PGDATABASE=local_production_database_name + - PGUSER=your_user + - PGPASSWORD=your_password + - SECRET=JWTSECRET You can choose a secret of your choice. +7. npm run setupdb Alternatively import db/init.sql in your preferred db admin tool ### Running the server @@ -105,11 +100,12 @@ create a local production psql data base and assign it to that user. ### Example users and passwords There are five default users, their email addresses are. -- admin@iscool.com -- tom@iscool.com -- chloe@iscool.com -- kat@iscool.com -- roger@iscool.com + +- admin@iscool.com +- tom@iscool.com +- chloe@iscool.com +- kat@iscool.com +- roger@iscool.com Their passwords are, unsurprisingly, 'password'. @@ -131,14 +127,13 @@ Send a post request to path above using raw json request. Example below: ```json { - "username": "Peter Pumpernicke;", - "email": "peter@iscool.com", - "password": "password" + "username": "Peter Pumpernicke;", + "email": "peter@iscool.com", + "password": "password" } ``` -If successful, user object is returned. -If user already exists, error will be returned. +If successful, user object is returned. If user already exists, error will be returned. ### Login as user @@ -148,13 +143,12 @@ Send a post request to path above using raw json request. Example below: ```json { - "email": "registered_email_address", - "password": "your_password" + "email": "registered_email_address", + "password": "your_password" } ``` -If successful, token object is returned. YOU WILL NEED THIS TOKEN TO ADD OR DELETE EXAMPLES! -If email or password are incorrect, error will be returned. +If successful, token object is returned. YOU WILL NEED THIS TOKEN TO ADD OR DELETE EXAMPLES! If email or password are incorrect, error will be returned. ### Get example with a specified ID @@ -176,9 +170,9 @@ You can use postman or similar tool. Request must be sent with AUTHORIZATION bea ```json { - "language": "js", - "title": "enter_title_here", - "example": "code_cnippet_example_here" + "language": "js", + "title": "enter_title_here", + "example": "code_cnippet_example_here" } ``` @@ -194,7 +188,7 @@ If successfull you will receive a json object as below: ```json { - "deleted": true + "deleted": true } ``` @@ -212,43 +206,39 @@ Request needs to be sent using raw json format as below: ```json { - "language": "value to update", - "title": "value to update", - "example": "value to update" + "language": "value to update", + "title": "value to update", + "example": "value to update" } ``` You only need to include the fields you want to update. Omitted fields will remain unchanged, - ### Search by keyword and filter by language example `GET /search/yourSearchTerm?lang=js` We sadly didn't get that far but lookout for this feature in the next version! - ### Project Acceptance Criteria -- [x] An Express server that only returns JSON - -- [x] A Postgres database to store the data - -- [x] Endpoints for creating, reading, updating & deleting resources +- [x] An Express server that only returns JSON -- [x] Token-based authentication so only the owner of a resource can change it +- [x] A Postgres database to store the data -- [x] Correct headers and response metadata (we think) +- [x] Endpoints for creating, reading, updating & deleting resources -- [x] Error-handling to make it easy to use the API to build something +- [x] Token-based authentication so only the owner of a resource can change it -- [x] Tests for server routes and database access +- [x] Correct headers and response metadata (we think) -- [x] Not process user input as SQL commands +- [x] Error-handling to make it easy to use the API to build something -- [x] Hidden environment variables (i.e. not on GitHub) +- [x] Tests for server routes and database access +- [x] Not process user input as SQL commands +- [x] Hidden environment variables (i.e. not on GitHub) ### The end diff --git a/db/build.js b/db/build.js index 0fd2c0f..24e8874 100644 --- a/db/build.js +++ b/db/build.js @@ -1,14 +1,16 @@ -const db = require('./connection'); -const path = require('path'); -const fs = require('fs'); +const db = require("./connection"); +const path = require("path"); +const fs = require("fs"); -const initPath = path.join(__dirname, 'init.sql'); -const initSql = fs.readFileSync(initPath, 'utf-8'); +const initPath = path.join(__dirname, "init.sql"); +const initSql = fs.readFileSync(initPath, "utf-8"); function build() { return db.query(initSql); -}; +} +// Allows build to be ran on the command line, npm run setupdb will now run build() if (require.main === module) build(); -module.exports = build; \ No newline at end of file +// Testing imports build but chooses when to run it +module.exports = build; diff --git a/db/connection.js b/db/connection.js index c95e4c8..7495eb0 100644 --- a/db/connection.js +++ b/db/connection.js @@ -1,11 +1,8 @@ const pg = require("pg"); -const dotenv = require("dotenv"); - -dotenv.config(); -// console.log(process.env); +require("dotenv").config(); const db = new pg.Pool({ connectionString: process.env.DATABASE_URL }); -module.exports = db; \ No newline at end of file +module.exports = db; diff --git a/db/init.sql b/db/init.sql index 0940445..6e48527 100644 --- a/db/init.sql +++ b/db/init.sql @@ -19,24 +19,25 @@ CREATE TABLE examples language VARCHAR(32), title VARCHAR(255), example TEXT NOT NULL, - date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP + date TIMESTAMP + WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -INSERT INTO users - (username, email, user_password, adminusr) -VALUES - ('admin', 'admin@iscool.com', '$2a$10$zH7.4s2AbH8Lz.SqsauRSOldLUacu3axD.0ZgoR2v2CJpM/pItOiy', true), - ('Tom', 'tom@iscool.com', '$2a$10$aHsFImUy5q1fj37Z72O6r.iUpDLL1CBH38UCaHGK25CEP5W5uyVQa', false), - ('Chloe', 'chloe@iscool.com', '$2a$10$QFV6woSkfTa6XhaJAYYCmu8fqkLOduWm.kDzZI56crZCTIaKzaFDy', false), - ('Kat', 'kat@iscool.com', '$2a$10$SSahAXMX/e.3VS0juErkceVbwwR1iL8/cWYnOD5IILyf.74EMnHr6', false), - ('Roger', 'roger@iscool.com', '$2a$10$./Rk0decBFt/XHJcIJX2XOq3Qq0AbfsQCPNQ7Gz66TA7dFK8l5/Fm', false); + INSERT INTO users + (username, email, user_password, adminusr) + VALUES + ('admin', 'admin@iscool.com', '$2a$10$zH7.4s2AbH8Lz.SqsauRSOldLUacu3axD.0ZgoR2v2CJpM/pItOiy', true), + ('Tom', 'tom@iscool.com', '$2a$10$aHsFImUy5q1fj37Z72O6r.iUpDLL1CBH38UCaHGK25CEP5W5uyVQa', false), + ('Chloe', 'chloe@iscool.com', '$2a$10$QFV6woSkfTa6XhaJAYYCmu8fqkLOduWm.kDzZI56crZCTIaKzaFDy', false), + ('Kat', 'kat@iscool.com', '$2a$10$SSahAXMX/e.3VS0juErkceVbwwR1iL8/cWYnOD5IILyf.74EMnHr6', false), + ('Roger', 'roger@iscool.com', '$2a$10$./Rk0decBFt/XHJcIJX2XOq3Qq0AbfsQCPNQ7Gz66TA7dFK8l5/Fm', false); -INSERT INTO examples - (owner_id, language, title, example) -VALUES - (1, 'js', 'Test example 1', 'Example 1 code goes here.'), - (2, 'sql', 'Test example 2', 'Example 2 code goes here.'), - (3, 'js', 'Test example 3', 'Example 3 code goes here.'), - (4, 'js', 'Test example 4', 'Example 4 code goes here.'); + INSERT INTO examples + (owner_id, language, title, example) + VALUES + (1, 'js', 'Test example 1', 'Example 1 code goes here.'), + (2, 'sql', 'Test example 2', 'Example 2 code goes here.'), + (3, 'js', 'Test example 3', 'Example 3 code goes here.'), + (4, 'js', 'Test example 4', 'Example 4 code goes here.'); -COMMIT; \ No newline at end of file + COMMIT; \ No newline at end of file diff --git a/handlers/examples-handlers.js b/handlers/examples-handlers.js new file mode 100644 index 0000000..ff32312 --- /dev/null +++ b/handlers/examples-handlers.js @@ -0,0 +1,71 @@ +const modelExample = require("../model/examples-model"); + +function getAllExamples(req, res, next) { + modelExample + .getAllExamples() + .then(example => res.send(example)) + .catch(next); +} + +// Inserts a new example into the examples table and returns the inserted row's id +function postExample(req, res, next) { + req.body.user_id = req.user.id; + req.body.admin = req.user.admin; + modelExample + .createExample(req.body) + .then(exampleId => { + res.status(201).send({ + exampleId: exampleId + }); + }) + .catch(next); +} + +function deleteExample(req, res, next) { + modelExample + .deleteExample(req.params.id, req.user) + .then(() => { + res.status(200).send({deleted: true}); + }) + .catch(next); +} + +function getExample(req, res, next) { + const id = req.params.id; + modelExample + .getExample(id) + .then(result => { + console.log(!result === undefined); + if (!result) { + res.status(204).send("Error: Resource not found"); + } + res.status(200).send(result); + }) + .catch(next); +} + +function updateExample(req, res, next) { + const id = Number(req.params.id); + const userID = req.user.id; + const newdata = req.body; + if (id === NaN) { + const err = new Error("This is not a valid ID"); + err.status = 401; + next(err); + } + + modelExample + .updateExamplebyID(id, newdata, userID) + .then(result => { + res.status(200).send(result); + }) + .catch(next); +} + +module.exports = { + getAllExamples, + postExample, + getExample, + deleteExample, + updateExample +}; diff --git a/handlers/examples.js b/handlers/examples.js deleted file mode 100644 index c377fe2..0000000 --- a/handlers/examples.js +++ /dev/null @@ -1,71 +0,0 @@ -const modelExample = require("../model/examples"); - -function getAllExamples(req, res, next) { - modelExample - .getAllExamples() - .then((example) => res.send(example)) - .catch(next); -} - -// Inserts a new example into the examples table and returns the inserted row's id -function post(req, res, next) { - req.body.user_id = req.user.id; - req.body.admin = req.user.admin; - modelExample - .createExample(req.body) - .then((exampleId) => { - res.status(201).send({ - exampleId: exampleId, - }); - }) - .catch(next); -} - -function del(req, res, next) { - modelExample - .deleteExample(req.params.id, req.user) - .then(() => { - res.status(200).send({ deleted: true }); - }) - .catch(next); -} - -function getExample(req, res, next) { - const id = req.params.id; - modelExample - .getExample(id) - .then((result) => { - console.log(!result === undefined); - if (!result) { - res.status(204).send("Error: Resource not found"); - } - res.status(200).send(result); - }) - .catch(next); -} - -function updateExample(req, res, next) { - const id = Number(req.params.id); - const userID = req.user.id; - const newdata = req.body; - if (id === NaN) { - const err = new Error("This is not a valid ID"); - err.status = 401; - next(err); - } - - modelExample - .updateExamplebyID(id, newdata, userID) - .then((result) => { - res.status(200).send(result); - }) - .catch(next); -} - -module.exports = { - getAllExamples, - post, - getExample, - del, - updateExample, -}; diff --git a/handlers/users-handlers.js b/handlers/users-handlers.js new file mode 100644 index 0000000..dae686c --- /dev/null +++ b/handlers/users-handlers.js @@ -0,0 +1,83 @@ +const model = require("../model/users-model"); +const jwt = require("jsonwebtoken"); +const bcrypt = require("bcryptjs"); + +require("dotenv").config(); + +const secret = process.env.SECRET; + +function signup(req, res, next) { + if ( + req.body.email === undefined || + req.body.username === undefined || + req.body.password === undefined + ) { + const error = new Error("Missing parameter: email, username, password all required."); + error.status = 400; + next(error); + } + const newUserEmail = req.body.email; + const newUserName = req.body.username; + const rawPassword = req.body.password; + + bcrypt + .genSalt(10) + .then(salt => bcrypt.hash(rawPassword, salt)) + .then(cookedPassword => { + const newUser = { + email: newUserEmail, + username: newUserName, + password: cookedPassword + }; + model + .createUser(newUser) + .then(userID => { + const token = jwt.sign( + { + user_id: userID, + admin: false + }, + secret, + { + expiresIn: "1h" + } + ); + res.status(201).send({ + username: newUserName, + email: newUserEmail, + token: token + }); + }) + .catch(next); + }) + .catch(console.error); +} +// login function +// IMPROVEMENTS +// display error message if email or password are missing +function login(req, res, next) { + model + .getUser(req.body.email) + .then(dbUser => { + return bcrypt.compare(req.body.password, dbUser.user_password).then(result => { + if (!result) throw new Error("Bad password!"); + + const claims = { + user_id: dbUser.id, + admin: dbUser.adminusr || false + }; + const token = jwt.sign(claims, secret, { + expiresIn: "24h" + }); + res.send({ + token: token + }); + }); + }) + .catch(next); +} + +module.exports = { + signup, + login +}; diff --git a/handlers/users.js b/handlers/users.js deleted file mode 100644 index 74de171..0000000 --- a/handlers/users.js +++ /dev/null @@ -1,82 +0,0 @@ -const model = require("../model/users"); -const dotenv = require("dotenv"); -const jwt = require("jsonwebtoken"); -const bcrypt = require("bcryptjs"); - -dotenv.config(); - -const secret = process.env.SECRET; - -function signup(req, res, next) { - if (req.body.email === undefined || req.body.username === undefined || req.body.password === undefined) { - const error = new Error("Missing parameter: email, username, password all required."); - error.status = 400 - next(error); - } - const newUserEmail = req.body.email; - const newUserName = req.body.username; - const rawPassword = req.body.password; - - bcrypt - .genSalt(10) - .then((salt) => bcrypt.hash(rawPassword, salt)) - .then((cookedPassword) => { - const newUser = { - email: newUserEmail, - username: newUserName, - password: cookedPassword, - }; - model - .createUser(newUser) - .then((userID) => { - const token = jwt.sign( - { - user_id: userID, - admin: false, - }, - secret, - { - expiresIn: "1h", - } - ); - res.status(201).send({ - username: newUserName, - email: newUserEmail, - token: token, - }); - }) - .catch(next); - }) - .catch(console.error); -} -// login function -// IMPROVEMENTS -// display error message if email or password are missing -function login(req, res, next) { - model - .getUser(req.body.email) - .then((dbUser) => { - return bcrypt - .compare(req.body.password, dbUser.user_password) - .then((result) => { - if (!result) throw new Error("Bad password!"); - - const claims = { - user_id: dbUser.id, - admin: dbUser.adminusr || false, - }; - const token = jwt.sign(claims, secret, { - expiresIn: "24h", - }); - res.send({ - token: token, - }); - }); - }) - .catch(next); -} - -module.exports = { - signup, - login, -}; diff --git a/middleware/auth.js b/middleware/auth.js index b6c90c8..cecdee9 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -1,37 +1,36 @@ -const dotenv = require("dotenv"); const jwt = require("jsonwebtoken"); -const model = require("../model/users"); +const model = require("../model/users-model"); -dotenv.config(); +require("dotenv").config(); const SECRET = process.env.SECRET; function verifyUser(req, res, next) { - const authHeader = req.headers.authorization; - if (!authHeader) { - const error = new Error("Authorization header is required"); - error.status = 400; - next(error); - } else { - const token = authHeader.replace("Bearer ", ""); - try { - // if verification fails JWT throws an error, hence the try/catch - const tokenData = jwt.verify(token, SECRET); - model - .getUserById(tokenData.user_id) - .then((user) => { - // attach the authenticated user to the request object - // so other handlers can access it without doing all this nonsense - req.user = user; - next(); - }) - .catch(next); - } catch (_) { - // we don't use the caught error, since we know it came from jwt.verify - const error = new Error("Unauthorized"); - error.status = 401; - next(error); + const authHeader = req.headers.authorization; + if (!authHeader) { + const error = new Error("Authorization header is required"); + error.status = 400; + next(error); + } else { + const token = authHeader.replace("Bearer ", ""); + try { + // if verification fails JWT throws an error, hence the try/catch + const tokenData = jwt.verify(token, SECRET); + model + .getUserById(tokenData.user_id) + .then(user => { + // attach the authenticated user to the request object + // so other handlers can access it without doing all this nonsense + req.user = user; + next(); + }) + .catch(next); + } catch (_) { + // we don't use the caught error, since we know it came from jwt.verify + const error = new Error("Unauthorized"); + error.status = 401; + next(error); + } } - } } module.exports = verifyUser; diff --git a/middleware/error.js b/middleware/error.js index 0a94c70..e8fd24c 100644 --- a/middleware/error.js +++ b/middleware/error.js @@ -1,9 +1,7 @@ -function handleError(err, req, res, next){ - +function handleError(err, req, res, next) { const errorStatus = err.status || 400; - res.status(errorStatus).send({ "error": err }); + res.status(errorStatus).send({error: err}); // console.error(err); - } -module.exports = handleError; \ No newline at end of file +module.exports = handleError; diff --git a/model/examples-model.js b/model/examples-model.js new file mode 100644 index 0000000..a3c47e4 --- /dev/null +++ b/model/examples-model.js @@ -0,0 +1,90 @@ +const db = require("../db/connection.js"); + +function getAllExamples() { + return db + .query( + `SELECT + users.username, + examples.id, + examples.owner_id, + examples.language, + examples.title, + examples.example, + examples.date + FROM + examples INNER JOIN users ON users.id = examples.owner_id + ORDER BY examples.date DESC;` + ) + .then(result => result.rows) + .catch(error => { + console.log("Error at getAllExamples handler is :" + error); + }); +} + +function createExample(example) { + return db + .query( + "INSERT INTO examples(owner_id, language, title, example) VALUES($1, $2, $3, $4) RETURNING id", + [example.user_id, example.language, example.title, example.example] + ) + .then(result => { + return result.rows[0].id; + }) + .catch(error => { + console.log("Error in model/examples.js, createExample()", error); + }); +} + +function deleteExample(exampleId, user) { + return getExample(exampleId).then(exampleObjectFromDB => { + if (exampleObjectFromDB.id === user.id || user.adminusr) { + return db + .query("DELETE FROM examples WHERE id = ($1);", [exampleId]) + .then(result => true) + .catch(err => { + const error = new Error("Delete query failed!" + err.message); + error.status = 400; + throw error; + }); + } else { + const error = new Error("Only owner or admin can delete this."); + error.status = 403; + throw error; + return false; + } + }); +} + +function getExample(id) { + return db.query("SELECT * FROM examples WHERE id=($1)", [id]).then(res => res.rows[0]); +} + +function updateExamplebyID(id, newdata, userId) { + return getExample(id).then(dbExample => { + if (dbExample.id === userId) { + //check if user wrote the example + const vals = [newdata.language, newdata.title, newdata.example, id]; + return ( + db + .query( + "UPDATE examples SET language = COALESCE($1, language), title = COALESCE($2, title), example = COALESCE($3, example) WHERE id =($4) RETURNING *", + vals + ) + //COALESCE only updates where values are not null + .then(res => res.rows[0]) + ); + } else { + const error = new Error("You do not own this example"); + error.status = 401; + throw error; + } + }); +} + +module.exports = { + getAllExamples, + createExample, + getExample, + deleteExample, + updateExamplebyID +}; diff --git a/model/examples.js b/model/examples.js deleted file mode 100644 index 3ad6a35..0000000 --- a/model/examples.js +++ /dev/null @@ -1,102 +0,0 @@ -const db = require("../db/connection.js"); - -function getAllExamples() { - return db - .query( - `SELECT - users.username, - examples.id, - examples.owner_id, - examples.language, - examples.title, - examples.example, - examples.date - FROM - examples INNER JOIN users ON users.id = examples.owner_id - ORDER BY examples.date DESC;` - ) - .then((result) => result.rows) - .catch((error) => { - console.log("Error at getAllExamples handler is :" + error); - }); -} - -function createExample(example) { - return db - .query( - "INSERT INTO examples(owner_id, language, title, example) VALUES($1, $2, $3, $4) RETURNING id", - [example.user_id, example.language, example.title, example.example] - ) - .then((result) => { - return result.rows[0].id; - }) - .catch((error) => { - console.log("Error in model/examples.js, createExample()", error); - }); -} - -function deleteExample(exampleId, user) { - return getExample(exampleId) - .then( exampleObjectFromDB => { - if(exampleObjectFromDB.id === user.id || user.adminusr){ - return db.query("DELETE FROM examples WHERE id = ($1);", [exampleId]) - .then( result => true ) - .catch( err => { - const error = new Error ('Delete query failed!' + err.message); - error.status = 400; - throw error; - }) - } else { - const error = new Error ("Only owner or admin can delete this."); - error.status = 403; - throw error; - return false; - } - }) -} - -function getExample(id) { - return db - .query("SELECT * FROM examples WHERE id=($1)", [id]) - .then((res) => res.rows[0]); -} - - -function updateExamplebyID(id, newdata, userId) { - return getExample(id) - .then(dbExample => { - if(dbExample.id === userId){ - const vals = [ newdata.language, newdata.title, newdata.example, id ]; - return db.query("UPDATE examples SET language = COALESCE($1, language), title = COALESCE($2, title), example = COALESCE($3, example) WHERE id =($4) RETURNING *", vals) - .then((res) => res.rows[0]); - } else { - const error = new Error("You do not own this example") - error.status = 401; - throw error; - } - }) -} - -// var query = ["UPDATE examples"]; -// query.push("SET"); - -// const set = []; -// const values = []; -// Object.keys(newdata).forEach((key, i) => { -// set.push(key + "=($" + (i + 1) + ")"); -// values.push(newdata[key]); -// }); -// query.push(set.join(", ")); - -// query.push("WHERE id=" + id + " RETURNING *"); - -// return db.query(query.join(" "), values) - -module.exports = { - getAllExamples, - createExample, - getExample, -// updateExample, - deleteExample, - updateExamplebyID, -}; diff --git a/model/users-model.js b/model/users-model.js new file mode 100644 index 0000000..e068ae0 --- /dev/null +++ b/model/users-model.js @@ -0,0 +1,32 @@ +const db = require("../db/connection.js"); + +function createUser(user) { + return db + .query( + "INSERT INTO users(username, email, user_password) VALUES($1, $2, $3) RETURNING id;", + [user.username, user.email, user.password] + ) + .then(res => res.rows[0].id); +} + +function getUsers() { + return db.query("SELECT * FROM users").then(res => res.rows); +} + +function getUser(email) { + return db.query("SELECT * FROM users WHERE email = ($1);", [email]).then(res => { + if (res.rows.length < 1) throw new Error("User does not exist"); + return res.rows[0]; + }); +} + +function getUserById(id) { + return db.query("SELECT * FROM users WHERE id = ($1)", [id]).then(res => res.rows[0]); +} + +module.exports = { + createUser, + getUsers, + getUser, + getUserById +}; diff --git a/model/users.js b/model/users.js deleted file mode 100644 index 8d3ccc1..0000000 --- a/model/users.js +++ /dev/null @@ -1,36 +0,0 @@ -const db = require("../db/connection.js"); - -function createUser(user) { - return db - .query( - "INSERT INTO users(username, email, user_password) VALUES($1, $2, $3) RETURNING id;", - [user.username, user.email, user.password] - ) - .then((res) => res.rows[0].id); -} - -function getUsers() { - return db.query("SELECT * FROM users").then((res) => res.rows); -} - -function getUser(email) { - return db - .query("SELECT * FROM users WHERE email = ($1);", [email]) - .then((res) => { - if (res.rows.length < 1) throw new Error("User does not exist"); - return res.rows[0]; - }); -} - -function getUserById(id) { - return db - .query("SELECT * FROM users WHERE id = ($1)", [id]) - .then((res) => res.rows[0]); -} - -module.exports = { - createUser, - getUsers, - getUser, - getUserById, -}; diff --git a/package-lock.json b/package-lock.json index 8ee9817..eace117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1534,6 +1534,12 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "prettier": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.4.tgz", + "integrity": "sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w==", + "dev": true + }, "pretty-ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-2.1.0.tgz", diff --git a/package.json b/package.json index b411049..485ea01 100644 --- a/package.json +++ b/package.json @@ -1,35 +1,37 @@ { - "name": "week7-crakt", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "PGDATABASE=localtest tape tests/*.test.js | tap-spec", - "dev": "nodemon server.js", - "setupdb": "node db/build.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/fac19/week7-CRaKT.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/fac19/week7-CRaKT/issues" - }, - "homepage": "https://github.com/fac19/week7-CRaKT#readme", - "dependencies": { - "bcryptjs": "^2.4.3", - "ci": "^1.0.0", - "dotenv": "^8.2.0", - "express": "^4.17.1", - "jsonwebtoken": "^8.5.1", - "pg": "^8.0.2" - }, - "devDependencies": { - "tap-spec": "^5.0.0", - "supertest": "^4.0.2", - "tape": "^4.13.2", - "nodemon": "^2.0.3" - } + "name": "week7-crakt", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "PGDATABASE=localtest tape tests/*.test.js | tap-spec", + "dev": "nodemon server.js", + "setupdb": "node db/build.js", + "format": "prettier --write '**/*.{js,css,md}'" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/fac19/week7-CRaKT.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/fac19/week7-CRaKT/issues" + }, + "homepage": "https://github.com/fac19/week7-CRaKT#readme", + "dependencies": { + "bcryptjs": "^2.4.3", + "ci": "^1.0.0", + "dotenv": "^8.2.0", + "express": "^4.17.1", + "jsonwebtoken": "^8.5.1", + "pg": "^8.0.2" + }, + "devDependencies": { + "nodemon": "^2.0.3", + "prettier": "^2.0.4", + "supertest": "^4.0.2", + "tap-spec": "^5.0.0", + "tape": "^4.13.2" + } } diff --git a/server.js b/server.js index 3dc3303..e546ab4 100644 --- a/server.js +++ b/server.js @@ -1,8 +1,8 @@ const express = require("express"); const handleError = require("./middleware/error"); const auth = require("./middleware/auth"); -const examples = require("./handlers/examples"); -const users = require("./handlers/users"); +const examples = require("./handlers/examples-handlers"); +const users = require("./handlers/users-handlers"); require("dotenv").config(); const PORT = process.env.PORT || 3000; @@ -10,9 +10,9 @@ const server = express(); server.use(express.json()); server.get("/", examples.getAllExamples); -server.post("/examples", auth, examples.post); +server.post("/examples", auth, examples.postExample); server.get("/examples/:id", examples.getExample); -server.delete("/examples/:id", auth, examples.del); +server.delete("/examples/:id", auth, examples.deleteExample); server.put("/examples/:id", auth, examples.updateExample); //NEED TO TEST server.post("/signup", users.signup); @@ -21,9 +21,7 @@ server.post("/login", users.login); server.use(handleError); if (process.env.PGDATABASE !== "localtest") { - server.listen(PORT, () => - console.log(`Listening on http://localhost:${PORT}`) - ); + server.listen(PORT, () => console.log(`Listening on http://localhost:${PORT}`)); } module.exports = server; diff --git a/tests/model.test.js b/tests/model.test.js index 6a30e31..16680db 100644 --- a/tests/model.test.js +++ b/tests/model.test.js @@ -1,98 +1,87 @@ const build = require("../db/build"); const test = require("tape"); -const request = require("supertest"); -const { - createUser, - getUsers, - getUser, - getUserById, - getExampleById -} = require("../model/users"); +const {createUser, getUsers, getUser, getUserById} = require("../model/users-model"); -const { - getExample, - updateExamplebyID -} = require("../model/examples"); +const {getExample, updateExamplebyID} = require("../model/examples-model"); -test("DB tests are running!", (t) => { - const x = 5; - t.equal(x, 5, "this is working"); - t.end(); +test("DB tests are running!", t => { + const x = 5; + t.equal(x, 5, "this is working"); + t.end(); }); -test("Can create new user", (t) => { - build().then(() => { - const user = { - username: "Bob123", - email: "bob@hello.com", - password: "54321", - }; - createUser(user).then(() => { - getUsers() - .then((res) => { - t.equal(res[res.length - 1].username, "Bob123", "User has correct name"); - t.equal(res.length, 6, "Users table is 1 longer"); - t.end(); - }) - .catch((err) => { - t.error(err); - t.end(); +test("Can create new user", t => { + build().then(() => { + const user = { + username: "Bob123", + email: "bob@hello.com", + password: "54321" + }; + createUser(user).then(() => { + getUsers() + .then(res => { + t.equal(res[res.length - 1].username, "Bob123", "User has correct name"); + t.equal(res.length, 6, "Users table is 1 longer"); + t.end(); + }) + .catch(err => { + t.error(err); + t.end(); + }); }); }); - }); }); -test("Returns user with a given email address", (t) => { - build().then(() => { - getUser("admin@iscool.com") - .then((res) => { - t.equal(res.username, "admin", "Correct name returned"); - t.equal(res.adminusr, true, "User has admin permissions"); - t.end(); - }) - .catch((err) => { - t.error(err); - t.end(); - }); - }); +test("Returns user with a given email address", t => { + build().then(() => { + getUser("admin@iscool.com") + .then(res => { + t.equal(res.username, "admin", "Correct name returned"); + t.equal(res.adminusr, true, "User has admin permissions"); + t.end(); + }) + .catch(err => { + t.error(err); + t.end(); + }); + }); }); -test("Can get an example by id", (t) => { - build().then(() => { - getExample(1) - .then((res) => { - t.equal(res.language, "js", "Correct language returned"); - t.equal(res.title, "Test example 1", "Correct title returned"); - t.equal(res.example, "Example 1 code goes here.", "Correct example text returned"); - t.end(); - }) - .catch((err) => { - t.error(err); - t.end(); - }); - }); +test("Can get an example by id", t => { + build().then(() => { + getExample(1) + .then(res => { + t.equal(res.language, "js", "Correct language returned"); + t.equal(res.title, "Test example 1", "Correct title returned"); + t.equal(res.example, "Example 1 code goes here.", "Correct example text returned"); + t.end(); + }) + .catch(err => { + t.error(err); + t.end(); + }); + }); }); - -test.only("Can get update an example by id without all values", (t) => { - build().then(() => { - const data = { - language: "sql", - example: "This is an example of SQL", - }; - updateExamplebyID(4, data, 4) - .then((res) => { - t.equal(res.language, "sql", "Language updated OK"); - t.equal(res.title, "Test example 4", "Title not altered"); - t.equal(res.example, "This is an example of SQL", "Example text updated OK"); - t.end(); - }) - .catch((err) => { - t.error(err); - t.end(); - }); - }); +test("Can get update an example by id without all values", t => { + build().then(() => { + const data = { + language: "sql", + example: "This is an example of SQL" + }; + updateExamplebyID(4, data, 4) + .then(res => { + t.equal(res.language, "sql", "Language updated OK"); + t.equal(res.title, "Test example 4", "Title not altered"); + t.equal(res.example, "This is an example of SQL", "Example text updated OK"); + t.end(); + }) + .catch(err => { + t.error(err); + t.end(); + }); + }); }); // test.only("Can update an example by id", (t) => { diff --git a/tests/routes.test.js b/tests/routes.test.js index d6c1291..bfb4a3f 100644 --- a/tests/routes.test.js +++ b/tests/routes.test.js @@ -6,287 +6,270 @@ const jwt = require("jsonwebtoken"); const dotenv = require("dotenv"); dotenv.config(); -test("Route tests are running!", (t) => { - const x = 5; - t.equal(x, 5, "this is working"); - t.end(); +test("Route tests are running!", t => { + const x = 5; + t.equal(x, 5, "this is working"); + t.end(); }); -test("Test main route returns 200", (t) => { - build().then(() => { - supertest(server) - .get("/") - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(res.text.includes("Kat"), true, "Kat should be present"); - t.equals( - res.text.includes("Test example 4"), - true, - "example title should be present" - ); - t.equals( - res.text.includes("Example 1 code goes here."), - true, - "example text should be present" - ); - t.end(); - }); - }); +test("Test main route returns 200", t => { + build().then(() => { + supertest(server) + .get("/") + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(res.text.includes("Kat"), true, "Kat should be present"); + t.equals( + res.text.includes("Test example 4"), + true, + "example title should be present" + ); + t.equals( + res.text.includes("Example 1 code goes here."), + true, + "example text should be present" + ); + t.end(); + }); + }); }); -test("Test /signup route", (t) => { - build().then(() => { - supertest(server) - .post("/signup") - .send({ - username: "Harry", - email: "harry@potter.com", - password: "wizard", - }) - .expect(201) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 201 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.username, "Harry", "Username should be Harry"); - t.notEquals(res.body.token, undefined, "Check that a token exists"); - t.equals( - /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test( - res.body.token - ), - true, - "Check for correct jwt token" - ); - t.end(); - }); - }); +test("Test /signup route", t => { + build().then(() => { + supertest(server) + .post("/signup") + .send({ + username: "Harry", + email: "harry@potter.com", + password: "wizard" + }) + .expect(201) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 201 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.username, "Harry", "Username should be Harry"); + t.notEquals(res.body.token, undefined, "Check that a token exists"); + t.equals( + /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(res.body.token), + true, + "Check for correct jwt token" + ); + t.end(); + }); + }); }); -test("Test /login route", (t) => { - build().then(() => { - supertest(server) - .post("/login") - .send({ - email: "roger@iscool.com", - password: "password", - }) - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.notEquals(res.body.token, undefined, "Check that a token exists"); - t.equals( - /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test( - res.body.token - ), - true, - "Check for correct jwt token" - ); - t.end(); - }); - }); +test("Test /login route", t => { + build().then(() => { + supertest(server) + .post("/login") + .send({ + email: "roger@iscool.com", + password: "password" + }) + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.notEquals(res.body.token, undefined, "Check that a token exists"); + t.equals( + /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(res.body.token), + true, + "Check for correct jwt token" + ); + t.end(); + }); + }); }); -test("Test /examples POST route with valid auth token", (t) => { - build().then(() => { - const token = jwt.sign( - { - user_id: 2, - admin: false, - }, - process.env.SECRET, - { - expiresIn: "1hr", - } - ); - supertest(server) - .post("/examples") - .set({ - Authorization: "Bearer " + token, - }) - .send({ - language: "js", - title: "Test Post 99", - example: "Test body 99", - }) - .expect(201) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals( - typeof res.body.exampleId, - typeof 1, - "Check we get an integer ID" +test("Test /examples POST route with valid auth token", t => { + build().then(() => { + const token = jwt.sign( + { + user_id: 2, + admin: false + }, + process.env.SECRET, + { + expiresIn: "1hr" + } ); - t.end(); - }); - }); + supertest(server) + .post("/examples") + .set({ + Authorization: "Bearer " + token + }) + .send({ + language: "js", + title: "Test Post 99", + example: "Test body 99" + }) + .expect(201) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(typeof res.body.exampleId, typeof 1, "Check we get an integer ID"); + t.end(); + }); + }); }); -test("Test /login route", (t) => { - build().then(() => { - supertest(server) - .post("/login") - .send({ - email: "roger@iscool.com", - password: "password", - }) - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.notEquals(res.body.token, undefined, "Check that a token exists"); - t.equals( - /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test( - res.body.token - ), - true, - "Check for correct jwt token" - ); - t.end(); - }); - }); +test("Test /login route", t => { + build().then(() => { + supertest(server) + .post("/login") + .send({ + email: "roger@iscool.com", + password: "password" + }) + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.notEquals(res.body.token, undefined, "Check that a token exists"); + t.equals( + /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(res.body.token), + true, + "Check for correct jwt token" + ); + t.end(); + }); + }); }); -test("Test GET/example/:id route", (t) => { - build().then(() => { - supertest(server) - .get("/examples/2") - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, "object", "Check that res.body is an object"); - t.equals(res.body.language, "sql", "Check the language is the same"); - t.equals( - res.body.title, - "Test example 2", - "Check the title is the same" - ); - t.end(); - }); - }); +test("Test GET/example/:id route", t => { + build().then(() => { + supertest(server) + .get("/examples/2") + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, "object", "Check that res.body is an object"); + t.equals(res.body.language, "sql", "Check the language is the same"); + t.equals(res.body.title, "Test example 2", "Check the title is the same"); + t.end(); + }); + }); }); -test("Test /example POST route fails without valid auth token", (t) => { - build().then(() => { - const token = jwt.sign( - { - user_id: 2, - admin: false, - }, - process.env.SECRET, - { - expiresIn: "1hr", - } - ); - supertest(server) - .post("/examples") - .set({ - Authorization: "Bearer lsdkdfjlskdfjlskdjfwoierwoierfksd", - }) - .send({ - language: "js", - title: "Test Post 99", - example: "Test body 99", - }) - .expect(401) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 401 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.error.status, 401, "Should get error object with status 401"); - t.end(); - }); - }); +test("Test /example POST route fails without valid auth token", t => { + build().then(() => { + const token = jwt.sign( + { + user_id: 2, + admin: false + }, + process.env.SECRET, + { + expiresIn: "1hr" + } + ); + supertest(server) + .post("/examples") + .set({ + Authorization: "Bearer lsdkdfjlskdfjlskdjfwoierwoierfksd" + }) + .send({ + language: "js", + title: "Test Post 99", + example: "Test body 99" + }) + .expect(401) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 401 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.error.status, 401, "Should get error object with status 401"); + t.end(); + }); + }); }); -test("Test /examples/3 DELETE route with correct owner", (t) => { - build().then(() => { - const token = jwt.sign({ user_id: 3 }, process.env.SECRET, { - expiresIn: "1hr", +test("Test /examples/3 DELETE route with correct owner", t => { + build().then(() => { + const token = jwt.sign({user_id: 3}, process.env.SECRET, { + expiresIn: "1hr" + }); + supertest(server) + .delete("/examples/3") + .set({ + Authorization: "Bearer " + token + }) + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.deleted, true, "Item deleted"); + t.end(); + }); }); - supertest(server) - .delete("/examples/3") - .set({ - Authorization: "Bearer " + token, - }) - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.deleted, true, "Item deleted"); - t.end(); - }); - }); }); +test("Test /examples/3 DELETE route with wrong owner", t => { + build().then(() => { + const token = jwt.sign({user_id: 2}, process.env.SECRET, { + expiresIn: "1hr" + }); + supertest(server) + .delete("/examples/3") + .set({ + Authorization: "Bearer " + token + }) + .expect(403) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 403 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.error.status, 403, "Should get error object with status 401"); -test("Test /examples/3 DELETE route with wrong owner", (t) => { - build().then(() => { - const token = jwt.sign({ user_id: 2 }, process.env.SECRET, { - expiresIn: "1hr", + t.end(); + }); }); - supertest(server) - .delete("/examples/3") - .set({ - Authorization: "Bearer " + token, - }) - .expect(403) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 403 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.error.status, 403, "Should get error object with status 401"); - - t.end(); - }); - }); }); -test("Test /examples/1 DELETE route with admin user who is not owner", (t) => { - build().then(() => { - const token = jwt.sign({ user_id: 1 }, process.env.SECRET, { - expiresIn: "1hr", +test("Test /examples/1 DELETE route with admin user who is not owner", t => { + build().then(() => { + const token = jwt.sign({user_id: 1}, process.env.SECRET, { + expiresIn: "1hr" + }); + supertest(server) + .delete("/examples/4") + .set({ + Authorization: "Bearer " + token + }) + .expect(200) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.deleted, true, "Item deleted"); + t.end(); + }); }); - supertest(server) - .delete("/examples/4") - .set({ - Authorization: "Bearer " + token, - }) - .expect(200) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.deleted, true, "Item deleted"); - t.end(); - }); - }); }); - -test("Test /example/1 DELETE route fails with unauthenticated user", (t) => { - build().then(() => { - supertest(server) - .delete("/examples/1") - .set({ - Authorization: "Bearer " + "dffgasdfhljsdfhdsflsdfj", - }) - .expect(401) - .expect("content-type", "application/json; charset=utf-8") - .end((err, res) => { - t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); - t.equals(typeof res.body, typeof {}, "Check an Object is returned"); - t.equals(res.body.error.status, 401, "Should get error object with status 401"); - t.end(); - }); - }); +test("Test /example/1 DELETE route fails with unauthenticated user", t => { + build().then(() => { + supertest(server) + .delete("/examples/1") + .set({ + Authorization: "Bearer " + "dffgasdfhljsdfhdsflsdfj" + }) + .expect(401) + .expect("content-type", "application/json; charset=utf-8") + .end((err, res) => { + t.error(err, "HTTP status is 200 and application/json; charset=utf-8"); + t.equals(typeof res.body, typeof {}, "Check an Object is returned"); + t.equals(res.body.error.status, 401, "Should get error object with status 401"); + t.end(); + }); + }); }); - diff --git a/tests/zzz.test.js b/tests/zzz.test.js index 4838322..7edb8d0 100644 --- a/tests/zzz.test.js +++ b/tests/zzz.test.js @@ -6,4 +6,4 @@ const db = require("../db/connection"); test("Close DB", t => { db.end(); t.end(); -}) \ No newline at end of file +});