Skip to content

Commit da0a111

Browse files
committed
Added integration tests
1 parent 3c53894 commit da0a111

File tree

9 files changed

+11115
-2696
lines changed

9 files changed

+11115
-2696
lines changed

.env.testing

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
APP_ENV=testing
2+
APP_DEBUG=true
3+
PORT=8000
4+
5+
# REDIS
6+
REDIS_HOST=localhost
7+
REDIS_PORT=6379
8+
REDIS_USERNAME=default
9+
REDIS_PASSWORD=password
10+
11+
# RATE LIMITER
12+
RATE_LIMITER_ENABLED=true
13+
RATE_LIMITER_MAX_REQUESTS=5
14+
RATE_LIMITER_TIME_WINDOW=60000

jest.config.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
require('dotenv').config({ path: '.env.testing' });
2+
3+
module.exports = {
4+
preset: 'ts-jest',
5+
testEnvironment: 'node',
6+
testMatch: ['**/*.test.ts'],
7+
moduleNameMapper: {
8+
'^@/(.*)$': '<rootDir>/src/$1',
9+
},
10+
globals: {
11+
__DEV__: true,
12+
},
13+
transform: {
14+
'^.+\\.tsx?$': 'ts-jest',
15+
},
16+
};

package-lock.json

+11,024-2,678
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22
"dependencies": {
33
"dotenv": "^16.0.3",
44
"express": "^4.18.2",
5-
"redis": "^4.6.5"
5+
"redis": "^4.6.5",
6+
"supertest": "^6.3.3"
67
},
78
"devDependencies": {
89
"@types/express": "^4.17.17",
910
"@types/fs-extra": "^9.0.13",
11+
"@types/jest": "^29.5.1",
1012
"@types/node": "^16.18.23",
1113
"@types/shelljs": "^0.8.11",
14+
"@types/supertest": "^2.0.12",
1215
"fs-extra": "^10.1.0",
16+
"jest": "^29.5.0",
1317
"nodemon": "^2.0.22",
1418
"npm-run-all": "^4.1.5",
1519
"rimraf": "^3.0.2",
1620
"shelljs": "^0.8.5",
21+
"ts-jest": "^29.1.0",
1722
"ts-node": "^10.9.1",
1823
"tslint": "^6.1.3",
1924
"typescript": "^4.9.5"
@@ -27,6 +32,6 @@
2732
"dev:start": "npm-run-all build start",
2833
"dev": "nodemon --watch src -e ts --exec npm run dev:start",
2934
"start": "node .",
30-
"test": "echo \"Error: no test specified\" && exit 1"
35+
"test": "jest --detectOpenHandles"
3136
}
3237
}

src/middlewares/rate-limiter.ts

-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ export const rateLimiter = async (req: Request, res: Response, next: NextFunctio
1212

1313
const current = await getCurrentWindow(key, Number(process.env.RATE_LIMITER_TIME_WINDOW));
1414

15-
// tslint:disable-next-line:no-console
16-
console.log(current);
17-
1815
if (current + 1 > Number(process.env.RATE_LIMITER_MAX_REQUESTS)) {
1916
return res.status(429).json({
2017
message: 'too many requests'

src/router.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import express from 'express';
2+
import { rateLimiter } from './middlewares/rate-limiter';
3+
4+
const app = express();
5+
6+
if (process.env.RATE_LIMITER_ENABLED === 'true') {
7+
app.use(rateLimiter.bind(this));
8+
}
9+
10+
app.get('/', (req, res) => res.json({ message: 'Hello World!' }));
11+
12+
export { app };

src/server.ts

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
import * as dotenv from "dotenv";
22
dotenv.config();
3-
import express from "express";
4-
import { client } from "./utils/redis";
5-
import { rateLimiter } from "./middlewares/rate-limiter";
6-
7-
const app = express();
8-
9-
if (process.env.RATE_LIMITER_ENABLED === 'true') {
10-
app.use(rateLimiter.bind(this));
11-
}
12-
13-
app.get('/', (req, res) => res.send(client.get('test')));
3+
import { app } from "./router";
144

155
// tslint:disable-next-line:no-console
16-
app.listen(process.env.PORT, () => console.log(`Application started listening http://localhost:${process.env.PORT}`));
6+
app.listen(process.env.PORT, () => console.log(`Application started listening http://localhost:${process.env.PORT}`));

test/middlewares/rate-limiter.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import request from "supertest";
2+
import { client } from "../../src/utils/redis";
3+
import { app } from "../../src/router";
4+
5+
let req: request.SuperTest<request.Test>;
6+
7+
describe('rate-limiter middleware', () => {
8+
beforeEach(async () => {
9+
await client.flushAll();
10+
11+
req = request(app);
12+
});
13+
14+
it('should return 429 if the rate limit is reached', async () => {
15+
let now = Date.now();
16+
await client.zAdd('rate-limiter:172.20.0.1', [
17+
{ score: now, value: now.toString() },
18+
{ score: ++now, value: now.toString() },
19+
{ score: ++now, value: now.toString() },
20+
{ score: ++now, value: now.toString() },
21+
{ score: ++now, value: now.toString() },
22+
]);
23+
24+
const res = await req.get('/').set('x-forwarded-for', '172.20.0.1');
25+
26+
expect(res.status).toEqual(429);
27+
});
28+
29+
it('should return 200 if the rate limit is not reached', async () => {
30+
const res = await req.get('/');
31+
32+
expect(res.status).toEqual(200);
33+
});
34+
35+
afterAll(async () => {
36+
await client.flushAll();
37+
await client.disconnect();
38+
});
39+
});

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"*": [
1313
"node_modules/*"
1414
]
15-
}
15+
},
1616
},
1717
"include": [
1818
"src/**/*"

0 commit comments

Comments
 (0)