mirror of
https://github.com/microsoft/playwright.git
synced 2024-09-11 20:37:54 +03:00
feat(ui-mode): add annotations tab (#31945)
<img width="867" alt="image" src="https://github.com/user-attachments/assets/7d714723-1d3f-49b2-944a-0a476d79aee8"> --------- Signed-off-by: Dmitry Gozman <dgozman@gmail.com> Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
This commit is contained in:
parent
6af2635343
commit
47714d6559
@ -20,7 +20,7 @@ import * as icons from './icons';
|
||||
import { TreeItem } from './treeItem';
|
||||
import { CopyToClipboard } from './copyToClipboard';
|
||||
import './links.css';
|
||||
import { linkifyText } from './renderUtils';
|
||||
import { linkifyText } from '@web/renderUtils';
|
||||
import { clsx } from '@web/uiUtils';
|
||||
|
||||
export function navigate(href: string) {
|
||||
|
@ -23,7 +23,7 @@ import { ProjectLink } from './links';
|
||||
import { statusIcon } from './statusIcon';
|
||||
import './testCaseView.css';
|
||||
import { TestResultView } from './testResultView';
|
||||
import { linkifyText } from './renderUtils';
|
||||
import { linkifyText } from '@web/renderUtils';
|
||||
import { hashStringToInt, msToString } from './utils';
|
||||
import { clsx } from '@web/uiUtils';
|
||||
|
||||
|
28
packages/trace-viewer/src/ui/annotationsTab.css
Normal file
28
packages/trace-viewer/src/ui/annotationsTab.css
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.annotations-tab {
|
||||
flex: auto;
|
||||
line-height: 24px;
|
||||
white-space: pre;
|
||||
overflow: auto;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.annotation-item {
|
||||
margin: 4px 8px;
|
||||
text-wrap: wrap;
|
||||
}
|
39
packages/trace-viewer/src/ui/annotationsTab.tsx
Normal file
39
packages/trace-viewer/src/ui/annotationsTab.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import './annotationsTab.css';
|
||||
import { PlaceholderPanel } from './placeholderPanel';
|
||||
import { linkifyText } from '@web/renderUtils';
|
||||
|
||||
type Annotation = { type: string; description?: string; };
|
||||
|
||||
export const AnnotationsTab: React.FunctionComponent<{
|
||||
annotations: Annotation[],
|
||||
}> = ({ annotations }) => {
|
||||
|
||||
if (!annotations.length)
|
||||
return <PlaceholderPanel text='No annotations' />;
|
||||
|
||||
return <div className='annotations-tab'>
|
||||
{annotations.map((annotation, i) => {
|
||||
return <div className='annotation-item' key={`annotation-${i}`}>
|
||||
<span style={{ fontWeight: 'bold' }}>{annotation.type}</span>
|
||||
{annotation.description && <span>: {linkifyText(annotation.description)}</span>}
|
||||
</div>;
|
||||
})}
|
||||
</div>;
|
||||
};
|
@ -97,6 +97,7 @@ export const TraceView: React.FC<{
|
||||
fallbackLocation={item.testFile}
|
||||
isLive={model?.isLive}
|
||||
status={item.treeItem?.status}
|
||||
annotations={item.testCase?.annotations || []}
|
||||
onOpenExternally={onOpenExternally}
|
||||
revealSource={revealSource}
|
||||
/>;
|
||||
|
@ -33,6 +33,7 @@ import type { TabbedPaneTabModel } from '@web/components/tabbedPane';
|
||||
import { Timeline } from './timeline';
|
||||
import { MetadataView } from './metadataView';
|
||||
import { AttachmentsTab } from './attachmentsTab';
|
||||
import { AnnotationsTab } from './annotationsTab';
|
||||
import type { Boundaries } from '../geometry';
|
||||
import { InspectorTab } from './inspectorTab';
|
||||
import { ToolbarButton } from '@web/components/toolbarButton';
|
||||
@ -52,12 +53,13 @@ export const Workbench: React.FunctionComponent<{
|
||||
onSelectionChanged?: (action: ActionTraceEventInContext) => void,
|
||||
isLive?: boolean,
|
||||
status?: UITestStatus,
|
||||
annotations?: { type: string; description?: string; }[];
|
||||
inert?: boolean,
|
||||
openPage?: (url: string, target?: string) => Window | any,
|
||||
onOpenExternally?: (location: modelUtil.SourceLocation) => void,
|
||||
revealSource?: boolean,
|
||||
showSettings?: boolean,
|
||||
}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status, inert, openPage, onOpenExternally, revealSource, showSettings }) => {
|
||||
}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status, annotations, inert, openPage, onOpenExternally, revealSource, showSettings }) => {
|
||||
const [selectedAction, setSelectedActionImpl] = React.useState<ActionTraceEventInContext | undefined>(undefined);
|
||||
const [revealedStack, setRevealedStack] = React.useState<StackFrame[] | undefined>(undefined);
|
||||
const [highlightedAction, setHighlightedAction] = React.useState<ActionTraceEventInContext | undefined>();
|
||||
@ -223,6 +225,17 @@ export const Workbench: React.FunctionComponent<{
|
||||
sourceTab,
|
||||
attachmentsTab,
|
||||
];
|
||||
|
||||
if (annotations !== undefined) {
|
||||
const annotationsTab: TabbedPaneTabModel = {
|
||||
id: 'annotations',
|
||||
title: 'Annotations',
|
||||
count: annotations.length,
|
||||
render: () => <AnnotationsTab annotations={annotations} />
|
||||
};
|
||||
tabs.push(annotationsTab);
|
||||
}
|
||||
|
||||
if (showSourcesFirst) {
|
||||
const sourceTabIndex = tabs.indexOf(sourceTab);
|
||||
tabs.splice(sourceTabIndex, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user