125 lines
3.4 KiB
TypeScript
125 lines
3.4 KiB
TypeScript
import type { AutomationResult } from 'packages/automation/application/ports/AutomationResults';
|
|
import { StepId } from '@gridpilot/automation/domain/value-objects/StepId';
|
|
import {
|
|
PlaywrightAutomationAdapter,
|
|
FixtureServer,
|
|
} from 'packages/automation/infrastructure/adapters/automation';
|
|
import { PinoLogAdapter } from 'packages/automation/infrastructure/adapters/logging/PinoLogAdapter';
|
|
|
|
export interface StepHarness {
|
|
server: FixtureServer;
|
|
adapter: PlaywrightAutomationAdapter;
|
|
baseUrl: string;
|
|
getFixtureUrl(step: number): string;
|
|
navigateToFixtureStep(step: number): Promise<void>;
|
|
executeStep(step: number, config: Record<string, unknown>): Promise<AutomationResult>;
|
|
executeStepWithAutoNavigation(
|
|
step: number,
|
|
config: Record<string, unknown>,
|
|
): Promise<AutomationResult>;
|
|
executeStepWithFixtureMismatch(
|
|
step: number,
|
|
config: Record<string, unknown>,
|
|
): Promise<AutomationResult>;
|
|
dispose(): Promise<void>;
|
|
}
|
|
|
|
async function createRealAdapter(baseUrl: string): Promise<PlaywrightAutomationAdapter> {
|
|
const logger = new PinoLogAdapter();
|
|
|
|
const adapter = new PlaywrightAutomationAdapter(
|
|
{
|
|
headless: true,
|
|
timeout: 8000,
|
|
mode: 'real',
|
|
baseUrl,
|
|
userDataDir: '',
|
|
},
|
|
logger,
|
|
);
|
|
|
|
const result = await adapter.connect(false);
|
|
if (!result.success) {
|
|
throw new Error(result.error || 'Failed to connect Playwright adapter');
|
|
}
|
|
|
|
return adapter;
|
|
}
|
|
|
|
async function createMockAdapter(): Promise<PlaywrightAutomationAdapter> {
|
|
const logger = new PinoLogAdapter();
|
|
|
|
const adapter = new PlaywrightAutomationAdapter(
|
|
{
|
|
headless: true,
|
|
timeout: 5000,
|
|
mode: 'mock',
|
|
},
|
|
logger,
|
|
);
|
|
|
|
const result = await adapter.connect();
|
|
if (!result.success) {
|
|
throw new Error(result.error || 'Failed to connect mock Playwright adapter');
|
|
}
|
|
|
|
return adapter;
|
|
}
|
|
|
|
export async function createStepHarness(useMock: boolean = false): Promise<StepHarness> {
|
|
const server = new FixtureServer();
|
|
const { url } = await server.start();
|
|
|
|
const adapter = useMock ? await createMockAdapter() : await createRealAdapter(url);
|
|
|
|
async function navigateToFixtureStep(step: number): Promise<void> {
|
|
await adapter.navigateToPage(server.getFixtureUrl(step));
|
|
await adapter.getPage()?.waitForLoadState('domcontentloaded');
|
|
}
|
|
|
|
async function executeStepWithAutoNavigation(
|
|
step: number,
|
|
config: Record<string, unknown>,
|
|
): Promise<AutomationResult> {
|
|
if ((config as any).__skipFixtureNavigation) {
|
|
throw new Error(
|
|
'__skipFixtureNavigation is not allowed in auto-navigation path',
|
|
);
|
|
}
|
|
return adapter.executeStep(StepId.create(step), config);
|
|
}
|
|
|
|
async function executeStepWithFixtureMismatch(
|
|
step: number,
|
|
config: Record<string, unknown>,
|
|
): Promise<AutomationResult> {
|
|
return adapter.executeStep(StepId.create(step), {
|
|
...config,
|
|
__skipFixtureNavigation: true,
|
|
});
|
|
}
|
|
|
|
async function executeStep(
|
|
step: number,
|
|
config: Record<string, unknown>,
|
|
): Promise<AutomationResult> {
|
|
return executeStepWithFixtureMismatch(step, config);
|
|
}
|
|
|
|
async function dispose(): Promise<void> {
|
|
await adapter.disconnect();
|
|
await server.stop();
|
|
}
|
|
|
|
return {
|
|
server,
|
|
adapter,
|
|
baseUrl: url,
|
|
getFixtureUrl: (step) => server.getFixtureUrl(step),
|
|
navigateToFixtureStep,
|
|
executeStep,
|
|
executeStepWithAutoNavigation,
|
|
executeStepWithFixtureMismatch,
|
|
dispose,
|
|
};
|
|
} |