diff --git a/.mocharc.js b/.mocharc.js index f37693e3e..f5f5c38ac 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -3,4 +3,5 @@ module.exports = { require: ["./test/setup"], exit: true, file: "./test/mocha-setup", + timeout: 4000, }; diff --git a/babel.config.js b/babel.config.js index 15efea47d..d505be62a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -13,6 +13,8 @@ module.exports = { plugins: [ "@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-modules-commonjs", + // Decorators + ["@babel/plugin-proposal-decorators", { version: "legacy" }], ], presets: [ ["@babel/preset-typescript", { allowDeclareFields: true }], diff --git a/global.d.ts b/global.d.ts index 86a2c05be..efcb02d0a 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,6 +1,6 @@ import { Action } from "redux"; import WebSocket from "ws"; -import { Team, User as UserModel } from "./src/models"; +import { Team, User as UserInterface } from "./src/interfaces"; declare global { interface Window { @@ -11,9 +11,10 @@ declare global { broadcast: (teamId: number, data: Action) => void; subdomain?: string; team?: Team; - user?: UserModel; + user?: UserInterface; wss?: Server; } + export interface User extends UserInterface {} } } diff --git a/package.json b/package.json index e889413c1..8d42ff819 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "react-scroll": "^1.8.9", "react-transition-group": "^4.4.5", "redux": "^4.2.1", + "reflect-metadata": "^0.1.13", "reselect": "^2.3.0", "reserved-usernames": "^1.0.3", "robust-websocket": "^0.2.1", @@ -74,6 +75,7 @@ "sendgrid": "^5.2.3", "sequelize": "^6.29.0", "sequelize-cli": "^6.6.0", + "sequelize-typescript": "^2.1.5", "serialize-javascript": "^6.0.1", "source-map-support": "^0.5.9", "sqlite3": "^5.1.5", @@ -86,6 +88,7 @@ "@babel/eslint-parser": "^7.19.1", "@babel/node": "^7.20.7", "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-decorators": "^7.21.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@babel/plugin-transform-react-constant-elements": "^7.20.2", @@ -115,6 +118,7 @@ "@types/method-override": "^0.0.32", "@types/mocha": "^10.0.1", "@types/morgan": "^1.9.4", + "@types/node": "^20.2.1", "@types/node-fetch": "^2.6.2", "@types/passport": "^1.0.11", "@types/passport-google-oauth20": "^2.0.11", @@ -122,6 +126,7 @@ "@types/proxyquire": "^1.3.28", "@types/react-dom": "^18.2.4", "@types/uuid": "^9.0.0", + "@types/validator": "^13.7.17", "@types/webpack-env": "^1.18.0", "@typescript-eslint/eslint-plugin": "^5.59.1", "@typescript-eslint/parser": "^5.59.1", @@ -130,6 +135,7 @@ "babel-loader": "^9.1.0", "babel-plugin-istanbul": "^6.1.1", "babel-plugin-transform-react-remove-prop-types": "^0.4.18", + "babel-plugin-transform-typescript-metadata": "^0.3.2", "browser-sync": "2.29.1", "chai": "4.3.7", "chai-jsdom": "^0.2.3", @@ -187,6 +193,7 @@ "supertest": "^6.3.3", "svg-url-loader": "^8.0.0", "ts-loader": "^9.4.2", + "ts-node": "^10.9.1", "typescript": "^4.9.5", "url-loader": "^4.1.1", "webpack": "^5.76.0", @@ -222,8 +229,8 @@ "fix-js": "npm run lint-js -- --fix", "fix-css": "npm run lint-css -- --fix", "fix": "npm run fix-js && npm run fix-css", - "test-file": "mocha", - "test-file-ci": "mocha --reporter mocha-junit-reporter", + "test-file": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha", + "test-file-ci": "npm run test-file --reporter mocha-junit-reporter", "test": "npm run test-file \"./src/**/*.test.{js,ts}\"", "test-ci": "npm run test-file-ci \"./src/**/*.test.{js,ts}\"", "test-watch": "npm run test --watch --notify", @@ -257,4 +264,4 @@ "prepare": "husky install" }, "packageManager": "yarn@3.5.1" -} +} \ No newline at end of file diff --git a/src/actions/restaurants.ts b/src/actions/restaurants.ts index 50bc1eac7..ca69ef8f0 100644 --- a/src/actions/restaurants.ts +++ b/src/actions/restaurants.ts @@ -1,8 +1,8 @@ +import { ThunkAction } from "@reduxjs/toolkit"; import { getDecision } from "../selectors/decisions"; import { getNewlyAdded } from "../selectors/listUi"; import { getCurrentUser } from "../selectors/user"; import { processResponse, credentials, jsonHeaders } from "../core/ApiClient"; -import { ThunkAction } from "@reduxjs/toolkit"; import { Action, Restaurant, State, Tag, Vote } from "../interfaces"; export function sortRestaurants(): ThunkAction { @@ -12,7 +12,7 @@ export function sortRestaurants(): ThunkAction { type: "SORT_RESTAURANTS", decision: getDecision(state), newlyAdded: getNewlyAdded(state), - user: getCurrentUser(state), + user: getCurrentUser(state)!, }); }; } diff --git a/src/actions/tags.ts b/src/actions/tags.ts index 100bf7749..fff23fe59 100644 --- a/src/actions/tags.ts +++ b/src/actions/tags.ts @@ -85,6 +85,6 @@ export function removeTag( method: "delete", }) .then((response) => processResponse(response, dispatch)) - .then(() => dispatch(tagDeleted(id, getState().user.id))); + .then(() => dispatch(tagDeleted(id, getState().user!.id))); }; } diff --git a/src/actions/users.ts b/src/actions/users.ts index 996ed737e..d70216b60 100644 --- a/src/actions/users.ts +++ b/src/actions/users.ts @@ -92,7 +92,7 @@ export function removeUser( return (dispatch, getState) => { const state = getState(); let isSelf = false; - if (getCurrentUser(state).id === id) { + if (getCurrentUser(state)!.id === id) { isSelf = true; } dispatch(deleteUser(id, team, isSelf)); @@ -183,7 +183,7 @@ export function changeUserRole( const state = getState(); const team = state.team; let isSelf = false; - if (getCurrentUser(state).id === id) { + if (getCurrentUser(state)!.id === id) { isSelf = true; } dispatch(patchUser(id, type, team, isSelf)); diff --git a/src/api/helpers/checkTeamRole.ts b/src/api/helpers/checkTeamRole.ts index 727a2a390..4f695c7dc 100644 --- a/src/api/helpers/checkTeamRole.ts +++ b/src/api/helpers/checkTeamRole.ts @@ -2,7 +2,7 @@ import { RequestHandler } from "express"; import { RoleType } from "src/interfaces"; import hasRole from "../../helpers/hasRole"; -export default (role: RoleType): RequestHandler => +export default (role?: RoleType): RequestHandler => (req, res, next) => { if (hasRole(req.user, req.team, role)) { next(); diff --git a/src/api/main/teams.js b/src/api/main/teams.ts similarity index 83% rename from src/api/main/teams.js rename to src/api/main/teams.ts index a6996892a..f25a916da 100644 --- a/src/api/main/teams.js +++ b/src/api/main/teams.ts @@ -1,7 +1,7 @@ -import { Router } from "express"; +import { RequestHandler, Response, Router } from "express"; import cors from "cors"; import { bsHost } from "../../config"; -import { Team, Role, User } from "../../models"; +import { Team, Role, User } from "../../db"; import reservedTeamSlugs from "../../constants/reservedTeamSlugs"; import { TEAM_LIMIT, TEAM_SLUG_REGEX } from "../../constants"; import generateUrl from "../../helpers/generateUrl"; @@ -11,23 +11,27 @@ import checkTeamRole from "../helpers/checkTeamRole"; import corsOptionsDelegate from "../helpers/corsOptionsDelegate"; import loggedIn from "../helpers/loggedIn"; -const getTeam = async (req, res, next) => { +const getTeam: RequestHandler = async (req, res, next) => { const id = parseInt(req.params.id, 10); const team = await Team.findOne({ where: { id } }); - req.team = team; // eslint-disable-line no-param-reassign - next(); + if (team) { + req.team = team; // eslint-disable-line no-param-reassign + next(); + } else { + next(new Error("Team doesn't exist")); + } }; -const error409 = (res, message) => +const error409 = (res: Response, message: string) => res.status(409).json({ error: true, data: { message } }); export default () => { - const router = new Router(); + const router = Router(); return router .get("/", loggedIn, async (req, res, next) => { try { - const teams = await Team.findAllForUser(req.user); + const teams = await Team.findAllForUser(req.user!); res.status(200).json({ error: false, data: teams }); } catch (err) { @@ -38,8 +42,8 @@ export default () => { const { address, lat, lng, name, slug } = req.body; const message409 = "Could not create new team. It might already exist."; - if (!req.user.superuser) { - const roles = await req.user.getRoles(); + if (!req.user!.superuser) { + const roles = await req.user!.$get("roles"); if (roles.length >= TEAM_LIMIT) { return res.status(403).json({ error: true, @@ -71,7 +75,7 @@ export default () => { slug, roles: [ { - userId: req.user.id, + userId: req.user!.id, type: "owner", }, ], @@ -81,7 +85,7 @@ export default () => { const json = obj.toJSON(); return res.status(201).send({ error: false, data: json }); - } catch (err) { + } catch (err: any) { if (err.name === "SequelizeUniqueConstraintError") { return error409(res, message409); } @@ -97,7 +101,7 @@ export default () => { checkTeamRole("owner"), async (req, res, next) => { try { - await req.team.destroy(); + await req.team!.destroy(); return res.status(204).send(); } catch (err) { return next(err); @@ -146,7 +150,9 @@ export default () => { ); } - const filteredPayload = {}; + const filteredPayload: { + [key in (typeof allowedFields)[number]["type"]]: string; + } = {}; allowedFields.forEach((f) => { const value = req.body[f.name]; @@ -159,7 +165,7 @@ export default () => { if (fieldCount) { try { - const oldSlug = req.team.get("slug"); + const oldSlug = req.team!.get("slug"); if ( oldSlug !== filteredPayload.slug && @@ -168,13 +174,13 @@ export default () => { return error409(res, message409); } - await req.team.update(filteredPayload); + await req.team!.update(filteredPayload); if (filteredPayload.slug && oldSlug !== filteredPayload.slug) { req.flash("success", "Team URL has been updated."); return req.session.save(async () => { const teamRoles = await Role.findAll({ - where: { teamId: req.team.get("id") }, + where: { teamId: req.team!.get("id") }, }); const userIds = teamRoles.map((r) => r.get("userId")); const recipients = await User.findAll({ @@ -185,10 +191,10 @@ export default () => { transporter .sendMail({ recipients, - subject: `${req.team.get("name")}'s team URL has changed`, + subject: `${req.team!.get("name")}'s team URL has changed`, text: `Hi there! -${req.user.get("name")} has changed the URL of the ${req.team.get( +${req.user!.get("name")} has changed the URL of the ${req.team!.get( "name" )} team on Lunch. @@ -206,7 +212,7 @@ Happy Lunching!`, }); } return res.status(200).json({ error: false, data: req.team }); - } catch (err) { + } catch (err: any) { if (err.name === "SequelizeUniqueConstraintError") { return error409(res, message409); } diff --git a/src/api/main/user.js b/src/api/main/user.ts similarity index 84% rename from src/api/main/user.js rename to src/api/main/user.ts index db1139b87..5250be355 100644 --- a/src/api/main/user.js +++ b/src/api/main/user.ts @@ -1,11 +1,11 @@ import { Router } from "express"; import getPasswordError from "../../helpers/getPasswordError"; import getUserPasswordUpdates from "../../helpers/getUserPasswordUpdates"; -import { User } from "../../models"; +import { User } from "../../db"; import loggedIn from "../helpers/loggedIn"; export default () => { - const router = new Router(); + const router = Router(); return router.patch("/", loggedIn, async (req, res, next) => { let fieldCount = 0; @@ -25,7 +25,9 @@ export default () => { }, ]; - const filteredPayload = {}; + const filteredPayload: { + [key in (typeof allowedFields)[number]["type"]]: string | boolean; + } = {}; allowedFields.forEach((f) => { const value = req.body[f.name]; @@ -53,17 +55,17 @@ export default () => { delete filteredPayload.password; } if (filteredPayload.name) { - if (req.user.get("name") !== filteredPayload.name) { + if (req.user!.get("name") !== filteredPayload.name) { filteredPayload.namedChanged = true; } } - await req.user.update(filteredPayload); + await req.user!.update(filteredPayload); // get user again because now req.user contains password fields - const user = await User.getSessionUser(req.user.get("id")); + const user = await User.getSessionUser(req.user!.id); return res.status(200).json({ error: false, data: user }); - } catch (err) { + } catch (err: any) { if (err.name === "SequelizeUniqueConstraintError") { return res.status(422).json({ error: true, diff --git a/src/api/team/decisions.js b/src/api/team/decisions.ts similarity index 57% rename from src/api/team/decisions.js rename to src/api/team/decisions.ts index 3304ad920..62672ebc7 100644 --- a/src/api/team/decisions.js +++ b/src/api/team/decisions.ts @@ -1,22 +1,33 @@ import { Router } from "express"; import dayjs from "dayjs"; -import { Op } from "../../models/db"; -import { Decision } from "../../models"; +import { + Attributes, + CreationAttributes, + FindOptions, + ModelStatic, + Op, +} from "sequelize"; +import { Decision } from "../../db"; import checkTeamRole from "../helpers/checkTeamRole"; import loggedIn from "../helpers/loggedIn"; import { decisionPosted, decisionsDeleted } from "../../actions/decisions"; export default () => { - const router = new Router({ mergeParams: true }); + const router = Router({ mergeParams: true }); return router .get("/", loggedIn, checkTeamRole(), async (req, res, next) => { try { - const opts = { where: { teamId: req.team.id } }; - const days = parseInt(req.query.days, 10); + const opts: FindOptions> = { + where: { teamId: req.team!.id }, + }; + const days = parseInt(req.query.days as string, 10); if (!Number.isNaN(days)) { - opts.where.createdAt = { - [Op.gt]: dayjs().subtract(days, "days").toDate(), + opts.where = { + ...opts.where, + createdAt: { + [Op.gt]: dayjs().subtract(days, "days").toDate(), + }, }; } @@ -30,19 +41,25 @@ export default () => { .post("/", loggedIn, checkTeamRole(), async (req, res, next) => { const restaurantId = parseInt(req.body.restaurantId, 10); try { - const destroyOpts = { where: { teamId: req.team.id } }; + const destroyOpts: FindOptions> = { + where: { teamId: req.team!.id }, + }; const daysAgo = parseInt(req.body.daysAgo, 10); - let MaybeScopedDecision = Decision; + let MaybeScopedDecision: typeof Decision | ModelStatic = + Decision; if (daysAgo > 0) { - destroyOpts.where.createdAt = { - [Op.gt]: dayjs() - .subtract(daysAgo, "days") - .subtract(12, "hours") - .toDate(), - [Op.lt]: dayjs() - .subtract(daysAgo, "days") - .add(12, "hours") - .toDate(), + destroyOpts.where = { + ...destroyOpts.where, + createdAt: { + [Op.gt]: dayjs() + .subtract(daysAgo, "days") + .subtract(12, "hours") + .toDate(), + [Op.lt]: dayjs() + .subtract(daysAgo, "days") + .add(12, "hours") + .toDate(), + }, }; } else { MaybeScopedDecision = MaybeScopedDecision.scope("fromToday"); @@ -52,9 +69,9 @@ export default () => { await MaybeScopedDecision.destroy(destroyOpts); try { - const createOpts = { + const createOpts: CreationAttributes = { restaurantId, - teamId: req.team.id, + teamId: req.team!.id, }; if (daysAgo > 0) { createOpts.createdAt = dayjs().subtract(daysAgo, "days").toDate(); @@ -63,8 +80,8 @@ export default () => { const json = obj.toJSON(); req.broadcast( - req.team.id, - decisionPosted(json, deselected, req.user.id) + req.team!.id, + decisionPosted(json, deselected, req.user!.id) ); res.status(201).send({ error: false, data: obj }); } catch (err) { @@ -78,13 +95,13 @@ export default () => { .delete("/fromToday", loggedIn, checkTeamRole(), async (req, res, next) => { try { const decisions = await Decision.scope("fromToday").findAll({ - where: { teamId: req.team.id }, + where: { teamId: req.team!.id }, }); await Decision.scope("fromToday").destroy({ - where: { teamId: req.team.id }, + where: { teamId: req.team!.id }, }); - req.broadcast(req.team.id, decisionsDeleted(decisions, req.user.id)); + req.broadcast(req.team!.id, decisionsDeleted(decisions, req.user!.id)); res.status(204).send(); } catch (err) { next(err); diff --git a/src/api/team/restaurantTags.js b/src/api/team/restaurantTags.js index b6d78fe02..8fb76fa20 100644 --- a/src/api/team/restaurantTags.js +++ b/src/api/team/restaurantTags.js @@ -1,5 +1,5 @@ import { Router } from "express"; -import { Tag, RestaurantTag } from "../../models"; +import { Tag, RestaurantTag } from "../../db"; import checkTeamRole from "../helpers/checkTeamRole"; import loggedIn from "../helpers/loggedIn"; import { diff --git a/src/api/team/restaurants.js b/src/api/team/restaurants.js index 88cd98e92..d9ff16c53 100644 --- a/src/api/team/restaurants.js +++ b/src/api/team/restaurants.js @@ -1,6 +1,6 @@ import { Router } from "express"; import fetch from "node-fetch"; -import { Restaurant, Vote, Tag } from "../../models"; +import { Restaurant, Vote, Tag } from "../../db"; import checkTeamRole from "../helpers/checkTeamRole"; import loggedIn from "../helpers/loggedIn"; import { diff --git a/src/api/team/tags.js b/src/api/team/tags.js index e2f00236a..d56711ac6 100644 --- a/src/api/team/tags.js +++ b/src/api/team/tags.js @@ -1,5 +1,5 @@ import { Router } from "express"; -import { Tag } from "../../models"; +import { Tag } from "../../db"; import checkTeamRole from "../helpers/checkTeamRole"; import loggedIn from "../helpers/loggedIn"; import { tagDeleted } from "../../actions/tags"; diff --git a/src/api/team/users.js b/src/api/team/users.ts similarity index 86% rename from src/api/team/users.js rename to src/api/team/users.ts index 827f60488..b9bf2a107 100644 --- a/src/api/team/users.js +++ b/src/api/team/users.ts @@ -1,6 +1,6 @@ -import { Router } from "express"; +import { Request, Router } from "express"; import cors from "cors"; -import { Invitation, Role, User } from "../../models"; +import { Invitation, Role, Team, User } from "../../db"; import { bsHost } from "../../config"; import { TEAM_LIMIT } from "../../constants"; import generateToken from "../../helpers/generateToken"; @@ -11,26 +11,31 @@ import canChangeRole from "../../helpers/canChangeRole"; import checkTeamRole from "../helpers/checkTeamRole"; import corsOptionsDelegate from "../helpers/corsOptionsDelegate"; import loggedIn from "../helpers/loggedIn"; +import { RoleType } from "../../interfaces"; import transporter from "../../mailers/transporter"; export default () => { - const router = new Router({ mergeParams: true }); + const router = Router({ mergeParams: true }); - const getRoleToChange = async (currentUser, targetId, team) => { + const getRoleToChange = async ( + currentUser: User, + targetId: number, + team: Team + ) => { if (currentUser.id === targetId) { return getRole(currentUser, team); } return Role.findOne({ where: { teamId: team.id, userId: targetId } }); }; - const hasOtherOwners = async (team, id) => { + const hasOtherOwners = async (team: Team, id: number) => { const allTeamRoles = await Role.findAll({ where: { teamId: team.id } }); return allTeamRoles.some( (role) => role.type === "owner" && role.userId !== id ); }; - const getExtraAttributes = (req) => { + const getExtraAttributes = (req: Request) => { if (hasRole(req.user, req.team, "owner")) { return ["email"]; } @@ -38,11 +43,11 @@ export default () => { }; const canChangeUser = async ( - user, - roleToChange, - target, - team, - noOtherOwners + user: User, + roleToChange: Role, + target: RoleType | undefined, + team: Team, + noOtherOwners: () => void ) => { let currentUserRole; if (user.id === roleToChange.userId) { @@ -78,12 +83,12 @@ export default () => { try { const users = await User.scope({ - method: ["withTeamRole", req.team.id, extraAttributes], + method: ["withTeamRole", req.team!.id, extraAttributes], }).findAll({ include: { attributes: [], model: Role, - where: { teamId: req.team.id }, + where: { teamId: req.team!.id }, }, }); @@ -116,12 +121,12 @@ export default () => { }); const UserWithTeamRole = User.scope({ - method: ["withTeamRole", req.team.id, extraAttributes], + method: ["withTeamRole", req.team!.id, extraAttributes], }); if (userToAdd) { if ( - !req.user.get("superuser") && + !req.user!.get("superuser") && userToAdd.roles.length >= TEAM_LIMIT ) { return res.status(403).json({ @@ -139,7 +144,7 @@ export default () => { }); } await Role.create({ - teamId: req.team.id, + teamId: req.team!.id, userId: userToAdd.id, type, }); @@ -152,13 +157,13 @@ export default () => { subject: "You were added to a team!", text: `Hi there! -${req.user.get("name")} invited you to the ${req.team.get( +${req.user!.get("name")} invited you to the ${req.team!.get( "name" )} team on Lunch! To get started, simply visit ${generateUrl( req, - `${req.team.get("slug")}.${bsHost}` + `${req.team!.get("slug")}.${bsHost}` )} and vote away. Happy Lunching!`, @@ -184,7 +189,7 @@ Happy Lunching!`, resetPasswordSentAt: new Date(), roles: [ { - teamId: req.team.id, + teamId: req.team!.id, type, }, ], @@ -205,7 +210,7 @@ Happy Lunching!`, subject: "Welcome to Lunch!", text: `Hi there! -${req.user.get("name")} invited you to the ${req.team.get( +${req.user!.get("name")} invited you to the ${req.team!.get( "name" )} team on Lunch! @@ -224,7 +229,9 @@ Happy Lunching!`, // Sequelize can't apply scopes on create, so just get user again. // Also will exclude hidden fields like password, token, etc. - newUser = await UserWithTeamRole.findOne({ where: { id: newUser.id } }); + newUser = (await UserWithTeamRole.findOne({ + where: { id: newUser.id }, + })) as User; return res.status(201).json({ error: false, data: newUser }); } catch (err) { @@ -241,14 +248,14 @@ Happy Lunching!`, const extraAttributes = getExtraAttributes(req); try { - const roleToChange = await getRoleToChange(req.user, id, req.team); + const roleToChange = await getRoleToChange(req.user!, id, req.team!); if (roleToChange) { const allowed = await canChangeUser( - req.user, + req.user!, roleToChange, req.body.type, - req.team, + req.team!, () => res.status(403).json({ error: true, @@ -267,7 +274,7 @@ Happy Lunching!`, if (allowed) { await roleToChange.update({ type: req.body.type }); const user = await User.scope({ - method: ["withTeamRole", req.team.id, extraAttributes], + method: ["withTeamRole", req.team!.id, extraAttributes], }).findOne({ where: { id } }); return res.status(200).json({ error: false, data: user }); } @@ -297,14 +304,14 @@ Happy Lunching!`, const id = parseInt(req.params.id, 10); try { - const roleToDelete = await getRoleToChange(req.user, id, req.team); + const roleToDelete = await getRoleToChange(req.user!, id, req.team!); if (roleToDelete) { const allowed = await canChangeUser( - req.user, + req.user!, roleToDelete, undefined, - req.team, + req.team!, () => res.status(403).json({ error: true, diff --git a/src/api/team/votes.js b/src/api/team/votes.js index 97754704b..57903d0cb 100644 --- a/src/api/team/votes.js +++ b/src/api/team/votes.js @@ -1,6 +1,5 @@ import { Router } from "express"; -import { Vote } from "../../models"; -import { sequelize } from "../../models/db"; +import { sequelize, Vote } from "../../db"; import checkTeamRole from "../helpers/checkTeamRole"; import loggedIn from "../helpers/loggedIn"; import { votePosted, voteDeleted } from "../../actions/restaurants"; diff --git a/src/api/tests/decisions.test.js b/src/api/tests/decisions.test.js index 8d70c6eb3..51db3d1e0 100644 --- a/src/api/tests/decisions.test.js +++ b/src/api/tests/decisions.test.js @@ -46,13 +46,7 @@ describe("api/team/decisions", () => { makeApp = (deps) => { const decisionsApi = proxyquireStrict("../team/decisions", { - "../../models/db": mockEsmodule({ - Op: { - lt: "lt", - gt: "gt", - }, - }), - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Decision: DecisionMock, }), "../helpers/loggedIn": mockEsmodule({ @@ -101,9 +95,10 @@ describe("api/team/decisions", () => { expect( findAllSpy.calledWith({ where: { - createdAt: { - gt: match.date, - }, + createdAt: match( + (value) => + value[Object.getOwnPropertySymbols(value)[0]] instanceof Date + ), teamId: 77, }, }) @@ -204,10 +199,12 @@ describe("api/team/decisions", () => { expect( destroySpy.calledWith({ where: { - createdAt: { - lt: match.date, - gt: match.date, - }, + createdAt: match( + (value) => + value[Object.getOwnPropertySymbols(value)[0]] instanceof + Date && + value[Object.getOwnPropertySymbols(value)[1]] instanceof Date + ), teamId: 77, }, }) @@ -284,7 +281,7 @@ describe("api/team/decisions", () => { let response; beforeEach((done) => { app = makeApp({ - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Decision: { create: stub().throws(), destroy: DecisionMock.destroy, diff --git a/src/api/tests/teams.test.js b/src/api/tests/teams.test.js index 5780a4c58..8f81138b8 100644 --- a/src/api/tests/teams.test.js +++ b/src/api/tests/teams.test.js @@ -35,7 +35,7 @@ describe("api/main/teams", () => { // eslint-disable-line no-param-reassign get: () => undefined, id: 231, - getRoles: () => [], + $get: () => [], roles: [], }; next(); @@ -45,7 +45,7 @@ describe("api/main/teams", () => { makeApp = (deps, middleware) => { const teamsApi = proxyquireStrict("../main/teams", { - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Team: TeamMock, Role: RoleMock, User: UserMock, @@ -129,7 +129,7 @@ describe("api/main/teams", () => { req.user = { // eslint-disable-line no-param-reassign id: 231, - getRoles: () => [{}, {}, {}, {}, {}], + $get: () => [{}, {}, {}, {}, {}], roles: [{}, {}, {}, {}, {}], }; next(); @@ -359,7 +359,7 @@ describe("api/main/teams", () => { let response; beforeEach((done) => { app = makeApp({ - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Team: { create: stub().throws(), destroy: TeamMock.destroy, diff --git a/src/api/tests/user.test.js b/src/api/tests/user.test.js index e1c222586..95a14f471 100644 --- a/src/api/tests/user.test.js +++ b/src/api/tests/user.test.js @@ -41,7 +41,7 @@ describe("api/main/user", () => { makeApp = (deps, middleware) => { const userApi = proxyquireStrict("../main/user", { - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ User: UserMock, }), "../helpers/loggedIn": mockEsmodule({ diff --git a/src/api/tests/users.test.js b/src/api/tests/users.test.js index 5ecb40100..b829f63c8 100644 --- a/src/api/tests/users.test.js +++ b/src/api/tests/users.test.js @@ -58,7 +58,7 @@ describe("api/team/users", () => { makeApp = (deps) => { const usersApi = proxyquireStrict("../team/users", { - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Invitation: InvitationMock, Role: RoleMock, User: UserMock, @@ -172,7 +172,7 @@ describe("api/team/users", () => { "../../helpers/hasRole": mockEsmodule({ default: () => true, }), - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ User: { scope: stub().throws("Oh No"), }, @@ -906,7 +906,7 @@ describe("api/team/users", () => { beforeEach((done) => { app = makeApp({ "../../helpers/hasRole": hasRole, - "../../models": mockEsmodule({ + "../../db": mockEsmodule({ Role: { findOne: stub().throws("Oh No"), }, diff --git a/src/components/HeaderLogin/HeaderLogin.js b/src/components/HeaderLogin/HeaderLogin.js index 572a4b22c..7e642771d 100644 --- a/src/components/HeaderLogin/HeaderLogin.js +++ b/src/components/HeaderLogin/HeaderLogin.js @@ -15,7 +15,7 @@ import s from "./HeaderLogin.scss"; const HeaderLogin = ({ user }) => { let content =
; - if (user.id === undefined) { + if (user === null) { content = (