diff --git a/.eslintrc.js b/.eslintrc.js index d8bc3457..437379bd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,10 +5,11 @@ module.exports = { tsconfigRootDir: __dirname, sourceType: 'module', }, - plugins: ['@typescript-eslint/eslint-plugin'], + plugins: ['@typescript-eslint/eslint-plugin', 'jest'], extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', + 'plugin:jest/recommended' ], root: true, env: { @@ -21,10 +22,16 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', - "prettier/prettier": [ - "error", + 'jest/expect-expect': [ + 'warn', { - "endOfLine": "auto" + 'assertFunctionNames': ['expect', 'request.**.expect'], + } + ], + 'prettier/prettier': [ + 'error', + { + 'endOfLine': 'auto' } ] }, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f03015e0..b3714aaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,15 @@ name: CI on: + workflow_dispatch: + push: + branches: + - main + tags: + - "*" pull_request: branches: - - master + - main - develop jobs: @@ -29,4 +35,7 @@ jobs: run: npm run lint:ci # Build App - name: Build App - run: npm run build \ No newline at end of file + run: npm run build + + - name: Test + run: npm test \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..6bc3f4c4 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,20 @@ +import type { Config } from 'jest'; + +const config: Config = { + moduleFileExtensions: ['js', 'json', 'ts'], + rootDir: 'src', + testRegex: '.*\\.spec\\.ts$', + transform: { + '^.+\\.(t|j)s$': 'ts-jest', + }, + collectCoverageFrom: ['**/*.(t|j)s'], + coverageDirectory: '../coverage', + moduleNameMapper: { + '^src/(.*)$': '/$1', + '^@/(.*)$': '/$1', + '^test/(.*)$': '/../$1', + }, + testEnvironment: 'node', +}; + +export default config; diff --git a/package-lock.json b/package-lock.json index 6c3ae692..455fac11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -4517,6 +4518,31 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-jest": { + "version": "28.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", + "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + }, + "engines": { + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", diff --git a/package.json b/package.json index 3212f2fd..b20634cd 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json", + "test:e2e": "jest --config ./test/jest.e2e.config.ts", "migrations:run": "npx prisma migrate deploy", "migrations:dev": "npx prisma migrate dev", "docker:compose": "docker-compose -f docker-compose.dev.yml up" @@ -53,6 +53,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -64,22 +65,5 @@ "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", "typescript": "^5.1.3" - }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "ts" - ], - "rootDir": "src", - "testRegex": ".*\\.spec\\.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - }, - "collectCoverageFrom": [ - "**/*.(t|j)s" - ], - "coverageDirectory": "../coverage", - "testEnvironment": "node" } } diff --git a/src/sessions/sessions.controller.spec.ts b/src/sessions/sessions.controller.spec.ts index 118ad549..a2d145e2 100644 --- a/src/sessions/sessions.controller.spec.ts +++ b/src/sessions/sessions.controller.spec.ts @@ -1,5 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SessionsController } from './sessions.controller'; +import { SessionsService } from './sessions.service'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { JwtService } from '@nestjs/jwt'; describe('SessionsController', () => { let controller: SessionsController; @@ -7,7 +10,14 @@ describe('SessionsController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SessionsController], - }).compile(); + providers: [SessionsService, JwtService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(SessionsController); }); diff --git a/src/sessions/sessions.service.spec.ts b/src/sessions/sessions.service.spec.ts index 923df18b..4115d43b 100644 --- a/src/sessions/sessions.service.spec.ts +++ b/src/sessions/sessions.service.spec.ts @@ -1,13 +1,21 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SessionsService } from './sessions.service'; +import { JwtService } from '@nestjs/jwt'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SessionsService', () => { let service: SessionsService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [SessionsService], - }).compile(); + providers: [SessionsService, JwtService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SessionsService); }); diff --git a/src/shelter-managers/shelter-managers.controller.spec.ts b/src/shelter-managers/shelter-managers.controller.spec.ts index 5bc76a94..01b41779 100644 --- a/src/shelter-managers/shelter-managers.controller.spec.ts +++ b/src/shelter-managers/shelter-managers.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterManagersController } from './shelter-managers.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { ShelterManagersService } from './shelter-managers.service'; describe('ShelterManagersController', () => { let controller: ShelterManagersController; @@ -7,7 +9,14 @@ describe('ShelterManagersController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterManagersController], - }).compile(); + providers: [ShelterManagersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get( ShelterManagersController, diff --git a/src/shelter-managers/shelter-managers.service.spec.ts b/src/shelter-managers/shelter-managers.service.spec.ts index 9d1878c6..51834fc4 100644 --- a/src/shelter-managers/shelter-managers.service.spec.ts +++ b/src/shelter-managers/shelter-managers.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterManagersService } from './shelter-managers.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterManagersService', () => { let service: ShelterManagersService; @@ -7,7 +8,13 @@ describe('ShelterManagersService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterManagersService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(ShelterManagersService); }); diff --git a/src/shelter-supply/shelter-supply.controller.spec.ts b/src/shelter-supply/shelter-supply.controller.spec.ts index 73f1a18d..04c0f885 100644 --- a/src/shelter-supply/shelter-supply.controller.spec.ts +++ b/src/shelter-supply/shelter-supply.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterSupplyController } from './shelter-supply.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { ShelterSupplyService } from './shelter-supply.service'; describe('ShelterSupplyController', () => { let controller: ShelterSupplyController; @@ -7,7 +9,14 @@ describe('ShelterSupplyController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterSupplyController], - }).compile(); + providers: [ShelterSupplyService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(ShelterSupplyController); }); diff --git a/src/shelter-supply/shelter-supply.service.spec.ts b/src/shelter-supply/shelter-supply.service.spec.ts index 2a4678ba..b3e3cae9 100644 --- a/src/shelter-supply/shelter-supply.service.spec.ts +++ b/src/shelter-supply/shelter-supply.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterSupplyService } from './shelter-supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterSupplyService', () => { let service: ShelterSupplyService; @@ -7,7 +8,13 @@ describe('ShelterSupplyService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterSupplyService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(ShelterSupplyService); }); diff --git a/src/shelter/shelter.controller.spec.ts b/src/shelter/shelter.controller.spec.ts index 6774fccb..eab66b66 100644 --- a/src/shelter/shelter.controller.spec.ts +++ b/src/shelter/shelter.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaService } from 'src/prisma/prisma.service'; import { ShelterController } from './shelter.controller'; +import { ShelterService } from './shelter.service'; describe('ShelterController', () => { let controller: ShelterController; @@ -7,7 +9,16 @@ describe('ShelterController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterController], - }).compile(); + providers: [ShelterService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); controller = module.get(ShelterController); }); diff --git a/src/shelter/shelter.service.spec.ts b/src/shelter/shelter.service.spec.ts index ac7cf4e0..1ce3198b 100644 --- a/src/shelter/shelter.service.spec.ts +++ b/src/shelter/shelter.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterService } from './shelter.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterService', () => { let service: ShelterService; @@ -7,7 +8,17 @@ describe('ShelterService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { + findMany: jest.fn().mockResolvedValue([]), + }, + }; + } + }) + .compile(); service = module.get(ShelterService); }); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 74d03860..190aedaa 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, OnModuleInit } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; import * as qs from 'qs'; @@ -17,10 +17,12 @@ import { import { subDays } from 'date-fns'; @Injectable() -export class ShelterService { +export class ShelterService implements OnModuleInit { private voluntaryIds: string[] = []; - constructor(private readonly prismaService: PrismaService) { + constructor(private readonly prismaService: PrismaService) {} + + onModuleInit() { this.loadVoluntaryIds(); } diff --git a/src/supply-categories/supply-categories.controller.spec.ts b/src/supply-categories/supply-categories.controller.spec.ts index e9e287a5..4e92c769 100644 --- a/src/supply-categories/supply-categories.controller.spec.ts +++ b/src/supply-categories/supply-categories.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyCategoriesController } from './supply-categories.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { SupplyCategoriesService } from './supply-categories.service'; describe('SupplyCategoriesController', () => { let controller: SupplyCategoriesController; @@ -7,7 +9,14 @@ describe('SupplyCategoriesController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SupplyCategoriesController], - }).compile(); + providers: [SupplyCategoriesService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get( SupplyCategoriesController, diff --git a/src/supply-categories/supply-categories.service.spec.ts b/src/supply-categories/supply-categories.service.spec.ts index 52a3e572..80f980c8 100644 --- a/src/supply-categories/supply-categories.service.spec.ts +++ b/src/supply-categories/supply-categories.service.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaService } from 'src/prisma/prisma.service'; import { SupplyCategoriesService } from './supply-categories.service'; describe('SupplyCategoriesService', () => { @@ -7,7 +8,13 @@ describe('SupplyCategoriesService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [SupplyCategoriesService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SupplyCategoriesService); }); diff --git a/src/supply/supply.controller.spec.ts b/src/supply/supply.controller.spec.ts index 60c2f5a4..0fb33288 100644 --- a/src/supply/supply.controller.spec.ts +++ b/src/supply/supply.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyController } from './supply.controller'; +import { SupplyService } from './supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SupplyController', () => { let controller: SupplyController; @@ -7,7 +9,14 @@ describe('SupplyController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SupplyController], - }).compile(); + providers: [SupplyService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(SupplyController); }); diff --git a/src/supply/supply.service.spec.ts b/src/supply/supply.service.spec.ts index f9034a62..7868d160 100644 --- a/src/supply/supply.service.spec.ts +++ b/src/supply/supply.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyService } from './supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SupplyService', () => { let service: SupplyService; @@ -7,7 +8,13 @@ describe('SupplyService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [SupplyService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SupplyService); }); diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts index 3e27c395..e2bcecdc 100644 --- a/src/users/users.controller.spec.ts +++ b/src/users/users.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UsersController } from './users.controller'; +import { UsersService } from './users.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('UsersController', () => { let controller: UsersController; @@ -7,7 +9,14 @@ describe('UsersController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [UsersController], - }).compile(); + providers: [UsersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(UsersController); }); diff --git a/src/users/users.service.spec.ts b/src/users/users.service.spec.ts index 62815ba6..05a1f82b 100644 --- a/src/users/users.service.spec.ts +++ b/src/users/users.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('UsersService', () => { let service: UsersService; @@ -7,7 +8,13 @@ describe('UsersService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [UsersService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(UsersService); }); diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts index 50cda623..4bcbd9bb 100644 --- a/test/app.e2e-spec.ts +++ b/test/app.e2e-spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; +import { AppModule } from 'src/app.module'; describe('AppController (e2e)', () => { let app: INestApplication; @@ -16,9 +16,6 @@ describe('AppController (e2e)', () => { }); it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); + return request(app.getHttpServer()).get('/').expect(404); }); }); diff --git a/test/jest-e2e.json b/test/jest-e2e.json deleted file mode 100644 index e9d912f3..00000000 --- a/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts new file mode 100644 index 00000000..d680f170 --- /dev/null +++ b/test/jest.e2e.config.ts @@ -0,0 +1,15 @@ +import type { Config } from 'jest'; +import { default as projectConfig } from '../jest.config'; + +const config: Config = { + ...projectConfig, + rootDir: '.', + moduleNameMapper: { + '^src/(.*)$': '/../src/$1', + '^@/(.*)$': '/../src/$1', + '^test/(.*)$': '/$1', + }, + testRegex: '.e2e-spec.ts$', +}; + +export default config;