From 9feb7409a3fc11daf5ca3e5751840c65d32f137d Mon Sep 17 00:00:00 2001 From: kyle hoell Date: Fri, 4 Dec 2020 01:43:04 -0500 Subject: [PATCH] started adding user unit tests --- backend/controllers/user.ts | 16 +- backend/models/user.ts | 2 + backend/services/UserService/index.ts | 5 +- backend/utils/sendPasswordResetEmail.ts | 4 + backend/utils/sendShareEmail.ts | 4 + backend/utils/sendVerificationEmail.ts | 4 + package.json | 6 +- .../{index.test.js => index.testtt.js} | 0 .../{index.test.js => index.testtt.js} | 0 .../{file.test.js => file.testtt.js} | 0 .../{folder.test.js => folder.testtt.js} | 0 tests/express-routers/user.test.js | 298 +++++++++++++++--- tests/fixtures/createUser.js | 10 +- tests/fixtures/createUserNotEmailVerified.js | 33 ++ tests/fixtures/loginUser.js | 14 + .../{index.test.js => index.testtt.js} | 0 .../{index.test.js => index.testtt.js} | 0 .../{index.test.js => index.testtt.js} | 0 18 files changed, 329 insertions(+), 67 deletions(-) rename tests/db/utils/fileUtils/{index.test.js => index.testtt.js} (100%) rename tests/db/utils/folderUtils/{index.test.js => index.testtt.js} (100%) rename tests/express-routers/{file.test.js => file.testtt.js} (100%) rename tests/express-routers/{folder.test.js => folder.testtt.js} (100%) create mode 100644 tests/fixtures/createUserNotEmailVerified.js create mode 100644 tests/fixtures/loginUser.js rename tests/services/FileService/{index.test.js => index.testtt.js} (100%) rename tests/services/FolderService/{index.test.js => index.testtt.js} (100%) rename tests/services/UserService/{index.test.js => index.testtt.js} (100%) diff --git a/backend/controllers/user.ts b/backend/controllers/user.ts index 83f66b2..2047ca4 100644 --- a/backend/controllers/user.ts +++ b/backend/controllers/user.ts @@ -59,14 +59,14 @@ class UserController { const {user, accessToken, refreshToken} = await UserProvider.login(body, ipAddress); - await user.save(); + // await user.save(); createLoginCookie(res, accessToken, refreshToken); - user.tokens = []; - user.tempTokens = [] - user.privateKey = undefined; - user.publicKey = undefined; + // user.tokens = []; + // user.tempTokens = [] + // user.privateKey = undefined; + // user.publicKey = undefined; res.status(200).send({user}); @@ -171,12 +171,6 @@ class UserController { const {user, accessToken, refreshToken} = await UserProvider.create(req.body, ipAddress); createLoginCookie(res, accessToken, refreshToken); - - user.tokens = []; - user.tempTokens = [] - user.password = ''; - user.privateKey = undefined; - user.publicKey = undefined; res.status(201).send({user}) diff --git a/backend/models/user.ts b/backend/models/user.ts index 572d19e..acecd27 100644 --- a/backend/models/user.ts +++ b/backend/models/user.ts @@ -267,6 +267,8 @@ userSchema.methods.toJSON = function() { delete userObject.password; delete userObject.tokens; delete userObject.tempTokens; + delete userObject.privateKey; + delete userObject.publicKey; return userObject; } diff --git a/backend/services/UserService/index.ts b/backend/services/UserService/index.ts index 121a56a..def236a 100644 --- a/backend/services/UserService/index.ts +++ b/backend/services/UserService/index.ts @@ -257,9 +257,6 @@ class UserService { if (!user.storageDataPersonal || (!user.storageDataPersonal.storageSize && !user.storageDataPersonal.failed)) user.storageDataPersonal = {storageSize: 0} if (!user.storageDataGoogle || (!user.storageDataGoogle.storageLimit && !user.storageDataGoogle.storageSize && !user.storageDataGoogle.failed)) user.storageDataGoogle = {storageLimit: 0, storageSize: 0} - delete user.privateKey; - delete user.publicKey; - return user; } @@ -342,6 +339,8 @@ class UserService { addName = async(userID: string, name: string) => { + if (!name || name.length === 0) throw new ForbiddenError("No name") + const user = await User.findById(userID); if (!user) throw new NotFoundError("Cannot find user") diff --git a/backend/utils/sendPasswordResetEmail.ts b/backend/utils/sendPasswordResetEmail.ts index 35ea70d..2eca089 100644 --- a/backend/utils/sendPasswordResetEmail.ts +++ b/backend/utils/sendPasswordResetEmail.ts @@ -4,6 +4,10 @@ import sgMail from "@sendgrid/mail"; const sendPasswordResetEmail = async (user: UserInterface, passwordResetToken: string) => { + if (process.env.NODE_ENV === "test") { + return; + } + const apiKey: any = env.sendgridKey; const sendgridEmail:any = env.sendgridEmail; const url = env.remoteURL + `/reset-password/${passwordResetToken}` diff --git a/backend/utils/sendShareEmail.ts b/backend/utils/sendShareEmail.ts index 9161d50..29e8921 100644 --- a/backend/utils/sendShareEmail.ts +++ b/backend/utils/sendShareEmail.ts @@ -5,6 +5,10 @@ const currentURL = env.remoteURL; const sendShareEmail = async (file: any, respient: string) => { + if (process.env.NODE_ENV === "test") { + return; + } + const apiKey: any = env.sendgridKey; const sendgridEmail:any = env.sendgridEmail; diff --git a/backend/utils/sendVerificationEmail.ts b/backend/utils/sendVerificationEmail.ts index 9154f8b..9b7d6a8 100644 --- a/backend/utils/sendVerificationEmail.ts +++ b/backend/utils/sendVerificationEmail.ts @@ -4,6 +4,10 @@ import sgMail from "@sendgrid/mail"; const sendVerificationEmail = async (user: UserInterface, emailToken: string) => { + if (process.env.NODE_ENV === "test") { + return; + } + const apiKey: any = env.sendgridKey; const sendgridEmail:any = env.sendgridEmail; const url = env.remoteURL + `/verify-email/${emailToken}` diff --git a/package.json b/package.json index 98cf530..6a81b46 100755 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ "build:docker": "export NODE_OPTIONS=--max_old_space_size=8000 && tsc && webpack -p --env production && webpack --config webUI.config.js && webpack --config webUISetup.config.js", "build:webUI": "webpack --config webUI.config.js", "build:dev": "tsc && webpack --env development", + "build:test": "tsc && webpack --env test", "build:webUISetup": "webpack --config webUISetup.config.js", "dev-server": "webpack-dev-server", - "test": "NODE_ENV=test env-cmd -f ./config/test.env jest --config=jest.config.json --watchAll --runInBand", + "test": "NODE_ENV=test env-cmd -f ./config/test.env jest --config=jest.config.json --runInBand", "start:dev": "NODE_ENV=development node dist/server/serverStart.js", "start:debug": "NODE_ENV=development node --inspect dist/server/serverStart.js", "start": "node dist/server/serverStart.js --env production", @@ -103,6 +104,7 @@ "request-ip": "^2.1.3", "sharp": "^0.23.4", "stream-skip": "^1.0.3", + "supertest-session": "^4.1.0", "sweetalert2": "^9.7.2", "temp": "^0.9.1", "typescript": "^3.8.3", @@ -132,7 +134,7 @@ "sass-loader": "^8.0.2", "style-loader": "^1.1.3", "superagent-binary-parser": "^1.0.1", - "supertest": "^4.0.2", + "supertest": "^6.0.1", "webpack-bundle-analyzer": "^3.6.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3" diff --git a/tests/db/utils/fileUtils/index.test.js b/tests/db/utils/fileUtils/index.testtt.js similarity index 100% rename from tests/db/utils/fileUtils/index.test.js rename to tests/db/utils/fileUtils/index.testtt.js diff --git a/tests/db/utils/folderUtils/index.test.js b/tests/db/utils/folderUtils/index.testtt.js similarity index 100% rename from tests/db/utils/folderUtils/index.test.js rename to tests/db/utils/folderUtils/index.testtt.js diff --git a/tests/express-routers/file.test.js b/tests/express-routers/file.testtt.js similarity index 100% rename from tests/express-routers/file.test.js rename to tests/express-routers/file.testtt.js diff --git a/tests/express-routers/folder.test.js b/tests/express-routers/folder.testtt.js similarity index 100% rename from tests/express-routers/folder.test.js rename to tests/express-routers/folder.testtt.js diff --git a/tests/express-routers/user.test.js b/tests/express-routers/user.test.js index 709bee1..c78c29a 100644 --- a/tests/express-routers/user.test.js +++ b/tests/express-routers/user.test.js @@ -5,6 +5,9 @@ const createUser = require("../fixtures/createUser"); import servers from "../../dist/server/server"; const request = require("supertest"); import env from "../../dist/enviroment/env"; +const session = require("supertest-session"); +const loginUser = require("../fixtures/loginUser"); +const createUserNotEmailVerified = require("../fixtures/createUserNotEmailVerified"); const {server, serverHttps} = servers; @@ -12,29 +15,57 @@ const app = server; let user; let userToken; +let userData; + +const waitForDatabase = () => { + + return new Promise((resolve, reject) => { + + if (conn.readyState !== 1) { + + conn.once("open", () => { + + resolve(); + + }) + + } else { + + resolve(); + } + + }) +} beforeEach(async(done) => { - if (conn.readyState === 0) { + await waitForDatabase(); - // user = await createUser(); - // userToken = user.tokens[0].token; - const {user: gotUser, token: gotToken} = await createUser(); - user = gotUser; - userToken = gotToken; + const {user: gotUser, userData: gotUserData} = await createUser(); + user = gotUser; + userData = gotUserData; - done() + done(); + // if (conn.readyState === 0) { - } else { + // // user = await createUser(); + // // userToken = user.tokens[0].token; + // const {user: gotUser, token: gotToken} = await createUser(); + // user = gotUser; + // userToken = gotToken; + + // done() + + // } else { - // user = await createUser(); - // userToken = user.tokens[0].token; - const {user: gotUser, token: gotToken} = await createUser(); - user = gotUser; - userToken = gotToken; + // // user = await createUser(); + // // userToken = user.tokens[0].token; + // const {user: gotUser, token: gotToken} = await createUser(); + // user = gotUser; + // userToken = gotToken; - done(); - } + // done(); + // } }) afterEach(async(done) => { @@ -45,9 +76,12 @@ afterEach(async(done) => { test("When authorized, should return user, with no sensitive data", async() => { - const response = await request(app) + const appSession = session(app); + + await loginUser(appSession, userData); + + const response = await appSession .get(`/user-service/user`) - .set("Authorization", `Bearer ${userToken}`) .send() .expect(200); @@ -66,34 +100,30 @@ test("When not authorized should return 401 for user", async() => { .send() .expect(401); - expect(response.body).toEqual({ - "error": "Error Authenticating", - }); + expect(response.body).toEqual({}); }) test("When giving credentials, should login user, and not return sensitive info", async() => { const response = await request(app) .post(`/user-service/login`) - .set("Authorization", `Bearer ${userToken}`) .send({ email: user.email, password: "12345678" }) .expect(200); - expect(response.body.password).toEqual(undefined); - expect(response.body.privateKey).toEqual(undefined); - expect(response.body.publicKey).toEqual(undefined); - expect(response.body.tokens).toEqual(undefined); - expect(response.body.tempTokens).toEqual(undefined); + expect(response.body.user.password).toEqual(undefined); + expect(response.body.user.privateKey).toEqual(undefined); + expect(response.body.user.publicKey).toEqual(undefined); + expect(response.body.user.tokens).toEqual(undefined); + expect(response.body.user.tempTokens).toEqual(undefined); }) test("When giving wrong creditentials, should return 500 error", async() => { const response = await request(app) .post(`/user-service/login`) - .set("Authorization", `Bearer ${userToken}`) .send({ email: user.email, password: "1454524" @@ -105,9 +135,12 @@ test("When giving wrong creditentials, should return 500 error", async() => { test("When authorized should logout user", async() => { - await request(app) + const appSession = session(app); + + await loginUser(appSession, userData); + + await appSession .post(`/user-service/logout`) - .set("Authorization", `Bearer ${userToken}`) .send() .expect(200); }) @@ -119,16 +152,17 @@ test("When not authorized for logout, should return 401 error", async() => { .send() .expect(401); - expect(response.body).toEqual({ - "error": "Error Authenticating", - }); + expect(response.body).toEqual({}); }) test("When authoized should logout all sessions of a user", async() => { - await request(app) + const appSession = session(app); + + await loginUser(appSession, userData); + + await appSession .post(`/user-service/logout-all`) - .set("Authorization", `Bearer ${userToken}`) .send() .expect(200); }) @@ -140,9 +174,7 @@ test("When not authorized for logout all, should return 401 error", async() => { .send() .expect(401); - expect(response.body).toEqual({ - "error": "Error Authenticating", - }); + expect(response.body).toEqual({}); }) test("When giving user data, should create account without returning sensitive data", async() => { @@ -179,27 +211,48 @@ test("When env variable is set to block accounts, should return 401 error", asyn test("When giving old password, and new password, should change password", async() => { + const appSession = session(app); + + await loginUser(appSession, userData); + const oldPassword = "12345678"; const newPassword = "987654321"; - await request(app) + await appSession .post(`/user-service/change-password`) - .set("Authorization", `Bearer ${userToken}`) .send({ oldPassword, newPassword }) .expect(200); + + await request(app) + .post(`/user-service/login`) + .send({ + email: user.email, + password: oldPassword + }) + .expect(500); + + await request(app) + .post(`/user-service/login`) + .send({ + email: user.email, + password: newPassword + }) + .expect(200); }) test("When giving wrong old password for change password, should return 500 error", async() => { + const appSession = session(app); + await loginUser(appSession, userData); + const wrongOldPassword = "12342345"; const newPassword = "987654321"; - await request(app) + await appSession .post(`/user-service/change-password`) - .set("Authorization", `Bearer ${userToken}`) .send({ wrongOldPassword, newPassword @@ -220,7 +273,162 @@ test("When not authorized for change password, should return 401 error", async() }) .expect(401); - expect(response.body).toEqual({ - "error": "Error Authenticating", - }); -}) \ No newline at end of file + expect(response.body).toEqual({}); +}) + +test("When not email verified should not change password", async() => { + + const appSession = session(app); + + const {userData: userData2} = await createUserNotEmailVerified() + await loginUser(appSession, userData2); + + const oldPassword = "12345678"; + const newPassword = "987654321"; + + await appSession + .post(`/user-service/change-password`) + .send({ + oldPassword, + newPassword + }) + .expect(401); +}) + +test("When not giving email, should not create user", async() => { + + await request(app) + .post(`/user-service/create`) + .send({ + email: "", + password: "12345678" + }) + .expect(500); +}) + +test("When giving not a valid email, should not create user", async() => { + + await request(app) + .post(`/user-service/create`) + .send({ + email: "imnotvalid", + password: "12345678" + }) + .expect(500); +}) + +test("When not giving long enouph password, should not create user", async() => { + + await request(app) + .post(`/user-service/create`) + .send({ + email: "test12341@email.com", + password: "123" + }) + .expect(500); +}) + +test("When giving duplicate email, should not create user", async() => { + + await request(app) + .post(`/user-service/create`) + .send({ + email: "test55@gmail.com", + password: "12345678" + }) + .expect(201); + + + await request(app) + .post(`/user-service/create`) + .send({ + email: "test55@gmail.com", + password: "12345678" + }) + .expect(500); +}) + +test("When authenticated should get refresh token", async() => { + + const appSession = session(app); + + await loginUser(appSession, userData); + + await appSession.post("/user-service/get-token").send().expect(201); +}) + +test("When authenticated should get detailed user", async() => { + + const appSession = session(app); + + await loginUser(appSession, userData); + + const response = await appSession.get("/user-service/user-detailed").send().expect(200); + + const responseData = response.body; + const email = responseData.email; + const username = responseData.username; + const password = responseData.password; + const emailVerified = responseData.emailVerified; + const tokens = responseData.tokens; + const publicKey = responseData.publicKey; + const privateKey = responseData.privateKey; + + expect(email).toEqual(userData.email); + expect(username).toEqual(userData.username); + expect(password).toEqual(undefined); + expect(emailVerified).toEqual(true); + expect(tokens).toEqual(undefined); + expect(publicKey).toEqual(undefined); + expect(privateKey).toEqual(undefined) +}) + +test("When not authenticated should not get detailed user", async() => { + + await request(app).get("/user-service/user-detailed").send().expect(401); +}) + +test("When not email verified should not get detailed user", async() => { + + const appSession = session(app); + + const {userData: userData2} = await createUserNotEmailVerified(); + await loginUser(appSession, userData2); + + await request(app).get("/user-service/user-detailed").send().expect(401); +}) + +test("When giving existing email should send password reset email", async() => { + + await request(app).post("/user-service/send-password-reset").send({email: userData.email}).expect(200); +}) + +test("When giving not existing email should return 404", async() => { + + await request(app).post("/user-service/send-password-reset").send({email: "idontexist@void.com"}).expect(404); +}) + +test("When autheniticated should set users name", async() => { + + const appSession = session(app); + await loginUser(appSession, userData); + + await appSession.patch("/user-service/add-name").send({name: "testname"}).expect(200); +}) + +test("When giving a not valid name length should not set users name", async() => { + + const appSession = session(app); + await loginUser(appSession, userData); + + await appSession.patch("/user-service/add-name").send({name: ""}).expect(403); +}) + +test("When not giving name should not set users name", async() => { + + const appSession = session(app); + await loginUser(appSession, userData); + + await appSession.patch("/user-service/add-name").send().expect(403); +}) + diff --git a/tests/fixtures/createUser.js b/tests/fixtures/createUser.js index 52049b2..118a033 100644 --- a/tests/fixtures/createUser.js +++ b/tests/fixtures/createUser.js @@ -16,6 +16,8 @@ const createUser = async() => { name: "Test User", email: "test2@test.com", password: "12345678", + emailVerified: true, + tokens: [] } let user = new User(userData); @@ -23,13 +25,9 @@ const createUser = async() => { await user.generateEncryptionKeys(); - const token = await user.generateAuthToken(); + await user.generateAuthToken("192.168.0.1"); - user.emailVerified = true; - - await user.save(); - - return {user, token}; + return {user, userData}; } module.exports = createUser; \ No newline at end of file diff --git a/tests/fixtures/createUserNotEmailVerified.js b/tests/fixtures/createUserNotEmailVerified.js new file mode 100644 index 0000000..c4a1efc --- /dev/null +++ b/tests/fixtures/createUserNotEmailVerified.js @@ -0,0 +1,33 @@ +const jwt = require("jsonwebtoken"); +import mongoose from "../../dist/db/mongoose"; +import User from "../../dist/models/user"; +import env from "../../dist/enviroment/env"; + +const createUser = async() => { + + env.key = "1234"; + env.password = "1234"; + process.env.KEY = "1234"; + process.env.PASSWORD = "1234"; + + const userID = new mongoose.Types.ObjectId(); + const userData = { + _id: userID, + name: "Test User", + email: "test23@test.com", + password: "12345678", + emailVerified: false, + tokens: [] + } + + let user = new User(userData); + await user.save(); + + await user.generateEncryptionKeys(); + + await user.generateAuthToken("192.168.0.1"); + + return {user, userData}; +} + +module.exports = createUser; \ No newline at end of file diff --git a/tests/fixtures/loginUser.js b/tests/fixtures/loginUser.js new file mode 100644 index 0000000..78fd8b6 --- /dev/null +++ b/tests/fixtures/loginUser.js @@ -0,0 +1,14 @@ +import mongoose from "../../dist/db/mongoose"; +import User from "../../dist/models/user"; +import env from "../../dist/enviroment/env"; +const request = require("supertest"); + +const loginUser = async(appSession, userData) => { + + const response = await appSession.post("/user-service/login") + .send({email: userData.email, password: userData.password}).expect(200); + + return response.body; +} + +module.exports = loginUser; \ No newline at end of file diff --git a/tests/services/FileService/index.test.js b/tests/services/FileService/index.testtt.js similarity index 100% rename from tests/services/FileService/index.test.js rename to tests/services/FileService/index.testtt.js diff --git a/tests/services/FolderService/index.test.js b/tests/services/FolderService/index.testtt.js similarity index 100% rename from tests/services/FolderService/index.test.js rename to tests/services/FolderService/index.testtt.js diff --git a/tests/services/UserService/index.test.js b/tests/services/UserService/index.testtt.js similarity index 100% rename from tests/services/UserService/index.test.js rename to tests/services/UserService/index.testtt.js