feat(inspector): collapse completed items (#5484)

This commit is contained in:
Pavel Feldman 2021-02-17 17:28:02 -08:00 коммит произвёл GitHub
Родитель dc51536bca
Коммит 3248c2449c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 55 добавлений и 67 удалений

Просмотреть файл

@ -35,6 +35,7 @@ export type CallLog = {
messages: string[];
status: 'in-progress' | 'done' | 'error' | 'paused';
error?: string;
reveal?: boolean;
};
export type SourceHighlight = {

Просмотреть файл

@ -81,10 +81,6 @@ body {
display: none !important;
}
.codicon {
color: var(--toolbar-color);
}
svg {
fill: currentColor;
}

Просмотреть файл

@ -25,9 +25,9 @@ export default {
} as Meta;
const Template: Story<ToolbarProps> = () => <Toolbar>
<ToolbarButton icon="clone" title="Copy" onClick={() => {}}></ToolbarButton>
<ToolbarButton icon="trashcan" title="Erase" onClick={() => {}}></ToolbarButton>
<ToolbarButton icon="close" title="Close" onClick={() => {}}></ToolbarButton>
<ToolbarButton icon='record' title='Record' onClick={() => {}}>Record</ToolbarButton>
<ToolbarButton icon='question' title='Inspect' onClick={() => {}}>Explore</ToolbarButton>
<ToolbarButton icon='files' title='Copy' onClick={() => {}}></ToolbarButton>
</Toolbar>;
export const Primary = Template.bind({});

Просмотреть файл

@ -22,6 +22,8 @@
padding: 0;
margin-left: 10px;
cursor: pointer;
display: flex;
align-items: center;
}
.toolbar-button:disabled {
@ -29,24 +31,10 @@
cursor: default;
}
.toolbar-button:not(.disabled):hover {
.toolbar-button:not(.disabled):not(.toggled):hover {
color: #555;
}
.toolbar-button.toggled {
color: #1ea7fd;
}
.toolbar-button.codicon-record.toggled {
color: #fd1e1e;
}
.toolbar-button.codicon-debug-continue,
.toolbar-button.codicon-debug-step-over {
color: #01bb01;
}
.toolbar-button.codicon-debug-continue:hover,
.toolbar-button.codicon-debug-step-over:hover {
color: #41ca1e;
.toolbar-button .codicon {
margin-right: 4px;
}

Просмотреть файл

@ -27,14 +27,15 @@ export interface ToolbarButtonProps {
}
export const ToolbarButton: React.FC<ToolbarButtonProps> = ({
children,
title = '',
icon = '',
disabled = false,
toggled = false,
onClick = () => {},
}) => {
let className = `toolbar-button codicon codicon-${icon}`;
let className = `toolbar-button ${icon}`;
if (toggled)
className += ' toggled';
return <button className={className} onClick={onClick} title={title} disabled={!!disabled}></button>;
return <button className={className} onClick={onClick} title={title} disabled={!!disabled}><span className={`codicon codicon-${icon}`}></span>{ children }</button>;
};

Просмотреть файл

@ -50,7 +50,7 @@ export function exampleCallLog(): CallLog[] {
'status': 'paused'
},
{
'id': 5,
'id': 6,
'messages': [
'navigating to "https://github.com/microsoft", waiting until "load"',
],

Просмотреть файл

@ -23,27 +23,37 @@ export interface CallLogProps {
}
export const CallLogView: React.FC<CallLogProps> = ({
log
log,
}) => {
const messagesEndRef = React.createRef<HTMLDivElement>();
const [expandOverrides, setExpandOverrides] = React.useState<Map<number, boolean>>(new Map());
React.useLayoutEffect(() => {
messagesEndRef.current?.scrollIntoView({ block: 'center', inline: 'nearest' });
if (log.find(callLog => callLog.reveal))
messagesEndRef.current?.scrollIntoView({ block: 'center', inline: 'nearest' });
}, [messagesEndRef]);
return <div className='vbox'>
<div className='call-log-header' style={{flex: 'none'}}>Log</div>
<div className='call-log' style={{flex: 'auto'}}>
{log.map(callLog => {
const expandOverride = expandOverrides.get(callLog.id);
const isExpanded = typeof expandOverride === 'boolean' ? expandOverride : callLog.status !== 'done';
return <div className={`call-log-call ${callLog.status}`} key={callLog.id}>
<div className='call-log-call-header'>
<span className={'codicon ' + iconClass(callLog)}></span>{ callLog.title }
<span className={`codicon codicon-chevron-${isExpanded ? 'down' : 'right'}`} style={{ cursor: 'pointer' }}onClick={() => {
const newOverrides = new Map(expandOverrides);
newOverrides.set(callLog.id, !isExpanded);
setExpandOverrides(newOverrides);
}}></span>
{ callLog.title }
<span className={'codicon ' + iconClass(callLog)}></span>
</div>
{ callLog.messages.map((message, i) => {
{ (isExpanded ? callLog.messages : []).map((message, i) => {
return <div className='call-log-message' key={i}>
{ message.trim() }
</div>;
})}
{ callLog.error ? <div className='call-log-message error'>
{ callLog.error ? <div className='call-log-message error' hidden={!isExpanded}>
{ callLog.error }
</div> : undefined }
</div>

Просмотреть файл

@ -42,8 +42,10 @@ export const Main: React.FC = ({
window.playwrightSetPaused = setPaused;
window.playwrightUpdateLogs = callLogs => {
const newLog = new Map<number, CallLog>(log);
for (const callLog of callLogs)
for (const callLog of callLogs) {
callLog.reveal = !log.has(callLog.id);
newLog.set(callLog.id, callLog);
}
setLog(newLog);
};

Просмотреть файл

@ -37,3 +37,21 @@
color: var(--toolbar-color);
margin-left: 16px;
}
.recorder .toolbar-button.toggled.question {
color: #12a3ff;
}
.recorder .toolbar-button.toggled.record {
color: #fd1e1e;
}
.recorder .toolbar-button:not([disabled]) .codicon-debug-continue,
.recorder .toolbar-button:not([disabled]) .codicon-debug-step-over {
color: #01bb01;
}
.recorder .toolbar-button:not([disabled]):hover .codicon-debug-continue,
.recorder .toolbar-button:not([disabled]):hover .codicon-debug-step-over {
color: #41ca1e;
}

Просмотреть файл

@ -57,15 +57,14 @@ export const Recorder: React.FC<RecorderProps> = ({
React.useLayoutEffect(() => {
messagesEndRef.current?.scrollIntoView({ block: 'center', inline: 'nearest' });
}, [messagesEndRef]);
return <div className='recorder'>
<Toolbar>
<ToolbarButton icon='record' title='Record' toggled={mode == 'recording'} onClick={() => {
window.dispatch({ event: 'setMode', params: { mode: mode === 'recording' ? 'none' : 'recording' }}).catch(() => { });
}}></ToolbarButton>
<ToolbarButton icon='question' title='Inspect' toggled={mode == 'inspecting'} onClick={() => {
}}>Record</ToolbarButton>
<ToolbarButton icon='question' title='Explore' toggled={mode == 'inspecting'} onClick={() => {
window.dispatch({ event: 'setMode', params: { mode: mode === 'inspecting' ? 'none' : 'inspecting' }}).catch(() => { });
}}></ToolbarButton>
}}>Explore</ToolbarButton>
<ToolbarButton icon='files' title='Copy' disabled={!source || !source.text} onClick={() => {
copy(source.text);
}}></ToolbarButton>
@ -78,12 +77,12 @@ export const Recorder: React.FC<RecorderProps> = ({
<ToolbarButton icon='debug-step-over' title='Step over' disabled={!paused} onClick={() => {
window.dispatch({ event: 'step' }).catch(() => {});
}}></ToolbarButton>
<select className='recorder-chooser' hidden={!sources.length} onChange={event => {
<select className='recorder-chooser' hidden={!sources.length} value={file} onChange={event => {
setFile(event.target.selectedOptions[0].value);
}}>{
sources.map(s => {
const title = s.file.replace(/.*[/\\]([^/\\]+)/, '$1');
return <option key={s.file} value={s.file} selected={s.file === file}>{title}</option>;
return <option key={s.file} value={s.file}>{title}</option>;
})
}
</select>

Просмотреть файл

@ -148,19 +148,6 @@ describe('pause', (suite, { mode }) => {
expect(await sanitizeLog(recorderPage)).toEqual([
'pause',
'click',
'waiting for selector "button"',
'selector resolved to visible <button>Submit</button>',
'attempting click action',
'waiting for element to be visible, enabled and stable',
'element is visible, enabled and stable',
'scrolling into view if needed',
'done scrolling',
'checking that element receives pointer events at ()',
'element does receive pointer events',
'performing click action',
'click action done',
'waiting for scheduled navigations to finish',
'navigations have finished',
'pause',
]);
await recorderPage.click('[title="Resume"]');
@ -183,21 +170,7 @@ describe('pause', (suite, { mode }) => {
expect(await sanitizeLog(recorderPage)).toEqual([
'pause',
'waitForEvent()',
'waiting for event \"console\"',
'click',
'waiting for selector "button"',
'selector resolved to visible <button onclick=\"console.log()\">Submit</button>',
'attempting click action',
'waiting for element to be visible, enabled and stable',
'element is visible, enabled and stable',
'scrolling into view if needed',
'done scrolling',
'checking that element receives pointer events at ()',
'element does receive pointer events',
'performing click action',
'click action done',
'waiting for scheduled navigations to finish',
'navigations have finished',
'pause',
]);
await recorderPage.click('[title="Resume"]');