chore: migrate codegen to controller events (#17450)

This commit is contained in:
Pavel Feldman 2022-09-20 14:32:21 -07:00 committed by GitHub
parent 4dccba72ed
commit 3abbe0d850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 160 additions and 90 deletions

View File

@ -25,7 +25,7 @@ import type { Playwright } from '../server/playwright';
import { IpcTransport, PipeTransport } from '../protocol/transport';
import { PlaywrightServer } from '../remote/playwrightServer';
import { gracefullyCloseAll } from '../utils/processLauncher';
import type { Mode } from '../server/recorder/recorderTypes';
import type { Mode } from '@recorder/recorderTypes';
import { ReuseController } from '../server/reuseController';
export function printApiJson() {

View File

@ -558,11 +558,26 @@ export type PlaywrightHideHighlightResult = void;
export interface PlaywrightEvents {
}
export type RecorderSource = {
isRecorded: boolean,
id: string,
label: string,
text: string,
language: string,
highlight: {
line: number,
type: string,
}[],
revealLine?: number,
group?: string,
};
// ----------- ReuseController -----------
export type ReuseControllerInitializer = {};
export interface ReuseControllerEventTarget {
on(event: 'inspectRequested', callback: (params: ReuseControllerInspectRequestedEvent) => void): this;
on(event: 'browsersChanged', callback: (params: ReuseControllerBrowsersChangedEvent) => void): this;
on(event: 'sourcesChanged', callback: (params: ReuseControllerSourcesChangedEvent) => void): this;
}
export interface ReuseControllerChannel extends ReuseControllerEventTarget, Channel {
_type_ReuseController: boolean;
@ -587,6 +602,9 @@ export type ReuseControllerBrowsersChangedEvent = {
}[],
}[],
};
export type ReuseControllerSourcesChangedEvent = {
sources: RecorderSource[],
};
export type ReuseControllerSetTrackHierarchyParams = {
enabled: boolean,
};
@ -648,6 +666,7 @@ export type ReuseControllerCloseAllBrowsersResult = void;
export interface ReuseControllerEvents {
'inspectRequested': ReuseControllerInspectRequestedEvent;
'browsersChanged': ReuseControllerBrowsersChangedEvent;
'sourcesChanged': ReuseControllerSourcesChangedEvent;
}
// ----------- SocksSupport -----------

View File

@ -622,6 +622,24 @@ Playwright:
hideHighlight:
RecorderSource:
type: object
properties:
isRecorded: boolean
id: string
label: string
text: string
language: string
highlight:
type: array
items:
type: object
properties:
line: number
type: string
revealLine: number?
group: string?
ReuseController:
type: interface
@ -686,6 +704,12 @@ ReuseController:
type: array
items: string
sourcesChanged:
parameters:
sources:
type: array
items: RecorderSource
SocksSupport:
type: interface

View File

@ -308,6 +308,19 @@ scheme.PlaywrightNewRequestResult = tObject({
});
scheme.PlaywrightHideHighlightParams = tOptional(tObject({}));
scheme.PlaywrightHideHighlightResult = tOptional(tObject({}));
scheme.RecorderSource = tObject({
isRecorded: tBoolean,
id: tString,
label: tString,
text: tString,
language: tString,
highlight: tArray(tObject({
line: tNumber,
type: tString,
})),
revealLine: tOptional(tNumber),
group: tOptional(tString),
});
scheme.ReuseControllerInitializer = tOptional(tObject({}));
scheme.ReuseControllerInspectRequestedEvent = tObject({
selector: tString,
@ -319,6 +332,9 @@ scheme.ReuseControllerBrowsersChangedEvent = tObject({
})),
})),
});
scheme.ReuseControllerSourcesChangedEvent = tObject({
sources: tArray(tType('RecorderSource')),
});
scheme.ReuseControllerSetTrackHierarchyParams = tObject({
enabled: tBoolean,
});

View File

