feat(#175): Implement E2E test harness
- Create comprehensive E2E test suite for job orchestration - Add test fixtures for Discord, BullMQ, and Prisma mocks - Implement 9 end-to-end test scenarios covering: * Happy path: webhook → job → step execution → completion * Event emission throughout job lifecycle * Step failure and retry handling * Job failure after max retries * Discord command parsing and job creation * WebSocket status updates integration * Job cancellation workflow * Job retry mechanism * Progress percentage tracking - Add helper methods to services for simplified testing: * JobStepsService: start(), complete(), fail(), findByJob() * RunnerJobsService: updateStatus(), updateProgress() * JobEventsService: findByJob() - Configure vitest.e2e.config.ts for E2E test execution - All 9 E2E tests passing - All 1405 unit tests passing - Quality gates: typecheck, lint, build all passing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
72
apps/api/test/fixtures/mock-discord.fixture.ts
vendored
Normal file
72
apps/api/test/fixtures/mock-discord.fixture.ts
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import { vi } from "vitest";
|
||||
import type { Client, Message, TextChannel } from "discord.js";
|
||||
|
||||
/**
|
||||
* Mock Discord client for testing
|
||||
*/
|
||||
export function createMockDiscordClient(): Partial<Client> {
|
||||
const mockChannel: Partial<TextChannel> = {
|
||||
send: vi.fn().mockResolvedValue({
|
||||
id: "mock-message-id",
|
||||
content: "Mock message sent",
|
||||
}),
|
||||
id: "mock-channel-id",
|
||||
name: "test-channel",
|
||||
};
|
||||
|
||||
return {
|
||||
channels: {
|
||||
fetch: vi.fn().mockResolvedValue(mockChannel),
|
||||
cache: {
|
||||
get: vi.fn().mockReturnValue(mockChannel),
|
||||
},
|
||||
} as never,
|
||||
on: vi.fn(),
|
||||
once: vi.fn(),
|
||||
login: vi.fn().mockResolvedValue("mock-token"),
|
||||
destroy: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock Discord message for testing command parsing
|
||||
*/
|
||||
export function createMockDiscordMessage(
|
||||
content: string,
|
||||
overrides?: Partial<Message>
|
||||
): Partial<Message> {
|
||||
return {
|
||||
content,
|
||||
author: {
|
||||
id: "mock-user-id",
|
||||
username: "test-user",
|
||||
bot: false,
|
||||
discriminator: "0001",
|
||||
avatar: null,
|
||||
tag: "test-user#0001",
|
||||
} as never,
|
||||
channel: {
|
||||
id: "mock-channel-id",
|
||||
type: 0, // GuildText
|
||||
send: vi.fn().mockResolvedValue({
|
||||
id: "response-message-id",
|
||||
content: "Response sent",
|
||||
}),
|
||||
} as never,
|
||||
guild: {
|
||||
id: "mock-guild-id",
|
||||
name: "Test Guild",
|
||||
} as never,
|
||||
createdTimestamp: Date.now(),
|
||||
id: "mock-message-id",
|
||||
mentions: {
|
||||
has: vi.fn().mockReturnValue(false),
|
||||
users: new Map(),
|
||||
} as never,
|
||||
reply: vi.fn().mockResolvedValue({
|
||||
id: "reply-message-id",
|
||||
content: "Reply sent",
|
||||
}),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user