express-generator-typescript 2.4.7 → 2.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/lib/express-generator-typescript.js +1 -1
  2. package/lib/project-files/package.json +2 -1
  3. package/lib/project-files/spec/support/apiCb.ts +76 -0
  4. package/lib/project-files/spec/tests/users.spec.ts +98 -135
  5. package/lib/project-files/spec/types/misc.ts +18 -0
  6. package/lib/project-files/src/models/User.ts +13 -27
  7. package/lib/project-files/src/public/scripts/http.js +3 -1
  8. package/lib/project-files/src/public/scripts/users.js +31 -65
  9. package/lib/project-files/src/public/stylesheets/users.css +4 -6
  10. package/lib/project-files/src/repos/UserRepo.ts +6 -1
  11. package/lib/project-files/src/repos/database.json +22 -1
  12. package/lib/project-files/src/routes/types/express/misc.ts +1 -5
  13. package/lib/project-files/src/routes/types/types.ts +0 -8
  14. package/lib/project-files/src/views/users.html +100 -5
  15. package/lib/project-files-auth/package.json +2 -1
  16. package/lib/project-files-auth/spec/support/apiCb.ts +76 -0
  17. package/lib/project-files-auth/spec/support/login.ts +3 -6
  18. package/lib/project-files-auth/spec/tests/auth.spec.ts +50 -67
  19. package/lib/project-files-auth/spec/tests/users.spec.ts +98 -142
  20. package/lib/project-files-auth/spec/types/misc.ts +18 -0
  21. package/lib/project-files-auth/src/models/User.ts +17 -12
  22. package/lib/project-files-auth/src/public/scripts/http.js +3 -1
  23. package/lib/project-files-auth/src/public/scripts/login.js +1 -3
  24. package/lib/project-files-auth/src/public/scripts/users.js +31 -63
  25. package/lib/project-files-auth/src/public/stylesheets/users.css +4 -11
  26. package/lib/project-files-auth/src/repos/UserRepo.ts +6 -1
  27. package/lib/project-files-auth/src/repos/database.json +1 -1
  28. package/lib/project-files-auth/src/services/UserService.ts +2 -8
  29. package/lib/project-files-auth/src/views/login.html +26 -3
  30. package/lib/project-files-auth/src/views/users.html +106 -8
  31. package/package.json +1 -1
  32. package/lib/project-files/spec/support/types.ts +0 -1
  33. package/lib/project-files-auth/spec/support/types.ts +0 -1
@@ -1,9 +1,18 @@
1
- // ***** Start **** //
1
+ // **** Variables **** //
2
2
 
3
- displayUsers();
3
+ const DateFormatter = new Intl.DateTimeFormat('en-US', {
4
+ year: 'numeric',
5
+ month: '2-digit',
6
+ day: '2-digit',
7
+ });
8
+
9
+ const formatDate = (date) => DateFormatter.format(new Date(date));
4
10
 
5
11
 
6
- // ***** Fetch and display users **** //
12
+ // **** Run **** //
13
+
14
+ // Start
15
+ displayUsers();
7
16
 
8
17
  /**
9
18
  * Call api
@@ -12,59 +21,22 @@ function displayUsers() {
12
21
  Http
13
22
  .get('/api/users/all')
14
23
  .then(resp => resp.json())
15
- .then((resp) => {
16
- var allUsers = resp.users;
17
- // Empty the anchor
24
+ .then(resp => {
25
+ var allUsersTemplate = document.getElementById('all-users-template'),
26
+ allUsersTemplateHtml = allUsersTemplate.innerHTML,
27
+ template = Handlebars.compile(allUsersTemplateHtml);
18
28
  var allUsersAnchor = document.getElementById('all-users-anchor');
19
- allUsersAnchor.innerHTML = '';
20
- // Append users to anchor
21
- allUsers.forEach((user) => {
22
- allUsersAnchor.innerHTML += getUserDisplayEle(user);
29
+ allUsersAnchor.innerHTML = template({
30
+ users: resp.users.map(user => ({
31
+ ...user,
32
+ createdFormatted: formatDate(user.created),
33
+ })),
23
34
  });
24
35
  });
25
36
  }
26
37
 
27
- /**
28
- * Get user display element
29
- */
30
- function getUserDisplayEle(user) {
31
- return (
32
- `<div class="user-display-ele">
33
-
34
- <div class="normal-view">
35
- <div>Name: ${user.name}</div>
36
- <div>Email: ${user.email}</div>
37
- <button class="edit-user-btn" data-user-id="${user.id}" data-user-role="${user.role}">
38
- Edit
39
- </button>
40
- <button class="delete-user-btn" data-user-id="${user.id}">
41
- Delete
42
- </button>
43
- </div>
44
-
45
- <div class="edit-view">
46
- <div>
47
- Name: <input class="name-edit-input" value="${user.name}">
48
- </div>
49
- <div>
50
- Email: <input class="email-edit-input" value="${user.email}">
51
- </div>
52
- <button class="submit-edit-btn" data-user-id="${user.id}">
53
- Submit
54
- </button>
55
- <button class="cancel-edit-btn" data-user-id="${user.id}">
56
- Cancel
57
- </button>
58
- </div>
59
- </div>`
60
- );
61
- }
62
-
63
-
64
- // **** Add, Edit, and Delete Users **** //
65
-
66
38
  // Setup event listener for button click
