Skip to content

Commit

Permalink
Client TypeORM repository + Tests added
Browse files Browse the repository at this point in the history
  • Loading branch information
AnderGI committed Feb 16, 2025
1 parent 940eb3a commit 42d4af9
Show file tree
Hide file tree
Showing 26 changed files with 205 additions and 33 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"rabbitmq:configure": "npx ts-node ./src/scripts/configure-rabbitmq/configure-rabbitmq.ts",
"rabbitmq:consume": "npx ts-node ./src/scripts/configure-rabbitmq/consume-rabbitmq.ts",
"test:backoffice:backend:spotify-user":"npm run test:backoffice:backend:spotify-user:unit && npm run test:backoffice:backend:spotify-user:integration",
"test:backoffice:backend:clients:unit":"cross-env NODE_ENV=test jest --passWithNoTests --testPathPattern './tests/contexts/backoffice/clients/application/.*\\.test\\.ts'",
"test:backoffice:backend:spotify-user:integration":"cross-env NODE_ENV=test NODE_OPTIONS=\"--experimental-vm-modules\" jest --passWithNoTests --testPathPattern './tests/contexts/backoffice/spotify-user/infrastructure/.*/.*\\.test\\.ts'"
"test:backoffice:backend:client:unit":"cross-env NODE_ENV=test jest --passWithNoTests --testPathPattern './tests/contexts/backoffice/client/application/.*\\.test\\.ts'",
"test:backoffice:backend:client:integration":"cross-env NODE_ENV=test NODE_OPTIONS=\"--experimental-vm-modules\" jest --passWithNoTests --testPathPattern './tests/contexts/backoffice/client/infrastructure/.*/.*\\.test\\.ts'"
},
"dependencies": {
"@langchain/core": "^0.3.23",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"imports": [
{ "resource": "./contexts/backoffice/shared/application.json" },
{ "resource": "./shared/application.json" },
{ "resource": "./apps/application.json" }
{ "resource": "./apps/application.json" },
{ "resource": "./contexts/backoffice/shared/application.json" },
{ "resource": "./contexts/backoffice/client/application.json" }

]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"services": {
"backoffice.client.ClientRepository": {
"class": "../../../../../../../contexts/backoffice/client/infrastructure/persistence/typeorm/TypeOrmClientRepository",
"arguments": ["@backoffice.shared.TypeOrmClientFactory"]
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AggregateRoot } from '../../../shared/domain/AggregateRoot';
import RegisterClientCommand from '../application/register/RegisterClientCommand';
import ClientCompany from './ClientCompany';
import ClientEmail from './ClientEmail';
Expand All @@ -8,15 +9,15 @@ import ClientPosition from './ClientPosition';
import ClientRepository from './ClientRepository';
import ClientSaver from './save/ClientSaver';

type CreateClientPrimitives = {
type ClientPrimitives = {
id: string;
name: string;
email: string;
phone: string;
company: string;
position: string;
};
export default class Client {
export default class Client implements AggregateRoot {
constructor(
readonly id: ClientId,
readonly name: ClientName,
Expand All @@ -26,7 +27,7 @@ export default class Client {
readonly position: ClientPosition
) {}

public static create(_: CreateClientPrimitives): Client {
public static create(_: ClientPrimitives): Client {
return new Client(
new ClientId(_.id),
new ClientName(_.name),
Expand All @@ -37,7 +38,7 @@ export default class Client {
);
}

public static fromPrimitives(_: CreateClientPrimitives): Client {
public static fromPrimitives(_: ClientPrimitives): Client {
return new Client(
new ClientId(_.id),
new ClientName(_.name),
Expand All @@ -53,4 +54,15 @@ export default class Client {
await ClientSaver.save(command, repository);
};
}

toPrimitives(): ClientPrimitives {
return {
id: this.id.getValue(),
name: this.name.getValue(),
email: this.email.getValue(),
phone: this.phone.getValue(),
company: this.company.getValue(),
position: this.position.getValue()
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { EntitySchema } from 'typeorm';

import { ValueObjectTransformer } from '../../../../../shared/infrastructure/persistence/typeorm/ValueObjectTransformer';
import Client from '../../../domain/Client';
import ClientCompany from '../../../domain/ClientCompany';
import ClientEmail from '../../../domain/ClientEmail';
import ClientId from '../../../domain/ClientId';
import ClientName from '../../../domain/ClientName';
import ClientPhone from '../../../domain/ClientPhone';
import ClientPosition from '../../../domain/ClientPosition';

export const ClientEntity = new EntitySchema<Client>({
name: 'Client',
tableName: 'clients',
target: Client,
columns: {
id: {
type: String,
primary: true,
transformer: ValueObjectTransformer(ClientId)
},
name: {
type: String,
transformer: ValueObjectTransformer(ClientName)
},
email: {
type: String,
transformer: ValueObjectTransformer(ClientEmail)
},
phone: {
type: String,
transformer: ValueObjectTransformer(ClientPhone)
},
company: {
type: String,
transformer: ValueObjectTransformer(ClientCompany)
},
position: {
type: String,
transformer: ValueObjectTransformer(ClientPosition)
}
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { DataSource, EntitySchema, Repository } from 'typeorm';

import { Nullable } from '../../../../../../shared/domain/Nullable';
import Client from '../../../domain/Client';
import ClientRepository from '../../../domain/ClientRepository';
import { ClientEntity } from './ClientEntity.entity';

export class TypeOrmClientRepository implements ClientRepository {
constructor(private readonly _client: Promise<DataSource>) {}

public async save(client: Client): Promise<void> {
return this.persist(client);
}

public async search(_: Client): Promise<Nullable<Client>> {
const repository = await this.repository();
const retrievedUser = await repository.findOne({
where: {
id: _.id.value
}
});

return retrievedUser;
}

public entitySchema(): EntitySchema<Client> {
return ClientEntity;
}

private async client(): Promise<DataSource> {
return this._client;
}

private async repository(): Promise<Repository<Client>> {
return (await this.client()).getRepository(this.entitySchema());
}

private async persist(aggregateRoot: Client): Promise<void> {
const repository = await this.repository();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await repository.save(aggregateRoot);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const config = convict({
doc: 'The database port',
format: Number,
env: 'TYPEORM_PORT',
default: 5432
default: 5433
},
username: {
doc: 'The database username',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import ClientRegistrar from '../../../../../../src/contexts/backoffice/clients/application/register/ClientRegistrar';
import RegisterClientCommandHandler from '../../../../../../src/contexts/backoffice/clients/application/register/RegisterClientCommandHandler';
import ClientRegistrar from '../../../../../../src/contexts/backoffice/client/application/register/ClientRegistrar';
import RegisterClientCommandHandler from '../../../../../../src/contexts/backoffice/client/application/register/RegisterClientCommandHandler';
import { ClientMother } from '../../domain/ClientMother';
import MockClientRepository from '../../domain/MockClientRepository';
import { RegisterClientCommandMother } from './RegisterClientCommandMother';

describe('ClientRegistrar', () => {
describe('#register', () => {
it('Should register a non existing client', () => {
it('Should register a non existing client', async () => {
const command = RegisterClientCommandMother.random();
const repository = new MockClientRepository();
const client = ClientMother.fromCommand(command);
const registar = new ClientRegistrar(repository);
const handler = new RegisterClientCommandHandler(registar);

handler.handle(command);
await handler.handle(command);

repository.ensureSaveHasBeenCalledWith(client);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from 'faker';

import RegisterClientCommand from '../../../../../../src/contexts/backoffice/clients/application/register/RegisterClientCommand';
import RegisterClientCommand from '../../../../../../src/contexts/backoffice/client/application/register/RegisterClientCommand';

export class RegisterClientCommandMother {
static random(): RegisterClientCommand {
Expand Down
33 changes: 33 additions & 0 deletions tests/contexts/backoffice/client/domain/ClientMother.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as fs from 'faker';

import RegisterClientCommand from '../../../../../src/contexts/backoffice/client/application/register/RegisterClientCommand';
import Client from '../../../../../src/contexts/backoffice/client/domain/Client';

export class ClientMother {
static create(): Client {
const primitives = {
id: fs.datatype.uuid(),
name: fs.name.firstName(),
email: fs.internet.email(),
phone: fs.phone.phoneNumber(),
company: fs.company.companyName(),
position: fs.name.jobType()
};

return Client.fromPrimitives(primitives);
}

static fromCommand(_: RegisterClientCommand): Client {
const { data } = _;
const primitives = {
id: data.id,
name: data.name,
email: data.email,
phone: data.phone,
company: data.company,
position: data.position
};

return Client.fromPrimitives(primitives);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Client from '../../../../../src/contexts/backoffice/clients/domain/Client';
import ClientRepository from '../../../../../src/contexts/backoffice/clients/domain/ClientRepository';
import Client from '../../../../../src/contexts/backoffice/client/domain/Client';
import ClientRepository from '../../../../../src/contexts/backoffice/client/domain/ClientRepository';

export default class MockClientRepository implements ClientRepository {
private readonly mockSave: jest.Mock;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ClientRepository from '../../../../../../src/contexts/backoffice/client/domain/ClientRepository';
import { EnvironmentArranger } from '../../../../shared/infrastructure/arranger/EnvironmentArranger';
import { ClientMother } from '../../domain/ClientMother';

export default class ClientRepositoryArrenger {
constructor(
private readonly repository: ClientRepository,
private readonly environmentArranger: EnvironmentArranger
) {}

public async saveClient(): Promise<void> {
await this.cleanFirst();
const client = ClientMother.create();
await this.repository.save(client);
await this.cleanEnd();
}

private async cleanFirst(): Promise<void> {
await this.environmentArranger.clean();
}

private async cleanEnd(): Promise<void> {
await this.environmentArranger.clean();
await this.environmentArranger.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import container from '../../../../../../src/apps/backoffice/backend/dependency-injection';
import ClientRepository from '../../../../../../src/contexts/backoffice/client/domain/ClientRepository';

export default class ClientRepositoryFactory {
public static getRepository(): ClientRepository {
return container.get('backoffice.client.ClientRepository');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import EnvironmentArrengerFactory from '../../../../shared/infrastructure/arranger/EnvironmentArrengerFactory';
import ClientRepositoryArrenger from './ClientRepositoryArrenger';
import ClientRepositoryFactory from './ClientRepositoryFactory';

describe('TypeOrmClientRepository', () => {
describe('#save', () => {
it('should upsert a client', async () => {
const arrenger = new ClientRepositoryArrenger(
ClientRepositoryFactory.getRepository(),
EnvironmentArrengerFactory.getArranger()
);
await arrenger.saveClient();
});
});
});
17 changes: 0 additions & 17 deletions tests/contexts/backoffice/clients/domain/ClientMother.ts

This file was deleted.

0 comments on commit 42d4af9

Please sign in to comment.