From bc4d7642ace2f12695e837faf864b33376372bd1 Mon Sep 17 00:00:00 2001 From: Chinedu Ekene Okpala Date: Thu, 1 Aug 2024 19:43:45 +0000 Subject: [PATCH] test(test): Setup jest and supertest for unit and e2e testing setup ioc mock container for test --- .gitignore | 4 +- jest.config.ts | 34 ++++++++++++++++ package.json | 2 + src/tests/configs/logger.test.ts | 5 +++ src/tests/controllers/auth.controller.test.ts | 5 +++ src/tests/controllers/user.controller.test.ts | 5 +++ src/tests/decorators/validate.test.ts | 5 +++ src/tests/models/user.model.test.ts | 5 +++ .../repositories/auth.repository.test.ts | 5 +++ .../repositories/user.repository.test.ts | 5 +++ src/tests/server.test.ts | 40 +++++++++++++++++++ src/tests/services/auth.service.test.ts | 5 +++ src/tests/services/user.service.test.ts | 5 +++ src/tests/test.container.ts | 15 +++++++ src/tests/test.context.ts | 25 ++++++++++++ 15 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 jest.config.ts create mode 100644 src/tests/configs/logger.test.ts create mode 100644 src/tests/controllers/auth.controller.test.ts create mode 100644 src/tests/controllers/user.controller.test.ts create mode 100644 src/tests/decorators/validate.test.ts create mode 100644 src/tests/models/user.model.test.ts create mode 100644 src/tests/repositories/auth.repository.test.ts create mode 100644 src/tests/repositories/user.repository.test.ts create mode 100644 src/tests/server.test.ts create mode 100644 src/tests/services/auth.service.test.ts create mode 100644 src/tests/services/user.service.test.ts create mode 100644 src/tests/test.container.ts create mode 100644 src/tests/test.context.ts diff --git a/.gitignore b/.gitignore index 2c284f6..62226a4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,4 @@ build coverage react-email-starter .babelrc -tests/ -events/ -jest.config.ts \ No newline at end of file +events/ \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..688d760 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,34 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ +import { createDefaultPreset } from 'ts-jest'; +import type { Config } from 'jest'; + +import { compilerOptions } from './tsconfig.json'; + +const config: Config = { + preset: 'ts-jest', + clearMocks: true, + collectCoverage: true, + coverageProvider: 'v8', + testEnvironment: 'node', + roots: [''], + setupFilesAfterEnv: ['reflect-metadata'], + modulePaths: [compilerOptions.baseUrl], + coverageDirectory: './coverage', + moduleFileExtensions: ['js', 'ts'], + testPathIgnorePatterns: ['/node_modules/'], + coveragePathIgnorePatterns: [ + 'node_modules', + 'src/db/migrations', + 'src/db/seeders', + 'src/db/config.js', + 'src/tests', + ], + transform: { + ...createDefaultPreset().transform, + }, +}; + +export default config; diff --git a/package.json b/package.json index 09e75b9..6a2f253 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "db:create": "pnpm run build && NODE_ENV=development npx sequelize-cli db:create", "db:migrate:up": "pnpm run build && NODE_ENV=development npx sequelize-cli db:migrate", "db:migrate:undo": "pnpm run build && NODE_ENV=development npx sequelize-cli db:migrate:undo", + "test": "env NODE_ENV=test jest", + "test:watch": "env NODE_ENV=test jest --runInBand --watch ./src/tests/server.test.ts", "lint": "eslint --ignore-path .eslintignore --ext .js,.ts" }, "author": "Chinedu", diff --git a/src/tests/configs/logger.test.ts b/src/tests/configs/logger.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/configs/logger.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/controllers/auth.controller.test.ts b/src/tests/controllers/auth.controller.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/controllers/auth.controller.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/controllers/user.controller.test.ts b/src/tests/controllers/user.controller.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/controllers/user.controller.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/decorators/validate.test.ts b/src/tests/decorators/validate.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/decorators/validate.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/models/user.model.test.ts b/src/tests/models/user.model.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/models/user.model.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/repositories/auth.repository.test.ts b/src/tests/repositories/auth.repository.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/repositories/auth.repository.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/repositories/user.repository.test.ts b/src/tests/repositories/user.repository.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/repositories/user.repository.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/server.test.ts b/src/tests/server.test.ts new file mode 100644 index 0000000..9064d1e --- /dev/null +++ b/src/tests/server.test.ts @@ -0,0 +1,40 @@ +import request from 'supertest'; +import { Express } from 'express'; +import { NOT_FOUND, OK } from 'http-status'; + +import { TestContext } from './test.context'; + +import { App } from 'app'; +import { AuthController, UserController } from 'controllers'; + +describe('Server Start', () => { + let app: Express; + beforeAll(async () => { + const testContext = new TestContext(); + testContext.mock(() => ({}), AuthController); + testContext.mock(() => ({}), UserController); + const _app = testContext.get(App); + await _app.initialize(); + app = _app.app; + }); + + it('responds with a not found message', async () => { + const response = await request(app) + .get('/not-found') + .set('Accept', 'application/json') + .expect(NOT_FOUND); + + expect(response.body.message).toEqual( + "Can't find /not-found on this server", + ); + }); + + it('responds with a health status', async () => { + const response = await request(app) + .get('/health-check') + .set('Accept', 'application/json') + .expect(OK); + + expect(response.body).toEqual({ status: 'success', health: '100%' }); + }); +}); diff --git a/src/tests/services/auth.service.test.ts b/src/tests/services/auth.service.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/services/auth.service.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/services/user.service.test.ts b/src/tests/services/user.service.test.ts new file mode 100644 index 0000000..c4841d2 --- /dev/null +++ b/src/tests/services/user.service.test.ts @@ -0,0 +1,5 @@ +describe('test', () => { + test('should first', () => { + expect(1 + 2).toEqual(3); + }); +}); diff --git a/src/tests/test.container.ts b/src/tests/test.container.ts new file mode 100644 index 0000000..78f4552 --- /dev/null +++ b/src/tests/test.container.ts @@ -0,0 +1,15 @@ +import { interfaces } from 'inversify'; + +import { Container } from 'di/container'; + +export class TestContainer extends Container { + public rebind( + serviceIdentifier: interfaces.ServiceIdentifier, + ): interfaces.BindingToSyntax { + return this.container.rebind(serviceIdentifier); + } + + public get(serviceIdentifier: interfaces.ServiceIdentifier): T { + return this.container.get(serviceIdentifier); + } +} diff --git a/src/tests/test.context.ts b/src/tests/test.context.ts new file mode 100644 index 0000000..abfb14e --- /dev/null +++ b/src/tests/test.context.ts @@ -0,0 +1,25 @@ +import 'reflect-metadata'; +import { interfaces } from 'inversify'; + +import { TestContainer } from './test.container'; + +export class TestContext { + private container = new TestContainer(); + + public mock( + implementation: () => Partial, + serviceIdentifier: interfaces.ServiceIdentifier, + ): T { + const mock = this.mockClass(implementation); + this.container.rebind(serviceIdentifier).toConstantValue(mock); + return mock; + } + + public get(serviceIdentifier: interfaces.ServiceIdentifier): T { + return this.container.get(serviceIdentifier); + } + + private mockClass(implementation: () => Partial): T { + return jest.fn(implementation)() as T; + } +}