Skip to content

Commit 0019955

Browse files
Replace mocha and chai with jest
1 parent e5e296a commit 0019955

File tree

11 files changed

+21576
-16636
lines changed

11 files changed

+21576
-16636
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ A window will automatically open at [localhost:4200](http://localhost:4200). Ang
6464
## Running tests
6565
Run `ng test` to execute the frontend unit tests via [Karma](https://karma-runner.github.io).
6666

67-
Run `npm run testbe` to execute the backend tests via [Mocha](https://mochajs.org/) (it requires `mongod` already running).
67+
Run `npm run testbe` to execute the backend tests via [Jest](https://jestjs.io/) (it requires mongod already running).
6868

6969
## Running linters
7070
Run `npm run lint` to execute [Angular ESLint](https://github.com/angular-eslint/angular-eslint), [HTML linting](https://github.com/htmlhint/HTMLHint) and [SASS linting](https://github.com/sasstools/sass-lint).

jest.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} */
2+
module.exports = {
3+
preset: 'ts-jest',
4+
testEnvironment: 'node',
5+
testRegex: '(/server/test/.*spec.ts)$'
6+
};

package-lock.json

+21,448-16,432
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+8-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"dev": "concurrently \"mongod\" \"ng serve --open\" \"tsc -w -p server\" \"nodemon dist/server/app.js\"",
1818
"prod": "concurrently \"mongod\" \"ng build && tsc -p server && node dist/server/app.js\"",
1919
"test": "ng test",
20-
"testbe": "tsc -p server && mocha dist/server/test --exit",
20+
"testbe": "tsc -p server && jest",
21+
"testbecov": "tsc -p server && jest --coverage",
2122
"lint": "ng lint && htmlhint \"client/**/*.html\" && sass-lint \"client/**/*.scss\" -v",
2223
"lintfix": "ng lint -- --fix"
2324
},
@@ -38,7 +39,7 @@
3839
"express": "^4.18.2",
3940
"font-awesome": "^4.7.0",
4041
"jsonwebtoken": "^9.0.0",
41-
"mongoose": "^6.8.4",
42+
"mongoose": "^6.10.3",
4243
"morgan": "^1.10.0",
4344
"rxjs": "~7.8.0",
4445
"tslib": "^2.3.0",
@@ -55,32 +56,32 @@
5556
"@angular/compiler-cli": "^15.2.2",
5657
"@angular/language-service": "^15.2.2",
5758
"@types/bcryptjs": "^2.4.2",
58-
"@types/chai-http": "^4.2.0",
5959
"@types/express": "^4.17.16",
6060
"@types/jasmine": "~4.3.0",
61+
"@types/jest": "^29.5.0",
6162
"@types/jsonwebtoken": "^9.0.1",
62-
"@types/mocha": "^10.0.1",
6363
"@types/morgan": "^1.9.4",
6464
"@types/node": "^18.11.18",
65+
"@types/supertest": "^2.0.12",
6566
"@typescript-eslint/eslint-plugin": "^5.43.0",
6667
"@typescript-eslint/parser": "^5.43.0",
67-
"chai": "^4.3.7",
68-
"chai-http": "^4.3.0",
6968
"concurrently": "^7.6.0",
7069
"eslint": "^8.35.0",
7170
"eslint-plugin-import": "^2.27.5",
7271
"eslint-plugin-jsdoc": "^40.0.1",
7372
"eslint-plugin-prefer-arrow": "^1.2.3",
7473
"htmlhint": "^1.1.4",
7574
"jasmine-core": "~4.5.0",
75+
"jest": "^29.5.0",
7676
"karma": "~6.4.0",
7777
"karma-chrome-launcher": "~3.1.0",
7878
"karma-coverage": "~2.2.0",
7979
"karma-jasmine": "~5.1.0",
8080
"karma-jasmine-html-reporter": "^2.0.0",
81-
"mocha": "^10.2.0",
8281
"nodemon": "^2.0.20",
8382
"sass-lint": "^1.13.1",
83+
"supertest": "^6.3.3",
84+
"ts-jest": "^29.0.5",
8485
"ts-node": "~8.3.0",
8586
"typescript": "~4.9.4"
8687
}

server/app.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as express from 'express';
44
import * as morgan from 'morgan';
55
import * as path from 'path';
66

7-
import setMongo from './mongo';
7+
import { connectToMongo } from './mongo';
88
import setRoutes from './routes';
99

1010
const app = express();
@@ -16,10 +16,11 @@ if (process.env.NODE_ENV !== 'test') {
1616
app.use(morgan('dev'));
1717
}
1818

19+
setRoutes(app);
20+
1921
const main = async (): Promise<any> => {
2022
try {
21-
await setMongo();
22-
setRoutes(app);
23+
await connectToMongo();
2324
app.get('/*', (req, res) => {
2425
res.sendFile(path.join(__dirname, '../public/index.html'));
2526
});
@@ -29,6 +30,8 @@ const main = async (): Promise<any> => {
2930
}
3031
};
3132

32-
main();
33+
if (process.env.NODE_ENV !== 'test') {
34+
main();
35+
}
3336

3437
export { app };

server/controllers/base.ts

+10
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ abstract class BaseCtrl {
6363
return res.status(400).json({ error: err.message });
6464
}
6565
};
66+
67+
// Drop collection (for tests)
68+
deleteAll = async (_req: Request, res: Response) => {
69+
try {
70+
await this.model.deleteMany();
71+
return res.sendStatus(200);
72+
} catch (err: any) {
73+
return res.status(400).json({ error: err.message });
74+
}
75+
};
6676
}
6777

6878
export default BaseCtrl;

server/mongo.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import * as mongoose from 'mongoose';
22

3-
const setMongo = async (): Promise<any> => {
3+
const connectToMongo = async (): Promise<void> => {
44
let mongodbURI: string;
55
if (process.env.NODE_ENV === 'test') {
66
mongodbURI = process.env.MONGODB_TEST_URI as string;
77
} else {
88
mongodbURI = process.env.MONGODB_URI as string;
99
}
1010
await mongoose.connect(mongodbURI);
11-
console.log('Connected to MongoDB');
11+
console.log(`Connected to MongoDB (db: ${mongodbURI.split('/').pop()})`);
1212
};
1313

14-
export default setMongo;
14+
const disconnectMongo = async (): Promise<void> => {
15+
await mongoose.connection.close();
16+
};
17+
18+
export { connectToMongo, disconnectMongo };

server/routes.ts

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ const setRoutes = (app: Application): void => {
2525
router.route('/user/:id').put(userCtrl.update);
2626
router.route('/user/:id').delete(userCtrl.delete);
2727

28+
// Test routes
29+
if (process.env.NODE_ENV === 'test') {
30+
router.route('/cats/delete').delete(catCtrl.deleteAll);
31+
router.route('/users/delete').delete(userCtrl.deleteAll);
32+
}
33+
2834
// Apply the routes to our application with the prefix /api
2935
app.use('/api', router);
3036

server/test/cats.spec.ts

+41-94
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,50 @@
1-
import * as chai from 'chai';
2-
import chaiHttp = require('chai-http');
3-
import { describe, it } from 'mocha';
41

2+
import * as request from 'supertest';
3+
import { describe, expect, test } from '@jest/globals';
54
process.env.NODE_ENV = 'test';
65
import { app } from '../app';
7-
import Cat from '../models/cat';
6+
import { connectToMongo, disconnectMongo } from '../mongo';
87

9-
chai.use(chaiHttp).should();
8+
const newCat = { name: 'Fluffy', weight: 4, age: 2 };
9+
let catId = '';
1010

11-
describe('Cats', () => {
12-
13-
beforeEach(done => {
14-
Cat.deleteMany({}, err => {
15-
done();
16-
});
17-
});
18-
19-
describe('Backend tests for cats', () => {
20-
21-
it('should get all the cats', done => {
22-
chai.request(app)
23-
.get('/api/cats')
24-
.end((err, res) => {
25-
res.should.have.status(200);
26-
res.body.should.be.a('array');
27-
res.body.length.should.be.eql(0);
28-
done();
29-
});
30-
});
31-
32-
it('should get cats count', done => {
33-
chai.request(app)
34-
.get('/api/cats/count')
35-
.end((err, res) => {
36-
res.should.have.status(200);
37-
res.body.should.be.a('number');
38-
res.body.should.be.eql(0);
39-
done();
40-
});
41-
});
42-
43-
it('should create new cat', done => {
44-
const cat = new Cat({ name: 'Fluffy', weight: 4, age: 2 });
45-
chai.request(app)
46-
.post('/api/cat')
47-
.send(cat)
48-
.end((err, res) => {
49-
res.should.have.status(201);
50-
res.body.should.be.a('object');
51-
res.body.should.have.a.property('name');
52-
res.body.should.have.a.property('weight');
53-
res.body.should.have.a.property('age');
54-
done();
55-
});
56-
});
57-
58-
it('should get a cat by its id', done => {
59-
const cat = new Cat({ name: 'Cat', weight: 2, age: 4 });
60-
cat.save((error, newCat) => {
61-
chai.request(app)
62-
.get(`/api/cat/${newCat.id}`)
63-
.end((err, res) => {
64-
res.should.have.status(200);
65-
res.body.should.be.a('object');
66-
res.body.should.have.property('name');
67-
res.body.should.have.property('weight');
68-
res.body.should.have.property('age');
69-
res.body.should.have.property('_id').eql(newCat.id);
70-
done();
71-
});
72-
});
73-
});
11+
beforeAll(async () => {
12+
await connectToMongo();
13+
});
7414

75-
it('should update a cat by its id', done => {
76-
const cat = new Cat({ name: 'Cat', weight: 2, age: 4 });
77-
cat.save((error, newCat) => {
78-
chai.request(app)
79-
.put(`/api/cat/${newCat.id}`)
80-
.send({ weight: 5 })
81-
.end((err, res) => {
82-
res.should.have.status(200);
83-
done();
84-
});
85-
});
86-
});
15+
afterAll(async () => {
16+
await request(app).delete('/api/cats/delete');
17+
await disconnectMongo();
18+
});
8719

88-
it('should delete a cat by its id', done => {
89-
const cat = new Cat({ name: 'Cat', weight: 2, age: 4 });
90-
cat.save((error, newCat) => {
91-
chai.request(app)
92-
.del(`/api/cat/${newCat.id}`)
93-
.end((err, res) => {
94-
res.should.have.status(200);
95-
done();
96-
});
97-
});
98-
});
20+
describe('Cat tests', () => {
21+
test('should get all cats', async () => {
22+
const res = await request(app).get('/api/cats');
23+
expect(res.statusCode).toBe(200);
24+
expect(res.body).toStrictEqual([]);
25+
});
26+
test('should count all cats', async () => {
27+
const res = await request(app).get('/api/cats/count');
28+
expect(res.statusCode).toBe(200);
29+
expect(res.body).toStrictEqual(0);
30+
});
31+
test('should create a new cat', async () => {
32+
const res = await request(app).post('/api/cat').send(newCat);
33+
expect(res.statusCode).toBe(201);
34+
expect(res.body).toMatchObject(newCat);
35+
catId = res.body._id;
36+
});
37+
test('should get a cat by id', async () => {
38+
const res = await request(app).get(`/api/cat/${catId}`);
39+
expect(res.statusCode).toBe(200);
40+
expect(res.body).toMatchObject(newCat);
41+
});
42+
test('should update a cat by id', async () => {
43+
const res = await request(app).put(`/api/cat/${catId}`).send({ weight: 5 });
44+
expect(res.statusCode).toBe(200);
45+
});
46+
test('should delete a cat by id', async () => {
47+
const res = await request(app).delete(`/api/cat/${catId}`);
48+
expect(res.statusCode).toBe(200);
9949
});
100-
10150
});
102-
103-

0 commit comments

Comments
 (0)