Skip to content

Commit ad69b2a

Browse files
authored
chore: unify recorder & tracer uis (#5791)
1 parent 43de259 commit ad69b2a

27 files changed

+302
-257
lines changed

src/server/snapshot/snapshotRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function snapshotScript() {
138138
for (const iframe of root.querySelectorAll('iframe')) {
139139
const src = iframe.getAttribute('src');
140140
if (!src) {
141-
iframe.setAttribute('src', 'data:text/html,<body>Snapshot is not available</body>');
141+
iframe.setAttribute('src', 'data:text/html,<body style="background: #ddd"></body>');
142142
} else {
143143
// Append query parameters to inherit ?name= or ?time= values from parent.
144144
iframe.setAttribute('src', window.location.origin + src + window.location.search);

src/server/snapshot/snapshotServer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class SnapshotServer {
7575
}
7676

7777
function respondNotAvailable(): Response {
78-
return new Response('<body>Snapshot is not available</body>', { status: 200, headers: { 'Content-Type': 'text/html' } });
78+
return new Response('<body style="background: #ddd"></body>', { status: 200, headers: { 'Content-Type': 'text/html' } });
7979
}
8080

8181
function removeHash(url: string) {

src/server/supplements/recorder/recorderTypes.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ export type UIState = {
3030
snapshotUrl?: string;
3131
};
3232

33+
export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused';
34+
3335
export type CallLog = {
3436
id: number;
3537
title: string;
3638
messages: string[];
37-
status: 'in-progress' | 'done' | 'error' | 'paused';
39+
status: CallLogStatus;
3840
error?: string;
3941
reveal?: boolean;
4042
duration?: number;
@@ -44,7 +46,7 @@ export type CallLog = {
4446
};
4547
snapshots: {
4648
before: boolean,
47-
in: boolean,
49+
action: boolean,
4850
after: boolean,
4951
}
5052
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { CallMetadata } from '../../instrumentation';
18+
import { CallLog, CallLogStatus } from './recorderTypes';
19+
20+
export function metadataToCallLog(metadata: CallMetadata, status: CallLogStatus, snapshots: Set<string>): CallLog {
21+
const title = metadata.apiName || metadata.method;
22+
if (metadata.error)
23+
status = 'error';
24+
const params = {
25+
url: metadata.params?.url,
26+
selector: metadata.params?.selector,
27+
};
28+
let duration = metadata.endTime ? metadata.endTime - metadata.startTime : undefined;
29+
if (typeof duration === 'number' && metadata.pauseStartTime && metadata.pauseEndTime) {
30+
duration -= (metadata.pauseEndTime - metadata.pauseStartTime);
31+
duration = Math.max(duration, 0);
32+
}
33+
const callLog: CallLog = {
34+
id: metadata.id,
35+
messages: metadata.log,
36+
title,
37+
status,
38+
error: metadata.error,
39+
params,
40+
duration,
41+
snapshots: {
42+
before: showBeforeSnapshot(metadata) && snapshots.has(`before@${metadata.id}`),
43+
action: showActionSnapshot(metadata) && snapshots.has(`action@${metadata.id}`),
44+
after: showAfterSnapshot(metadata) && snapshots.has(`after@${metadata.id}`),
45+
}
46+
};
47+
return callLog;
48+
}
49+
50+
function showBeforeSnapshot(metadata: CallMetadata): boolean {
51+
return metadata.method === 'close';
52+
}
53+
54+
function showActionSnapshot(metadata: CallMetadata): boolean {
55+
return ['click', 'dblclick', 'check', 'uncheck', 'fill', 'press'].includes(metadata.method);
56+
}
57+
58+
function showAfterSnapshot(metadata: CallMetadata): boolean {
59+
return ['goto', 'click', 'dblclick', 'dblclick', 'check', 'uncheck', 'fill', 'press'].includes(metadata.method);
60+
}

src/server/supplements/recorderSupplement.ts

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ import * as consoleApiSource from '../../generated/consoleApiSource';
3131
import { RecorderApp } from './recorder/recorderApp';
3232
import { CallMetadata, internalCallMetadata, SdkObject } from '../instrumentation';
3333
import { Point } from '../../common/types';
34-
import { CallLog, EventData, Mode, Source, UIState } from './recorder/recorderTypes';
34+
import { CallLog, CallLogStatus, EventData, Mode, Source, UIState } from './recorder/recorderTypes';
3535
import { isUnderTest, monotonicTime } from '../../utils/utils';
3636
import { InMemorySnapshotter } from '../snapshot/inMemorySnapshotter';
37+
import { metadataToCallLog } from './recorder/recorderUtils';
3738

3839
type BindingSource = { frame: Frame, page: Page };
3940

@@ -56,7 +57,7 @@ export class RecorderSupplement {
5657
private _recorderSources: Source[];
5758
private _userSources = new Map<string, Source>();
5859
private _snapshotter: InMemorySnapshotter;
59-
private _hoveredSnapshot: { callLogId: number, phase: 'before' | 'after' | 'in' } | undefined;
60+
private _hoveredSnapshot: { callLogId: number, phase: 'before' | 'after' | 'action' } | undefined;
6061
private _snapshots = new Set<string>();
6162
private _allMetadatas = new Map<number, CallMetadata>();
6263

@@ -209,7 +210,7 @@ export class RecorderSupplement {
209210
if (this._hoveredSnapshot) {
210211
const metadata = this._allMetadatas.get(this._hoveredSnapshot.callLogId)!;
211212
snapshotUrl = `${metadata.pageId}?name=${this._hoveredSnapshot.phase}@${this._hoveredSnapshot.callLogId}`;
212-
actionPoint = this._hoveredSnapshot.phase === 'in' ? metadata?.point : undefined;
213+
actionPoint = this._hoveredSnapshot.phase === 'action' ? metadata?.point : undefined;
213214
} else {
214215
for (const [metadata, sdkObject] of this._currentCallsMetadata) {
215216
if (source.page === sdkObject.attribution.page) {
@@ -401,7 +402,7 @@ export class RecorderSupplement {
401402
this._generator.signal(pageAlias, page.mainFrame(), { name: 'dialog', dialogAlias: String(++this._lastDialogOrdinal) });
402403
}
403404

404-
_captureSnapshot(sdkObject: SdkObject, metadata: CallMetadata, phase: 'before' | 'after' | 'in') {
405+
_captureSnapshot(sdkObject: SdkObject, metadata: CallMetadata, phase: 'before' | 'after' | 'action') {
405406
if (sdkObject.attribution.page) {
406407
const snapshotName = `${phase}@${metadata.id}`;
407408
this._snapshots.add(snapshotName);
@@ -428,7 +429,7 @@ export class RecorderSupplement {
428429
async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
429430
if (this._mode === 'recording')
430431
return;
431-
await this._captureSnapshot(sdkObject, metadata, 'after');
432+
this._captureSnapshot(sdkObject, metadata, 'after');
432433
if (!metadata.error)
433434
this._currentCallsMetadata.delete(metadata);
434435
this._pausedCallsMetadata.delete(metadata);
@@ -473,49 +474,24 @@ export class RecorderSupplement {
473474
async onBeforeInputAction(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
474475
if (this._mode === 'recording')
475476
return;
476-
await this._captureSnapshot(sdkObject, metadata, 'in');
477+
this._captureSnapshot(sdkObject, metadata, 'action');
477478
if (this._pauseOnNextStatement)
478479
await this.pause(metadata);
479480
}
480481

481-
async updateCallLog(metadatas: CallMetadata[]): Promise<void> {
482+
updateCallLog(metadatas: CallMetadata[]) {
482483
if (this._mode === 'recording')
483484
return;
484485
const logs: CallLog[] = [];
485486
for (const metadata of metadatas) {
486487
if (!metadata.method)
487488
continue;
488-
const title = metadata.apiName || metadata.method;
489-
let status: 'done' | 'in-progress' | 'paused' | 'error' = 'done';
489+
let status: CallLogStatus = 'done';
490490
if (this._currentCallsMetadata.has(metadata))
491491
status = 'in-progress';
492492
if (this._pausedCallsMetadata.has(metadata))
493493
status = 'paused';
494-
if (metadata.error)
495-
status = 'error';
496-
const params = {
497-
url: metadata.params?.url,
498-
selector: metadata.params?.selector,
499-
};
500-
let duration = metadata.endTime ? metadata.endTime - metadata.startTime : undefined;
501-
if (typeof duration === 'number' && metadata.pauseStartTime && metadata.pauseEndTime) {
502-
duration -= (metadata.pauseEndTime - metadata.pauseStartTime);
503-
duration = Math.max(duration, 0);
504-
}
505-
logs.push({
506-
id: metadata.id,
507-
messages: metadata.log,
508-
title,
509-
status,
510-
error: metadata.error,
511-
params,
512-
duration,
513-
snapshots: {
514-
before: showBeforeSnapshot(metadata) && this._snapshots.has(`before@${metadata.id}`),
515-
in: showInSnapshot(metadata) && this._snapshots.has(`in@${metadata.id}`),
516-
after: showAfterSnapshot(metadata) && this._snapshots.has(`after@${metadata.id}`),
517-
}
518-
});
494+
logs.push(metadataToCallLog(metadata, status, this._snapshots));
519495
}
520496
this._recorderApp?.updateCallLogs(logs);
521497
}
@@ -548,15 +524,3 @@ function shouldPauseOnCall(sdkObject: SdkObject, metadata: CallMetadata): boolea
548524
function shouldPauseOnStep(sdkObject: SdkObject, metadata: CallMetadata): boolean {
549525
return metadata.method === 'goto' || metadata.method === 'close';
550526
}
551-
552-
function showBeforeSnapshot(metadata: CallMetadata): boolean {
553-
return metadata.method === 'close';
554-
}
555-
556-
function showInSnapshot(metadata: CallMetadata): boolean {
557-
return ['click', 'dblclick', 'check', 'uncheck', 'fill', 'press'].includes(metadata.method);
558-
}
559-
560-
function showAfterSnapshot(metadata: CallMetadata): boolean {
561-
return ['goto', 'click', 'dblclick', 'dblclick', 'check', 'uncheck', 'fill', 'press'].includes(metadata.method);
562-
}

src/server/trace/recorder/tracer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class ContextTracer {
108108
await this._snapshotter.start();
109109
}
110110

111-
async _captureSnapshot(name: string, sdkObject: SdkObject, metadata: CallMetadata, element?: ElementHandle): Promise<void> {
111+
async _captureSnapshot(name: 'before' | 'after' | 'action', sdkObject: SdkObject, metadata: CallMetadata, element?: ElementHandle): Promise<void> {
112112
if (!sdkObject.attribution.page)
113113
return;
114114
const snapshotName = `${name}@${metadata.id}`;

src/server/trace/viewer/traceViewer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class TraceViewer {
115115
const traceViewerPlaywright = createPlaywright(true);
116116
const args = [
117117
'--app=data:text/html,',
118-
'--window-position=1280,10',
118+
'--window-size=1280,800'
119119
];
120120
if (isUnderTest())
121121
args.push(`--remote-debugging-port=0`);

src/web/common.css

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
:root {
1818
--toolbar-bg-color: #fafafa;
19-
--toolbar-color: #777;
19+
--toolbar-color: #555;
2020

2121
--light-background: #f3f2f1;
2222
--background: #edebe9;
@@ -27,7 +27,7 @@
2727
--purple: #9C27B0;
2828
--yellow: #FFC107;
2929
--white: #FFFFFF;
30-
--blue: #2196F3;
30+
--blue: #0b7ad5;
3131
--transparent-blue: #2196F355;
3232
--orange: #d24726;
3333
--black: #1E1E1E;
@@ -53,7 +53,6 @@ html, body {
5353
margin: 0;
5454
overflow: hidden;
5555
display: flex;
56-
background: var(--background);
5756
overscroll-behavior-x: none;
5857
}
5958

@@ -64,7 +63,6 @@ html, body {
6463
}
6564

6665
body {
67-
background-color: var(--background);
6866
color: var(--color);
6967
font-size: 14px;
7068
font-family: SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;

src/web/components/source.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
font-size: 11px;
2525
line-height: 16px;
2626
background: white;
27+
user-select: text;
2728
}
2829

2930
.source-line {
@@ -36,7 +37,7 @@
3637
padding: 0 8px;
3738
width: 30px;
3839
text-align: right;
39-
background: #edebe9;
40+
background: #f6f5f4;
4041
user-select: none;
4142
}
4243

src/web/components/splitView.css

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
position: relative;
2222
}
2323

24+
.split-view.horizontal {
25+
flex-direction: row;
26+
}
27+
2428
.split-view-main {
2529
display: flex;
2630
flex: auto;
@@ -32,12 +36,29 @@
3236
border-top: 1px solid #ddd;
3337
}
3438

39+
.split-view.vertical > .split-view-sidebar {
40+
border-top: 1px solid #ddd;
41+
}
42+
43+
.split-view.horizontal > .split-view-sidebar {
44+
border-left: 1px solid #ddd;
45+
}
46+
3547
.split-view-resizer {
3648
position: absolute;
49+
z-index: 100;
50+
}
51+
52+
.split-view.vertical > .split-view-resizer {
3753
left: 0;
3854
right: 0;
3955
height: 12px;
40-
cursor: resize;
4156
cursor: ns-resize;
42-
z-index: 100;
57+
}
58+
59+
.split-view.horizontal > .split-view-resizer {
60+
top: 0;
61+
bottom: 0;
62+
width: 12px;
63+
cursor: ew-resize;
4364
}

0 commit comments

Comments
 (0)