@hexadrop/command
Version:
Hexagonal architecture utils library
189 lines (149 loc) • 4.82 kB
text/typescript
import Either from '@hexadrop/either';
import DomainError from '@hexadrop/error';
import { beforeEach, describe, expect, test } from 'bun:test';
import type { CommandBusCallback, CommandHandler } from './bus';
import Command from './command';
import { CommandNotRegisteredError } from './error';
import InMemoryCommandHandlers from './in-memory.command-handlers';
class Command1 extends Command {
static override COMMAND_NAME = 'Command1';
constructor() {
super(Command1.COMMAND_NAME, 'id');
}
}
class Command2 extends Command {
static override COMMAND_NAME = 'Command2';
constructor() {
super(Command2.COMMAND_NAME, 'id');
}
}
class Command3 extends Command {
static override COMMAND_NAME = 'Command3';
constructor() {
super(Command3.COMMAND_NAME, 'id');
}
}
class Command4 extends Command {
static override COMMAND_NAME = 'Command4';
constructor() {
super(Command4.COMMAND_NAME, 'id');
}
}
class Command5 extends Command {
static override COMMAND_NAME = 'Command5';
constructor() {
super(Command5.COMMAND_NAME, 'id');
}
}
class Command6 extends Command {
static override COMMAND_NAME = 'Command6';
constructor() {
super(Command6.COMMAND_NAME, 'id');
}
}
class Service {
async hello(): Promise<string> {
return await Promise.resolve('world');
}
}
class Command1Handler implements CommandHandler<Command1> {
constructor(private readonly service: Service) {}
async run(): Promise<Either<DomainError, void>> {
await this.service.hello();
return Either.right();
}
}
class Command23Handler implements CommandHandler<Command2 | Command3> {
run(): Either<DomainError, void> {
return Either.right();
}
}
class Command4Handler implements CommandHandler<Command4> {
constructor(private readonly service: Service) {}
async run(): Promise<Either<DomainError, void>> {
await this.service.hello();
return Either.right();
}
}
describe('InMemoryCommandHandlers', () => {
let c1: Command;
let c2: Command;
let c3: Command;
let c4: Command;
let c5: Command;
let c6: Command;
let svc: Service;
let expectedCommand1Handler: CommandHandler;
let expectedCommand23Handler: CommandHandler;
let expectedCommand4Handler: CommandHandler;
let expectedCommand56Handler: CommandBusCallback;
let info: InMemoryCommandHandlers;
beforeEach(() => {
c1 = new Command1();
c2 = new Command2();
c3 = new Command3();
c4 = new Command4();
c5 = new Command5();
c6 = new Command6();
svc = new Service();
expectedCommand1Handler = new Command1Handler(svc);
expectedCommand23Handler = new Command23Handler();
expectedCommand4Handler = new Command4Handler(svc);
expectedCommand56Handler = function expectedCommand56Handler(): Either<DomainError, void> {
return Either.right();
};
info = new InMemoryCommandHandlers();
info.register(Command1, expectedCommand1Handler);
info.register(Command2, expectedCommand23Handler);
info.register(Command3, expectedCommand23Handler);
});
describe('search()', () => {
test('should return a registered command handler', () => {
const h1 = info.search(c1);
expect(h1).toBeDefined();
const h2 = info.search(c2);
expect(h2).toBeDefined();
const h3 = info.search(c3);
expect(h3).toBeDefined();
const h4 = info.search(Command3);
expect(h4).toBeDefined();
expect(h4).toBe(h3);
});
test('should throw and error if command handler is not registered', () => {
const expectedError = new CommandNotRegisteredError(Command4.COMMAND_NAME);
expect(() => info.search(c4)).toThrow(expectedError);
expect(() => info.search(Command4)).toThrow(expectedError);
expect(expectedError.message).toBe(
`The command '${Command4.COMMAND_NAME}' hasn't a command handler associated`
);
});
});
describe('register()', () => {
test('should register a non previous registered command handler', () => {
info.register(Command4, expectedCommand4Handler);
info.register(Command5, expectedCommand56Handler);
info.register(Command6, expectedCommand56Handler);
const h4 = info.search(c4);
expect(h4).toBeDefined();
const h5 = info.search(c5);
expect(h5).toBeDefined();
expect(h5).toStrictEqual(expectedCommand56Handler);
const h6 = info.search(c6);
expect(h6).toBeDefined();
expect(h6).toStrictEqual(expectedCommand56Handler);
});
test('should register a previous registered command handler', () => {
info.register(Command1, expectedCommand4Handler);
const h4 = info.search(c1);
expect(h4).toBeDefined();
});
});
describe('unregister()', () => {
test('should unregister a previous registered command handler', () => {
const h3 = info.search(c3);
expect(h3).toBeDefined();
info.unregister(Command3);
expect(() => info.search(c3)).toThrow(new CommandNotRegisteredError(Command3.COMMAND_NAME));
});
});
});