Skip to content

Commit 0dc021b

Browse files
committed
WIP implements identities
1 parent 2c4d946 commit 0dc021b

File tree

8 files changed

+372
-3
lines changed

8 files changed

+372
-3
lines changed

service/src/core/core.module.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,30 @@ import { RouterModule } from '@nestjs/core'
33
import { CoreService } from '~/core/core.service'
44
import { CoreController } from '~/core/core.controller'
55
import { AuthModule } from './auth/auth.module'
6-
import { UsersModule } from './users/users.module'
76
import { CategoriesModule } from './categories/categories.module'
87
import { ProjectModule } from './projects/project.module'
98
import { TriggersModule } from './triggers/triggers.module'
109
import { CrontabsModule } from './crontabs/crontabs.module'
1110
import { PreferencesModule } from './preferences/preferences.module'
1211
import { FilestorageModule } from './filestorage/filestorage.module'
12+
import { EntitesModule } from '~/core/entites/entites.module'
13+
import { IdentitiesModule } from '~/core/identities/identities.module'
1314

1415
@Module({
1516
imports: [
1617
AuthModule,
17-
UsersModule,
1818
CategoriesModule,
19-
ProjectModule,
19+
ProjectModule,
2020
TriggersModule,
2121
CrontabsModule,
2222
PreferencesModule,
2323
FilestorageModule,
24+
CategoriesModule,
25+
ProjectModule,
26+
TriggersModule,
27+
CrontabsModule,
28+
EntitesModule,
29+
IdentitiesModule,
2430
],
2531
providers: [CoreService],
2632
controllers: [CoreController],
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { PartialType } from "@nestjs/swagger"
2+
3+
export class IdentitiesCreateDto {
4+
5+
}
6+
7+
export class IdentitiesUpdateDto extends PartialType(IdentitiesCreateDto) {}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import { DeleteResult } from 'mongodb'
2+
import { Test, TestingModule } from '@nestjs/testing'
3+
import { IdentitiesController } from './identities.controller'
4+
import { IdentitiesService } from './identities.service'
5+
import { IdentitiesDto } from './dto/identities.dto'
6+
import { Identities } from './schemas/identities.schema'
7+
import { HttpException, HttpStatus } from '@nestjs/common'
8+
import { Types } from 'mongoose'
9+
import { Response, Request } from 'express'
10+
import { getMockReq, getMockRes } from '@jest-mock/express'
11+
12+
describe('IdentitiesController', () => {
13+
let controller: IdentitiesController
14+
let service: IdentitiesService
15+
const date = new Date()
16+
const _id = new Types.ObjectId()
17+
const { res, mockClear } = getMockRes()
18+
const object: Identities = {
19+
_id,
20+
metadata: {
21+
createdAt: date,
22+
createdBy: 'console',
23+
lastUpdateAt: date,
24+
lastUpdateBy: 'console',
25+
},
26+
info: [],
27+
}
28+
29+
beforeEach(async () => {
30+
mockClear()
31+
const module: TestingModule = await Test.createTestingModule({
32+
controllers: [IdentitiesController],
33+
providers: [
34+
IdentitiesService,
35+
{
36+
provide: IdentitiesService,
37+
useValue: {
38+
search: jest.fn().mockResolvedValue([[object], 1]),
39+
create: jest.fn().mockResolvedValue(object),
40+
read: jest.fn().mockResolvedValue(object),
41+
update: jest.fn().mockResolvedValue(object),
42+
remove: jest.fn().mockResolvedValue({
43+
acknowledged: true,
44+
deletedCount: 1,
45+
}),
46+
},
47+
},
48+
],
49+
}).compile()
50+
51+
controller = module.get<IdentitiesController>(IdentitiesController)
52+
service = module.get<IdentitiesService>(IdentitiesService)
53+
})
54+
55+
describe('search', () => {
56+
it('should return an array of Identities objects and the total count', async () => {
57+
const req = getMockReq()
58+
const query = { _id: _id.toString() }
59+
const limit = 10
60+
const skip = 1
61+
const expectedResult: [Identities[], number] = [[object], 1]
62+
jest.spyOn(service, 'search').mockImplementation(async () => await expectedResult)
63+
const response = await controller.search(req, res, query, limit.toString(), skip.toString(), null)
64+
expect(response.json).toHaveBeenCalledWith({ data: expectedResult[0], total: expectedResult[1] })
65+
expect(response.status).toHaveBeenCalledWith(HttpStatus.OK)
66+
})
67+
68+
it('should return an array of Identities objects with default pagination', async () => {
69+
const req = getMockReq()
70+
const query = { _id: _id.toString() }
71+
const limit = 0
72+
const skip = 0
73+
const expectedResult: [Identities[], number] = [[object], 1]
74+
jest.spyOn(service, 'search').mockImplementation(async () => await expectedResult)
75+
const response = await controller.search(req, res, query, limit.toString(), skip.toString(), null)
76+
expect(response.json).toHaveBeenCalledWith({ data: expectedResult[0], total: expectedResult[1] })
77+
expect(response.status).toHaveBeenCalledWith(HttpStatus.OK)
78+
})
79+
80+
it('should throw HttpException with BAD_REQUEST status when an error occurs', async () => {
81+
const req = {} as Request
82+
const res = {} as Response
83+
const query = { someParam: 'value' }
84+
const limit = 10
85+
const skip = 0
86+
jest.spyOn(service, 'search').mockRejectedValue(new Error('Something went wrong'))
87+
88+
try {
89+
await controller.search(req, res, query, limit.toString(), skip.toString(), null)
90+
} catch (error) {
91+
const status = error.getStatus()
92+
const response = error.getResponse()
93+
94+
expect(error).toBeInstanceOf(HttpException)
95+
expect(status).toBe(400)
96+
expect(response).toBe('Something went wrong')
97+
}
98+
})
99+
})
100+
101+
describe('read', () => {
102+
it('should return the data successfully', async () => {
103+
const expectedResult: Identities = object
104+
jest.spyOn(service, 'read').mockImplementation(async () => await expectedResult)
105+
const result = await controller.read(_id.toString(), res)
106+
expect(res.status).toHaveBeenCalledWith(HttpStatus.OK)
107+
expect(res.json).toHaveBeenCalledWith(expectedResult)
108+
expect(result).toEqual(res)
109+
})
110+
111+
it('should throw an HttpException with the error message', async () => {
112+
const errorMessage = 'Error message'
113+
jest.spyOn(service, 'read').mockRejectedValue(new Error(errorMessage))
114+
try {
115+
await controller.read(_id.toString(), res)
116+
} catch (error) {
117+
expect(error.getStatus()).toBe(HttpStatus.BAD_REQUEST)
118+
expect(error.getResponse()).toBe(errorMessage)
119+
}
120+
})
121+
})
122+
123+
describe('create', () => {
124+
it('should return a Identities object', async () => {
125+
const dto: IdentitiesDto = { someProp: 'value' }
126+
const expectedResult = object
127+
jest.spyOn(service, 'create').mockImplementation(async () => await expectedResult)
128+
const response = await controller.create(dto, res)
129+
expect(response.status).toHaveBeenCalledWith(HttpStatus.CREATED)
130+
expect(response.json).toHaveBeenCalledWith(expectedResult)
131+
})
132+
133+
it('should throw HttpException with BAD_REQUEST status when an error occurs', async () => {
134+
const dto: IdentitiesDto = { someProp: 'value' }
135+
jest.spyOn(service, 'create').mockRejectedValue(new Error('Something went wrong'))
136+
137+
try {
138+
await controller.create(dto, res)
139+
} catch (error) {
140+
expect(error).toBeInstanceOf(HttpException)
141+
expect(error.getStatus()).toBe(400)
142+
expect(error.getResponse()).toBe('Something went wrong')
143+
}
144+
})
145+
})
146+
147+
describe('update', () => {
148+
it('should return a Identities object', async () => {
149+
const id = _id.toString()
150+
const dto: IdentitiesDto = { someProp: 'value' }
151+
const expectedResult: Identities = object
152+
jest.spyOn(service, 'update').mockImplementation(async () => await expectedResult)
153+
const response = await controller.update(id, dto, res)
154+
expect(response.status).toHaveBeenCalledWith(HttpStatus.OK)
155+
expect(response.json).toHaveBeenCalledWith(expectedResult)
156+
})
157+
158+
it('should throw HttpException with BAD_REQUEST status when an error occurs', async () => {
159+
const id = _id.toString()
160+
const dto: IdentitiesDto = { someProp: 'value' }
161+
jest.spyOn(service, 'update').mockRejectedValue(new Error('Something went wrong'))
162+
163+
try {
164+
await controller.update(id, dto, res)
165+
} catch (error) {
166+
expect(error).toBeInstanceOf(HttpException)
167+
expect(error.getStatus()).toBe(400)
168+
expect(error.getResponse()).toBe('Something went wrong')
169+
}
170+
})
171+
})
172+
173+
describe('remove', () => {
174+
it('should return a Identities object', async () => {
175+
const id = _id.toString()
176+
const expectedResult: DeleteResult = {
177+
acknowledged: true,
178+
deletedCount: 1,
179+
}
180+
jest.spyOn(service, 'remove').mockImplementation(async () => await expectedResult)
181+
const response = await controller.remove(id, res)
182+
expect(response.status).toHaveBeenCalledWith(HttpStatus.OK)
183+
expect(response.json).toHaveBeenCalledWith(expectedResult)
184+
})
185+
186+
it('should throw HttpException with BAD_REQUEST status when an error occurs', async () => {
187+
const id = _id.toString()
188+
jest.spyOn(service, 'remove').mockRejectedValue(new Error('Something went wrong'))
189+
190+
try {
191+
await controller.remove(id, res)
192+
} catch (error) {
193+
expect(error).toBeInstanceOf(HttpException)
194+
expect(error.getStatus()).toBe(400)
195+
expect(error.getResponse()).toBe('Something went wrong')
196+
}
197+
})
198+
})
199+
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Controller } from '@nestjs/common'
2+
import { IdentitiesService } from './identities.service'
3+
import { AbstractController } from '~/_common/abstracts/abstract.controller'
4+
5+
@Controller('identities')
6+
export class IdentitiesController extends AbstractController {
7+
constructor(private readonly service: IdentitiesService) {
8+
super()
9+
}
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Module } from '@nestjs/common'
2+
import { MongooseModule } from '@nestjs/mongoose'
3+
import { IdentitiesSchema, Identities } from './schemas/identities.schema'
4+
import { IdentitiesService } from './identities.service'
5+
import { IdentitiesController } from './identities.controller'
6+
7+
@Module({
8+
imports: [
9+
MongooseModule.forFeatureAsync([
10+
{
11+
name: Identities.name,
12+
useFactory: () => IdentitiesSchema,
13+
},
14+
]),
15+
],
16+
providers: [IdentitiesService],
17+
controllers: [IdentitiesController],
18+
})
19+
export class IdentitiesModule {}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { DeleteResult } from 'mongodb'
2+
import { Test, TestingModule } from '@nestjs/testing'
3+
import { IdentitiesService } from './identities.service'
4+
import { getModelToken } from '@nestjs/mongoose'
5+
import { Identities } from './schemas/identities.schema'
6+
import { Model, Types } from 'mongoose'
7+
8+
describe('IdentitiesService', () => {
9+
let service: IdentitiesService
10+
let model: Model<Identities>
11+
const _id = new Types.ObjectId()
12+
const date = new Date()
13+
const mockIdentities: Identities = {
14+
_id,
15+
metadata: {
16+
createdAt: date,
17+
createdBy: 'console',
18+
lastUpdateAt: date,
19+
lastUpdateBy: 'console',
20+
},
21+
info: [],
22+
}
23+
24+
beforeEach(async () => {
25+
const module: TestingModule = await Test.createTestingModule({
26+
providers: [
27+
IdentitiesService,
28+
{
29+
provide: getModelToken(Identities.name),
30+
useValue: Model,
31+
},
32+
],
33+
}).compile()
34+
service = module.get<IdentitiesService>(IdentitiesService)
35+
model = module.get<Model<Identities>>(getModelToken(Identities.name))
36+
})
37+
38+
describe('create', () => {
39+
it('should create a new record', async () => {
40+
const createTest = {}
41+
jest.spyOn(model, 'create').mockImplementationOnce(() => Promise.resolve(mockIdentities))
42+
const result = await service.create(createTest)
43+
expect(result).toEqual(mockIdentities)
44+
})
45+
})
46+
47+
describe('search', () => {
48+
it('should return an array of records and total count', async () => {
49+
const expected = [mockIdentities]
50+
const total = 1
51+
jest.spyOn(model, 'countDocuments').mockResolvedValueOnce(total)
52+
jest.spyOn(model, 'find').mockResolvedValueOnce(expected)
53+
const [result, resultTotal] = await service.search()
54+
expect(result).toEqual(expected)
55+
expect(resultTotal).toEqual(total)
56+
})
57+
58+
it('should return an empty array if no records are found', async () => {
59+
const expected = []
60+
const total = 0
61+
jest.spyOn(model, 'countDocuments').mockResolvedValueOnce(total)
62+
jest.spyOn(model, 'find').mockResolvedValueOnce(expected)
63+
const [result, resultTotal] = await service.search()
64+
expect(result).toEqual(expected)
65+
expect(resultTotal).toEqual(total)
66+
})
67+
})
68+
69+
describe('read', () => {
70+
it('should return a Identities record by ID', async () => {
71+
const expected = mockIdentities
72+
jest.spyOn(model, 'findById').mockResolvedValueOnce(expected)
73+
const result = await service.read(_id.toString())
74+
expect(result).toEqual(expected)
75+
})
76+
77+
it('should return null if Identities record is not found', async () => {
78+
const expected = null
79+
jest.spyOn(model, 'findById').mockResolvedValueOnce(expected)
80+
const result = await service.read('123')
81+
expect(result).toEqual(expected)
82+
})
83+
})
84+
85+
describe('update', () => {
86+
it('should update a Identities record by ID with metadata', async () => {
87+
const identitiesDto = { info: { key: 'updated value' } }
88+
const newObject = { ...mockIdentities }
89+
const expected = newObject.info.push(identitiesDto.info)
90+
jest.spyOn(model, 'findByIdAndUpdate').mockResolvedValueOnce(expected)
91+
const result = await service.update(_id.toString(), identitiesDto)
92+
expect(result).toEqual(expected)
93+
})
94+
})
95+
96+
describe('remove', () => {
97+
it('should remove a Identities record by ID', async () => {
98+
const id = '123'
99+
const deleteResult: DeleteResult = { acknowledged: true, deletedCount: 1 }
100+
jest.spyOn(model, 'deleteOne').mockResolvedValueOnce(deleteResult)
101+
const result = await service.remove(id)
102+
expect(result).toEqual(deleteResult)
103+
})
104+
})
105+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Injectable } from '@nestjs/common'
2+
import { InjectModel } from '@nestjs/mongoose'
3+
import { Identities } from './schemas/identities.schema'
4+
import { Model } from 'mongoose'
5+
import { AbstractService } from '~/_common/abstracts/abstract.service'
6+
7+
@Injectable()
8+
export class IdentitiesService extends AbstractService {
9+
constructor(@InjectModel(Identities.name) protected model: Model<Identities>,
10+
) {
11+
super()
12+
}
13+
}

0 commit comments

Comments
 (0)