chore(trace): remove embedded trace viewer (#33651)
This commit is contained in:
parent
0b312248cd
commit
acd862c6c9
|
|
@ -1,27 +0,0 @@
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Playwright Trace Viewer for VS Code</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/embedded.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
/**
|
|
||||||
* 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 '@web/common.css';
|
|
||||||
import { applyTheme } from '@web/theme';
|
|
||||||
import '@web/third_party/vscode/codicon.css';
|
|
||||||
import * as ReactDOM from 'react-dom/client';
|
|
||||||
import { EmbeddedWorkbenchLoader } from './ui/embeddedWorkbenchLoader';
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
applyTheme();
|
|
||||||
|
|
||||||
// workaround to send keystrokes back to vscode webview to keep triggering key bindings there
|
|
||||||
const handleKeyEvent = (e: KeyboardEvent) => {
|
|
||||||
if (!e.isTrusted)
|
|
||||||
return;
|
|
||||||
window.parent?.postMessage({
|
|
||||||
type: e.type,
|
|
||||||
key: e.key,
|
|
||||||
keyCode: e.keyCode,
|
|
||||||
code: e.code,
|
|
||||||
shiftKey: e.shiftKey,
|
|
||||||
altKey: e.altKey,
|
|
||||||
ctrlKey: e.ctrlKey,
|
|
||||||
metaKey: e.metaKey,
|
|
||||||
repeat: e.repeat,
|
|
||||||
}, '*');
|
|
||||||
};
|
|
||||||
window.addEventListener('keydown', handleKeyEvent);
|
|
||||||
window.addEventListener('keyup', handleKeyEvent);
|
|
||||||
|
|
||||||
if (window.location.protocol !== 'file:') {
|
|
||||||
if (!navigator.serviceWorker)
|
|
||||||
throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`);
|
|
||||||
navigator.serviceWorker.register('sw.bundle.js');
|
|
||||||
if (!navigator.serviceWorker.controller) {
|
|
||||||
await new Promise<void>(f => {
|
|
||||||
navigator.serviceWorker.oncontrollerchange = () => f();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep SW running.
|
|
||||||
setInterval(function() { fetch('ping'); }, 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactDOM.createRoot(document.querySelector('#root')!).render(<EmbeddedWorkbenchLoader />);
|
|
||||||
})();
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.empty-state {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex: auto;
|
|
||||||
flex-direction: column;
|
|
||||||
background-color: var(--vscode-editor-background);
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 100;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body .empty-state {
|
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.dark-mode .empty-state {
|
|
||||||
background: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-state .title {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
flex: none;
|
|
||||||
width: 100%;
|
|
||||||
height: 3px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner-progress {
|
|
||||||
background-color: var(--vscode-progressBar-background);
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workbench-loader {
|
|
||||||
contain: size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Limit to a reasonable minimum viewport */
|
|
||||||
html, body {
|
|
||||||
min-width: 550px;
|
|
||||||
min-height: 450px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
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 type { ContextEntry } from '../types/entries';
|
|
||||||
import { MultiTraceModel } from './modelUtil';
|
|
||||||
import './embeddedWorkbenchLoader.css';
|
|
||||||
import { Workbench } from './workbench';
|
|
||||||
import { currentTheme, toggleTheme } from '@web/theme';
|
|
||||||
import type { SourceLocation } from './modelUtil';
|
|
||||||
|
|
||||||
function openPage(url: string, target?: string) {
|
|
||||||
if (url)
|
|
||||||
window.parent!.postMessage({ method: 'openExternal', params: { url, target } }, '*');
|
|
||||||
}
|
|
||||||
|
|
||||||
function openSourceLocation({ file, line, column }: SourceLocation) {
|
|
||||||
window.parent!.postMessage({ method: 'openSourceLocation', params: { file, line, column } }, '*');
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EmbeddedWorkbenchLoader: React.FunctionComponent = () => {
|
|
||||||
const [traceURLs, setTraceURLs] = React.useState<string[]>([]);
|
|
||||||
const [model, setModel] = React.useState<MultiTraceModel>(emptyModel);
|
|
||||||
const [progress, setProgress] = React.useState<{ done: number, total: number }>({ done: 0, total: 0 });
|
|
||||||
const [processingErrorMessage, setProcessingErrorMessage] = React.useState<string | null>(null);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
window.addEventListener('message', async ({ data: { method, params } }) => {
|
|
||||||
if (method === 'loadTraceRequested') {
|
|
||||||
setTraceURLs(params.traceUrl ? [params.traceUrl] : []);
|
|
||||||
setProcessingErrorMessage(null);
|
|
||||||
} else if (method === 'applyTheme') {
|
|
||||||
if (currentTheme() !== params.theme)
|
|
||||||
toggleTheme();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// notify vscode that it is now listening to its messages
|
|
||||||
window.parent!.postMessage({ type: 'loaded' }, '*');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (traceURLs.length) {
|
|
||||||
const swListener = (event: any) => {
|
|
||||||
if (event.data.method === 'progress')
|
|
||||||
setProgress(event.data.params);
|
|
||||||
};
|
|
||||||
navigator.serviceWorker.addEventListener('message', swListener);
|
|
||||||
setProgress({ done: 0, total: 1 });
|
|
||||||
const contextEntries: ContextEntry[] = [];
|
|
||||||
for (let i = 0; i < traceURLs.length; i++) {
|
|
||||||
const url = traceURLs[i];
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
params.set('trace', url);
|
|
||||||
params.set('limit', String(traceURLs.length));
|
|
||||||
const response = await fetch(`contexts?${params.toString()}`);
|
|
||||||
if (!response.ok) {
|
|
||||||
setProcessingErrorMessage((await response.json()).error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
contextEntries.push(...(await response.json()));
|
|
||||||
}
|
|
||||||
navigator.serviceWorker.removeEventListener('message', swListener);
|
|
||||||
const model = new MultiTraceModel(contextEntries);
|
|
||||||
setProgress({ done: 0, total: 0 });
|
|
||||||
setModel(model);
|
|
||||||
} else {
|
|
||||||
setModel(emptyModel);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [traceURLs]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (processingErrorMessage)
|
|
||||||
window.parent?.postMessage({ method: 'showErrorMessage', params: { message: processingErrorMessage } }, '*');
|
|
||||||
}, [processingErrorMessage]);
|
|
||||||
|
|
||||||
return <div className='vbox workbench-loader'>
|
|
||||||
<div className='progress'>
|
|
||||||
<div className='inner-progress' style={{ width: progress.total ? (100 * progress.done / progress.total) + '%' : 0 }}></div>
|
|
||||||
</div>
|
|
||||||
<Workbench model={model} openPage={openPage} onOpenExternally={openSourceLocation} />
|
|
||||||
{!traceURLs.length && <div className='empty-state'>
|
|
||||||
<div className='title'>Select test to see the trace</div>
|
|
||||||
</div>}
|
|
||||||
</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const emptyModel = new MultiTraceModel([]);
|
|
||||||
|
|
@ -40,8 +40,7 @@ export const SnapshotTabsView: React.FunctionComponent<{
|
||||||
setIsInspecting: (isInspecting: boolean) => void,
|
setIsInspecting: (isInspecting: boolean) => void,
|
||||||
highlightedLocator: string,
|
highlightedLocator: string,
|
||||||
setHighlightedLocator: (locator: string) => void,
|
setHighlightedLocator: (locator: string) => void,
|
||||||
openPage?: (url: string, target?: string) => Window | any,
|
}> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator }) => {
|
||||||
}> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => {
|
|
||||||
const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action');
|
const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action');
|
||||||
|
|
||||||
const snapshots = React.useMemo(() => {
|
const snapshots = React.useMemo(() => {
|
||||||
|
|
@ -66,9 +65,7 @@ export const SnapshotTabsView: React.FunctionComponent<{
|
||||||
})}
|
})}
|
||||||
<div style={{ flex: 'auto' }}></div>
|
<div style={{ flex: 'auto' }}></div>
|
||||||
<ToolbarButton icon='link-external' title='Open snapshot in a new tab' disabled={!snapshotUrls?.popoutUrl} onClick={() => {
|
<ToolbarButton icon='link-external' title='Open snapshot in a new tab' disabled={!snapshotUrls?.popoutUrl} onClick={() => {
|
||||||
if (!openPage)
|
const win = window.open(snapshotUrls?.popoutUrl || '', '_blank');
|
||||||
openPage = window.open;
|
|
||||||
const win = openPage(snapshotUrls?.popoutUrl || '', '_blank');
|
|
||||||
win?.addEventListener('DOMContentLoaded', () => {
|
win?.addEventListener('DOMContentLoaded', () => {
|
||||||
const injectedScript = new InjectedScript(win as any, false, sdkLanguage, testIdAttributeName, 1, 'chromium', []);
|
const injectedScript = new InjectedScript(win as any, false, sdkLanguage, testIdAttributeName, 1, 'chromium', []);
|
||||||
new ConsoleAPI(injectedScript);
|
new ConsoleAPI(injectedScript);
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,9 @@ export const Workbench: React.FunctionComponent<{
|
||||||
status?: UITestStatus,
|
status?: UITestStatus,
|
||||||
annotations?: { type: string; description?: string; }[];
|
annotations?: { type: string; description?: string; }[];
|
||||||
inert?: boolean,
|
inert?: boolean,
|
||||||
openPage?: (url: string, target?: string) => Window | any,
|
|
||||||
onOpenExternally?: (location: modelUtil.SourceLocation) => void,
|
onOpenExternally?: (location: modelUtil.SourceLocation) => void,
|
||||||
revealSource?: boolean,
|
revealSource?: boolean,
|
||||||
}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, openPage, onOpenExternally, revealSource }) => {
|
}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, onOpenExternally, revealSource }) => {
|
||||||
const [selectedCallId, setSelectedCallId] = React.useState<string | undefined>(undefined);
|
const [selectedCallId, setSelectedCallId] = React.useState<string | undefined>(undefined);
|
||||||
const [revealedError, setRevealedError] = React.useState<ErrorDescription | undefined>(undefined);
|
const [revealedError, setRevealedError] = React.useState<ErrorDescription | undefined>(undefined);
|
||||||
const [revealedAttachment, setRevealedAttachment] = React.useState<AfterActionTraceEventAttachment | undefined>(undefined);
|
const [revealedAttachment, setRevealedAttachment] = React.useState<AfterActionTraceEventAttachment | undefined>(undefined);
|
||||||
|
|
@ -344,8 +343,7 @@ export const Workbench: React.FunctionComponent<{
|
||||||
isInspecting={isInspecting}
|
isInspecting={isInspecting}
|
||||||
setIsInspecting={setIsInspecting}
|
setIsInspecting={setIsInspecting}
|
||||||
highlightedLocator={highlightedLocator}
|
highlightedLocator={highlightedLocator}
|
||||||
setHighlightedLocator={locatorPicked}
|
setHighlightedLocator={locatorPicked} />}
|
||||||
openPage={openPage} />}
|
|
||||||
sidebar={
|
sidebar={
|
||||||
<TabbedPane
|
<TabbedPane
|
||||||
tabs={[actionsTab, metadataTab]}
|
tabs={[actionsTab, metadataTab]}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ export default defineConfig({
|
||||||
input: {
|
input: {
|
||||||
index: path.resolve(__dirname, 'index.html'),
|
index: path.resolve(__dirname, 'index.html'),
|
||||||
uiMode: path.resolve(__dirname, 'uiMode.html'),
|
uiMode: path.resolve(__dirname, 'uiMode.html'),
|
||||||
embedded: path.resolve(__dirname, 'embedded.html'),
|
|
||||||
recorder: path.resolve(__dirname, 'recorder.html'),
|
recorder: path.resolve(__dirname, 'recorder.html'),
|
||||||
snapshot: path.resolve(__dirname, 'snapshot.html'),
|
snapshot: path.resolve(__dirname, 'snapshot.html'),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue