@practica/create-node-app
Version:
Create Node.js app that is packed with best practices AND strive for simplicity
248 lines (203 loc) • 6.41 kB
text/typescript
import express, { Express } from 'express';
import { Server } from 'http';
import { AddressInfo } from 'net';
import axios from 'axios';
import { context } from '@practica/global-context';
import { addRequestId } from '../index';
let currentServer!: Server;
const REQUEST_ID_HEADER = 'x-request-id';
async function setupExpressServer(setupRoutes: (app: Express) => void) {
const app = express();
setupRoutes(app);
const serverInstance = await new Promise<Server>((resolve) => {
currentServer = app.listen(0, () => resolve(currentServer));
});
const { port } = serverInstance.address() as AddressInfo;
return axios.create({
baseURL: `http://127.0.0.1:${port}`,
// Don't throw on any HTTP status code, validate those in the tests
validateStatus: () => true,
});
}
describe('Request ID express middleware', () => {
afterEach(async () => {
// Cleaning up the created server instance
if (currentServer) {
await new Promise<void>((resolve, reject) => {
currentServer.close((error) => (error ? reject(error) : resolve()));
});
}
});
describe('when the request ID already exists in the request header', () => {
test('when sending a request to an EXISTING route WITH request ID in the request header it should add it to the response header', async () => {
// Arrange
const requestId = '801d9251-5916-4b26-85d9-7a33aaa86c9d';
const client = await setupExpressServer((app) => {
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({});
});
});
// Act
const response = await client.get('/', {
headers: {
[REQUEST_ID_HEADER]: requestId,
},
});
// Assert
expect(response).toMatchObject({
status: 200,
data: {},
headers: {
[REQUEST_ID_HEADER]: requestId,
},
});
});
test('when sending a request to MISSING route WITH request ID in the request header it should add it to the response header', async () => {
// Arrange
const requestId = '801d9251-5916-4b26-85d9-7a33aaa86c9d';
const client = await setupExpressServer((app) => {
app.use(addRequestId);
});
// Act
const response = await client.get('/some-missing-route', {
headers: {
[REQUEST_ID_HEADER]: requestId,
},
});
// Assert
expect(response).toMatchObject({
status: 404,
data: {},
headers: {
[REQUEST_ID_HEADER]: requestId,
},
});
});
test('the provided request id should be available in the request context', async () => {
// Arrange
const requestId = '801d9251-5916-4b26-85d9-7a33aaa86c9d';
const client = await setupExpressServer((app) => {
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({ ...context().getStore() });
});
});
// Act
const response = await client.get('/', {
headers: {
[REQUEST_ID_HEADER]: requestId,
},
});
// Assert
expect(response).toMatchObject({
status: 200,
data: {
requestId,
},
});
});
});
describe('when the request ID does not exists in the request header', () => {
test('when sending a request to an EXISTING route WITHOUT request ID in the request header it should generate one and it to the response header', async () => {
// Arrange
const client = await setupExpressServer((app) => {
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({});
});
});
// Act
const response = await client.get('/');
// Assert
expect(response).toMatchObject({
status: 200,
data: {},
headers: {
[REQUEST_ID_HEADER]: expect.any(String),
},
});
});
test('when sending a request to MISSING route WITH request ID in the request header it should add it to the response header', async () => {
// Arrange
const client = await setupExpressServer((app) => {
app.use(addRequestId);
});
// Act
const response = await client.get('/some-missing-route');
// Assert
expect(response).toMatchObject({
status: 404,
data: {},
headers: {
[REQUEST_ID_HEADER]: expect.any(String),
},
});
});
test('the generated request id should be available in the request context', async () => {
// Arrange
const client = await setupExpressServer((app) => {
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({ ...context().getStore() });
});
});
// Act
const response = await client.get('/');
// Assert
expect(response).toMatchObject({
status: 200,
data: {
requestId: expect.any(String),
},
});
});
test('the request id in the request context should be the same as the one sent in the response header', async () => {
// Arrange
const client = await setupExpressServer((app) => {
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({ ...context().getStore() });
});
});
// Act
const response = await client.get('/');
// Assert
const responseRequestId = response.headers[REQUEST_ID_HEADER];
expect(response).toMatchObject({
status: 200,
data: {
requestId: responseRequestId,
},
headers: {
[REQUEST_ID_HEADER]: expect.any(String),
},
});
});
});
test('when request content already exist it should append to it', async () => {
// Arrange
const existingContextData = {
userId: 1,
};
const client = await setupExpressServer((app) => {
app.use((req, res, next) => {
context().run({ ...existingContextData }, () => next());
});
app.use(addRequestId);
app.get('/', (req, res) => {
res.send({ ...context().getStore() });
});
});
// Act
const response = await client.get('/');
// Assert
expect(response).toMatchObject({
status: 200,
data: {
requestId: expect.any(String),
...existingContextData,
},
});
});
});