Files
gridpilot.gg/tests/e2e/hosted-real/step-03-race-information.real.e2e.test.ts
2025-12-16 11:09:13 +01:00

162 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { promises as fs } from 'fs';
import path from 'path';
import { StepId } from '@gridpilot/automation/domain/value-objects/StepId';
import {
PlaywrightAutomationAdapter,
} from 'core/automation/infrastructure//automation';
import {
IRACING_SELECTORS,
IRACING_TIMEOUTS,
} from 'core/automation/infrastructure//automation/dom/IRacingSelectors';
import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter';
const shouldRun = process.env.HOSTED_REAL_E2E === '1';
const describeMaybe = shouldRun ? describe : describe.skip;
describeMaybe('Real-site hosted session Race Information step (members.iracing.com)', () => {
let adapter: PlaywrightAutomationAdapter;
beforeAll(async () => {
const logger = new PinoLogAdapter();
adapter = new PlaywrightAutomationAdapter(
{
headless: true,
timeout: IRACING_TIMEOUTS.navigation,
mode: 'real',
baseUrl: '',
userDataDir: '',
},
logger,
);
const result = await adapter.connect(false);
expect(result.success).toBe(true);
expect(adapter.isConnected()).toBe(true);
const step1Result = await adapter.executeStep(StepId.create(1), {});
expect(step1Result.success).toBe(true);
const step2Result = await adapter.executeStep(StepId.create(2), {});
expect(step2Result.success).toBe(true);
const page = adapter.getPage();
expect(page).not.toBeNull();
const createRaceButton = page!
.locator(IRACING_SELECTORS.hostedRacing.createRaceButton)
.first();
await expect(
createRaceButton.count(),
'Create Race button should exist on Hosted Racing page',
).resolves.toBeGreaterThan(0);
await createRaceButton.click({ timeout: IRACING_TIMEOUTS.elementWait });
const raceInfoContainer = page!
.locator(IRACING_SELECTORS.wizard.stepContainers.raceInformation)
.first();
await raceInfoContainer.waitFor({
state: 'attached',
timeout: IRACING_TIMEOUTS.elementWait,
});
expect(await raceInfoContainer.count()).toBeGreaterThan(0);
}, 300_000);
afterAll(async () => {
if (adapter) {
await adapter.disconnect();
}
});
it(
'shows Race Information sidebar text matching fixtures and keeps text inputs writable',
async () => {
const page = adapter.getPage();
expect(page).not.toBeNull();
const sidebarLink = page!
.locator(IRACING_SELECTORS.wizard.sidebarLinks.raceInformation)
.first();
await sidebarLink.waitFor({
state: 'attached',
timeout: IRACING_TIMEOUTS.elementWait,
});
const sidebarText = (await sidebarLink.innerText()).trim();
expect(sidebarText.length).toBeGreaterThan(0);
let fixtureSidebarText: string | null = null;
try {
const fixturePath = path.join(
process.cwd(),
'html-dumps-optimized',
'iracing-hosted-sessions',
'03-race-information.json',
);
const raw = await fs.readFile(fixturePath, 'utf8');
const items = JSON.parse(raw) as Array<{ i: string; t: string }>;
const sidebarItem =
items.find(
(i) =>
i.i === 'wizard-sidebar-link-set-session-information' &&
typeof i.t === 'string',
) ?? null;
if (sidebarItem) {
fixtureSidebarText = sidebarItem.t;
}
} catch {
fixtureSidebarText = null;
}
if (fixtureSidebarText) {
const expected = fixtureSidebarText.toLowerCase();
const actual = sidebarText.toLowerCase();
expect(
actual.includes('race') || actual.includes(expected.slice(0, 4)),
).toBe(true);
}
const config = {
sessionName: 'GridPilot Real Race Information',
password: 'real-site-secret',
description: 'Real-site Race Information writable fields check',
};
const result = await adapter.executeStep(StepId.create(3), config);
expect(result.success).toBe(true);
const sessionNameInput = page!
.locator(IRACING_SELECTORS.steps.sessionName)
.first();
const passwordInput = page!
.locator(IRACING_SELECTORS.steps.password)
.first();
const descriptionInput = page!
.locator(IRACING_SELECTORS.steps.description)
.first();
await sessionNameInput.waitFor({
state: 'attached',
timeout: IRACING_TIMEOUTS.elementWait,
});
await passwordInput.waitFor({
state: 'attached',
timeout: IRACING_TIMEOUTS.elementWait,
});
await descriptionInput.waitFor({
state: 'attached',
timeout: IRACING_TIMEOUTS.elementWait,
});
const sessionNameValue = await sessionNameInput.inputValue();
const passwordValue = await passwordInput.inputValue();
const descriptionValue = await descriptionInput.inputValue();
expect(sessionNameValue).toBe(config.sessionName);
expect(passwordValue).toBe(config.password);
expect(descriptionValue).toBe(config.description);
},
300_000,
);
});