* add webview test

* pass browser launcher in from binder

* only run webview test on the windows platform with pipeline support for edge

* updated webview demo to build a portable release version of WebView2Sample.exe per https://github.com/MicrosoftEdge/WebView2Samples/pull/16

* update webview readme
This commit is contained in:
John 2020-02-12 08:41:17 -08:00 коммит произвёл GitHub
Родитель 5de1b34c42
Коммит 81693fe224
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 109 добавлений и 17 удалений

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

@ -19,4 +19,14 @@ jobs:
pool:
vmImage: 'vs2017-win2016'
steps:
- powershell: |
# This step can be removed once Edge is included on the test VM image.
# The download URI comes from: https://www.microsoftedgeinsider.com/en-us/download
$InstallerDownloadURI = "https://go.microsoft.com/fwlink/?linkid=2084649&Channel=Canary&language=en&Consent=1"
$InstallerExe = "$ENV:BUILD_ARTIFACTSTAGINGDIRECTORY\MicrosoftEdgeSetup.exe"
Invoke-WebRequest -Uri $InstallerDownloadURI -OutFile $InstallerExe
Start-Process $InstallerExe -Wait -ArgumentList '/silent /install'
# Cleanup installer
Remove-Item $InstallerExe
displayName: Install Edge Canary
- template: common-validation.yml

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

@ -103,6 +103,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

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

@ -21,6 +21,5 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="$(MSBuildThisFileDirectory)$(EffectivePlatform)\WebView2Loader.dll" />
</ItemGroup>
</Project>

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

