2016-08-03 18:00:07 -04:00
|
|
|
/**
|
|
|
|
* @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 {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
|
2016-08-03 15:32:26 -04:00
|
|
|
import {Json, isBlank, isPresent} from '@angular/facade/src/lang';
|
2016-08-02 18:53:34 -04:00
|
|
|
import {IOsDriverExtension, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from 'benchpress/common';
|
2015-05-27 17:57:54 -04:00
|
|
|
|
|
|
|
import {TraceEventFactory} from '../trace_event_factory';
|
|
|
|
|
|
|
|
export function main() {
|
|
|
|
describe('ios driver extension', () => {
|
|
|
|
var log;
|
|
|
|
var extension;
|
|
|
|
|
|
|
|
var normEvents = new TraceEventFactory('timeline', 'pid0');
|
|
|
|
|
2016-02-19 14:49:31 -05:00
|
|
|
function createExtension(perfRecords = null): WebDriverExtension {
|
2015-05-27 17:57:54 -04:00
|
|
|
if (isBlank(perfRecords)) {
|
|
|
|
perfRecords = [];
|
|
|
|
}
|
|
|
|
log = [];
|
2016-08-03 18:00:07 -04:00
|
|
|
extension =
|
|
|
|
ReflectiveInjector
|
|
|
|
.resolveAndCreate([
|
|
|
|
IOsDriverExtension.PROVIDERS,
|
|
|
|
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)}
|
|
|
|
])
|
|
|
|
.get(IOsDriverExtension);
|
2015-05-27 17:57:54 -04:00
|
|
|
return extension;
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should throw on forcing gc', () => {
|
|
|
|
expect(() => createExtension().gc()).toThrowError('Force GC is not supported on iOS');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension().timeBegin('someName').then((_) => {
|
|
|
|
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension().timeEnd('someName', null).then((_) => {
|
|
|
|
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
it('should mark the timeline via console.time() and console.timeEnd()',
|
|
|
|
inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension().timeEnd('name1', 'name2').then((_) => {
|
|
|
|
expect(log).toEqual(
|
|
|
|
[['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
describe('readPerfLog', () => {
|
|
|
|
|
|
|
|
it('should execute a dummy script before reading them',
|
|
|
|
inject([AsyncTestCompleter], (async) => {
|
|
|
|
// TODO(tbosch): This seems to be a bug in ChromeDriver:
|
|
|
|
// Sometimes it does not report the newest events of the performance log
|
|
|
|
// to the WebDriver client unless a script is executed...
|
|
|
|
createExtension([]).readPerfLog().then((_) => {
|
|
|
|
expect(log).toEqual([['executeScript', '1+1'], ['logs', 'performance']]);
|
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should report FunctionCall records as "script"', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension([durationRecord('FunctionCall', 1, 5)]).readPerfLog().then((events) => {
|
|
|
|
expect(events).toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension([internalScriptRecord(1, 5)]).readPerfLog().then((events) => {
|
|
|
|
expect(events).toEqual([]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
it('should report begin time', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension([timeBeginRecord('someName', 12)]).readPerfLog().then((events) => {
|
|
|
|
expect(events).toEqual([normEvents.markStart('someName', 12)]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
it('should report end timestamps', inject([AsyncTestCompleter], (async) => {
|
2016-08-03 18:00:07 -04:00
|
|
|
createExtension([timeEndRecord('someName', 12)]).readPerfLog().then((events) => {
|
|
|
|
expect(events).toEqual([normEvents.markEnd('someName', 12)]);
|
|
|
|
async.done();
|
|
|
|
});
|
2015-05-27 17:57:54 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint', 'Rasterize', 'CompositeLayers']
|
|
|
|
.forEach((recordType) => {
|
|
|
|
it(`should report ${recordType}`, inject([AsyncTestCompleter], (async) => {
|
|
|
|
createExtension([durationRecord(recordType, 0, 1)])
|
|
|
|
.readPerfLog()
|
|
|
|
.then((events) => {
|
|
|
|
expect(events).toEqual([
|
|
|
|
normEvents.start('render', 0),
|
|
|
|
normEvents.end('render', 1),
|
|
|
|
]);
|
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('should walk children', inject([AsyncTestCompleter], (async) => {
|
|
|
|
createExtension([durationRecord('FunctionCall', 1, 5, [timeBeginRecord('someName', 2)])])
|
|
|
|
.readPerfLog()
|
|
|
|
.then((events) => {
|
|
|
|
expect(events).toEqual([
|
2016-08-03 18:00:07 -04:00
|
|
|
normEvents.start('script', 1), normEvents.markStart('someName', 2),
|
2015-05-27 17:57:54 -04:00
|
|
|
normEvents.end('script', 5)
|
|
|
|
]);
|
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should match safari browsers', () => {
|
|
|
|
expect(createExtension().supports({'browserName': 'safari'})).toBe(true);
|
|
|
|
|
|
|
|
expect(createExtension().supports({'browserName': 'Safari'})).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function timeBeginRecord(name, time) {
|
|
|
|
return {'type': 'Time', 'startTime': time, 'data': {'message': name}};
|
|
|
|
}
|
|
|
|
|
|
|
|
function timeEndRecord(name, time) {
|
|
|
|
return {'type': 'TimeEnd', 'startTime': time, 'data': {'message': name}};
|
|
|
|
}
|
|
|
|
|
|
|
|
function durationRecord(type, startTime, endTime, children = null) {
|
|
|
|
if (isBlank(children)) {
|
|
|
|
children = [];
|
|
|
|
}
|
|
|
|
return {'type': type, 'startTime': startTime, 'endTime': endTime, 'children': children};
|
|
|
|
}
|
|
|
|
|
|
|
|
function internalScriptRecord(startTime, endTime) {
|
|
|
|
return {
|
|
|
|
'type': 'FunctionCall',
|
|
|
|
'startTime': startTime,
|
|
|
|
'endTime': endTime,
|
|
|
|
'data': {'scriptName': 'InjectedScript'}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
class MockDriverAdapter extends WebDriverAdapter {
|
2015-08-28 14:29:19 -04:00
|
|
|
constructor(private _log: any[], private _perfRecords: any[]) { super(); }
|
2015-05-27 17:57:54 -04:00
|
|
|
|
|
|
|
executeScript(script) {
|
2015-06-17 14:17:21 -04:00
|
|
|
this._log.push(['executeScript', script]);
|
2016-08-02 18:53:34 -04:00
|
|
|
return Promise.resolve(null);
|
2015-05-27 17:57:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
logs(type) {
|
2015-06-17 14:17:21 -04:00
|
|
|
this._log.push(['logs', type]);
|
2015-05-27 17:57:54 -04:00
|
|
|
if (type === 'performance') {
|
2016-08-02 18:53:34 -04:00
|
|
|
return Promise.resolve(this._perfRecords.map(function(record) {
|
2015-05-27 17:57:54 -04:00
|
|
|
return {
|
|
|
|
'message': Json.stringify(
|
|
|
|
{'message': {'method': 'Timeline.eventRecorded', 'params': {'record': record}}})
|
|
|
|
};
|
|
|
|
}));
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|