chore(trace): improve loading progress bar (#22201)

Fixes: https://github.com/microsoft/playwright/issues/22118
This commit is contained in:
Pavel Feldman 2023-04-05 13:03:25 -07:00 committed by GitHub
parent bc1de5f28d
commit 0d31d69d65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 9 deletions

View file

@ -26,6 +26,18 @@ import { SnapshotStorage } from './snapshotStorage';
const zipjs = zipImport as typeof zip;
type Progress = (done: number, total: number) => void;
const splitProgress = (progress: Progress, weights: number[]): Progress[] => {
const doneList = new Array(weights.length).fill(0);
return new Array(weights.length).fill(0).map((_, i) => {
return (done: number, total: number) => {
doneList[i] = done / total * weights[i] * 1000;
progress(doneList.reduce((a, b) => a + b, 0), 1000);
};
});
};
export class TraceModel {
contextEntries: ContextEntry[] = [];
pageEntries = new Map<string, PageEntry>();
@ -38,7 +50,9 @@ export class TraceModel {
async load(traceURL: string, progress: (done: number, total: number) => void) {
const isLive = traceURL.endsWith('json');
this._backend = isLive ? new FetchTraceModelBackend(traceURL) : new ZipTraceModelBackend(traceURL, progress);
// Allow 10% to hop from sw to page.
const [fetchProgress, unzipProgress] = splitProgress(progress, [0.5, 0.4, 0.1]);
this._backend = isLive ? new FetchTraceModelBackend(traceURL) : new ZipTraceModelBackend(traceURL, fetchProgress);
const ordinals: string[] = [];
let hasSource = false;
@ -54,6 +68,9 @@ export class TraceModel {
this._snapshotStorage = new SnapshotStorage();
// 3 * ordinals progress increments below.
const total = ordinals.length * 3;
let done = 0;
for (const ordinal of ordinals) {
const contextEntry = createEmptyContext();
const actionMap = new Map<string, trace.ActionTraceEvent>();
@ -63,10 +80,12 @@ export class TraceModel {
const trace = await this._backend.readText(ordinal + 'trace.trace') || '';
for (const line of trace.split('\n'))
this.appendEvent(contextEntry, actionMap, line);
unzipProgress(++done, total);
const network = await this._backend.readText(ordinal + 'trace.network') || '';
for (const line of network.split('\n'))
this.appendEvent(contextEntry, actionMap, line);
unzipProgress(++done, total);
contextEntry.actions = [...actionMap.values()].sort((a1, a2) => a1.startTime - a2.startTime);
if (!isLive) {
@ -82,6 +101,7 @@ export class TraceModel {
for (const action of contextEntry.actions)
action.stack = action.stack || callMetadata.get(action.callId);
}
unzipProgress(++done, total);
this.contextEntries.push(contextEntry);
}

View file

@ -90,6 +90,8 @@ function renderProperty(property: Property, key: string) {
function propertyToString(event: ActionTraceEvent, name: string, value: any, sdkLanguage: Language | undefined): Property {
const isEval = event.method.includes('eval') || event.method === 'waitForFunction';
if (name === 'files')
return { text: '<files>', type: 'string', name };
if (name === 'eventInit' || name === 'expectedValue' || (name === 'arg' && isEval))
value = parseSerializedValue(value.value, new Array(10).fill({ handle: '<handle>' }));
if ((name === 'value' && isEval) || (name === 'received' && event.method === 'expect'))
@ -101,7 +103,7 @@ function propertyToString(event: ActionTraceEvent, name: string, value: any, sdk
return { text: String(value), type, name };
if (value.guid)
return { text: '<handle>', type: 'handle', name };
return { text: JSON.stringify(value), type: 'object', name };
return { text: JSON.stringify(value).slice(0, 1000), type: 'object', name };
}
function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {

View file

@ -59,15 +59,14 @@
}
.progress {
position: relative;
margin: auto;
width: 400px;
height: 10px;
border: 1px solid #aaa;
width: 100%;
height: 3px;
margin-top: -3px;
z-index: 10;
}
.inner-progress {
background-color: #aaa;
background-color: var(--vscode-progressBar-background);
height: 100%;
}

View file

@ -125,10 +125,10 @@ export const WorkbenchLoader: React.FunctionComponent<{
<div className='spacer'></div>
<ToolbarButton icon='color-mode' title='Toggle color mode' toggled={false} onClick={() => toggleTheme()}></ToolbarButton>
</div>
<Workbench model={model} />
{!!progress.total && <div className='progress'>
<div className='inner-progress' style={{ width: (100 * progress.done / progress.total) + '%' }}></div>
</div>}
<Workbench model={model} />
{fileForLocalModeError && <div className='drop-target'>
<div>Trace Viewer uses Service Workers to show traces. To view trace:</div>
<div style={{ paddingTop: 20 }}>