chore: add storybook dep (#5082)

This commit is contained in:
Pavel Feldman 2021-01-21 08:29:01 -08:00 committed by GitHub
parent 043ed975c1
commit c757ba72a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 7837 additions and 67 deletions

1
.gitignore vendored
View file

@ -18,3 +18,4 @@ drivers/
.gradle/
nohup.out
api.json
.trace

11
.storybook/main.js Normal file
View file

@ -0,0 +1,11 @@
module.exports = {
"stories": [
"../src/cli/traceViewer/web/ui/*.stories.tsx",
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
],
"typescript": {
}
}

16
.storybook/preview.js Normal file
View file

@ -0,0 +1,16 @@
import { addDecorator } from '@storybook/react';
import { GlobalStyles } from '../src/cli/traceViewer/web/styles';
import { applyTheme } from '../src/cli/traceViewer/web/theme';
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
}
addDecorator(storyFn => {
applyTheme();
return <div style={{backgroundColor: 'var(--background)'}}>
<GlobalStyles />
{storyFn()}
</div>
});

7648
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -26,7 +26,9 @@
"test-types": "node utils/generate_types/ && npx -p typescript@3.7.5 tsc -p utils/generate_types/test/tsconfig.json && tsc -p ./test/",
"roll-browser": "node utils/roll_browser.js",
"check-deps": "node utils/check_deps.js",
"build-android-driver": "./utils/build_android_driver.sh"
"build-android-driver": "./utils/build_android_driver.sh",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
},
"author": {
"name": "Microsoft Corporation"
@ -84,6 +86,11 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"socksv5": "0.0.6",
"@storybook/addon-actions": "^6.1.14",
"@storybook/addon-essentials": "^6.1.14",
"@storybook/addon-links": "^6.1.14",
"@storybook/node-logger": "^6.1.14",
"@storybook/react": "^6.1.14",
"style-loader": "^1.2.1",
"ts-loader": "^8.0.3",
"typescript": "^4.0.2",

View file

@ -338,7 +338,7 @@ async function codegen(options: Options, url: string | undefined, target: string
const { context, browserName, launchOptions, contextOptions } = await launchContext(options, false);
if (process.env.PWTRACE)
contextOptions.recordVideo = { dir: path.join(process.cwd(), '.trace') };
(contextOptions as any)._traceDir = path.join(process.cwd(), '.trace');
const outputs: CodeGeneratorOutput[] = [TerminalOutput.create(process.stdout, languageGenerator.highlighterType())];
if (outputFile)

View file

@ -51,6 +51,7 @@ export type PageEntry = {
export type ActionEntry = {
actionId: string;
action: trace.ActionTraceEvent;
thumbnailUrl: string;
resources: trace.NetworkResourceTraceEvent[];
};
@ -108,9 +109,11 @@ export function readTraceFile(events: trace.TraceEvent[], traceModel: TraceModel
}
case 'action': {
const pageEntry = pageEntries.get(event.pageId!)!;
const actionId = event.contextId + '/' + event.pageId + '/' + pageEntry.actions.length;
const action: ActionEntry = {
actionId: event.contextId + '/' + event.pageId + '/' + pageEntry.actions.length,
actionId,
action: event,
thumbnailUrl: `action-preview/${actionId}.png`,
resources: pageEntry.resources,
};
pageEntry.resources = [];

View file

@ -15,11 +15,11 @@
*/
import { TraceModel, VideoMetaInfo, trace } from '../traceModel';
import './common.css';
import './third_party/vscode/codicon.css';
import { Workbench } from './ui/workbench';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { applyTheme } from './theme';
declare global {
interface Window {
@ -30,27 +30,8 @@ declare global {
}
}
function platformName(): string {
if (window.navigator.userAgent.includes('Linux'))
return 'platform-linux';
if (window.navigator.userAgent.includes('Windows'))
return 'platform-windows';
if (window.navigator.userAgent.includes('Mac'))
return 'platform-mac';
return 'platform-generic';
}
(async () => {
document!.defaultView!.addEventListener('focus', (event: any) => {
if (event.target.document.nodeType === Node.DOCUMENT_NODE)
document.body.classList.remove('inactive');
}, false);
document!.defaultView!.addEventListener('blur', event => {
document.body.classList.add('inactive');
}, false);
document.documentElement.classList.add(platformName());
applyTheme();
const traceModel = await window.getTraceModel();
ReactDOM.render(<Workbench traceModel={traceModel} />, document.querySelector('#root'));
})();

View file

@ -14,6 +14,9 @@
limitations under the License.
*/
import * as React from 'react';
export const GlobalStyles = () => <style>{`
:root {
--light-background: #f3f2f1;
--background: #edebe9;
@ -51,6 +54,20 @@ html, body {
overscroll-behavior-x: none;
}
#root {
width: 100%;
height: 100%;
display: flex;
}
body {
background-color: var(--background);
color: var(--color);
font-size: 14px;
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;
-webkit-font-smoothing: antialiased;
}
* {
box-sizing: border-box;
min-width: 0;
@ -69,20 +86,6 @@ svg {
fill: currentColor;
}
body {
background-color: var(--background);
color: var(--color);
font-size: 14px;
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;
-webkit-font-smoothing: antialiased;
}
#root {
width: 100%;
height: 100%;
display: flex;
}
.platform-windows {
--monospace-font: Consolas, Inconsolata, "Courier New", monospace;
}
@ -121,3 +124,4 @@ body {
::-webkit-scrollbar-corner {
background-color: var(--background);
}
`}</style>;

View 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.
*/
function platformName(): string {
if (window.navigator.userAgent.includes('Linux'))
return 'platform-linux';
if (window.navigator.userAgent.includes('Windows'))
return 'platform-windows';
if (window.navigator.userAgent.includes('Mac'))
return 'platform-mac';
return 'platform-generic';
}
export function applyTheme() {
if ((document as any).playwrightThemeInitialized)
return;
(document as any).playwrightThemeInitialized = true;
document!.defaultView!.addEventListener('focus', (event: any) => {
if (event.target.document.nodeType === Node.DOCUMENT_NODE)
document.body.classList.remove('inactive');
}, false);
document!.defaultView!.addEventListener('blur', event => {
document.body.classList.add('inactive');
}, false);
document.documentElement.classList.add(platformName());
}

20
src/cli/traceViewer/web/types.d.ts vendored Normal file
View file

@ -0,0 +1,20 @@
/*
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.
*/
declare module '*.png' {
const value: any;
export = value;
}

View file

@ -19,9 +19,7 @@
display: flex;
flex-direction: column;
flex: none;
overflow: auto;
position: relative;
contain: size;
padding: 0 var(--layout-gap);
}

View file

@ -0,0 +1,64 @@
/*
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 { Story, Meta } from '@storybook/react/types-6-0';
import { ActionList, ActionListProps } from './actionList';
import gotoThumbnailUrl from './assets/action-thumbnail-goto.png';
import clickThumbnailUrl from './assets/action-thumbnail-click.png';
export default {
title: 'TraceViewer/ActionList',
component: ActionList,
backgrounds: {
default: '#edebe9',
}
} as Meta;
const Template: Story<ActionListProps> = args => <ActionList {...args} />;
export const Primary = Template.bind({});
Primary.args = {
actions: [
{
actionId: 'id2',
action: {
timestamp: Date.now(),
type: 'action',
contextId: '<context>',
action: 'goto',
value: 'https://github.com/microsoft',
startTime: Date.now(),
endTime: Date.now(),
},
thumbnailUrl: gotoThumbnailUrl,
resources: [],
},
{
actionId: 'id',
action: {
timestamp: Date.now(),
type: 'action',
contextId: '<context>',
action: 'click',
selector: 'input[aria-label="Find a repository…"]',
startTime: Date.now(),
endTime: Date.now(),
},
thumbnailUrl: clickThumbnailUrl,
resources: [],
}
]
};

View file

@ -18,16 +18,24 @@ import { ActionEntry } from '../../traceModel';
import './actionList.css';
import * as React from 'react';
export const ActionList: React.FunctionComponent<{
export interface ActionListProps {
actions: ActionEntry[],
selectedAction: ActionEntry | undefined,
highlightedAction: ActionEntry | undefined,
onSelected: (action: ActionEntry) => void,
onHighlighted: (action: ActionEntry | undefined) => void,
}> = ({ actions, selectedAction, highlightedAction, onSelected, onHighlighted }) => {
}
export const ActionList: React.FC<ActionListProps> = ({
actions = [],
selectedAction = undefined,
highlightedAction = undefined,
onSelected = () => {},
onHighlighted = () => {},
}) => {
const targetAction = highlightedAction || selectedAction;
return <div className='action-list'>{actions.map(actionEntry => {
const { action, actionId } = actionEntry;
const { action, actionId, thumbnailUrl } = actionEntry;
return <div
className={'action-entry' + (actionEntry === targetAction ? ' selected' : '')}
key={actionId}
@ -42,7 +50,7 @@ export const ActionList: React.FunctionComponent<{
{action.action === 'goto' && action.value && <div className='action-url' title={action.value}>{action.value}</div>}
</div>
<div className='action-thumbnail'>
{action.snapshot ? <img src={`action-preview/${actionId}.png`} /> : 'No snapshot available'}
<img src={thumbnailUrl} />
</div>
</div>;
})}</div>;

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View file

@ -21,6 +21,7 @@ import { Timeline } from './timeline';
import './workbench.css';
import * as React from 'react';
import { ContextSelector } from './contextSelector';
import { GlobalStyles } from '../styles';
export const Workbench: React.FunctionComponent<{
traceModel: TraceModel,
@ -39,6 +40,7 @@ export const Workbench: React.FunctionComponent<{
const snapshotSize = context.created.viewportSize || { width: 1280, height: 720 };
return <div className='vbox workbench'>
<GlobalStyles />
<div className='hbox header'>
<div className='logo'>🎭</div>
<div className='product'>Playwright</div>
@ -63,7 +65,7 @@ export const Workbench: React.FunctionComponent<{
/>
</div>
<div className='hbox'>
<div style={{ display: 'flex', flex: 'none' }}>
<div style={{ display: 'flex', flex: 'none', overflow: 'auto' }}>
<ActionList
actions={actions}
selectedAction={selectedAction}

View file

@ -235,14 +235,6 @@ declare module 'highlight.js' {
export = hljs;
}
declare module 'highlight.js/lib/core' {
export = hljs;
}
declare module 'highlight.js/lib/core.js' {
export = hljs;
}
declare module 'highlight.js/lib/languages/*' {
export default function(hljs?: HLJSApi): LanguageDetail;
}