diff --git a/src/server/snapshot/snapshotterInjected.ts b/src/server/snapshot/snapshotterInjected.ts
index 2004c556f8..27db1ff823 100644
--- a/src/server/snapshot/snapshotterInjected.ts
+++ b/src/server/snapshot/snapshotterInjected.ts
@@ -443,8 +443,8 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
doctype: document.doctype ? document.doctype.name : undefined,
resourceOverrides: [],
viewport: {
- width: Math.max(document.body ? document.body.offsetWidth : 0, document.documentElement ? document.documentElement.offsetWidth : 0),
- height: Math.max(document.body ? document.body.offsetHeight : 0, document.documentElement ? document.documentElement.offsetHeight : 0),
+ width: window.innerWidth,
+ height: window.innerHeight,
},
url: location.href,
timestamp,
diff --git a/src/server/trace/recorder/tracing.ts b/src/server/trace/recorder/tracing.ts
index 60cd64e5eb..bd63f2374c 100644
--- a/src/server/trace/recorder/tracing.ts
+++ b/src/server/trace/recorder/tracing.ts
@@ -36,7 +36,7 @@ export type TracerOptions = {
screenshots?: boolean;
};
-export const VERSION = 1;
+export const VERSION = 2;
type RecordingState = {
options: TracerOptions,
diff --git a/src/server/trace/viewer/traceModel.ts b/src/server/trace/viewer/traceModel.ts
index 46c9397a9d..c259fe5433 100644
--- a/src/server/trace/viewer/traceModel.ts
+++ b/src/server/trace/viewer/traceModel.ts
@@ -38,7 +38,8 @@ export class TraceModel {
browserName: '',
options: { sdkLanguage: '' },
pages: [],
- resources: []
+ resources: [],
+ snapshotSizes: {},
};
}
@@ -98,6 +99,8 @@ export class TraceModel {
break;
case 'frame-snapshot':
this._snapshotStorage.addFrameSnapshot(event.snapshot);
+ if (event.snapshot.snapshotName && event.snapshot.isMainFrame)
+ this.contextEntry.snapshotSizes[event.snapshot.snapshotName] = event.snapshot.viewport;
break;
}
if (event.type === 'action' || event.type === 'event') {
@@ -123,6 +126,14 @@ export class TraceModel {
}
return event;
}
+
+ _modernize_1_to_2(event: any): any {
+ if (event.type === 'frame-snapshot' && event.snapshot.isMainFrame) {
+ // Old versions had completely wrong viewport.
+ event.snapshot.viewport = this.contextEntry.options.viewport || { width: 1280, height: 720 };
+ }
+ return event;
+ }
}
export type ContextEntry = {
@@ -132,18 +143,19 @@ export type ContextEntry = {
options: BrowserContextOptions;
pages: PageEntry[];
resources: ResourceSnapshot[];
+ snapshotSizes: { [snapshotName: string]: { width: number, height: number } };
};
export type PageEntry = {
actions: trace.ActionTraceEvent[];
events: trace.ActionTraceEvent[];
- objects: { [ket: string]: any };
+ objects: { [key: string]: any };
screencastFrames: {
sha1: string,
timestamp: number,
width: number,
height: number,
- }[]
+ }[];
};
export class PersistentSnapshotStorage extends BaseSnapshotStorage {
diff --git a/src/web/traceViewer/ui/callTab.tsx b/src/web/traceViewer/ui/callTab.tsx
index 5f0500816a..fb0fb14a19 100644
--- a/src/web/traceViewer/ui/callTab.tsx
+++ b/src/web/traceViewer/ui/callTab.tsx
@@ -39,12 +39,12 @@ export const CallTab: React.FunctionComponent<{
{action.metadata.apiName}
{ !!paramKeys.length && Parameters
}
{
- !!paramKeys.length && paramKeys.map(name => renderLine(action.metadata, name, params[name]))
+ !!paramKeys.length && paramKeys.map((name, index) => renderLine(action.metadata, name, params[name], 'param-' + index))
}
{ !!action.metadata.result && Return value
}
{
- !!action.metadata.result && Object.keys(action.metadata.result).map(name =>
- renderLine(action.metadata, name, action.metadata.result[name])
+ !!action.metadata.result && Object.keys(action.metadata.result).map((name, index) =>
+ renderLine(action.metadata, name, action.metadata.result[name], 'result-' + index)
)
}
Log
@@ -58,12 +58,12 @@ export const CallTab: React.FunctionComponent<{
;
};
-function renderLine(metadata: CallMetadata, name: string, value: any) {
+function renderLine(metadata: CallMetadata, name: string, value: any, key: string) {
const { title, type } = toString(metadata, name, value);
let text = trimRight(title.replace(/\n/g, '↵'), 80);
if (type === 'string')
text = `"${text}"`;
- return {name}: {text}
;
+ return {name}: {text}
;
}
function toString(metadata: CallMetadata, name: string, value: any): { title: string, type: string } {
diff --git a/src/web/traceViewer/ui/snapshotTab.tsx b/src/web/traceViewer/ui/snapshotTab.tsx
index 41943ed3f0..e911528a36 100644
--- a/src/web/traceViewer/ui/snapshotTab.tsx
+++ b/src/web/traceViewer/ui/snapshotTab.tsx
@@ -24,8 +24,9 @@ import { ActionTraceEvent } from '../../../server/trace/common/traceEvents';
export const SnapshotTab: React.FunctionComponent<{
action: ActionTraceEvent | undefined,
- snapshotSize: Size,
-}> = ({ action, snapshotSize }) => {
+ snapshotSizes: { [snapshotName: string]: Size },
+ defaultSnapshotSize: Size,
+}> = ({ action, snapshotSizes, defaultSnapshotSize }) => {
const [measure, ref] = useMeasure();
const [snapshotIndex, setSnapshotIndex] = React.useState(0);
@@ -61,6 +62,10 @@ export const SnapshotTab: React.FunctionComponent<{
}
}, [action, snapshotIndex, iframeRef, snapshots]);
+ let snapshotSize = defaultSnapshotSize;
+ if (snapshots[snapshotIndex] && snapshots[snapshotIndex].snapshotName)
+ snapshotSize = snapshotSizes[snapshots[snapshotIndex].snapshotName] || defaultSnapshotSize;
+
const scale = Math.min(measure.width / snapshotSize.width, measure.height / snapshotSize.height);
const scaledSize = {
width: snapshotSize.width * scale,
diff --git a/src/web/traceViewer/ui/workbench.tsx b/src/web/traceViewer/ui/workbench.tsx
index 46b6293f8d..69b61b9ad1 100644
--- a/src/web/traceViewer/ui/workbench.tsx
+++ b/src/web/traceViewer/ui/workbench.tsx
@@ -54,7 +54,7 @@ export const Workbench: React.FunctionComponent<{
return actions;
}, [context]);
- const snapshotSize = context.options.viewport || { width: 1280, height: 720 };
+ const defaultSnapshotSize = context.options.viewport || { width: 1280, height: 720 };
const boundaries = { minimum: context.startTime, maximum: context.endTime };
// Leave some nice free space on the right hand side.
@@ -89,7 +89,7 @@ export const Workbench: React.FunctionComponent<{
-
+
},
{ id: 'console', title: 'Console', count: consoleCount, render: () => },
@@ -124,5 +124,6 @@ const emptyContext: ContextEntry = {
_debugName: '',
},
pages: [],
- resources: []
+ resources: [],
+ snapshotSizes: {},
};
diff --git a/tests/trace-viewer/trace-viewer.spec.ts b/tests/trace-viewer/trace-viewer.spec.ts
index b525713fd8..2615edfaaa 100644
--- a/tests/trace-viewer/trace-viewer.spec.ts
+++ b/tests/trace-viewer/trace-viewer.spec.ts
@@ -42,6 +42,9 @@ class TraceViewerPage {
await this.page.click(`.action-title:has-text("${title}")`);
}
+ async selectSnapshot(name: string) {
+ await this.page.click(`.snapshot-tab .tab-label:has-text("${name}")`);
+ }
async callLines() {
await this.page.waitForSelector('.call-line:visible');
@@ -74,6 +77,13 @@ class TraceViewerPage {
await this.page.waitForSelector('.console-stack:visible');
return await this.page.$$eval('.console-stack:visible', ee => ee.map(e => e.textContent));
}
+
+ async snapshotSize() {
+ return this.page.$eval('.snapshot-container', e => {
+ const style = window.getComputedStyle(e);
+ return { width: style.width, height: style.height };
+ });
+ }
}
const test = playwrightTest.extend<{ showTraceViewer: (trace: string) => Promise }>({
@@ -110,6 +120,7 @@ test.beforeAll(async ({ browser, browserName }, workerInfo) => {
page.waitForNavigation(),
page.waitForTimeout(200).then(() => page.goto('data:text/html,Hello world 2'))
]);
+ await page.setViewportSize({ width: 500, height: 600 });
await page.close();
traceFile = path.join(workerInfo.project.outputDir, browserName, 'trace.zip');
await context.tracing.stop({ path: traceFile });
@@ -129,6 +140,7 @@ test('should open simple trace viewer', async ({ showTraceViewer }) => {
'page.click\"Click\"',
'page.waitForNavigation',
'page.gotodata:text/html,Hello world 2',
+ 'page.setViewportSize',
]);
});
@@ -166,14 +178,14 @@ test('should open console errors on click', async ({ showTraceViewer, browserNam
test.fixme(browserName === 'firefox', 'Firefox generates stray console message for page error');
const traceViewer = await showTraceViewer(traceFile);
expect(await traceViewer.actionIconsText('page.evaluate')).toEqual(['2', '1']);
- expect(await traceViewer.page.isHidden('.console-tab'));
+ expect(await traceViewer.page.isHidden('.console-tab')).toBeTruthy();
await (await traceViewer.actionIcons('page.evaluate')).click();
- expect(await traceViewer.page.waitForSelector('.console-tab'));
+ expect(await traceViewer.page.waitForSelector('.console-tab')).toBeTruthy();
});
test('should show params and return value', async ({ showTraceViewer, browserName }) => {
const traceViewer = await showTraceViewer(traceFile);
- expect(await traceViewer.selectAction('page.evaluate'));
+ await traceViewer.selectAction('page.evaluate');
expect(await traceViewer.callLines()).toEqual([
'page.evaluate',
'expression: "({↵ a↵ }) => {↵ console.log(\'Info\');↵ console.warn(\'Warning\');↵ con…"',
@@ -182,3 +194,12 @@ test('should show params and return value', async ({ showTraceViewer, browserNam
'value: "return paramA"'
]);
});
+
+test('should have correct snapshot size', async ({ showTraceViewer }) => {
+ const traceViewer = await showTraceViewer(traceFile);
+ await traceViewer.selectAction('page.setViewport');
+ await traceViewer.selectSnapshot('Before');
+ expect(await traceViewer.snapshotSize()).toEqual({ width: '1280px', height: '720px' });
+ await traceViewer.selectSnapshot('After');
+ expect(await traceViewer.snapshotSize()).toEqual({ width: '500px', height: '600px' });
+});