fix(ui-mode): use server side path separator (#32523)

Fixes https://github.com/microsoft/playwright/issues/32323
This commit is contained in:
Max Schmitt 2024-09-09 22:07:28 +02:00 committed by GitHub
parent 363e79ee87
commit 4b5422a3c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 16 additions and 8 deletions

View file

@ -109,6 +109,8 @@ export async function startTraceViewerServer(options?: TraceViewerServerOptions)
export async function installRootRedirect(server: HttpServer, traceUrls: string[], options: TraceViewerRedirectOptions) { export async function installRootRedirect(server: HttpServer, traceUrls: string[], options: TraceViewerRedirectOptions) {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (path.sep !== path.posix.sep)
params.set('pathSeparator', path.sep);
for (const traceUrl of traceUrls) for (const traceUrl of traceUrls)
params.append('trace', traceUrl); params.append('trace', traceUrl);
if (server.wsGuid()) if (server.wsGuid())

View file

@ -31,7 +31,8 @@ export const TraceView: React.FC<{
rootDir?: string, rootDir?: string,
onOpenExternally?: (location: SourceLocation) => void, onOpenExternally?: (location: SourceLocation) => void,
revealSource?: boolean, revealSource?: boolean,
}> = ({ item, rootDir, onOpenExternally, revealSource }) => { pathSeparator: string,
}> = ({ item, rootDir, onOpenExternally, revealSource, pathSeparator }) => {
const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>(); const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>();
const [counter, setCounter] = React.useState(0); const [counter, setCounter] = React.useState(0);
const pollTimer = React.useRef<NodeJS.Timeout | null>(null); const pollTimer = React.useRef<NodeJS.Timeout | null>(null);
@ -69,7 +70,12 @@ export const TraceView: React.FC<{
return; return;
} }
const traceLocation = `${outputDir}/${artifactsFolderName(result!.workerIndex)}/traces/${item.testCase?.id}.json`; const traceLocation = [
outputDir,
artifactsFolderName(result!.workerIndex),
'traces',
`${item.testCase?.id}.json`
].join(pathSeparator);
// Start polling running test. // Start polling running test.
pollTimer.current = setTimeout(async () => { pollTimer.current = setTimeout(async () => {
try { try {

View file

@ -38,8 +38,6 @@ import { TestListView } from './uiModeTestListView';
import { TraceView } from './uiModeTraceView'; import { TraceView } from './uiModeTraceView';
import { SettingsView } from './settingsView'; import { SettingsView } from './settingsView';
const pathSeparator = navigator.userAgent.toLowerCase().includes('windows') ? '\\' : '/';
let xtermSize = { cols: 80, rows: 24 }; let xtermSize = { cols: 80, rows: 24 };
const xtermDataSource: XtermDataSource = { const xtermDataSource: XtermDataSource = {
pending: [], pending: [],
@ -63,6 +61,7 @@ const queryParams = {
outputDir: searchParams.get('outputDir') || undefined, outputDir: searchParams.get('outputDir') || undefined,
updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined, updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined,
reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined, reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined,
pathSeparator: searchParams.get('pathSeparator') || '/',
}; };
if (queryParams.updateSnapshots && !['all', 'none', 'missing'].includes(queryParams.updateSnapshots)) if (queryParams.updateSnapshots && !['all', 'none', 'missing'].includes(queryParams.updateSnapshots))
queryParams.updateSnapshots = undefined; queryParams.updateSnapshots = undefined;
@ -170,7 +169,7 @@ export const UIModeView: React.FC<{}> = ({
onError: error => { onError: error => {
xtermDataSource.write((error.stack || error.value || '') + '\n'); xtermDataSource.write((error.stack || error.value || '') + '\n');
}, },
pathSeparator, pathSeparator: queryParams.pathSeparator,
}); });
setTeleSuiteUpdater(teleSuiteUpdater); setTeleSuiteUpdater(teleSuiteUpdater);
@ -242,8 +241,8 @@ export const UIModeView: React.FC<{}> = ({
// Test tree is built from the model and filters. // Test tree is built from the model and filters.
const { testTree } = React.useMemo(() => { const { testTree } = React.useMemo(() => {
if (!testModel) if (!testModel)
return { testTree: new TestTree('', new TeleSuite('', 'root'), [], projectFilters, pathSeparator) }; return { testTree: new TestTree('', new TeleSuite('', 'root'), [], projectFilters, queryParams.pathSeparator) };
const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, pathSeparator); const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator);
testTree.filterTree(filterText, statusFilters, isRunningTest ? runningState?.testIds : undefined); testTree.filterTree(filterText, statusFilters, isRunningTest ? runningState?.testIds : undefined);
testTree.sortAndPropagateStatus(); testTree.sortAndPropagateStatus();
testTree.shortenRoot(); testTree.shortenRoot();
@ -332,7 +331,7 @@ export const UIModeView: React.FC<{}> = ({
// run affected watched tests // run affected watched tests
const testModel = teleSuiteUpdater.asModel(); const testModel = teleSuiteUpdater.asModel();
const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, pathSeparator); const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator);
const testIds: string[] = []; const testIds: string[] = [];
const set = new Set(params.testFiles); const set = new Set(params.testFiles);
@ -435,6 +434,7 @@ export const UIModeView: React.FC<{}> = ({
</div> </div>
<div className={clsx('vbox', isShowingOutput && 'hidden')}> <div className={clsx('vbox', isShowingOutput && 'hidden')}>
<TraceView <TraceView
pathSeparator={queryParams.pathSeparator}
item={selectedItem} item={selectedItem}
rootDir={testModel?.config?.rootDir} rootDir={testModel?.config?.rootDir}
revealSource={revealSource} revealSource={revealSource}