angular-cn/packages/benchpress/src/webdriver/ios_driver_extension.ts

127 lines
4.2 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable} from '@angular/core';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
@Injectable()
export class IOsDriverExtension extends WebDriverExtension {
static PROVIDERS = [IOsDriverExtension];
constructor(private _driver: WebDriverAdapter) { super(); }
gc(): Promise<any> { throw new Error('Force GC is not supported on iOS'); }
timeBegin(name: string): Promise<any> {
return this._driver.executeScript(`console.time('${name}');`);
}
timeEnd(name: string, restartName: string|null = null): Promise<any> {
let script = `console.timeEnd('${name}');`;
if (restartName != null) {
script += `console.time('${restartName}');`;
}
return this._driver.executeScript(script);
}
// See https://github.com/WebKit/webkit/tree/master/Source/WebInspectorUI/Versions
readPerfLog() {
// TODO(tbosch): Bug in IOsDriver: Need to execute at least one command
// so that the browser logs can be read out!
return this._driver.executeScript('1+1')
.then((_) => this._driver.logs('performance'))
.then((entries) => {
const records: any[] = [];
entries.forEach((entry: any) => {
const message = JSON.parse(entry['message'])['message'];
if (message['method'] === 'Timeline.eventRecorded') {
records.push(message['params']['record']);
}
});
return this._convertPerfRecordsToEvents(records);
});
}
/** @internal */
private _convertPerfRecordsToEvents(records: any[], events: PerfLogEvent[]|null = null) {
if (!events) {
events = [];
}
records.forEach((record) => {
let endEvent: PerfLogEvent|null = null;
const type = record['type'];
const data = record['data'];
const startTime = record['startTime'];
const endTime = record['endTime'];
if (type === 'FunctionCall' && (data == null || data['scriptName'] !== 'InjectedScript')) {
events !.push(createStartEvent('script', startTime));
endEvent = createEndEvent('script', endTime);
} else if (type === 'Time') {
events !.push(createMarkStartEvent(data['message'], startTime));
} else if (type === 'TimeEnd') {
events !.push(createMarkEndEvent(data['message'], startTime));
} else if (
type === 'RecalculateStyles' || type === 'Layout' || type === 'UpdateLayerTree' ||
type === 'Paint' || type === 'Rasterize' || type === 'CompositeLayers') {
events !.push(createStartEvent('render', startTime));
endEvent = createEndEvent('render', endTime);
}
// Note: ios used to support GCEvent up until iOS 6 :-(
if (record['children'] != null) {
this._convertPerfRecordsToEvents(record['children'], events);
}
if (endEvent != null) {
events !.push(endEvent);
}
});
return events;
}
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true}); }
supports(capabilities: {[key: string]: any}): boolean {
return capabilities['browserName'].toLowerCase() === 'safari';
}
}
function createEvent(
ph: 'X' | 'B' | 'E' | 'B' | 'E', name: string, time: number, args: any = null) {
const result: PerfLogEvent = {
'cat': 'timeline',
'name': name,
'ts': time,
'ph': ph,
// The ios protocol does not support the notions of multiple processes in
// the perflog...
'pid': 'pid0'
};
if (args != null) {
result['args'] = args;
}
return result;
}
function createStartEvent(name: string, time: number, args: any = null) {
return createEvent('B', name, time, args);
}
function createEndEvent(name: string, time: number, args: any = null) {
return createEvent('E', name, time, args);
}
function createMarkStartEvent(name: string, time: number) {
return createEvent('B', name, time);
}
function createMarkEndEvent(name: string, time: number) {
return createEvent('E', name, time);
}