mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2025-12-31 02:32:40 +00:00
refactor to ddh, first commit
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { DatabaseException } from '../../exceptions/database.exception';
|
||||
import { ICollection } from '../../interfaces/collection.interface';
|
||||
import { IRepository } from '../../interfaces/repository.interface';
|
||||
import { PrismaService } from './prisma.service';
|
||||
|
||||
/**
|
||||
* Child classes MUST redefined model property with appropriate model name
|
||||
*/
|
||||
@Injectable()
|
||||
export abstract class PrismaRepository<T> implements IRepository<T> {
|
||||
protected model: string;
|
||||
|
||||
constructor(protected readonly prisma: PrismaService) {}
|
||||
|
||||
findAll = async (
|
||||
page = 1,
|
||||
perPage = 10,
|
||||
where?: any,
|
||||
include?: any,
|
||||
): Promise<ICollection<T>> => {
|
||||
const [data, total] = await this.prisma.$transaction([
|
||||
this.prisma[this.model].findMany({
|
||||
where,
|
||||
include,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
this.prisma[this.model].count({
|
||||
where,
|
||||
}),
|
||||
]);
|
||||
return Promise.resolve({
|
||||
data,
|
||||
total,
|
||||
});
|
||||
};
|
||||
|
||||
findOneByUuid = async (uuid: string): Promise<T> => {
|
||||
try {
|
||||
const entity = await this.prisma[this.model].findUnique({
|
||||
where: { uuid },
|
||||
});
|
||||
|
||||
return entity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
findOne = async (where: any, include?: any): Promise<T> => {
|
||||
try {
|
||||
const entity = await this.prisma[this.model].findFirst({
|
||||
where: where,
|
||||
include: include,
|
||||
});
|
||||
|
||||
return entity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TODO : using any is not good, but needed for nested entities
|
||||
// TODO : Refactor for good clean architecture ?
|
||||
async create(entity: Partial<T> | any, include?: any): Promise<T> {
|
||||
try {
|
||||
const res = await this.prisma[this.model].create({
|
||||
data: entity,
|
||||
include: include,
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update = async (uuid: string, entity: Partial<T>): Promise<T> => {
|
||||
try {
|
||||
const updatedEntity = await this.prisma[this.model].update({
|
||||
where: { uuid },
|
||||
data: entity,
|
||||
});
|
||||
return updatedEntity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateWhere = async (
|
||||
where: any,
|
||||
entity: Partial<T> | any,
|
||||
include?: any,
|
||||
): Promise<T> => {
|
||||
try {
|
||||
const updatedEntity = await this.prisma[this.model].update({
|
||||
where: where,
|
||||
data: entity,
|
||||
include: include,
|
||||
});
|
||||
|
||||
return updatedEntity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (uuid: string): Promise<T> => {
|
||||
try {
|
||||
const entity = await this.prisma[this.model].delete({
|
||||
where: { uuid },
|
||||
});
|
||||
|
||||
return entity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
deleteMany = async (where: any): Promise<void> => {
|
||||
try {
|
||||
const entity = await this.prisma[this.model].deleteMany({
|
||||
where: where,
|
||||
});
|
||||
|
||||
return entity;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
findAllByQuery = async (
|
||||
include: string[],
|
||||
where: string[],
|
||||
): Promise<ICollection<T>> => {
|
||||
const query = `SELECT ${include.join(',')} FROM ${
|
||||
this.model
|
||||
} WHERE ${where.join(' AND ')}`;
|
||||
const data: T[] = await this.prisma.$queryRawUnsafe(query);
|
||||
return Promise.resolve({
|
||||
data,
|
||||
total: data.length,
|
||||
});
|
||||
};
|
||||
|
||||
createWithFields = async (fields: object): Promise<number> => {
|
||||
try {
|
||||
const command = `INSERT INTO ${this.model} ("${Object.keys(fields).join(
|
||||
'","',
|
||||
)}") VALUES (${Object.values(fields).join(',')})`;
|
||||
return await this.prisma.$executeRawUnsafe(command);
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateWithFields = async (uuid: string, entity: object): Promise<number> => {
|
||||
entity['"updatedAt"'] = `to_timestamp(${Date.now()} / 1000.0)`;
|
||||
const values = Object.keys(entity).map((key) => `${key} = ${entity[key]}`);
|
||||
try {
|
||||
const command = `UPDATE ${this.model} SET ${values.join(
|
||||
', ',
|
||||
)} WHERE uuid = '${uuid}'`;
|
||||
return await this.prisma.$executeRawUnsafe(command);
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
healthCheck = async (): Promise<boolean> => {
|
||||
try {
|
||||
await this.prisma.$queryRaw`SELECT 1`;
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseException(
|
||||
Prisma.PrismaClientKnownRequestError.name,
|
||||
e.code,
|
||||
e.message,
|
||||
);
|
||||
} else {
|
||||
throw new DatabaseException();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
15
old/modules/database/adapters/secondaries/prisma.service.ts
Normal file
15
old/modules/database/adapters/secondaries/prisma.service.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient implements OnModuleInit {
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
|
||||
async enableShutdownHooks(app: INestApplication) {
|
||||
this.$on('beforeExit', async () => {
|
||||
await app.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
8
old/modules/database/database.module.ts
Normal file
8
old/modules/database/database.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PrismaService } from './adapters/secondaries/prisma.service';
|
||||
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class DatabaseModule {}
|
||||
3
old/modules/database/domain/database.repository.ts
Normal file
3
old/modules/database/domain/database.repository.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { PrismaRepository } from '../adapters/secondaries/prisma.repository.abstract';
|
||||
|
||||
export class DatabaseRepository<T> extends PrismaRepository<T> {}
|
||||
24
old/modules/database/exceptions/database.exception.ts
Normal file
24
old/modules/database/exceptions/database.exception.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export class DatabaseException implements Error {
|
||||
name: string;
|
||||
message: string;
|
||||
|
||||
constructor(
|
||||
private _type: string = 'unknown',
|
||||
private _code: string = '',
|
||||
message?: string,
|
||||
) {
|
||||
this.name = 'DatabaseException';
|
||||
this.message = message ?? 'An error occured with the database.';
|
||||
if (this.message.includes('Unique constraint failed')) {
|
||||
this.message = 'Already exists.';
|
||||
}
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this._code;
|
||||
}
|
||||
}
|
||||
4
old/modules/database/interfaces/collection.interface.ts
Normal file
4
old/modules/database/interfaces/collection.interface.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface ICollection<T> {
|
||||
data: T[];
|
||||
total: number;
|
||||
}
|
||||
18
old/modules/database/interfaces/repository.interface.ts
Normal file
18
old/modules/database/interfaces/repository.interface.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { ICollection } from './collection.interface';
|
||||
|
||||
export interface IRepository<T> {
|
||||
findAll(
|
||||
page: number,
|
||||
perPage: number,
|
||||
params?: any,
|
||||
include?: any,
|
||||
): Promise<ICollection<T>>;
|
||||
findOne(where: any, include?: any): Promise<T>;
|
||||
findOneByUuid(uuid: string, include?: any): Promise<T>;
|
||||
create(entity: Partial<T> | any, include?: any): Promise<T>;
|
||||
update(uuid: string, entity: Partial<T>, include?: any): Promise<T>;
|
||||
updateWhere(where: any, entity: Partial<T> | any, include?: any): Promise<T>;
|
||||
delete(uuid: string): Promise<T>;
|
||||
deleteMany(where: any): Promise<void>;
|
||||
healthCheck(): Promise<boolean>;
|
||||
}
|
||||
571
old/modules/database/tests/unit/prisma-repository.spec.ts
Normal file
571
old/modules/database/tests/unit/prisma-repository.spec.ts
Normal file
@@ -0,0 +1,571 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PrismaService } from '../../adapters/secondaries/prisma.service';
|
||||
import { PrismaRepository } from '../../adapters/secondaries/prisma.repository.abstract';
|
||||
import { DatabaseException } from '../../exceptions/database.exception';
|
||||
import { Prisma } from '@prisma/client';
|
||||
|
||||
class FakeEntity {
|
||||
uuid?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
let entityId = 2;
|
||||
const entityUuid = 'uuid-';
|
||||
const entityName = 'name-';
|
||||
|
||||
const createRandomEntity = (): FakeEntity => {
|
||||
const entity: FakeEntity = {
|
||||
uuid: `${entityUuid}${entityId}`,
|
||||
name: `${entityName}${entityId}`,
|
||||
};
|
||||
|
||||
entityId++;
|
||||
|
||||
return entity;
|
||||
};
|
||||
|
||||
const fakeEntityToCreate: FakeEntity = {
|
||||
name: 'test',
|
||||
};
|
||||
|
||||
const fakeEntityCreated: FakeEntity = {
|
||||
...fakeEntityToCreate,
|
||||
uuid: 'some-uuid',
|
||||
};
|
||||
|
||||
const fakeEntities: FakeEntity[] = [];
|
||||
Array.from({ length: 10 }).forEach(() => {
|
||||
fakeEntities.push(createRandomEntity());
|
||||
});
|
||||
|
||||
@Injectable()
|
||||
class FakePrismaRepository extends PrismaRepository<FakeEntity> {
|
||||
protected model = 'fake';
|
||||
}
|
||||
|
||||
class FakePrismaService extends PrismaService {
|
||||
fake: any;
|
||||
}
|
||||
|
||||
const mockPrismaService = {
|
||||
$transaction: jest.fn().mockImplementation(async (data: any) => {
|
||||
const entities = await data[0];
|
||||
if (entities.length == 1) {
|
||||
return Promise.resolve([[fakeEntityCreated], 1]);
|
||||
}
|
||||
|
||||
return Promise.resolve([fakeEntities, fakeEntities.length]);
|
||||
}),
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
$queryRawUnsafe: jest.fn().mockImplementation((query?: string) => {
|
||||
return Promise.resolve(fakeEntities);
|
||||
}),
|
||||
$executeRawUnsafe: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce(fakeEntityCreated)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((fields: object) => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((fields: object) => {
|
||||
throw new Error('an unknown error');
|
||||
})
|
||||
.mockResolvedValueOnce(fakeEntityCreated)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((fields: object) => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((fields: object) => {
|
||||
throw new Error('an unknown error');
|
||||
}),
|
||||
$queryRaw: jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
return true;
|
||||
})
|
||||
.mockImplementation(() => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('Database unavailable', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
}),
|
||||
fake: {
|
||||
create: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce(fakeEntityCreated)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Prisma.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) {
|
||||
return Promise.resolve([fakeEntityCreated]);
|
||||
}
|
||||
|
||||
return Promise.resolve(fakeEntities);
|
||||
}),
|
||||
count: jest.fn().mockResolvedValue(fakeEntities.length),
|
||||
|
||||
findUnique: jest.fn().mockImplementation(async (params?: any) => {
|
||||
let entity;
|
||||
|
||||
if (params?.where?.uuid) {
|
||||
entity = fakeEntities.find(
|
||||
(entity) => entity.uuid === params?.where?.uuid,
|
||||
);
|
||||
}
|
||||
|
||||
if (!entity && params?.where?.uuid == 'unknown') {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
} else if (!entity) {
|
||||
throw new Error('no entity');
|
||||
}
|
||||
|
||||
return entity;
|
||||
}),
|
||||
|
||||
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 Prisma.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()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Prisma.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,
|
||||
);
|
||||
Object.entries(params.data).map(([key, value]) => {
|
||||
entity[key] = value;
|
||||
});
|
||||
|
||||
return Promise.resolve(entity);
|
||||
}),
|
||||
|
||||
delete: jest
|
||||
.fn()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementation((params: any) => {
|
||||
let found = false;
|
||||
|
||||
fakeEntities.forEach((entity, index) => {
|
||||
if (entity.uuid === params?.where?.uuid) {
|
||||
found = true;
|
||||
fakeEntities.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
throw new Error();
|
||||
}
|
||||
}),
|
||||
|
||||
deleteMany: jest
|
||||
.fn()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.mockImplementationOnce((params?: any) => {
|
||||
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
|
||||
code: 'code',
|
||||
clientVersion: 'version',
|
||||
});
|
||||
})
|
||||
.mockImplementation((params: any) => {
|
||||
let found = false;
|
||||
|
||||
fakeEntities.forEach((entity, index) => {
|
||||
if (entity.uuid === params?.where?.uuid) {
|
||||
found = true;
|
||||
fakeEntities.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
throw new Error();
|
||||
}
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
describe('PrismaRepository', () => {
|
||||
let fakeRepository: FakePrismaRepository;
|
||||
let prisma: FakePrismaService;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
FakePrismaRepository,
|
||||
{
|
||||
provide: PrismaService,
|
||||
useValue: mockPrismaService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
fakeRepository = module.get<FakePrismaRepository>(FakePrismaRepository);
|
||||
prisma = module.get<PrismaService>(PrismaService) as FakePrismaService;
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(fakeRepository).toBeDefined();
|
||||
expect(prisma).toBeDefined();
|
||||
});
|
||||
|
||||
describe('findAll', () => {
|
||||
it('should return an array of entities', async () => {
|
||||
jest.spyOn(prisma.fake, 'findMany');
|
||||
jest.spyOn(prisma.fake, 'count');
|
||||
jest.spyOn(prisma, '$transaction');
|
||||
|
||||
const entities = await fakeRepository.findAll();
|
||||
expect(entities).toStrictEqual({
|
||||
data: fakeEntities,
|
||||
total: fakeEntities.length,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an array containing only one entity', async () => {
|
||||
const entities = await fakeRepository.findAll(1, 10, { limit: 1 });
|
||||
|
||||
expect(prisma.fake.findMany).toHaveBeenCalledWith({
|
||||
skip: 0,
|
||||
take: 10,
|
||||
where: { limit: 1 },
|
||||
});
|
||||
expect(entities).toEqual({
|
||||
data: [fakeEntityCreated],
|
||||
total: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should create an entity', async () => {
|
||||
jest.spyOn(prisma.fake, 'create');
|
||||
|
||||
const newEntity = await fakeRepository.create(fakeEntityToCreate);
|
||||
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);
|
||||
});
|
||||
|
||||
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'),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
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 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, {
|
||||
name: newName,
|
||||
});
|
||||
expect(fakeEntities[0].name).toBe(newName);
|
||||
});
|
||||
|
||||
it("should throw an exception if an entity doesn't exist", async () => {
|
||||
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;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const res = await fakeRepository.delete(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.delete('fake-uuid')).rejects.toBeInstanceOf(
|
||||
DatabaseException,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteMany', () => {
|
||||
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({ uuid: 'fake-uuid' }),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findAllByquery', () => {
|
||||
it('should return an array of entities', async () => {
|
||||
const entities = await fakeRepository.findAllByQuery(
|
||||
['uuid', 'name'],
|
||||
['name is not null'],
|
||||
);
|
||||
expect(entities).toStrictEqual({
|
||||
data: fakeEntities,
|
||||
total: fakeEntities.length,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createWithFields', () => {
|
||||
it('should create an entity', async () => {
|
||||
jest.spyOn(prisma, '$queryRawUnsafe');
|
||||
|
||||
const newEntity = await fakeRepository.createWithFields({
|
||||
uuid: '804319b3-a09b-4491-9f82-7976bfce0aff',
|
||||
name: 'my-name',
|
||||
});
|
||||
expect(newEntity).toBe(fakeEntityCreated);
|
||||
expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.createWithFields({
|
||||
uuid: '804319b3-a09b-4491-9f82-7976bfce0aff',
|
||||
name: 'my-name',
|
||||
}),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException if uuid is not found', async () => {
|
||||
await expect(
|
||||
fakeRepository.createWithFields({
|
||||
name: 'my-name',
|
||||
}),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateWithFields', () => {
|
||||
it('should update an entity', async () => {
|
||||
jest.spyOn(prisma, '$queryRawUnsafe');
|
||||
|
||||
const updatedEntity = await fakeRepository.updateWithFields(
|
||||
'804319b3-a09b-4491-9f82-7976bfce0aff',
|
||||
{
|
||||
name: 'my-name',
|
||||
},
|
||||
);
|
||||
expect(updatedEntity).toBe(fakeEntityCreated);
|
||||
expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(
|
||||
fakeRepository.updateWithFields(
|
||||
'804319b3-a09b-4491-9f82-7976bfce0aff',
|
||||
{
|
||||
name: 'my-name',
|
||||
},
|
||||
),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException if uuid is not found', async () => {
|
||||
await expect(
|
||||
fakeRepository.updateWithFields(
|
||||
'804319b3-a09b-4491-9f82-7976bfce0aff',
|
||||
{
|
||||
name: 'my-name',
|
||||
},
|
||||
),
|
||||
).rejects.toBeInstanceOf(DatabaseException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('healthCheck', () => {
|
||||
it('should throw a DatabaseException for client error', async () => {
|
||||
await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf(
|
||||
DatabaseException,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return a healthy result', async () => {
|
||||
const res = await fakeRepository.healthCheck();
|
||||
expect(res).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should throw an exception if database is not available', async () => {
|
||||
await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf(
|
||||
DatabaseException,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user