@ -31,6 +31,9 @@ export class ReuseControllerDispatcher extends Dispatcher<ReuseController, chann
this._object.on(ReuseController.Events.InspectRequested, selector => {
this._dispatchEvent('inspectRequested', { selector });
});
this._object.on(ReuseController.Events.SourcesChanged, sources => {
this._dispatchEvent('sourcesChanged', { sources });
});
}
async setTrackHierarchy(params: channels.ReuseControllerSetTrackHierarchyParams) {

View File

@ -18,7 +18,7 @@ import type * as actions from '../recorder/recorderActions';
import { type InjectedScript } from '../injected/injectedScript';
import { generateSelector, querySelector } from '../injected/selectorGenerator';
import type { Point } from '../../common/types';
import type { UIState } from '../recorder/recorderTypes';
import type { UIState } from '@recorder/recorderTypes';
import { Highlight } from '../injected/highlight';

View File

@ -34,7 +34,7 @@ import type { IRecorderApp } from './recorder/recorderApp';
import { RecorderApp } from './recorder/recorderApp';
import type { CallMetadata, InstrumentationListener, SdkObject } from './instrumentation';
import type { Point } from '../common/types';
import type { CallLog, CallLogStatus, EventData, Mode, Source, UIState } from './recorder/recorderTypes';
import type { CallLog, CallLogStatus, EventData, Mode, Source, UIState } from '@recorder/recorderTypes';
import { createGuid, monotonicTime } from '../utils';
import { metadataToCallLog } from './recorder/recorderUtils';
import { Debugger } from './debugger';

View File

@ -20,7 +20,7 @@ import type { Page } from '../page';
import { ProgressController } from '../progress';
import { EventEmitter } from 'events';
import { serverSideCallMetadata } from '../instrumentation';
import type { CallLog, EventData, Mode, Source } from './recorderTypes';
import type { CallLog, EventData, Mode, Source } from '@recorder/recorderTypes';
import { isUnderTest } from '../../utils';
import { mime } from '../../utilsBundle';
import { installAppIcon } from '../chromium/crApp';

View File

@ -1,64 +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 type { Point } from '../../common/types';
import type { SerializedError } from '../../protocol/channels';
export type Mode = 'inspecting' | 'recording' | 'none';
export type EventData = {
event: 'clear' | 'resume' | 'step' | 'pause' | 'setMode' | 'selectorUpdated';
params: any;
};
export type UIState = {
mode: Mode;
actionPoint?: Point;
actionSelector?: string;
};
export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused';
export type CallLog = {
id: string;
title: string;
messages: string[];
status: CallLogStatus;
error?: SerializedError;
reveal?: boolean;
duration?: number;
params: {
url?: string,
selector?: string,
};
};
export type SourceHighlight = {
line: number;
type: 'running' | 'paused' | 'error';
};
export type Source = {
isRecorded: boolean;
id: string;
label: string;
text: string;
language: string;
highlight: SourceHighlight[];
revealLine?: number;
// used to group the language generators
group?: string;
};

View File

@ -15,7 +15,7 @@
*/
import type { CallMetadata } from '../instrumentation';
import type { CallLog, CallLogStatus } from './recorderTypes';
import type { CallLog, CallLogStatus } from '@recorder/recorderTypes';
export function metadataToCallLog(metadata: CallMetadata, status: CallLogStatus): CallLog {
let title = metadata.apiName || metadata.method;
@ -38,7 +38,7 @@ export function metadataToCallLog(metadata: CallMetadata, status: CallLogStatus)
messages: metadata.log,
title,
status,
error: metadata.error,
error: metadata.error?.error?.message,
params,
duration,
};

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import type { Mode } from '../server/recorder/recorderTypes';
import type { Mode, Source } from '@recorder/recorderTypes';
import { gracefullyCloseAll } from '../utils/processLauncher';
import type { Browser } from './browser';
import type { BrowserContext } from './browserContext';
@ -29,7 +29,8 @@ const internalMetadata = serverSideCallMetadata();
export class ReuseController extends SdkObject {
static Events = {
BrowsersChanged: 'browsersChanged',
InspectRequested: 'inspectRequested'
InspectRequested: 'inspectRequested',
SourcesChanged: 'sourcesChanged',
};
private _autoCloseTimer: NodeJS.Timeout | undefined;
@ -61,9 +62,9 @@ export class ReuseController extends SdkObject {
onPageNavigated: () => this._emitSnapshot(),
onPageClose: () => this._emitSnapshot(),
};
this.instrumentation.addListener(this._trackHierarchyListener, null);
this._playwright.instrumentation.addListener(this._trackHierarchyListener, null);
} else if (!enabled && this._trackHierarchyListener) {
this.instrumentation.removeListener(this._trackHierarchyListener);
this._playwright.instrumentation.removeListener(this._trackHierarchyListener);
this._trackHierarchyListener = undefined;
}
}
@ -216,4 +217,8 @@ class InspectingRecorderApp extends EmptyRecorderApp {
override async setSelector(selector: string): Promise<void> {
this._reuseController.emit(ReuseController.Events.InspectRequested, selector);
}
override async setSources(sources: Source[]): Promise<void> {
this._reuseController.emit(ReuseController.Events.SourcesChanged, sources);
}
}

