mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(ui/html): hide _ attachments (#35044)
Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
This commit is contained in:
parent
f3a75e2cfe
commit
1d9647b864
@ -72,7 +72,7 @@ export const TestResultView: React.FC<{
|
|||||||
result: TestResult,
|
result: TestResult,
|
||||||
}> = ({ test, result }) => {
|
}> = ({ test, result }) => {
|
||||||
const { screenshots, videos, traces, otherAttachments, diffs, errors, otherAttachmentAnchors, screenshotAnchors } = React.useMemo(() => {
|
const { screenshots, videos, traces, otherAttachments, diffs, errors, otherAttachmentAnchors, screenshotAnchors } = React.useMemo(() => {
|
||||||
const attachments = result.attachments;
|
const attachments = result.attachments.filter(a => !a.name.startsWith('_'));
|
||||||
const screenshots = new Set(attachments.filter(a => a.contentType.startsWith('image/')));
|
const screenshots = new Set(attachments.filter(a => a.contentType.startsWith('image/')));
|
||||||
const screenshotAnchors = [...screenshots].map(a => `attachment-${attachments.indexOf(a)}`);
|
const screenshotAnchors = [...screenshots].map(a => `attachment-${attachments.indexOf(a)}`);
|
||||||
const videos = attachments.filter(a => a.contentType.startsWith('video/'));
|
const videos = attachments.filter(a => a.contentType.startsWith('video/'));
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import './attachmentsTab.css';
|
import './attachmentsTab.css';
|
||||||
import { ImageDiffView } from '@web/shared/imageDiffView';
|
import { ImageDiffView } from '@web/shared/imageDiffView';
|
||||||
import type { MultiTraceModel } from './modelUtil';
|
import type { Attachment, MultiTraceModel } from './modelUtil';
|
||||||
import { PlaceholderPanel } from './placeholderPanel';
|
import { PlaceholderPanel } from './placeholderPanel';
|
||||||
import type { AfterActionTraceEventAttachment } from '@trace/trace';
|
import type { AfterActionTraceEventAttachment } from '@trace/trace';
|
||||||
import { CodeMirrorWrapper, lineHeight } from '@web/components/codeMirrorWrapper';
|
import { CodeMirrorWrapper, lineHeight } from '@web/components/codeMirrorWrapper';
|
||||||
@ -26,8 +26,6 @@ import { Expandable } from '@web/components/expandable';
|
|||||||
import { linkifyText } from '@web/renderUtils';
|
import { linkifyText } from '@web/renderUtils';
|
||||||
import { clsx, useFlash } from '@web/uiUtils';
|
import { clsx, useFlash } from '@web/uiUtils';
|
||||||
|
|
||||||
type Attachment = AfterActionTraceEventAttachment & { traceUrl: string };
|
|
||||||
|
|
||||||
type ExpandableAttachmentProps = {
|
type ExpandableAttachmentProps = {
|
||||||
attachment: Attachment;
|
attachment: Attachment;
|
||||||
reveal?: any;
|
reveal?: any;
|
||||||
@ -97,14 +95,8 @@ export const AttachmentsTab: React.FunctionComponent<{
|
|||||||
revealedAttachment?: [AfterActionTraceEventAttachment, number],
|
revealedAttachment?: [AfterActionTraceEventAttachment, number],
|
||||||
}> = ({ model, revealedAttachment }) => {
|
}> = ({ model, revealedAttachment }) => {
|
||||||
const { diffMap, screenshots, attachments } = React.useMemo(() => {
|
const { diffMap, screenshots, attachments } = React.useMemo(() => {
|
||||||
const attachments = new Set<Attachment>();
|
const attachments = new Set(model?.visibleAttachments ?? []);
|
||||||
const screenshots = new Set<Attachment>();
|
const screenshots = new Set<Attachment>();
|
||||||
|
|
||||||
for (const action of model?.actions || []) {
|
|
||||||
const traceUrl = action.context.traceUrl;
|
|
||||||
for (const attachment of action.attachments || [])
|
|
||||||
attachments.add({ ...attachment, traceUrl });
|
|
||||||
}
|
|
||||||
const diffMap = new Map<string, { expected: Attachment | undefined, actual: Attachment | undefined, diff: Attachment | undefined }>();
|
const diffMap = new Map<string, { expected: Attachment | undefined, actual: Attachment | undefined, diff: Attachment | undefined }>();
|
||||||
|
|
||||||
for (const attachment of attachments) {
|
for (const attachment of attachments) {
|
||||||
|
@ -57,6 +57,8 @@ export type ErrorDescription = {
|
|||||||
prompt?: trace.AfterActionTraceEventAttachment & { traceUrl: string };
|
prompt?: trace.AfterActionTraceEventAttachment & { traceUrl: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Attachment = trace.AfterActionTraceEventAttachment & { traceUrl: string };
|
||||||
|
|
||||||
export class MultiTraceModel {
|
export class MultiTraceModel {
|
||||||
readonly startTime: number;
|
readonly startTime: number;
|
||||||
readonly endTime: number;
|
readonly endTime: number;
|
||||||
@ -68,6 +70,8 @@ export class MultiTraceModel {
|
|||||||
readonly options: trace.BrowserContextEventOptions;
|
readonly options: trace.BrowserContextEventOptions;
|
||||||
readonly pages: PageEntry[];
|
readonly pages: PageEntry[];
|
||||||
readonly actions: ActionTraceEventInContext[];
|
readonly actions: ActionTraceEventInContext[];
|
||||||
|
readonly attachments: Attachment[];
|
||||||
|
readonly visibleAttachments: Attachment[];
|
||||||
readonly events: (trace.EventTraceEvent | trace.ConsoleMessageTraceEvent)[];
|
readonly events: (trace.EventTraceEvent | trace.ConsoleMessageTraceEvent)[];
|
||||||
readonly stdio: trace.StdioTraceEvent[];
|
readonly stdio: trace.StdioTraceEvent[];
|
||||||
readonly errors: trace.ErrorTraceEvent[];
|
readonly errors: trace.ErrorTraceEvent[];
|
||||||
@ -103,6 +107,8 @@ export class MultiTraceModel {
|
|||||||
this.hasSource = contexts.some(c => c.hasSource);
|
this.hasSource = contexts.some(c => c.hasSource);
|
||||||
this.hasStepData = contexts.some(context => context.origin === 'testRunner');
|
this.hasStepData = contexts.some(context => context.origin === 'testRunner');
|
||||||
this.resources = [...contexts.map(c => c.resources)].flat();
|
this.resources = [...contexts.map(c => c.resources)].flat();
|
||||||
|
this.attachments = this.actions.flatMap(action => action.attachments?.map(attachment => ({ ...attachment, traceUrl: action.context.traceUrl })) ?? []);
|
||||||
|
this.visibleAttachments = this.attachments.filter(attachment => !attachment.name.startsWith('_'));
|
||||||
|
|
||||||
this.events.sort((a1, a2) => a1.time - a2.time);
|
this.events.sort((a1, a2) => a1.time - a2.time);
|
||||||
this.resources.sort((a1, a2) => a1._monotonicTime! - a2._monotonicTime!);
|
this.resources.sort((a1, a2) => a1._monotonicTime! - a2._monotonicTime!);
|
||||||
@ -130,18 +136,10 @@ export class MultiTraceModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _errorDescriptorsFromTestRunner(): ErrorDescription[] {
|
private _errorDescriptorsFromTestRunner(): ErrorDescription[] {
|
||||||
const errorPrompts: Record<string, trace.AfterActionTraceEventAttachment & { traceUrl: string }> = {};
|
|
||||||
for (const action of this.actions) {
|
|
||||||
for (const attachment of action.attachments ?? []) {
|
|
||||||
if (attachment.name.startsWith('_prompt-'))
|
|
||||||
errorPrompts[attachment.name] = { ...attachment, traceUrl: action.context.traceUrl };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.errors.filter(e => !!e.message).map((error, i) => ({
|
return this.errors.filter(e => !!e.message).map((error, i) => ({
|
||||||
stack: error.stack,
|
stack: error.stack,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
prompt: errorPrompts[`_prompt-${i}`],
|
prompt: this.attachments.find(a => a.name === `_prompt-${i}`),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,9 +163,6 @@ export const Workbench: React.FunctionComponent<{
|
|||||||
const consoleModel = useConsoleTabModel(model, selectedTime);
|
const consoleModel = useConsoleTabModel(model, selectedTime);
|
||||||
const networkModel = useNetworkTabModel(model, selectedTime);
|
const networkModel = useNetworkTabModel(model, selectedTime);
|
||||||
const errorsModel = useErrorsTabModel(model);
|
const errorsModel = useErrorsTabModel(model);
|
||||||
const attachments = React.useMemo(() => {
|
|
||||||
return model?.actions.map(a => a.attachments || []).flat() || [];
|
|
||||||
}, [model]);
|
|
||||||
|
|
||||||
const sdkLanguage = model?.sdkLanguage || 'javascript';
|
const sdkLanguage = model?.sdkLanguage || 'javascript';
|
||||||
|
|
||||||
@ -241,7 +238,7 @@ export const Workbench: React.FunctionComponent<{
|
|||||||
const attachmentsTab: TabbedPaneTabModel = {
|
const attachmentsTab: TabbedPaneTabModel = {
|
||||||
id: 'attachments',
|
id: 'attachments',
|
||||||
title: 'Attachments',
|
title: 'Attachments',
|
||||||
count: attachments.length,
|
count: model?.visibleAttachments.length,
|
||||||
render: () => <AttachmentsTab model={model} revealedAttachment={revealedAttachment} />
|
render: () => <AttachmentsTab model={model} revealedAttachment={revealedAttachment} />
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user