fix(trace viewer): make red dot to the center of the target element (#26825)
Also make sure red dot is visible in the popout tab. Fixes #24532.
This commit is contained in:
parent
fa286de0b3
commit
f3c02a5b4f
|
|
@ -197,6 +197,7 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
|
||||||
function applyPlaywrightAttributes(unwrapPopoutUrl: (url: string) => string, ...targetIds: (string | undefined)[]) {
|
function applyPlaywrightAttributes(unwrapPopoutUrl: (url: string) => string, ...targetIds: (string | undefined)[]) {
|
||||||
const scrollTops: Element[] = [];
|
const scrollTops: Element[] = [];
|
||||||
const scrollLefts: Element[] = [];
|
const scrollLefts: Element[] = [];
|
||||||
|
const targetElements: Element[] = [];
|
||||||
|
|
||||||
const visit = (root: Document | ShadowRoot) => {
|
const visit = (root: Document | ShadowRoot) => {
|
||||||
// Collect all scrolled elements for later use.
|
// Collect all scrolled elements for later use.
|
||||||
|
|
@ -223,6 +224,7 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
|
||||||
const style = (target as HTMLElement).style;
|
const style = (target as HTMLElement).style;
|
||||||
style.outline = '2px solid #006ab1';
|
style.outline = '2px solid #006ab1';
|
||||||
style.backgroundColor = '#6fa8dc7f';
|
style.backgroundColor = '#6fa8dc7f';
|
||||||
|
targetElements.push(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,10 +233,8 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
|
||||||
if (!src) {
|
if (!src) {
|
||||||
iframe.setAttribute('src', 'data:text/html,<body style="background: #ddd"></body>');
|
iframe.setAttribute('src', 'data:text/html,<body style="background: #ddd"></body>');
|
||||||
} else {
|
} else {
|
||||||
// Append query parameters to inherit ?name= or ?time= values from parent.
|
// Retain query parameters to inherit name=, time=, showPoint= and other values from parent.
|
||||||
const url = new URL(unwrapPopoutUrl(window.location.href));
|
const url = new URL(unwrapPopoutUrl(window.location.href));
|
||||||
url.searchParams.delete('pointX');
|
|
||||||
url.searchParams.delete('pointY');
|
|
||||||
// We can be loading iframe from within iframe, reset base to be absolute.
|
// We can be loading iframe from within iframe, reset base to be absolute.
|
||||||
const index = url.pathname.lastIndexOf('/snapshot/');
|
const index = url.pathname.lastIndexOf('/snapshot/');
|
||||||
if (index !== -1)
|
if (index !== -1)
|
||||||
|
|
@ -284,23 +284,25 @@ function snapshotScript(...targetIds: (string | undefined)[]) {
|
||||||
element.removeAttribute('__playwright_scroll_left_');
|
element.removeAttribute('__playwright_scroll_left_');
|
||||||
}
|
}
|
||||||
|
|
||||||
const search = new URL(window.location.href).searchParams;
|
|
||||||
const pointX = search.get('pointX');
|
|
||||||
const pointY = search.get('pointY');
|
|
||||||
if (pointX) {
|
|
||||||
const pointElement = document.createElement('x-pw-pointer');
|
|
||||||
pointElement.style.position = 'fixed';
|
|
||||||
pointElement.style.backgroundColor = '#f44336';
|
|
||||||
pointElement.style.width = '20px';
|
|
||||||
pointElement.style.height = '20px';
|
|
||||||
pointElement.style.borderRadius = '10px';
|
|
||||||
pointElement.style.margin = '-10px 0 0 -10px';
|
|
||||||
pointElement.style.zIndex = '2147483647';
|
|
||||||
pointElement.style.left = pointX + 'px';
|
|
||||||
pointElement.style.top = pointY + 'px';
|
|
||||||
document.documentElement.appendChild(pointElement);
|
|
||||||
}
|
|
||||||
document.styleSheets[0].disabled = true;
|
document.styleSheets[0].disabled = true;
|
||||||
|
|
||||||
|
const search = new URL(window.location.href).searchParams;
|
||||||
|
if (search.get('showPoint')) {
|
||||||
|
for (const target of targetElements) {
|
||||||
|
const pointElement = document.createElement('x-pw-pointer');
|
||||||
|
pointElement.style.position = 'fixed';
|
||||||
|
pointElement.style.backgroundColor = '#f44336';
|
||||||
|
pointElement.style.width = '20px';
|
||||||
|
pointElement.style.height = '20px';
|
||||||
|
pointElement.style.borderRadius = '10px';
|
||||||
|
pointElement.style.margin = '-10px 0 0 -10px';
|
||||||
|
pointElement.style.zIndex = '2147483647';
|
||||||
|
const box = target.getBoundingClientRect();
|
||||||
|
pointElement.style.left = (box.left + box.width / 2) + 'px';
|
||||||
|
pointElement.style.top = (box.top + box.height / 2) + 'px';
|
||||||
|
document.documentElement.appendChild(pointElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDOMContentLoaded = () => visit(document);
|
const onDOMContentLoaded = () => visit(document);
|
||||||
|
|
|
||||||
|
|
@ -42,23 +42,24 @@ export const SnapshotTab: React.FunctionComponent<{
|
||||||
const [measure, ref] = useMeasure<HTMLDivElement>();
|
const [measure, ref] = useMeasure<HTMLDivElement>();
|
||||||
const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action');
|
const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action');
|
||||||
|
|
||||||
|
type Snapshot = { action: ActionTraceEvent, snapshotName: string, showPoint?: boolean };
|
||||||
const { snapshots } = React.useMemo(() => {
|
const { snapshots } = React.useMemo(() => {
|
||||||
if (!action)
|
if (!action)
|
||||||
return { snapshots: {} };
|
return { snapshots: {} };
|
||||||
|
|
||||||
// if the action has no beforeSnapshot, use the last available afterSnapshot.
|
// if the action has no beforeSnapshot, use the last available afterSnapshot.
|
||||||
let beforeSnapshot = action.beforeSnapshot ? { action, snapshotName: action.beforeSnapshot } : undefined;
|
let beforeSnapshot: Snapshot | undefined = action.beforeSnapshot ? { action, snapshotName: action.beforeSnapshot } : undefined;
|
||||||
let a = action;
|
let a = action;
|
||||||
while (!beforeSnapshot && a) {
|
while (!beforeSnapshot && a) {
|
||||||
a = prevInList(a);
|
a = prevInList(a);
|
||||||
beforeSnapshot = a?.afterSnapshot ? { action: a, snapshotName: a?.afterSnapshot } : undefined;
|
beforeSnapshot = a?.afterSnapshot ? { action: a, snapshotName: a?.afterSnapshot } : undefined;
|
||||||
}
|
}
|
||||||
const afterSnapshot = action.afterSnapshot ? { action, snapshotName: action.afterSnapshot } : beforeSnapshot;
|
const afterSnapshot: Snapshot | undefined = action.afterSnapshot ? { action, snapshotName: action.afterSnapshot } : beforeSnapshot;
|
||||||
const actionSnapshot = action.inputSnapshot ? { action, snapshotName: action.inputSnapshot } : afterSnapshot;
|
const actionSnapshot: Snapshot | undefined = action.inputSnapshot ? { action, snapshotName: action.inputSnapshot, showPoint: !!action.point } : afterSnapshot;
|
||||||
return { snapshots: { action: actionSnapshot, before: beforeSnapshot, after: afterSnapshot } };
|
return { snapshots: { action: actionSnapshot, before: beforeSnapshot, after: afterSnapshot } };
|
||||||
}, [action]);
|
}, [action]);
|
||||||
|
|
||||||
const { snapshotInfoUrl, snapshotUrl, pointX, pointY, popoutUrl } = React.useMemo(() => {
|
const { snapshotInfoUrl, snapshotUrl, popoutUrl } = React.useMemo(() => {
|
||||||
const snapshot = snapshots[snapshotTab];
|
const snapshot = snapshots[snapshotTab];
|
||||||
if (!snapshot)
|
if (!snapshot)
|
||||||
return { snapshotUrl: kBlankSnapshotUrl };
|
return { snapshotUrl: kBlankSnapshotUrl };
|
||||||
|
|
@ -66,16 +67,18 @@ export const SnapshotTab: React.FunctionComponent<{
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.set('trace', context(snapshot.action).traceUrl);
|
params.set('trace', context(snapshot.action).traceUrl);
|
||||||
params.set('name', snapshot.snapshotName);
|
params.set('name', snapshot.snapshotName);
|
||||||
|
if (snapshot.showPoint)
|
||||||
|
params.set('showPoint', '1');
|
||||||
const snapshotUrl = new URL(`snapshot/${snapshot.action.pageId}?${params.toString()}`, window.location.href).toString();
|
const snapshotUrl = new URL(`snapshot/${snapshot.action.pageId}?${params.toString()}`, window.location.href).toString();
|
||||||
const snapshotInfoUrl = new URL(`snapshotInfo/${snapshot.action.pageId}?${params.toString()}`, window.location.href).toString();
|
const snapshotInfoUrl = new URL(`snapshotInfo/${snapshot.action.pageId}?${params.toString()}`, window.location.href).toString();
|
||||||
|
|
||||||
const pointX = snapshotTab === 'action' ? snapshot.action.point?.x : undefined;
|
|
||||||
const pointY = snapshotTab === 'action' ? snapshot.action.point?.y : undefined;
|
|
||||||
const popoutParams = new URLSearchParams();
|
const popoutParams = new URLSearchParams();
|
||||||
popoutParams.set('r', snapshotUrl);
|
popoutParams.set('r', snapshotUrl);
|
||||||
popoutParams.set('trace', context(snapshot.action).traceUrl);
|
popoutParams.set('trace', context(snapshot.action).traceUrl);
|
||||||
|
if (snapshot.showPoint)
|
||||||
|
popoutParams.set('showPoint', '1');
|
||||||
const popoutUrl = new URL(`snapshot.html?${popoutParams.toString()}`, window.location.href).toString();
|
const popoutUrl = new URL(`snapshot.html?${popoutParams.toString()}`, window.location.href).toString();
|
||||||
return { snapshots, snapshotInfoUrl, snapshotUrl, pointX, pointY, popoutUrl };
|
return { snapshots, snapshotInfoUrl, snapshotUrl, popoutUrl };
|
||||||
}, [snapshots, snapshotTab]);
|
}, [snapshots, snapshotTab]);
|
||||||
|
|
||||||
const iframeRef0 = React.useRef<HTMLIFrameElement>(null);
|
const iframeRef0 = React.useRef<HTMLIFrameElement>(null);
|
||||||
|
|
@ -111,12 +114,11 @@ export const SnapshotTab: React.FunctionComponent<{
|
||||||
iframe.addEventListener('load', loadedCallback);
|
iframe.addEventListener('load', loadedCallback);
|
||||||
iframe.addEventListener('error', loadedCallback);
|
iframe.addEventListener('error', loadedCallback);
|
||||||
|
|
||||||
const newUrl = snapshotUrl + (pointX === undefined ? '' : `&pointX=${pointX}&pointY=${pointY}`);
|
|
||||||
// Try preventing history entry from being created.
|
// Try preventing history entry from being created.
|
||||||
if (iframe.contentWindow)
|
if (iframe.contentWindow)
|
||||||
iframe.contentWindow.location.replace(newUrl);
|
iframe.contentWindow.location.replace(snapshotUrl);
|
||||||
else
|
else
|
||||||
iframe.src = newUrl;
|
iframe.src = snapshotUrl;
|
||||||
|
|
||||||
await loadedPromise;
|
await loadedPromise;
|
||||||
} catch {
|
} catch {
|
||||||
|
|
@ -132,7 +134,7 @@ export const SnapshotTab: React.FunctionComponent<{
|
||||||
loadingRef.current.visibleIframe = newVisibleIframe;
|
loadingRef.current.visibleIframe = newVisibleIframe;
|
||||||
setSnapshotInfo(newSnapshotInfo);
|
setSnapshotInfo(newSnapshotInfo);
|
||||||
})();
|
})();
|
||||||
}, [snapshotUrl, snapshotInfoUrl, pointX, pointY]);
|
}, [snapshotUrl, snapshotInfoUrl]);
|
||||||
|
|
||||||
const windowHeaderHeight = 40;
|
const windowHeaderHeight = 40;
|
||||||
const snapshotContainerSize = {
|
const snapshotContainerSize = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue