express-generator-typescript 2.7.7 → 2.7.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.
- package/README-git +2 -3
- package/README.md +1 -1
- package/lib/express-generator-typescript.js +1 -1
- package/package.json +1 -1
- package/lib/project-files/README.md +0 -65
- package/lib/project-files/config/.env.development +0 -15
- package/lib/project-files/config/.env.production +0 -15
- package/lib/project-files/config/.env.test +0 -14
- package/lib/project-files/config.ts +0 -22
- package/lib/project-files/eslint.config.ts +0 -100
- package/lib/project-files/gitignore +0 -6
- package/lib/project-files/package.json +0 -57
- package/lib/project-files/scripts/build.ts +0 -28
- package/lib/project-files/scripts/common/utils.ts +0 -93
- package/lib/project-files/src/common/constants/ENV.ts +0 -19
- package/lib/project-files/src/common/constants/HTTP_STATUS_CODES.ts +0 -81
- package/lib/project-files/src/common/constants/PATHS.ts +0 -15
- package/lib/project-files/src/common/constants/index.ts +0 -11
- package/lib/project-files/src/common/util/misc.ts +0 -11
- package/lib/project-files/src/common/util/route-errors.ts +0 -38
- package/lib/project-files/src/common/util/validators.ts +0 -21
- package/lib/project-files/src/index.ts +0 -27
- package/lib/project-files/src/models/User.ts +0 -69
- package/lib/project-files/src/models/common/types/index.ts +0 -5
- package/lib/project-files/src/public/scripts/http.js +0 -26
- package/lib/project-files/src/public/scripts/users.js +0 -141
- package/lib/project-files/src/public/stylesheets/users.css +0 -48
- package/lib/project-files/src/repos/MockOrm.ts +0 -63
- package/lib/project-files/src/repos/UserRepo.ts +0 -134
- package/lib/project-files/src/repos/database.json +0 -1
- package/lib/project-files/src/repos/database.test.json +0 -1
- package/lib/project-files/src/routes/UserRoutes.ts +0 -69
- package/lib/project-files/src/routes/common/types/index.ts +0 -10
- package/lib/project-files/src/routes/common/util/index.ts +0 -16
- package/lib/project-files/src/routes/index.ts +0 -31
- package/lib/project-files/src/server.ts +0 -86
- package/lib/project-files/src/services/UserService.ts +0 -70
- package/lib/project-files/src/views/users.html +0 -132
- package/lib/project-files/tests/common/types/index.ts +0 -16
- package/lib/project-files/tests/common/util/index.ts +0 -55
- package/lib/project-files/tests/support/setup.ts +0 -26
- package/lib/project-files/tests/users.test.ts +0 -138
- package/lib/project-files/tsconfig.json +0 -35
- package/lib/project-files/tsconfig.prod.json +0 -30
- package/lib/project-files/vitest.config.mts +0 -18
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import morgan from 'morgan';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import helmet from 'helmet';
|
|
4
|
-
import express, { Request, Response, NextFunction } from 'express';
|
|
5
|
-
import logger from 'jet-logger';
|
|
6
|
-
|
|
7
|
-
import BaseRouter from '@src/routes';
|
|
8
|
-
|
|
9
|
-
import Paths from '@src/common/constants/PATHS';
|
|
10
|
-
import ENV from '@src/common/constants/ENV';
|
|
11
|
-
import HTTP_STATUS_CODES, {
|
|
12
|
-
HttpStatusCodes,
|
|
13
|
-
} from '@src/common/constants/HTTP_STATUS_CODES';
|
|
14
|
-
import { RouteError } from '@src/common/util/route-errors';
|
|
15
|
-
import { NODE_ENVS } from '@src/common/constants';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/******************************************************************************
|
|
19
|
-
Setup
|
|
20
|
-
******************************************************************************/
|
|
21
|
-
|
|
22
|
-
const app = express();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// **** Middleware **** //
|
|
26
|
-
|
|
27
|
-
// Basic middleware
|
|
28
|
-
app.use(express.json());
|
|
29
|
-
app.use(express.urlencoded({extended: true}));
|
|
30
|
-
|
|
31
|
-
// Show routes called in console during development
|
|
32
|
-
if (ENV.NodeEnv === NODE_ENVS.Dev) {
|
|
33
|
-
app.use(morgan('dev'));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Security
|
|
37
|
-
if (ENV.NodeEnv === NODE_ENVS.Production) {
|
|
38
|
-
// eslint-disable-next-line n/no-process-env
|
|
39
|
-
if (!process.env.DISABLE_HELMET) {
|
|
40
|
-
app.use(helmet());
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Add APIs, must be after middleware
|
|
45
|
-
app.use(Paths._, BaseRouter);
|
|
46
|
-
|
|
47
|
-
// Add error handler
|
|
48
|
-
app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
|
|
49
|
-
if (ENV.NodeEnv !== NODE_ENVS.Test.valueOf()) {
|
|
50
|
-
logger.err(err, true);
|
|
51
|
-
}
|
|
52
|
-
let status: HttpStatusCodes = HTTP_STATUS_CODES.BadRequest;
|
|
53
|
-
if (err instanceof RouteError) {
|
|
54
|
-
status = err.status;
|
|
55
|
-
res.status(status).json({ error: err.message });
|
|
56
|
-
}
|
|
57
|
-
return next(err);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// **** FrontEnd Content **** //
|
|
62
|
-
|
|
63
|
-
// Set views directory (html)
|
|
64
|
-
const viewsDir = path.join(__dirname, 'views');
|
|
65
|
-
app.set('views', viewsDir);
|
|
66
|
-
|
|
67
|
-
// Set static directory (js and css).
|
|
68
|
-
const staticDir = path.join(__dirname, 'public');
|
|
69
|
-
app.use(express.static(staticDir));
|
|
70
|
-
|
|
71
|
-
// Nav to users pg by default
|
|
72
|
-
app.get('/', (_: Request, res: Response) => {
|
|
73
|
-
return res.redirect('/users');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// Redirect to login if not logged in.
|
|
77
|
-
app.get('/users', (_: Request, res: Response) => {
|
|
78
|
-
return res.sendFile('users.html', { root: viewsDir });
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
/******************************************************************************
|
|
83
|
-
Export default
|
|
84
|
-
******************************************************************************/
|
|
85
|
-
|
|
86
|
-
export default app;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { RouteError } from '@src/common/util/route-errors';
|
|
2
|
-
import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
|
|
3
|
-
|
|
4
|
-
import UserRepo from '@src/repos/UserRepo';
|
|
5
|
-
import { IUser } from '@src/models/User';
|
|
6
|
-
|
|
7
|
-
/******************************************************************************
|
|
8
|
-
Constants
|
|
9
|
-
******************************************************************************/
|
|
10
|
-
|
|
11
|
-
export const USER_NOT_FOUND_ERR = 'User not found';
|
|
12
|
-
|
|
13
|
-
/******************************************************************************
|
|
14
|
-
Functions
|
|
15
|
-
******************************************************************************/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Get all users.
|
|
19
|
-
*/
|
|
20
|
-
function getAll(): Promise<IUser[]> {
|
|
21
|
-
return UserRepo.getAll();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Add one user.
|
|
26
|
-
*/
|
|
27
|
-
function addOne(user: IUser): Promise<void> {
|
|
28
|
-
return UserRepo.add(user);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Update one user.
|
|
33
|
-
*/
|
|
34
|
-
async function updateOne(user: IUser): Promise<void> {
|
|
35
|
-
const persists = await UserRepo.persists(user.id);
|
|
36
|
-
if (!persists) {
|
|
37
|
-
throw new RouteError(
|
|
38
|
-
HTTP_STATUS_CODES.NotFound,
|
|
39
|
-
USER_NOT_FOUND_ERR,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
// Return user
|
|
43
|
-
return UserRepo.update(user);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Delete a user by their id.
|
|
48
|
-
*/
|
|
49
|
-
async function _delete(id: number): Promise<void> {
|
|
50
|
-
const persists = await UserRepo.persists(id);
|
|
51
|
-
if (!persists) {
|
|
52
|
-
throw new RouteError(
|
|
53
|
-
HTTP_STATUS_CODES.NotFound,
|
|
54
|
-
USER_NOT_FOUND_ERR,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
// Delete user
|
|
58
|
-
return UserRepo.delete(id);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/******************************************************************************
|
|
62
|
-
Export default
|
|
63
|
-
******************************************************************************/
|
|
64
|
-
|
|
65
|
-
export default {
|
|
66
|
-
getAll,
|
|
67
|
-
addOne,
|
|
68
|
-
updateOne,
|
|
69
|
-
delete: _delete,
|
|
70
|
-
} as const;
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<!-- Head -->
|
|
5
|
-
<head>
|
|
6
|
-
<meta charset="UTF-8">
|
|
7
|
-
<title>Users</title>
|
|
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>
|
|
25
|
-
</head>
|
|
26
|
-
|
|
27
|
-
<!-- Body -->
|
|
28
|
-
<body>
|
|
29
|
-
|
|
30
|
-
<!-- Add Users -->
|
|
31
|
-
<div class="users-column add-user-col">
|
|
32
|
-
<div class="column-header">
|
|
33
|
-
Add User:
|
|
34
|
-
</div>
|
|
35
|
-
<div>
|
|
36
|
-
<input
|
|
37
|
-
id="name-input"
|
|
38
|
-
type="text"
|
|
39
|
-
class="form-control"
|
|
40
|
-
placeholder="Name"
|
|
41
|
-
/>
|
|
42
|
-
</div>
|
|
43
|
-
<div>
|
|
44
|
-
<input
|
|
45
|
-
id="email-input"
|
|
46
|
-
type="email"
|
|
47
|
-
class="form-control"
|
|
48
|
-
placeholder="Email"
|
|
49
|
-
/>
|
|
50
|
-
</div>
|
|
51
|
-
<div>
|
|
52
|
-
<button
|
|
53
|
-
id="add-user-btn"
|
|
54
|
-
class="btn btn-success"
|
|
55
|
-
>
|
|
56
|
-
Add
|
|
57
|
-
</button>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<!-- Display Users -->
|
|
62
|
-
<div class="users-column">
|
|
63
|
-
<div class="column-header">
|
|
64
|
-
Users:
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div id="all-users-anchor"></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>
|
|
92
|
-
|
|
93
|
-
<div class="edit-view">
|
|
94
|
-
<div>
|
|
95
|
-
Name:
|
|
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:
|
|
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>
|
|
128
|
-
</body>
|
|
129
|
-
|
|
130
|
-
<script src="scripts/http.js"></script>
|
|
131
|
-
<script src="scripts/users.js"></script>
|
|
132
|
-
</html>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Response } from 'supertest';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/******************************************************************************
|
|
5
|
-
Types
|
|
6
|
-
******************************************************************************/
|
|
7
|
-
|
|
8
|
-
// Use generics to add properties to 'body'
|
|
9
|
-
export type TRes<T = object> = Omit<Response, 'body'> & {
|
|
10
|
-
body: T & { error?: string | IErrorObject },
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
interface IErrorObject {
|
|
14
|
-
message: string;
|
|
15
|
-
[key: string]: unknown;
|
|
16
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { IParseObjectError, parseJson } from 'jet-validators/utils';
|
|
2
|
-
import { isString } from 'jet-validators';
|
|
3
|
-
import { IUser } from '@src/models/User';
|
|
4
|
-
|
|
5
|
-
/******************************************************************************
|
|
6
|
-
Types
|
|
7
|
-
******************************************************************************/
|
|
8
|
-
|
|
9
|
-
type TUserArray = IUser[] | readonly IUser[];
|
|
10
|
-
|
|
11
|
-
interface IValidationError {
|
|
12
|
-
message: string;
|
|
13
|
-
errors: IParseObjectError[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/******************************************************************************
|
|
17
|
-
Functions
|
|
18
|
-
******************************************************************************/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* JSON parse a validation error.
|
|
22
|
-
*/
|
|
23
|
-
export function parseValidationError(arg: unknown): IValidationError {
|
|
24
|
-
if (!isString(arg)) {
|
|
25
|
-
throw new Error('Not a string');
|
|
26
|
-
}
|
|
27
|
-
return parseJson<IValidationError>(arg);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Compare to user arrays. Order does not matter and this assumes the email
|
|
32
|
-
* field is unique
|
|
33
|
-
*/
|
|
34
|
-
export function compareUserArrays(a: TUserArray, b: TUserArray): boolean {
|
|
35
|
-
if (a.length !== b.length) return false;
|
|
36
|
-
const aSorted = sortByEmail(a);
|
|
37
|
-
const bSorted = sortByEmail(b);
|
|
38
|
-
for (let i = 0; i < aSorted.length; i++) {
|
|
39
|
-
const a = aSorted[i],
|
|
40
|
-
b = bSorted[i];
|
|
41
|
-
if (a.email !== b.email || a.name !== b.name) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Sort user array by email.
|
|
50
|
-
*/
|
|
51
|
-
function sortByEmail(arr: TUserArray): IUser[] {
|
|
52
|
-
return [...arr].sort((x, y) => {
|
|
53
|
-
return x.email.localeCompare(y.email);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { beforeAll } from 'vitest';
|
|
3
|
-
import supertest, { Test } from 'supertest';
|
|
4
|
-
import TestAgent from 'supertest/lib/agent';
|
|
5
|
-
|
|
6
|
-
import app from '@src/server';
|
|
7
|
-
import MockOrm from '@src/repos/MockOrm';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/******************************************************************************
|
|
11
|
-
Run
|
|
12
|
-
******************************************************************************/
|
|
13
|
-
|
|
14
|
-
let agent: TestAgent<Test>;
|
|
15
|
-
|
|
16
|
-
beforeAll(async () => {
|
|
17
|
-
agent = supertest.agent(app);
|
|
18
|
-
await MockOrm.cleanDb();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/******************************************************************************
|
|
23
|
-
Export
|
|
24
|
-
******************************************************************************/
|
|
25
|
-
|
|
26
|
-
export { agent };
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import insertUrlParams from 'inserturlparams';
|
|
2
|
-
|
|
3
|
-
import UserRepo from '@src/repos/UserRepo';
|
|
4
|
-
import User, { IUser } from '@src/models/User';
|
|
5
|
-
import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
|
|
6
|
-
|
|
7
|
-
import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
|
|
8
|
-
import { ValidationError } from '@src/common/util/route-errors';
|
|
9
|
-
import { JET_PATHS as Paths } from '@src/common/constants/PATHS';
|
|
10
|
-
|
|
11
|
-
import { compareUserArrays, parseValidationError } from './common/util';
|
|
12
|
-
import { agent } from './support/setup';
|
|
13
|
-
import { TRes } from './common/types';
|
|
14
|
-
|
|
15
|
-
/******************************************************************************
|
|
16
|
-
Constants
|
|
17
|
-
******************************************************************************/
|
|
18
|
-
|
|
19
|
-
// Dummy users for GET req
|
|
20
|
-
const DB_USERS = [
|
|
21
|
-
User.new({ name: 'Sean Maxwell', email: 'sean.maxwell@gmail.com' }),
|
|
22
|
-
User.new({ name: 'John Smith', email: 'john.smith@gmail.com' }),
|
|
23
|
-
User.new({ name: 'Gordan Freeman', email: 'gordan.freeman@gmail.com' }),
|
|
24
|
-
] as const;
|
|
25
|
-
|
|
26
|
-
/******************************************************************************
|
|
27
|
-
Tests
|
|
28
|
-
IMPORTANT: Following TypeScript best practices, we test all scenarios that
|
|
29
|
-
can be triggered by a user under normal circumstances. Not all theoretically
|
|
30
|
-
scenarios (i.e. a failed database connection).
|
|
31
|
-
******************************************************************************/
|
|
32
|
-
|
|
33
|
-
describe('UserRouter', () => {
|
|
34
|
-
|
|
35
|
-
let dbUsers: IUser[] = [];
|
|
36
|
-
|
|
37
|
-
// Run before all tests
|
|
38
|
-
beforeEach(async () => {
|
|
39
|
-
await UserRepo.deleteAllUsers();
|
|
40
|
-
dbUsers = await UserRepo.insertMult(DB_USERS);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Get all users
|
|
44
|
-
describe(`"GET:${Paths.Users.Get}"`, () => {
|
|
45
|
-
|
|
46
|
-
// Success
|
|
47
|
-
it('should return a JSON object with all the users and a status code ' +
|
|
48
|
-
`of "${HTTP_STATUS_CODES.Ok}" if the request was successful.`, async () => {
|
|
49
|
-
const res: TRes<{ users: IUser[]}> = await agent.get(Paths.Users.Get);
|
|
50
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
51
|
-
expect(compareUserArrays(res.body.users, DB_USERS)).toBeTruthy();
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Test add user
|
|
56
|
-
describe(`"POST:${Paths.Users.Add}"`, () => {
|
|
57
|
-
|
|
58
|
-
// Test add user success
|
|
59
|
-
it(`should return a status code of "${HTTP_STATUS_CODES.Created}" if ` +
|
|
60
|
-
'the request was successful.', async () => {
|
|
61
|
-
const user = User.new({ name: 'a', email: 'a@a.com' }),
|
|
62
|
-
res = await agent.post(Paths.Users.Add).send({ user });
|
|
63
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.Created);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Missing param
|
|
67
|
-
it('should return a JSON object with an error message of and a status ' +
|
|
68
|
-
`code of "${HTTP_STATUS_CODES.BadRequest}" if the user param was ` +
|
|
69
|
-
'missing.', async () => {
|
|
70
|
-
const res: TRes = await agent.post(Paths.Users.Add).send({ user: null });
|
|
71
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
|
|
72
|
-
const errorObj = parseValidationError(res.body.error);
|
|
73
|
-
expect(errorObj.message).toBe(ValidationError.MESSAGE);
|
|
74
|
-
expect(errorObj.errors[0].prop).toBe('user');
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Update users
|
|
79
|
-
describe(`"PUT:${Paths.Users.Update}"`, () => {
|
|
80
|
-
|
|
81
|
-
// Success
|
|
82
|
-
it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
|
|
83
|
-
'request was successful.', async () => {
|
|
84
|
-
const user = DB_USERS[0];
|
|
85
|
-
user.name = 'Bill';
|
|
86
|
-
const res = await agent.put(Paths.Users.Update).send({ user });
|
|
87
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Id is the wrong data type
|
|
91
|
-
it('should return a JSON object with an error message and a status code ' +
|
|
92
|
-
`of "${HTTP_STATUS_CODES.BadRequest}" if the user param was missing`,
|
|
93
|
-
async () => {
|
|
94
|
-
const user = User.new();
|
|
95
|
-
user.id = ('5' as unknown as number);
|
|
96
|
-
const res: TRes = await agent.put(Paths.Users.Update).send({ user });
|
|
97
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
|
|
98
|
-
const errorObj = parseValidationError(res.body.error);
|
|
99
|
-
expect(errorObj.message).toBe(ValidationError.MESSAGE);
|
|
100
|
-
expect(errorObj.errors[0].prop).toBe('user');
|
|
101
|
-
expect(errorObj.errors[0].children?.[0].prop).toBe('id');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// User not found
|
|
105
|
-
it('should return a JSON object with the error message of ' +
|
|
106
|
-
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
107
|
-
`"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
|
|
108
|
-
const user = User.new({ id: 4, name: 'a', email: 'a@a.com' }),
|
|
109
|
-
res: TRes = await agent.put(Paths.Users.Update).send({ user });
|
|
110
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
|
|
111
|
-
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Delete User
|
|
116
|
-
describe(`"DELETE:${Paths.Users.Delete()}"`, () => {
|
|
117
|
-
|
|
118
|
-
const getPath = (id: number) => insertUrlParams(Paths.Users.Delete({ id}),
|
|
119
|
-
{ id });
|
|
120
|
-
|
|
121
|
-
// Success
|
|
122
|
-
it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
|
|
123
|
-
'request was successful.', async () => {
|
|
124
|
-
const id = dbUsers[0].id,
|
|
125
|
-
res = await agent.delete(getPath(id));
|
|
126
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// User not found
|
|
130
|
-
it('should return a JSON object with the error message of ' +
|
|
131
|
-
`"${USER_NOT_FOUND_ERR}" and a status code of ` +
|
|
132
|
-
`"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
|
|
133
|
-
const res: TRes = await agent.delete(getPath(-1));
|
|
134
|
-
expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
|
|
135
|
-
expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"lib": ["ES2020"],
|
|
6
|
-
"strict": true,
|
|
7
|
-
"baseUrl": "./",
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"forceConsistentCasingInFileNames": true,
|
|
11
|
-
"paths": {
|
|
12
|
-
"@src/*": ["src/*"]
|
|
13
|
-
},
|
|
14
|
-
"useUnknownInCatchVariables": false,
|
|
15
|
-
"types": ["vitest/globals"],
|
|
16
|
-
},
|
|
17
|
-
"ts-node": {
|
|
18
|
-
"swc": true,
|
|
19
|
-
"require": [
|
|
20
|
-
"tsconfig-paths/register",
|
|
21
|
-
"./config.ts"
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
"include": [
|
|
25
|
-
"src/**/*.ts",
|
|
26
|
-
"tests/**/*.ts",
|
|
27
|
-
"config.ts",
|
|
28
|
-
"scripts",
|
|
29
|
-
"eslint.config.ts",
|
|
30
|
-
"vitest.config.mts"
|
|
31
|
-
],
|
|
32
|
-
"exclude": [
|
|
33
|
-
"src/public/*"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"lib": ["ES2020"],
|
|
6
|
-
"strict": true,
|
|
7
|
-
"baseUrl": "./",
|
|
8
|
-
"outDir": "temp",
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"paths": {
|
|
13
|
-
"@src/*": ["src/*"]
|
|
14
|
-
},
|
|
15
|
-
"useUnknownInCatchVariables": false,
|
|
16
|
-
"sourceMap": false,
|
|
17
|
-
"removeComments": true
|
|
18
|
-
},
|
|
19
|
-
"include": [
|
|
20
|
-
"src/**/*.ts",
|
|
21
|
-
"config.ts"
|
|
22
|
-
],
|
|
23
|
-
"exclude": [
|
|
24
|
-
"tests",
|
|
25
|
-
"src/public/",
|
|
26
|
-
"scripts",
|
|
27
|
-
"eslint.config.ts",
|
|
28
|
-
"vitest.config.js"
|
|
29
|
-
]
|
|
30
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
const config = defineConfig({
|
|
5
|
-
test: {
|
|
6
|
-
globals: true,
|
|
7
|
-
environment: 'node',
|
|
8
|
-
setupFiles: ['config.ts', './tests/support/setup.ts'],
|
|
9
|
-
isolate: true,
|
|
10
|
-
},
|
|
11
|
-
resolve: {
|
|
12
|
-
alias: {
|
|
13
|
-
'@src': path.resolve(__dirname, './src'),
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export default config;
|