Merge branch 'fakeToPush' into 'main'
improve tests See merge request v3/services/auth!8
This commit is contained in:
commit
edbb491d35
|
@ -3,7 +3,7 @@ import { InjectMapper } from '@automapper/nestjs';
|
|||
import { Controller, UsePipes } from '@nestjs/common';
|
||||
import { CommandBus, QueryBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { DatabaseException } from 'src/modules/database/src/exceptions/DatabaseException';
|
||||
import { DatabaseException } from 'src/modules/database/src/exceptions/database.exception';
|
||||
import { AddUsernameCommand } from '../../commands/add-username.command';
|
||||
import { CreateAuthenticationCommand } from '../../commands/create-authentication.command';
|
||||
import { DeleteAuthenticationCommand } from '../../commands/delete-authentication.command';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { TestingModule, Test } from '@nestjs/testing';
|
||||
import { DatabaseModule } from '../../../database/database.module';
|
||||
import { PrismaService } from '../../../database/src/adapters/secondaries/prisma-service';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/DatabaseException';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/database.exception';
|
||||
import { AuthenticationRepository } from '../../adapters/secondaries/authentication.repository';
|
||||
import { v4 } from 'uuid';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { TestingModule, Test } from '@nestjs/testing';
|
||||
import { DatabaseModule } from '../../../database/database.module';
|
||||
import { PrismaService } from '../../../database/src/adapters/secondaries/prisma-service';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/DatabaseException';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/database.exception';
|
||||
import { v4 } from 'uuid';
|
||||
import { Type } from '../../domain/dtos/type.enum';
|
||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthenticationMessager } from '../../adapters/secondaries/authentication.messager';
|
||||
|
||||
const mockAmqpConnection = {
|
||||
publish: jest.fn().mockImplementation(),
|
||||
};
|
||||
|
||||
describe('AuthenticationMessager', () => {
|
||||
let authenticationMessager: AuthenticationMessager;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [],
|
||||
providers: [
|
||||
AuthenticationMessager,
|
||||
{
|
||||
provide: AmqpConnection,
|
||||
useValue: mockAmqpConnection,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
authenticationMessager = module.get<AuthenticationMessager>(
|
||||
AuthenticationMessager,
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(authenticationMessager).toBeDefined();
|
||||
});
|
||||
|
||||
it('should publish a message', async () => {
|
||||
jest.spyOn(mockAmqpConnection, 'publish');
|
||||
await authenticationMessager.publish(
|
||||
'authentication.create.info',
|
||||
'my-test',
|
||||
);
|
||||
expect(mockAmqpConnection.publish).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
|
||||
|
||||
const mockAmqpConnection = {
|
||||
publish: jest.fn().mockImplementation(),
|
||||
};
|
||||
|
||||
describe('LoggingMessager', () => {
|
||||
let loggingMessager: LoggingMessager;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [],
|
||||
providers: [
|
||||
LoggingMessager,
|
||||
{
|
||||
provide: AmqpConnection,
|
||||
useValue: mockAmqpConnection,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
loggingMessager = module.get<LoggingMessager>(LoggingMessager);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(LoggingMessager).toBeDefined();
|
||||
});
|
||||
|
||||
it('should publish a message', async () => {
|
||||
jest.spyOn(mockAmqpConnection, 'publish');
|
||||
await loggingMessager.publish('authentication.create.info', 'my-test');
|
||||
expect(mockAmqpConnection.publish).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
|
@ -9,7 +9,7 @@ import { ValidateAuthenticationQuery } from '../../queries/validate-authenticati
|
|||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||
import { Type } from '../../domain/dtos/type.enum';
|
||||
import { NotFoundException, UnauthorizedException } from '@nestjs/common';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/DatabaseException';
|
||||
import { DatabaseException } from '../../../database/src/exceptions/database.exception';
|
||||
import { ValidateAuthenticationRequest } from '../../domain/dtos/validate-authentication.request';
|
||||
|
||||
const mockAuthenticationRepository = {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
|
||||
import { DatabaseException } from '../../exceptions/DatabaseException';
|
||||
import { DatabaseException } from '../../exceptions/database.exception';
|
||||
import { ICollection } from '../../interfaces/collection.interface';
|
||||
import { IRepository } from '../../interfaces/repository.interface';
|
||||
import { PrismaService } from './prisma-service';
|
||||
|
|
|
@ -2,7 +2,8 @@ import { Injectable } from '@nestjs/common';
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaService } from '../../src/adapters/secondaries/prisma-service';
|
||||
import { PrismaRepository } from '../../src/adapters/secondaries/prisma-repository.abstract';
|
||||
import { DatabaseException } from '../../src/exceptions/DatabaseException';
|
||||
import { DatabaseException } from '../../src/exceptions/database.exception';
|
||||
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
|
||||
|
||||
class FakeEntity {
|
||||
uuid?: string;
|
||||
|
@ -33,7 +34,7 @@ const fakeEntityCreated: FakeEntity = {
|
|||
uuid: 'some-uuid',
|
||||
};
|
||||
|
||||
let fakeEntities: FakeEntity[] = [];
|
||||
const fakeEntities: FakeEntity[] = [];
|
||||
Array.from({ length: 10 }).forEach(() => {
|
||||
fakeEntities.push(createRandomEntity());
|
||||
});
|
||||
|
@ -57,7 +58,20 @@ const mockPrismaService = {
|
|||
return Promise.resolve([fakeEntities, fakeEntities.length]);
|
||||
}),
|
||||
fake: {
|
||||
create: jest.fn().mockResolvedValue(fakeEntityCreated),
|
||||
create: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce(fakeEntityCreated)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Error('an unknown error');
|
||||
}),
|
||||
|
||||
findMany: jest.fn().mockImplementation((params?: any) => {
|
||||
if (params?.where?.limit == 1) {
|
||||
|
@ -77,22 +91,66 @@ const mockPrismaService = {
|
|||
);
|
||||
}
|
||||
|
||||
if (!entity) {
|
||||
if (!entity && params?.where?.uuid == 'unknown') {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
} else if (!entity) {
|
||||
throw new Error('no entity');
|
||||
}
|
||||
|
||||
return entity;
|
||||
}),
|
||||
|
||||
findFirst: jest.fn().mockImplementation((params?: any) => {
|
||||
findFirst: jest
|
||||
.fn()
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
if (params?.where?.name) {
|
||||
return Promise.resolve(
|
||||
fakeEntities.find((entity) => entity.name === params?.where?.name),
|
||||
);
|
||||
}
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Error('an unknown error');
|
||||
}),
|
||||
|
||||
update: jest.fn().mockImplementation((params: any) => {
|
||||
update: jest
|
||||
.fn()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementationOnce((params: any) => {
|
||||
const entity = fakeEntities.find(
|
||||
(entity) => entity.name === params.where.name,
|
||||
);
|
||||
Object.entries(params.data).map(([key, value]) => {
|
||||
entity[key] = value;
|
||||
});
|
||||
|
||||
return Promise.resolve(entity);
|
||||
})
|
||||
.mockImplementation((params: any) => {
|
||||
const entity = fakeEntities.find(
|
||||
(entity) => entity.uuid === params.where.uuid,
|
||||
);
|
||||
|
@ -103,7 +161,16 @@ const mockPrismaService = {
|
|||
return Promise.resolve(entity);
|
||||
}),
|
||||
|
||||
delete: jest.fn().mockImplementation((params: any) => {
|
||||
delete: jest
|
||||
.fn()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementation((params: any) => {
|
||||
let found = false;
|
||||
|
||||
fakeEntities.forEach((entity, index) => {
|
||||
|
@ -118,18 +185,28 @@ const mockPrismaService = {
|
|||
}
|
||||
}),
|
||||
|
||||
deleteMany: jest.fn().mockImplementation((params: any) => {
|
||||
const foundEntities = fakeEntities.filter((entity) =>
|
||||
entity.name.startsWith(params?.where?.name),
|
||||
);
|
||||
deleteMany: jest
|
||||
.fn()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementation((params: any) => {
|
||||
let found = false;
|
||||
|
||||
if (foundEntities.length == 0) {
|
||||
fakeEntities.forEach((entity, index) => {
|
||||
if (entity.uuid === params?.where?.uuid) {
|
||||
found = true;
|
||||
fakeEntities.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
fakeEntities = fakeEntities.filter(
|
||||
(entity) => !entity.name.startsWith(params?.where?.name),
|
||||
);
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
@ -194,14 +271,32 @@ describe('PrismaRepository', () => {
|
|||
expect(newEntity).toBe(fakeEntityCreated);
|
||||
expect(prisma.fake.create).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.create(fakeEntityToCreate),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
describe('findOne', () => {
|
||||
it('should throw a DatabaseException if uuid is not found', async () => {
|
||||
await expect(
|
||||
fakeRepository.create(fakeEntityToCreate),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findOneByUuid', () => {
|
||||
it('should find an entity by uuid', async () => {
|
||||
const entity = await fakeRepository.findOneByUuid(fakeEntities[0].uuid);
|
||||
expect(entity).toBe(fakeEntities[0]);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.findOneByUuid('unknown'),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException if uuid is not found', async () => {
|
||||
await expect(
|
||||
fakeRepository.findOneByUuid('wrong-uuid'),
|
||||
|
@ -209,8 +304,55 @@ describe('PrismaRepository', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('findOne', () => {
|
||||
it('should find one entity', async () => {
|
||||
const entity = await fakeRepository.findOne({
|
||||
name: fakeEntities[0].name,
|
||||
});
|
||||
|
||||
expect(entity.name).toBe(fakeEntities[0].name);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.findOne({
|
||||
name: fakeEntities[0].name,
|
||||
}),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for unknown error', async () => {
|
||||
await expect(
|
||||
fakeRepository.findOne({
|
||||
name: fakeEntities[0].name,
|
||||
}),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should update an entity', async () => {
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.update('fake-uuid', { name: 'error' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
await expect(
|
||||
fakeRepository.updateWhere({ name: 'error' }, { name: 'new error' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should update an entity with name', async () => {
|
||||
const newName = 'new-random-name';
|
||||
|
||||
await fakeRepository.updateWhere(
|
||||
{ name: fakeEntities[0].name },
|
||||
{
|
||||
name: newName,
|
||||
},
|
||||
);
|
||||
expect(fakeEntities[0].name).toBe(newName);
|
||||
});
|
||||
|
||||
it('should update an entity with uuid', async () => {
|
||||
const newName = 'random-name';
|
||||
|
||||
await fakeRepository.update(fakeEntities[0].uuid, {
|
||||
|
@ -223,10 +365,19 @@ describe('PrismaRepository', () => {
|
|||
await expect(
|
||||
fakeRepository.update('fake-uuid', { name: 'error' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
await expect(
|
||||
fakeRepository.updateWhere({ name: 'error' }, { name: 'new error' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(fakeRepository.delete('fake-uuid')).rejects.toBeInstanceOf(
|
||||
DatabaseException,
|
||||
);
|
||||
});
|
||||
|
||||
it('should delete an entity', async () => {
|
||||
const savedUuid = fakeEntities[0].uuid;
|
||||
|
||||
|
@ -246,28 +397,28 @@ describe('PrismaRepository', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('findOne', () => {
|
||||
it('should find one entity', async () => {
|
||||
const entity = await fakeRepository.findOne({
|
||||
name: fakeEntities[0].name,
|
||||
});
|
||||
|
||||
expect(entity.name).toBe(fakeEntities[0].name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteMany', () => {
|
||||
it('should delete many entities', async () => {
|
||||
await fakeRepository.deleteMany({ name: 'name' });
|
||||
const nbEntities = fakeEntities.filter((entity) =>
|
||||
entity.name.startsWith('name'),
|
||||
).length;
|
||||
expect(nbEntities).toBe(0);
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.deleteMany({ uuid: 'fake-uuid' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should delete entities based on their uuid', async () => {
|
||||
const savedUuid = fakeEntities[0].uuid;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const res = await fakeRepository.deleteMany({ uuid: savedUuid });
|
||||
|
||||
const deletedEntity = fakeEntities.find(
|
||||
(entity) => entity.uuid === savedUuid,
|
||||
);
|
||||
expect(deletedEntity).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should throw an exception if an entity doesn't exist", async () => {
|
||||
await expect(
|
||||
fakeRepository.deleteMany({ name: 'fake-name' }),
|
||||
fakeRepository.deleteMany({ uuid: 'fake-uuid' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { ArgumentMetadata } from '@nestjs/common';
|
||||
import { ValidateAuthenticationRequest } from '../../../modules/authentication/domain/dtos/validate-authentication.request';
|
||||
import { RpcValidationPipe } from '../../pipes/rpc.validation-pipe';
|
||||
|
||||
describe('RpcValidationPipe', () => {
|
||||
it('should not validate request', async () => {
|
||||
const target: RpcValidationPipe = new RpcValidationPipe({
|
||||
whitelist: true,
|
||||
forbidUnknownValues: false,
|
||||
});
|
||||
const metadata: ArgumentMetadata = {
|
||||
type: 'body',
|
||||
metatype: ValidateAuthenticationRequest,
|
||||
data: '',
|
||||
};
|
||||
await target
|
||||
.transform(<ValidateAuthenticationRequest>{}, metadata)
|
||||
.catch((err) => {
|
||||
expect(err.message).toEqual('Rpc Exception');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue