Files
Autonomous-Bug-Explorer/tests/modules/crawling.test.ts

116 lines
4.8 KiB
TypeScript

import { CrawlSession } from '../../src/modules/crawling/domain/entities/CrawlSession';
import { StartCrawlCommand } from '../../src/modules/crawling/application/commands/StartCrawlCommand';
import { ICrawlSessionRepository } from '../../src/modules/crawling/domain/ports/ICrawlSessionRepository';
import { EventBus } from '../../src/shared/application/EventBus';
import { DomainEvent } from '../../src/shared/domain/DomainEvent';
import { EventHandler } from '../../src/shared/application/EventHandler';
import { UniqueId } from '../../src/shared/domain/UniqueId';
import { isOk, isErr } from '../../src/shared/domain/Result';
// --- CrawlSession domain ---
describe('CrawlSession', () => {
it('create returns Ok for valid url', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 42, maxStates: 10 });
expect(isOk(result)).toBe(true);
});
it('create returns Err for invalid url', () => {
const result = CrawlSession.create({ url: 'not-a-url', seed: 42, maxStates: 10 });
expect(isErr(result)).toBe(true);
});
it('emits CrawlStarted event on create', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!result.ok) throw new Error('Expected Ok');
const session = result.value;
expect(session.domainEvents).toHaveLength(1);
expect(session.domainEvents[0]?.eventName).toBe('crawl.started');
});
it('status starts as running', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!result.ok) throw new Error('Expected Ok');
expect(result.value.status).toBe('running');
});
it('complete changes status and adds event', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!result.ok) throw new Error('Expected Ok');
const session = result.value;
session.clearEvents();
session.complete();
expect(session.status).toBe('completed');
expect(session.domainEvents[0]?.eventName).toBe('crawl.completed');
});
it('fail changes status and adds CrawlFailed event', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!result.ok) throw new Error('Expected Ok');
const session = result.value;
session.clearEvents();
session.fail('browser crashed');
expect(session.status).toBe('failed');
expect(session.domainEvents[0]?.eventName).toBe('crawl.failed');
});
it('incrementStatesVisited increments counter', () => {
const result = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!result.ok) throw new Error('Expected Ok');
const session = result.value;
session.incrementStatesVisited();
session.incrementStatesVisited();
expect(session.statesVisited).toBe(2);
});
it('equals compares by id', () => {
const r1 = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
const r2 = CrawlSession.create({ url: 'https://example.com', seed: 1, maxStates: 5 });
if (!r1.ok || !r2.ok) throw new Error('Expected Ok');
expect(r1.value.equals(r2.value)).toBe(false); // different ids
});
});
// --- StartCrawlCommand ---
describe('StartCrawlCommand', () => {
const makeMockRepo = (): ICrawlSessionRepository => {
const store = new Map<string, CrawlSession>();
return {
save: async (session) => { store.set(session.id.toString(), session); },
findById: async (id: UniqueId) => store.get(id.toString()) ?? null,
findAll: async () => [...store.values()],
update: async (session) => { store.set(session.id.toString(), session); },
};
};
const makeMockBus = (): EventBus & { events: DomainEvent[] } => {
const events: DomainEvent[] = [];
return {
events,
publish: async (event: DomainEvent) => { events.push(event); },
subscribe: (_name: string, _handler: EventHandler) => {},
};
};
it('returns Ok with sessionId for valid url', async () => {
const cmd = new StartCrawlCommand(makeMockRepo(), makeMockBus());
const result = await cmd.execute({ url: 'https://example.com', seed: 42, maxStates: 10 });
expect(isOk(result)).toBe(true);
if (result.ok) {
expect(typeof result.value.sessionId).toBe('string');
}
});
it('returns Err for invalid url', async () => {
const cmd = new StartCrawlCommand(makeMockRepo(), makeMockBus());
const result = await cmd.execute({ url: 'not-a-url', seed: 42, maxStates: 10 });
expect(isErr(result)).toBe(true);
});
it('publishes CrawlStarted event via EventBus', async () => {
const bus = makeMockBus();
const cmd = new StartCrawlCommand(makeMockRepo(), bus);
await cmd.execute({ url: 'https://example.com', seed: 1, maxStates: 5 });
expect(bus.events.some(e => e.eventName === 'crawl.started')).toBe(true);
});
});