67
- document.addEventListener('click', function (event) {
39
+ document.addEventListener('click', event => {
68
40
  event.preventDefault();
69
41
  var ele = event.target;
70
42
  if (ele.matches('#add-user-btn')) {
@@ -77,8 +49,6 @@ document.addEventListener('click', function (event) {
77
49
  submitEdit(ele);
78
50
  } else if (ele.matches('.delete-user-btn')) {
79
51
  deleteUser(ele);
80
- } else if (ele.matches('#logout-btn')) {
81
- logoutUser();
82
52
  }
83
53
  }, false);
84
54
 
@@ -93,13 +63,17 @@ function addUser() {
93
63
  id: -1,
94
64
  name: nameInput.value,
95
65
  email: emailInput.value,
96
- role: 0,
66
+ created: new Date(),
97
67
  },
98
68
  };
99
69
  // Call api
100
70
  Http
101
71
  .post('/api/users/add', data)
102
- .then(() => displayUsers());
72
+ .then(() => {
73
+ nameInput.value = '';
74
+ emailInput.value = '';
75
+ displayUsers();
76
+ });
103
77
  }
104
78
 
105
79
  /**
@@ -130,13 +104,14 @@ function submitEdit(ele) {
130
104
  var nameInput = userEle.getElementsByClassName('name-edit-input')[0];
131
105
  var emailInput = userEle.getElementsByClassName('email-edit-input')[0];
132
106
  var id = ele.getAttribute('data-user-id');
133
- var role = ele.getAttribute('data-user-role');
107
+ var created = ele.getAttribute('data-user-created');
108
+ console.log(ele, created)
134
109
  var data = {
135
110
  user: {
136
111
  id: Number(id),
137
112
  name: nameInput.value,
138
113
  email: emailInput.value,
139
- role: Number(role),
114
+ created: new Date(created),
140
115
  },
141
116
  };
142
117
  Http
@@ -153,12 +128,3 @@ function deleteUser(ele) {
153
128
  .delete('/api/users/delete/' + id)
154
129
  .then(() => displayUsers());
155
130
  }
156
-
157
-
158
- // **** Logout **** //
159
-
160
- function logoutUser() {
161
- Http
162
- .get('/api/auth/logout')
163
- .then(() => window.location.href = '/');
164
- }
@@ -27,15 +27,13 @@ body .add-user-col #add-user-btn {
27
27
  margin-bottom: 10px;
28
28
  }
29
29
 
30
- body .add-user-col #logout-btn {
31
- margin-top: 25px;
32
- margin-bottom: 10px;
33
- font-size: 15px;
34
- }
35
-
36
30
 
37
31
  /** Users Display Column **/
38
32
 
33
+ .email-edit {
34
+ padding-bottom: 8px;
35
+ }
36
+
39
37
  body .users-column .user-display-ele {
40
38
  padding-bottom: 10px;
41
39
  }
@@ -56,7 +56,12 @@ async function update(user: IUser): Promise<void> {
56
56
  const db = await orm.openDb();
57
57
  for (let i = 0; i < db.users.length; i++) {
58
58
  if (db.users[i].id === user.id) {
59
- db.users[i] = user;
59
+ const dbUser = db.users[i];
60
+ db.users[i] = {
61
+ ...dbUser,
62
+ name: user.name,
63
+ email: user.email,
64
+ };
60
65
  return orm.saveDb(db);
61
66
  }
62
67
  }
@@ -1 +1,22 @@
1
- {"users":[{"name":"Sean Maxwell","email":"sean.maxwell@gmail.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":1,"id":159123164363},{"name":"Gordan Freeman","email":"gordan.freeman@halflife.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":906524522143},{"name":"John Smith","email":"jsmith@yahoo.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":357437875835}]}
1
+ {
2
+ "users": [
3
+ {
4
+ "id": 366115170645,
5
+ "name": "Sean Maxwell",
6
+ "email": "smaxwell@example.com",
7
+ "created": "2024-03-22T05:14:36.252Z"
8
+ },
9
+ {
10
+ "id": 310946254456,
11
+ "name": "John Smith",
12
+ "email": "john.smith@example.com",
13
+ "created": "2024-03-22T05:20:55.079Z"
14
+ },
15
+ {
16
+ "id": 143027113460,
17
+ "name": "Gordan Freeman",
18
+ "email": "nova@prospect.com",
19
+ "created": "2024-03-22T05:42:18.895Z"
20
+ }
21
+ ]
22
+ }
@@ -1,7 +1,5 @@
1
1
  import * as e from 'express';
2
2
 
3
- import { ISessionUser } from '@src/models/User';
4
-
5
3
 
6
4
  // **** Express **** //
7
5
 
@@ -10,7 +8,5 @@ export interface IReq<T = void> extends e.Request {
10
8
  }
11
9
 
12
10
  export interface IRes extends e.Response {
13
- locals: {
14
- sessionUser?: ISessionUser;
15
- };
11
+ locals: Record<string, unknown>;
16
12
  }
@@ -1,8 +1,6 @@
1
1
  import * as e from 'express';
2
2
  import { Query } from 'express-serve-static-core';
3
3
 
4
- import { ISessionUser } from '@src/models/User';
5
-
6
4
 
7
5
  // **** Express **** //
8
6
 
@@ -14,9 +12,3 @@ export interface IReqQuery<T extends Query, U = void> extends e.Request {
14
12
  query: T;
15
13
  body: U;
16
14
  }
17
-
18
- export interface IRes extends e.Response {
19
- locals: {
20
- sessionUser: ISessionUser;
21
- };
22
- }
@@ -1,10 +1,30 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
+
4
+ <!-- Head -->
3
5
  <head>
4
6
  <meta charset="UTF-8">
5
7
  <title>Users</title>
6
8
  <link rel="stylesheet" type="text/css" href="/stylesheets/users.css" />
9
+
10
+ <!-- Handlebars -->
11
+ <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>
12
+
13
+ <!-- Bootstrap -->
14
+ <link
15
+ href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
16
+ rel="stylesheet"
17
+ integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
18
+ crossorigin="anonymous"
19
+ />
20
+ <script
21
+ src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
22
+ integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
23
+ crossorigin="anonymous"
24
+ ></script>
7
25
  </head>
26
+
27
+ <!-- Body -->
8
28
  <body>
9
29
 
10
30
  <!-- Add Users -->
@@ -13,13 +33,26 @@
13
33
  Add User:
14
34
  </div>
15
35
  <div>
16
- <input id="name-input" placeholder="Name" />
36
+ <input
37
+ id="name-input"
38
+ type="text"
39
+ class="form-control"
40
+ placeholder="Name"
41
+ />
17
42
  </div>
18
43
  <div>
19
- <input id="email-input" placeholder="Email" />
44
+ <input
45
+ id="email-input"
46
+ type="email"
47
+ class="form-control"
48
+ placeholder="Email"
49
+ />
20
50
  </div>
21
51
  <div>
22
- <button id="add-user-btn">
52
+ <button
53
+ id="add-user-btn"
54
+ class="btn btn-success"
55
+ >
23
56
  Add
24
57
  </button>
25
58
  </div>
@@ -27,11 +60,73 @@
27
60
 
28
61
  <!-- Display Users -->
29
62
  <div class="users-column">
30
- <div class="column-header">Users:</div>
63
+ <div class="column-header">
64
+ Users:
65
+ </div>
66
+
31
67
  <div id="all-users-anchor"></div>
32
- </div>
68
+ <script
69
+ id="all-users-template"
70
+ type="text/x-handlebars-template"
71
+ >
72
+ {{#each users}}
73
+ <div class="user-display-ele">
74
+ <div class="normal-view">
75
+ <div><b>Name:</b> {{name}}</div>
76
+ <div><b>Email:</b> {{email}}</div>
77
+ <div><b>Created:</b> {{createdFormatted}}</div>
78
+ <button
79
+ type="button"
80
+ class="btn btn-primary edit-user-btn"
81
+ data-user-id="{{id}}"
82
+ >
83
+ Edit
84
+ </button>
85
+ <button
86
+ class="btn btn-danger delete-user-btn"
87
+ data-user-id="{{id}}"
88
+ >
89
+ Delete
90
+ </button>
91
+ </div>
33
92
 
93
+ <div class="edit-view">
94
+ <div>
95
+ Name:&nbsp;
96
+ <input
97
+ type="text"
98
+ class="form-control name-edit-input"
99
+ value="{{name}}"
100
+ />
101
+ </div>
102
+ <div class="email-edit">
103
+ Email:&nbsp;
104
+ <input
105
+ type="email"
106
+ class="form-control email-edit-input"
107
+ value="{{email}}"
108
+ />
109
+ </div>
110
+ <button
111
+ class="btn btn-primary submit-edit-btn"
112
+ data-user-id="{{id}}"
113
+ data-user-created="{{created}}"
114
+ >
115
+ Submit
116
+ </button>
117
+ <button
118
+ class="btn btn-secondary cancel-edit-btn"
119
+ data-user-id="{{id}}"
120
+ >
121
+ Cancel
122
+ </button>
123
+ </div>
124
+ </div>
125
+ {{/each}}
126
+ </script>
127
+ </div>
34
128
  </body>
129
+
35
130
  <script src="scripts/http.js"></script>
36
131
  <script src="scripts/users.js"></script>
37
132
  </html>
@@ -35,11 +35,12 @@
35
35
  "helmet": "^6.0.0",
36
36
  "inserturlparams": "^1.0.1",
37
37
  "jet-logger": "^1.3.1",
38
- "jet-validator": "^1.0.3",
39
38
  "jet-paths": "^1.0.5",
39
+ "jet-validator": "^1.0.3",
40
40
  "jsonfile": "^6.1.0",
41
41
  "jsonwebtoken": "^8.5.1",
42
42
  "module-alias": "^2.2.2",
43
+ "moment": "^2.30.1",
43
44
  "morgan": "^1.10.0",
44
45
  "ts-command-line-args": "^2.4.2"
45
46
  },
@@ -0,0 +1,76 @@
1
+ import { CallbackHandler } from 'supertest';
2
+ import moment from 'moment';
3
+ import logger from 'jet-logger';
4
+
5
+ import { TApiCb, TRes } from 'spec/types/misc';
6
+
7
+
8
+ /**
9
+ * API callback function.
10
+ */
11
+ function apiCb(
12
+ cb: TApiCb,
13
+ dateParam = 'created',
14
+ printErr?: boolean,
15
+ ): CallbackHandler {
16
+ return (err: Error, res: TRes) => {
17
+ if (printErr) {
18
+ logger.err(err);
19
+ }
20
+ _strToDate(res.body, dateParam);
21
+ return cb(res);
22
+ };
23
+ }
24
+
25
+ /**
26
+ * When date objects get sent through supertest they are converted to
27
+ * iso-strings. This will cause "toEqual()"" tests to fail, so we need to
28
+ * convert them back to Date objects.
29
+ */
30
+ function _strToDate(
31
+ param: unknown,
32
+ prop: string,
33
+ ): void {
34
+ return _iterate(param, prop);
35
+ }
36
+
37
+ /**
38
+ * Interate object recursively and convert string-dates to "Date" objects.
39
+ */
40
+ function _iterate(param: unknown, prop: string): void {
41
+ if (!param || typeof param !== 'object') {
42
+ return;
43
+ }
44
+ const paramF = param as Record<string, unknown>;
45
+ // For Arrays
46
+ if (Array.isArray(paramF)) {
47
+ for (const item of paramF) {
48
+ _iterate(item, prop);
49
+ }
50
+ return;
51
+ }
52
+ // Check valid string or Date object. If undefined just skip
53
+ const val = paramF[prop];
54
+ if (
55
+ (typeof val !== 'undefined') &&
56
+ !((typeof val === 'string') || (val instanceof Date)) &&
57
+ !moment(val as string | Date).isValid()
58
+ ) {
59
+ throw new Error('Property must be a valid date-string or Date() object');
60
+ }
61
+ // Convert and iterate
62
+ if (typeof val !== 'undefined') {
63
+ paramF[prop] = new Date(val as string | Date);
64
+ }
65
+ for (const key in paramF) {
66
+ const oval = paramF[key];
67
+ if (typeof oval === 'object' && key !== prop) {
68
+ _iterate(oval, prop);
69
+ }
70
+ }
71
+ }
72
+
73
+
74
+ // **** Export default **** //
75
+
76
+ export default apiCb;
@@ -8,16 +8,12 @@ import PwdUtil from '@src/util/PwdUtil';
8
8
  import Paths from './Paths';
9
9
 
10
10
 
11
- // **** Variables **** //
12
-
11
+ // Login Credentials
13
12
  const LoginCreds = {
14
13
  email: 'jsmith@gmail.com',
15
14
  password: 'Password@1',
16
15
  } as const;
17
16
 
18
-
19
- // **** Functions **** //
20
-
21
17
  /**
22
18
  * Login a user.
23
19
  */
@@ -25,7 +21,8 @@ function login(beforeAgent: TestAgent<Test>, done: (arg: string) => void) {
25
21
  // Setup dummy data
26
22
  const role = UserRoles.Admin,
27
23
  pwdHash = PwdUtil.hashSync(LoginCreds.password),
28
- loginUser = User.new('john smith', LoginCreds.email, role, pwdHash);
24
+ loginUser = User.new('john smith', LoginCreds.email, new Date(), role,
25
+ pwdHash);
29
26
  // Add spy
30
27
  spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
31
28
  // Call Login API
@@ -1,4 +1,5 @@
1
1
  import supertest, { Test, Response } from 'supertest';
2
+ import TestAgent from 'supertest/lib/agent';
2
3
 
3
4
  import app from '@src/server';
4
5
 
@@ -11,36 +12,18 @@ import EnvVars from '@src/constants/EnvVars';
11
12
  import HttpStatusCodes from '@src/constants/HttpStatusCodes';
12
13
 
13
14
  import Paths from 'spec/support/Paths';
14
- import { TReqBody } from 'spec/support/types';
15
- import TestAgent from 'supertest/lib/agent';
16
-
15
+ import apiCb from 'spec/support/apiCb';
16
+ import { TApiCb } from 'spec/types/misc';
17
17
 
18
- // **** Variables **** //
19
18
 
20
- // StatusCodes
21
- const {
22
- OK,
23
- UNAUTHORIZED,
24
- } = HttpStatusCodes;
25
-
26
- // Login credentials
19
+ // Login Creds
27
20
  const LoginCreds = {
28
21
  email: 'jsmith@gmail.com',
29
22
  password: 'Password@1',
30
23
  } as const;
31
24
 
32
25
 
33
- // **** Types **** //
34
-
35
- type TRes = Omit<Response, 'body'> & {
36
- body: {
37
- error: string;
38
- }
39
- };
40
-
41
-
42
- // **** Tests **** //
43
-
26
+ // Tests
44
27
  describe('AuthRouter', () => {
45
28
 
46
29
  let agent: TestAgent<Test>;
@@ -51,82 +34,82 @@ describe('AuthRouter', () => {
51
34
  done();
52
35
  });
53
36
 
54
- // ** Test login ** //
37
+ // Login
55
38
  describe(`"POST:${Paths.Auth.Login}"`, () => {
56
39
 
57
40
  const EMAIL_NOT_FOUND_ERR = Errors.EmailNotFound(LoginCreds.email);
58
41
 
59
- const callApi = (reqBody: TReqBody) =>
42
+ // Setup API
43
+ const callApi = (creds: typeof LoginCreds, cb: TApiCb) =>
60
44
  agent
61
45
  .post(Paths.Auth.Login)
62
- .type('form')
63
- .send(reqBody);
46
+ .send(creds)
47
+ .end(apiCb(cb));
64
48
 
65
49
  // Success
66
- it(`should return a response with a status of "${OK}" and a cookie with ` +
67
- 'a jwt if the login was successful.', (done) => {
50
+ it(`should return a response with a status of "${HttpStatusCodes.OK}" ` +
51
+ 'and a cookie with a jwt if the login was successful.', done => {
68
52
  // Setup data
69
- const role = UserRoles.Standard,
70
- pwdHash = PwdUtil.hashSync(LoginCreds.password),
71
- loginUser = User.new('john smith', LoginCreds.email, role, pwdHash);
53
+ const pwdHash = PwdUtil.hashSync(LoginCreds.password),
54
+ loginUser = User.new('john smith', LoginCreds.email, new Date(),
55
+ UserRoles.Standard, pwdHash);
72
56
  // Add spy
73
57
  spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
74
58
  // Call API
75
- callApi(LoginCreds)
76
- .end((_: Error, res: Response) => {
77
- expect(res.status).toBe(OK);
78
- const cookie = res.headers['set-cookie'][0];
79
- expect(cookie).toContain(EnvVars.CookieProps.Key);
80
- done();
81
- });
59
+ callApi(LoginCreds, res => {
60
+ expect(res.status).toBe(HttpStatusCodes.OK);
61
+ const cookie = res.headers['set-cookie'][0];
62
+ expect(cookie).toContain(EnvVars.CookieProps.Key);
63
+ done();
64
+ });
82
65
  });
83
66
 
84
67
  // Email not found error
85
- it(`should return a response with a status of "${UNAUTHORIZED}" and a ` +
86
- `json with an error message of "${EMAIL_NOT_FOUND_ERR}" if the email ` +
87
- 'was not found.', (done) => {
68
+ it('should return a response with a status of ' +
69
+ `"${HttpStatusCodes.UNAUTHORIZED}" and a json with an error message of ` +
70
+ `"${EMAIL_NOT_FOUND_ERR}" if the email was not found.`, done => {
88
71
  // Spy
89
72
  spyOn(UserRepo, 'getOne').and.resolveTo(null);
90
73
  // Call
91
- callApi(LoginCreds)
92
- .end((_: Error, res: TRes) => {
93
- expect(res.status).toBe(UNAUTHORIZED);
94
- expect(res.body.error).toBe(EMAIL_NOT_FOUND_ERR);
95
- done();
96
- });
74
+ callApi(LoginCreds, res => {
75
+ expect(res.status).toBe(HttpStatusCodes.UNAUTHORIZED);
76
+ expect(res.body.error).toBe(EMAIL_NOT_FOUND_ERR);
77
+ done();
78
+ });
97
79
  });
98
80
 
99
81
  // Password failed
100
- it(`should return a response with a status of "${UNAUTHORIZED}" and a ` +
101
- `json with the error "${Errors.Unauth}" if the password failed.`,
102
- (done) => {
82
+ it('should return a response with a status of ' +
83
+ `"${HttpStatusCodes.UNAUTHORIZED}" and a json with the error ` +
84
+ `"${Errors.Unauth}" if the password failed.`, done => {
103
85
  // Setup data
104
- const role = UserRoles.Standard,
105
- pwdHash = PwdUtil.hashSync('bad password'),
106
- loginUser = User.new('john smith', LoginCreds.email, role, pwdHash);
86
+ const pwdHash = PwdUtil.hashSync('bad password'),
87
+ loginUser = User.new('john smith', LoginCreds.email, new Date(),
88
+ UserRoles.Standard, pwdHash);
107
89
  // Add spy
108
90
  spyOn(UserRepo, 'getOne').and.resolveTo(loginUser);
109
91
  // Call API
110
- callApi(LoginCreds)
111
- .end((_: Error, res: TRes) => {
112
- expect(res.status).toBe(UNAUTHORIZED);
113
- expect(res.body.error).toBe(Errors.Unauth);
114
- done();
115
- });
92
+ callApi(LoginCreds, res => {
93
+ expect(res.status).toBe(HttpStatusCodes.UNAUTHORIZED);
94
+ expect(res.body.error).toBe(Errors.Unauth);
95
+ done();
96
+ });
116
97
  });
117
98
 
118
99
  });
119
100
 
120
- // ** Test logout ** //
101
+ // Test logout
121
102
  describe(`"GET:${Paths.Auth.Logout}"`, () => {
122
103
 
123
104
  // Successful logout
124
- it(`should return a response with a status of ${OK}`, (done) => {
125
- agent.get(Paths.Auth.Logout)
126
- .end((_: Error, res: Response) => {
127
- expect(res.status).toBe(HttpStatusCodes.OK);
128
- done();
129
- });
130
- });
105
+ it(`should return a response with a status of ${HttpStatusCodes.OK}`,
106
+ done => {
107
+ agent
108
+ .get(Paths.Auth.Logout)
109
+ .end((_: Error, res: Response) => {
110
+ expect(res.status).toBe(HttpStatusCodes.OK);
111
+ done();
112
+ });
113
+ });
131
114
  });
132
115
  });