diff --git a/packages/playwright-test/src/runner/uiMode.ts b/packages/playwright-test/src/runner/uiMode.ts index 693d5c5aad..28bf7187d7 100644 --- a/packages/playwright-test/src/runner/uiMode.ts +++ b/packages/playwright-test/src/runner/uiMode.ts @@ -51,7 +51,7 @@ class UIMode { for (const p of config.projects) p.retries = 0; config._internal.configCLIOverrides.use = config._internal.configCLIOverrides.use || {}; - config._internal.configCLIOverrides.use.trace = 'on'; + config._internal.configCLIOverrides.use.trace = { mode: 'on', sources: false }; this._originalStderr = process.stderr.write.bind(process.stderr); process.stdout.write = (chunk: string | Buffer) => { diff --git a/packages/trace-viewer/src/ui/sourceTab.tsx b/packages/trace-viewer/src/ui/sourceTab.tsx index cca9e06222..248dd2ebef 100644 --- a/packages/trace-viewer/src/ui/sourceTab.tsx +++ b/packages/trace-viewer/src/ui/sourceTab.tsx @@ -55,7 +55,14 @@ export const SourceTab: React.FunctionComponent<{ return ''; if (!stackInfo.fileContent.has(filePath)) { const sha1 = await calculateSha1(filePath); - stackInfo.fileContent.set(filePath, await fetch(`sha1/src@${sha1}.txt`).then(response => response.text()).catch(() => ``)); + try { + let response = await fetch(`sha1/src@${sha1}.txt`); + if (response.status === 404) + response = await fetch(`file?path=${filePath}`); + stackInfo.fileContent.set(filePath, await response.text()); + } catch { + stackInfo.fileContent.set(filePath, ``); + } } return stackInfo.fileContent.get(filePath)!; }, [stackInfo, selectedFrame], ''); diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index 8358896b69..6be206122d 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -36,12 +36,23 @@ export const Workbench: React.FunctionComponent<{ output?: React.ReactElement, rightToolbar?: React.ReactElement[], }> = ({ model, output, rightToolbar }) => { - const [selectedAction, setSelectedAction] = React.useState(); + const [selectedAction, setSelectedAction] = React.useState(undefined); const [highlightedAction, setHighlightedAction] = React.useState(); const [selectedNavigatorTab, setSelectedNavigatorTab] = React.useState('actions'); const [selectedPropertiesTab, setSelectedPropertiesTab] = React.useState(output ? 'output' : 'call'); const activeAction = model ? highlightedAction || selectedAction : undefined; + React.useEffect(() => { + if (selectedAction) + return; + const failedAction = model?.actions.find(a => a.error); + if (failedAction) + setSelectedAction(failedAction); + // In the UI mode, selecting the first error should reveal source. + if (output) + setSelectedPropertiesTab('source'); + }, [model, output, selectedAction, setSelectedAction, setSelectedPropertiesTab]); + const { errors, warnings } = activeAction ? modelUtil.stats(activeAction) : { errors: 0, warnings: 0 }; const consoleCount = errors + warnings; const networkCount = activeAction ? modelUtil.resourcesForAction(activeAction).length : 0;