Select a file to debug manually in a custom browser not controlled by Web Test Runner.
Advanced functionalities such commands for changing viewport and screenshots don't work here.
Use the regular debug option to debug in a controlled browser.
Test files
${listItems}
`;
}
function getInjectIndex(html: string) {
const headIndex = html.indexOf('');
if (headIndex !== -1) return ''.length + headIndex;
const bodyIndex = html.indexOf('');
if (bodyIndex !== -1) return ''.length + bodyIndex;
return 0;
}
function injectRuntime(
html: string,
config: Record,
browserLogs: boolean,
preloadedModule?: string,
) {
const preloadLink = preloadedModule
? ``
: '';
const configScript = ``;
const injectedHtml = `${preloadLink}${browserLogs ? `${trackBrowserLogs}` : ''}${configScript}`;
const injectLocation = getInjectIndex(html);
return `${html.substring(0, injectLocation)}${injectedHtml}${html.substring(injectLocation)}`;
}
function createTestRunnerHtml(
testFrameworkImport: string,
config: TestRunnerCoreConfig,
groupConfig?: TestRunnerGroupConfig,
) {
let body: string;
if (groupConfig?.testRunnerHtml) {
// there is a group in scope, regular test or debug
body = groupConfig.testRunnerHtml(testFrameworkImport, config, groupConfig);
} else if (config.testRunnerHtml) {
// there is no group in scope, ex. when manually debugging
body = config.testRunnerHtml(testFrameworkImport, config);
} else {
// no user defined test runner HTML
body = ``;
}
return { body, type: 'html' };
}
export function serveTestRunnerHtmlPlugin(
config: TestRunnerCoreConfig,
testFiles: string[],
sessions: TestSessionManager,
testFrameworkImport?: string,
) {
return {
name: 'wtr-test-runner-html',
async serve(context: Context) {
if (!testFrameworkImport) {
throw new Error('Cannot test javascript files without a testFramework configured.');
}
if (context.path === '/') {
const { searchParams } = context.URL;
if (searchParams.has(PARAM_TEST_FILE)) {
return createTestRunnerHtml(testFrameworkImport, config);
}
const sessionId = searchParams.get(PARAM_SESSION_ID);
if (sessionId) {
const session = sessions.get(sessionId) ?? sessions.getDebug(sessionId);
if (!session) {
throw new Error(`Could not find session ${sessionId}`);
}
return createTestRunnerHtml(testFrameworkImport, config, session.group);
}
if (searchParams.get('mode') === 'iframe') {
return {
type: 'html',
body: iframeModePage,
};
}
return {
type: 'html',
body: await createManualDebugPage(config, context, testFiles),
};
}
},
async transform(context: Context) {
if (!context.response.is('html')) {
return;
}
const isTestRunnerHtml = context.path === '/';
if (
!isTestRunnerHtml &&
!testFiles.includes(getRequestFilePath(context.url, config.rootDir))
) {
return;
}
const { searchParams } = context.URL;
const sessionId = searchParams.get(PARAM_SESSION_ID);
if (sessionId) {
const session = sessions.get(sessionId) ?? sessions.getDebug(sessionId);
if (!session) {
throw new Error(`Could not find session ${sessionId}`);
}
const testFile = await createTestFileImportPath(
config,
context,
session.testFile,
sessionId,
);
const runtimeConfig = {
testFile,
watch: !!config.watch,
debug: session.debug,
testFrameworkConfig: config.testFramework?.config,
};
context.body = injectRuntime(
context.body as string,
runtimeConfig,
!!config.browserLogs,
isTestRunnerHtml ? testFile : undefined,
);
return;
}
const testFile = searchParams.get(PARAM_TEST_FILE);
if (testFile) {
const runtimeConfig = {
testFile,
watch: !!config.watch,
debug: true,
testFrameworkConfig: config.testFramework?.config,
};
context.body = injectRuntime(
context.body as string,
runtimeConfig,
!!config.browserLogs,
isTestRunnerHtml ? testFile : undefined,
)!;
return;
}
},
};
}