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
|
|
|
|
*/
|
|
|
|
|
2017-03-02 15:12:46 -05:00
|
|
|
import {AsyncTestCompleter, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal';
|
2015-05-27 17:57:54 -04:00
|
|
|
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 15:33:29 -04:00
|
|
|
import {IOsDriverExtension, Injector, WebDriverAdapter, WebDriverExtension} from '../../index';
|
2015-05-27 17:57:54 -04:00
|
|
|
import {TraceEventFactory} from '../trace_event_factory';
|
|
|
|
|
2017-12-16 17:42:55 -05:00
|
|
|
{
|
2015-05-27 17:57:54 -04:00
|
|
|
describe('ios driver extension', () => {
|
2016-11-12 08:08:58 -05:00
|
|
|
let log: any[];
|
|
|
|
let extension: IOsDriverExtension;
|
2015-05-27 17:57:54 -04:00
|
|
|
|
2016-11-12 08:08:58 -05:00
|
|
|
const normEvents = new TraceEventFactory('timeline', 'pid0');
|
2015-05-27 17:57:54 -04:00
|
|
|
|
2017-03-24 12:56:50 -04:00
|
|
|
function createExtension(perfRecords: any[] | null = null): WebDriverExtension {
|
2016-09-30 12:26:53 -04:00
|
|
|
if (!perfRecords) {
|
2015-05-27 17:57:54 -04:00
|
|
|
perfRecords = [];
|
|
|
|
}
|
|
|
|
log = [];
|
2016-08-03 18:00:07 -04:00
|
|
|
extension =
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 15:33:29 -04:00
|
|
|
Injector
|
|
|
|
.create([
|
2016-08-03 18:00:07 -04:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should mark the timeline via console.time()',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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
|
|
|
}));
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should mark the timeline via console.timeEnd()',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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()',
|
2016-08-26 19:34:08 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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',
|
2016-08-26 19:34:08 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-05-27 17:57:54 -04:00
|
|
|
// 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();
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should report FunctionCall records as "script"',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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
|
|
|
}));
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should ignore FunctionCalls from webdriver',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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
|
|
|
}));
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should report begin time', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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
|
|
|
}));
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should report end timestamps',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
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) => {
|
2016-08-26 19:34:08 -04:00
|
|
|
it(`should report ${recordType}`,
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-05-27 17:57:54 -04:00
|
|
|
createExtension([durationRecord(recordType, 0, 1)])
|
|
|
|
.readPerfLog()
|
|
|
|
.then((events) => {
|
|
|
|
expect(events).toEqual([
|
|
|
|
normEvents.start('render', 0),
|
|
|
|
normEvents.end('render', 1),
|
|
|
|
]);
|
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
it('should walk children', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-05-27 17:57:54 -04:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
function timeBeginRecord(name: string, time: number) {
|
2015-05-27 17:57:54 -04:00
|
|
|
return {'type': 'Time', 'startTime': time, 'data': {'message': name}};
|
|
|
|
}
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
function timeEndRecord(name: string, time: number) {
|
2015-05-27 17:57:54 -04:00
|
|
|
return {'type': 'TimeEnd', 'startTime': time, 'data': {'message': name}};
|
|
|
|
}
|
|
|
|
|
2017-03-24 12:56:50 -04:00
|
|
|
function durationRecord(
|
|
|
|
type: string, startTime: number, endTime: number, children: any[] | null = null) {
|
2016-09-30 12:26:53 -04:00
|
|
|
if (!children) {
|
2015-05-27 17:57:54 -04:00
|
|
|
children = [];
|
|
|
|
}
|
|
|
|
return {'type': type, 'startTime': startTime, 'endTime': endTime, 'children': children};
|
|
|
|
}
|
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
function internalScriptRecord(startTime: number, endTime: number) {
|
2015-05-27 17:57:54 -04:00
|
|
|
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
|
|
|
|
2016-08-26 19:34:08 -04:00
|
|
|
executeScript(script: string) {
|
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
|
|
|
}
|
|
|
|
|
2017-03-24 12:56:50 -04:00
|
|
|
logs(type: string): Promise<any[]> {
|
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 {
|
2016-10-19 16:42:39 -04:00
|
|
|
'message': JSON.stringify(
|
|
|
|
{'message': {'method': 'Timeline.eventRecorded', 'params': {'record': record}}}, null,
|
|
|
|
2)
|
2015-05-27 17:57:54 -04:00
|
|
|
};
|
|
|
|
}));
|
|
|
|
} else {
|
2017-03-24 12:56:50 -04:00
|
|
|
return null !;
|
2015-05-27 17:57:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|