@ -43,7 +43,7 @@ const packageJson = require('../../package.json');
export interface IBinderDelegate {
acquireDap(target: ITarget): Promise<DapConnection>;
// Returns whether we should disable child session treatment.
initAdapter(debugAdapter: DebugAdapter, target: ITarget): Promise<boolean>;
initAdapter(debugAdapter: DebugAdapter, target: ITarget, launcher: ILauncher): Promise<boolean>;
releaseDap(target: ITarget): void;
}
@ -84,7 +84,7 @@ export class Binder implements IDisposable {
launcher.onTargetListChanged(
() => {
const targets = this.targetList();
this._attachToNewTargets(targets);
this._attachToNewTargets(targets, launcher);
this._detachOrphanThreads(targets);
this._onTargetListChangedEmitter.fire();
},
@ -322,7 +322,7 @@ export class Binder implements IDisposable {
return result;
}
async attach(target: ITarget) {
async attach(target: ITarget, launcher: ILauncher) {
if (!target.canAttach()) return;
const cdp = await target.attach();
if (!cdp) return;
@ -357,7 +357,7 @@ export class Binder implements IDisposable {
cdp.Runtime.runIfWaitingForDebugger({});
return {};
};
if (await this._delegate.initAdapter(debugAdapter, target)) {
if (await this._delegate.initAdapter(debugAdapter, target, launcher)) {
startThread();
} else {
dap.on('attach', startThread);
@ -386,7 +386,7 @@ export class Binder implements IDisposable {
this._releaseTarget(target);
}
_attachToNewTargets(targets: ITarget[]) {
_attachToNewTargets(targets: ITarget[], launcher: ILauncher) {
for (const target of targets.values()) {
if (!target.waitingForDebugger()) {
continue;
@ -394,7 +394,7 @@ export class Binder implements IDisposable {
const thread = this._threads.get(target);
if (!thread) {
this.attach(target);
this.attach(target, launcher);
}
}
}

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

@ -19,10 +19,10 @@ import {
INodeLaunchConfiguration,
nodeAttachConfigDefaults,
nodeLaunchConfigDefaults,
AnyChromiumLaunchConfiguration,
} from '../configuration';
import Dap from '../dap/api';
import DapConnection from '../dap/connection';
import { ChromeLauncher } from '../targets/browser/chromeLauncher';
import { ITarget } from '../targets/targets';
import { GoldenText } from './goldenText';
import { Logger } from './logger';
@ -32,6 +32,7 @@ import { TelemetryReporter } from '../telemetry/telemetryReporter';
import { ILogger } from '../common/logging';
import { Logger as AdapterLogger } from '../common/logging/logger';
import { createTopLevelSessionContainer, createGlobalContainer } from '../ioc';
import { BrowserLauncher } from '../targets/browser/browserLauncher';
export const kStabilizeNames = ['id', 'threadId', 'sourceReference', 'variablesReference'];
@ -112,7 +113,11 @@ export interface ITestHandle {
readonly assertLog: AssertLog;
load(): Promise<void>;
_init(adapter: DebugAdapter, target: ITarget): Promise<boolean>;
_init(
adapter: DebugAdapter,
target: ITarget,
launcher: BrowserLauncher<AnyChromiumLaunchConfiguration>,
): Promise<boolean>;
}
export class TestP implements ITestHandle {
@ -196,7 +201,11 @@ export class TestP implements ITestHandle {
return this._root.workspacePath(relative);
}
async _init(adapter: DebugAdapter) {
async _init(
adapter: DebugAdapter,
_target: ITarget,
launcher: BrowserLauncher<AnyChromiumLaunchConfiguration>,
) {
adapter.breakpointManager.setPredictorDisabledForTest(true);
adapter.sourceContainer.setSourceMapTimeouts({
load: 0,
@ -206,7 +215,8 @@ export class TestP implements ITestHandle {
});
this._adapter = adapter;
this._connection = this._root._browserLauncher.connectionForTest()!;
this._root._browserLauncher = launcher;
this._connection = this._root._browserLauncher?.connectionForTest()!;
const result = await this._connection.rootSession().Target.attachToBrowserTarget({});
const testSession = this._connection.createSession(result!.sessionId);
const { sessionId } = (await testSession.Target.attachToTarget({
@ -306,7 +316,7 @@ export class TestRoot {
private _workerCallback: (session: ITestHandle) => void;
private _launchCallback: (session: ITestHandle) => void;
_browserLauncher: ChromeLauncher;
_browserLauncher: BrowserLauncher<AnyChromiumLaunchConfiguration> | undefined;
readonly binder: Binder;
private _onSessionCreatedEmitter = new EventEmitter<ITestHandle>();
@ -337,7 +347,7 @@ export class TestRoot {
const services = createTopLevelSessionContainer(
createGlobalContainer({ storagePath, isVsCode: true }),
);
this._browserLauncher = services.get(ChromeLauncher);
this.binder = new Binder(
this,
this._root.adapterConnection,
@ -359,13 +369,17 @@ export class TestRoot {
return p._session.adapterConnection;
}
async initAdapter(adapter: DebugAdapter, target: ITarget): Promise<boolean> {
async initAdapter(
adapter: DebugAdapter,
target: ITarget,
launcher: BrowserLauncher<AnyChromiumLaunchConfiguration>,
): Promise<boolean> {
const p = this._targetToP.get(target);
if (!p) {
return true;
}
const boot = await p._init(adapter, target);
const boot = await p._init(adapter, target, launcher);
if (target.parent()) this._workerCallback(p);
else this._launchCallback(p);
this._onSessionCreatedEmitter.fire(p);
@ -489,7 +503,7 @@ export class TestRoot {
async disconnect(): Promise<void> {
return new Promise<void>(cb => {
this.initialize.then(() => {
const connection = this._browserLauncher.connectionForTest();
const connection = this._browserLauncher?.connectionForTest();
if (connection) {
const disposable = connection.onDisconnected(() => {
cb();

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

@ -87,7 +87,16 @@ export async function run(): Promise<void> {
runner.addFile(join(__dirname, 'console/consoleAPITest'));
runner.addFile(join(__dirname, 'extension/nodeConfigurationProvidersTests'));
for (const file of glob.sync('**/*.test.js', { cwd: __dirname })) {
const options = { cwd: __dirname };
const files = glob.sync('**/*.test.js', options);
// Only run tests on supported platforms
// https://nodejs.org/api/process.html#process_process_platform
if (process.platform === 'win32') {
files.push(...glob.sync('**/*.test.win.js', options));
}
for (const file of files) {
runner.addFile(join(__dirname, file));
}
}

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

@ -0,0 +1,16 @@
{
allThreadsStopped : false
description : Paused on debugger statement
reason : pause
threadId : <number>
}
<anonymous> @ ${workspaceFolder}/web/script.js:10:1
{
allThreadsStopped : false
description : Paused on breakpoint
reason : breakpoint
threadId : <number>
}
bar @ ${workspaceFolder}/web/script.js:6:3
foo @ ${workspaceFolder}/web/script.js:2:3
<anonymous> @ ${workspaceFolder}/web/script.js:11:1

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

@ -0,0 +1,39 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import { ITestHandle } from '../test';
import Dap from '../../dap/api';
import { itIntegrates } from '../testIntegrationUtils';
import { IChromeLaunchConfiguration } from '../../configuration';
import { DebugType } from '../../common/contributionUtils';
describe('webview breakpoints', () => {
async function waitForPause(p: ITestHandle, cb?: (threadId: string) => Promise<void>) {
const { threadId } = p.log(await p.dap.once('stopped'));
await p.logger.logStackTrace(threadId);
if (cb) await cb(threadId);
return p.dap.continue({ threadId });
}
itIntegrates('launched script', async ({ r }) => {
// Breakpoint in separate script set after launch.
const p = await r.launchUrl('script.html', ({
type: DebugType.Edge,
runtimeExecutable: r.workspacePath('webview/win/WebView2Sample.exe'),
useWebView: true,
// WebView2Sample.exe launches about:blank
urlFilter: 'about:blank',
// TODO: Test.launchUrl should support AnyLaunchConfiguration
} as unknown) as IChromeLaunchConfiguration);
p.load();
await waitForPause(p, async () => {
const source: Dap.Source = {
path: p.workspacePath('web/script.js'),
};
await p.dap.setBreakpoints({ source, breakpoints: [{ line: 6 }] });
});
await waitForPause(p);
p.assertLog();
});
});

2
testWorkspace/webview/win/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
# User directories created by WebView application
WebView2Sample.exe.WebView2*/

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

@ -0,0 +1,2 @@
The WebView2Sample.exe is a Release x64 build.
The source code can be found in `demos\webview`.

Двоичные данные
testWorkspace/webview/win/WebView2Loader.dll Normal file

Двоичный файл не отображается.

Двоичные данные
testWorkspace/webview/win/WebView2Sample.exe Normal file

Двоичный файл не отображается.

Двоичные данные
testWorkspace/webview/win/WebView2Sample.pdb Normal file

Двоичный файл не отображается.