View File

@ -16,7 +16,7 @@
import './callLog.css';
import * as React from 'react';
import type { CallLog } from '@playwright-core/server/recorder/recorderTypes';
import type { CallLog } from './recorderTypes';
import { msToString } from '@web/uiUtils';
export interface CallLogProps {
@ -54,7 +54,7 @@ export const CallLogView: React.FC<CallLogProps> = ({
{ message.trim() }
</div>;
})}
{ !!callLog.error && <div className='call-log-message error' hidden={!isExpanded}>{ callLog.error.error?.message }</div> }
{ !!callLog.error && <div className='call-log-message error' hidden={!isExpanded}>{ callLog.error }</div> }
</div>;
})}
<div ref={messagesEndRef}></div>

View File

@ -14,21 +14,11 @@
limitations under the License.
*/
import type { CallLog, Mode, Source } from '@playwright-core/server/recorder/recorderTypes';
import type { CallLog, Mode, Source } from './recorderTypes';
import * as React from 'react';
import { Recorder } from './recorder';
import './recorder.css';
declare global {
interface Window {
playwrightSetMode: (mode: Mode) => void;
playwrightSetPaused: (paused: boolean) => void;
playwrightSetSources: (sources: Source[]) => void;
playwrightUpdateLogs: (callLogs: CallLog[]) => void;
playwrightSourcesEchoForTest: Source[];
}
}
export const Main: React.FC = ({
}) => {
const [sources, setSources] = React.useState<Source[]>([]);

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
import type { CallLog, Mode, Source } from '@playwright-core/server/recorder/recorderTypes';
import type { CallLog, Mode, Source } from './recorderTypes';
import { Source as SourceView } from '@web/components/source';
import { SplitView } from '@web/components/splitView';
import { Toolbar } from '@web/components/toolbar';

View File

@ -0,0 +1,76 @@
/*
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.
*/
export type Point = { x: number, y: number };
export type Mode = 'inspecting' | 'recording' | 'none';
export type EventData = {
event: 'clear' | 'resume' | 'step' | 'pause' | 'setMode' | 'selectorUpdated';
params: any;
};
export type UIState = {
mode: Mode;
actionPoint?: Point;
actionSelector?: string;
};
export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused';
export type CallLog = {
id: string;
title: string;
messages: string[];
status: CallLogStatus;
error?: string;
reveal?: boolean;
duration?: number;
params: {
url?: string,
selector?: string,
};
};
export type SourceHighlight = {
line: number;
type: 'running' | 'paused' | 'error';
};
export type Source = {
isRecorded: boolean;
id: string;
label: string;
text: string;
language: string;
highlight: SourceHighlight[];
revealLine?: number;
// used to group the language generators
group?: string;
};
declare global {
interface Window {
playwrightSetMode: (mode: Mode) => void;
playwrightSetPaused: (paused: boolean) => void;
playwrightSetSources: (sources: Source[]) => void;
playwrightUpdateLogs: (callLogs: CallLog[]) => void;
playwrightSetFileIfNeeded: (file: string) => void;
playwrightSetSelector: (selector: string, focus?: boolean) => void;
playwrightSourcesEchoForTest: Source[];
dispatch(data: any): Promise<void>;
}
}

View File

@ -18,7 +18,6 @@
"useUnknownInCatchVariables": false,
"paths": {
"@web/*": ["../web/src/*"],
"@playwright-core/*": ["../playwright-core/src/*"],
}
},
"include": ["src"],

View File

@ -16,6 +16,7 @@
"jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@recorder/*": ["../recorder/src/*"],
"@web/*": ["../web/src/*"],
"@playwright-core/*": ["../playwright-core/src/*"],
},

View File

@ -17,7 +17,7 @@
import { contextTest } from '../../config/browserTest';
import type { ConsoleMessage, Page } from 'playwright-core';
import * as path from 'path';
import type { Source } from '../../../packages/playwright-core/src/server/recorder/recorderTypes';
import type { Source } from '../../../packages/recorder/src/recorderTypes';
import type { CommonFixtures, TestChildProcess } from '../../config/commonFixtures';
export { expect } from '@playwright/test';

View File

@ -11,6 +11,7 @@
- playwright-core/lib means require dependency
*/
"@playwright-core/*": ["./packages/playwright-core/src/*"],
"@recorder/*": ["./packages/recorder/src/*"],
"playwright-core/lib/*": ["./packages/playwright-core/src/*"]
},
"esModuleInterop": true,