feat(perf): add AngularDart v1 of table scrolling benchmark
This commit is contained in:
parent
474f1768c6
commit
737914061f
|
@ -0,0 +1,33 @@
|
|||
var perfUtil = require('../../e2e_test_lib/e2e_test/perf_util');
|
||||
|
||||
describe('ng-dart1.x naive infinite scroll benchmark', function () {
|
||||
|
||||
var URL = 'benchmarks_external/web/naive_infinite_scroll/index.html';
|
||||
|
||||
afterEach(perfUtil.verifyNoBrowserErrors);
|
||||
|
||||
[1, 2, 4].forEach(function(appSize) {
|
||||
it('should run scroll benchmark and collect stats for appSize = ' +
|
||||
appSize, function() {
|
||||
perfUtil.runBenchmark({
|
||||
url: URL,
|
||||
id: 'ng1-dart1.x.naive_infinite_scroll',
|
||||
work: function() {
|
||||
browser.executeScript(
|
||||
'document.querySelector("scroll-app /deep/ #reset-btn").click()');
|
||||
browser.executeScript(
|
||||
'document.querySelector("scroll-app /deep/ #run-btn").click()');
|
||||
browser.sleep(1000);
|
||||
},
|
||||
params: [{
|
||||
name: 'appSize', value: appSize
|
||||
}, {
|
||||
name: 'iterationCount', value: 20, scale: 'linear'
|
||||
}, {
|
||||
name: 'scrollIncrement', value: 40
|
||||
}]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
var testUtil = require('../../e2e_test_lib/e2e_test/test_util');
|
||||
|
||||
describe('ng-dart1.x naive infinite scroll benchmark', function () {
|
||||
|
||||
var URL = 'benchmarks_external/web/naive_infinite_scroll/index.html';
|
||||
|
||||
afterEach(testUtil.verifyNoBrowserErrors);
|
||||
|
||||
it('should not throw errors', function() {
|
||||
browser.get(URL);
|
||||
browser.executeScript(
|
||||
'document.querySelector("scroll-app /deep/ #reset-btn").click()');
|
||||
browser.executeScript(
|
||||
'document.querySelector("scroll-app /deep/ #run-btn").click()');
|
||||
browser.sleep(1000);
|
||||
});
|
||||
|
||||
});
|
|
@ -4,7 +4,11 @@ environment:
|
|||
dependencies:
|
||||
e2e_test_lib:
|
||||
path: ../e2e_test_lib
|
||||
angular: ">=1.0.0 <2.0.0"
|
||||
angular: '>=1.0.0 <2.0.0'
|
||||
browser: '>=0.10.0 <0.11.0'
|
||||
fixnum: '>=0.9.0 <1.0.0'
|
||||
transformers:
|
||||
- angular
|
||||
- angular:
|
||||
html_files:
|
||||
- web/naive_infinite_scroll/scroll_area.html
|
||||
- web/naive_infinite_scroll/scroll_item.html
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
<li>
|
||||
<a href="largetable/largetable_benchmark.html">Largetable benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="naive_infinite_scroll/index.html">Naive infinite scroll benchmark</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
library scroll_app;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
import 'package:angular/angular.dart';
|
||||
import 'package:e2e_test_lib/benchmark_util.dart';
|
||||
|
||||
@Component(
|
||||
selector: 'scroll-app',
|
||||
template: '''
|
||||
<div>
|
||||
<div style="display: flex">
|
||||
<scroll-area scroll-top="scrollTop"></scroll-area>
|
||||
<div style="padding-left: 20px">
|
||||
<button id='run-btn'>Run</button>
|
||||
<button id='reset-btn'>Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="scrollAreas.length > 0">
|
||||
<p>Following tables are only here to add weight to the UI:</p>
|
||||
<scroll-area ng-repeat="scrollArea in scrollAreas"></scroll-area>
|
||||
</div>
|
||||
</div>
|
||||
''')
|
||||
class App implements ShadowRootAware {
|
||||
final VmTurnZone ngZone;
|
||||
List<int> scrollAreas;
|
||||
int scrollTop = 0;
|
||||
int iterationCount;
|
||||
int scrollIncrement;
|
||||
|
||||
App(this.ngZone) {
|
||||
int appSize = getIntParameter('appSize');
|
||||
iterationCount = getIntParameter('iterationCount');
|
||||
scrollIncrement = getIntParameter('scrollIncrement');
|
||||
appSize = appSize > 1 ? appSize - 1 : 0; // draw at least one table
|
||||
scrollAreas = new List.generate(appSize, (i) => i);
|
||||
}
|
||||
|
||||
@override
|
||||
void onShadowRoot(ShadowRoot shadowRoot) {
|
||||
bindAction('scroll-app /deep/ #run-btn', () {
|
||||
runBenchmark();
|
||||
});
|
||||
bindAction('scroll-app /deep/ #reset-btn', () {
|
||||
scrollTop = 0;
|
||||
});
|
||||
}
|
||||
|
||||
void runBenchmark() {
|
||||
int n = iterationCount;
|
||||
scheduleScroll() {
|
||||
new Future(() {
|
||||
scrollTop += scrollIncrement;
|
||||
n--;
|
||||
if (n > 0) {
|
||||
scheduleScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
scheduleScroll();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
library cells;
|
||||
|
||||
import 'package:angular/angular.dart';
|
||||
import 'common.dart';
|
||||
|
||||
@Component(
|
||||
selector: 'company-name',
|
||||
template: '''
|
||||
<div style="width: {{width}}">{{company.name}}</div>
|
||||
''',
|
||||
map: const {
|
||||
'company': '=>company',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class CompanyNameComponent {
|
||||
String width;
|
||||
Company company;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'opportunity-name',
|
||||
template: '''
|
||||
<div style="width: {{width}}">{{opportunity.name}}</div>
|
||||
''',
|
||||
map: const {
|
||||
'opportunity': '=>opportunity',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class OpportunityNameComponent {
|
||||
String width;
|
||||
Opportunity opportunity;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'offering-name',
|
||||
template: '''
|
||||
<div style="width: {{width}}">{{offering.name}}</div>
|
||||
''',
|
||||
map: const {
|
||||
'offering': '=>offering',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class OfferingNameComponent {
|
||||
String width;
|
||||
Offering offering;
|
||||
}
|
||||
|
||||
class Stage {
|
||||
String name;
|
||||
bool isDisabled;
|
||||
Map style;
|
||||
Function apply;
|
||||
|
||||
String get styleString => style != null
|
||||
? style.keys
|
||||
.map((prop) => '$prop: ${style[prop]}')
|
||||
.join(';')
|
||||
: '';
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'stage-buttons',
|
||||
template: '''
|
||||
<div style="width: {{width}}">
|
||||
<button ng-repeat="stage in stages"
|
||||
ng-disabled="stage.isDisabled"
|
||||
style="{{stage.styleString}}"
|
||||
ng-click="setStage(stage)">
|
||||
{{stage.name}}
|
||||
</button>
|
||||
</div>
|
||||
''',
|
||||
map: const {
|
||||
'offering': '=>offering',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class StageButtonsComponent {
|
||||
Offering _offering;
|
||||
List<Stage> stages;
|
||||
String width;
|
||||
|
||||
Offering get offering => _offering;
|
||||
set offering(Offering offering) {
|
||||
_offering = offering;
|
||||
_computeStageButtons();
|
||||
}
|
||||
|
||||
setStage(Stage stage) {
|
||||
_offering.status = stage.name;
|
||||
_computeStageButtons();
|
||||
}
|
||||
|
||||
_computeStageButtons() {
|
||||
bool disabled = true;
|
||||
stages = STATUS_LIST
|
||||
.map((String status) {
|
||||
bool isCurrent = offering.status == status;
|
||||
var stage = new Stage();
|
||||
stage
|
||||
..name = status
|
||||
..isDisabled = disabled
|
||||
..style = {
|
||||
'background-color': disabled
|
||||
? '#DDD'
|
||||
: isCurrent
|
||||
? '#DDF'
|
||||
: '#FDD'
|
||||
};
|
||||
if (isCurrent) {
|
||||
disabled = false;
|
||||
}
|
||||
return stage;
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'account-cell',
|
||||
template: '''
|
||||
<div style="width: {{width}}">
|
||||
<a href="/account/{{account.accountId}}">
|
||||
{{account.accountId}}
|
||||
</a>
|
||||
</div>
|
||||
''',
|
||||
map: const {
|
||||
'account': '=>account',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class AccountCellComponent {
|
||||
Account account;
|
||||
String width;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'formatted-cell',
|
||||
template: '''<div style="width: {{width}}">{{formattedValue}}</div>''',
|
||||
map: const {
|
||||
'value': '=>value',
|
||||
'cell-width': '=>width',
|
||||
})
|
||||
class FormattedCellComponent {
|
||||
String formattedValue;
|
||||
String width;
|
||||
|
||||
set value(dynamic value) {
|
||||
if (value is DateTime) {
|
||||
formattedValue = '${value.month}/${value.day}/${value.year}';
|
||||
} else {
|
||||
formattedValue = value.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
library common.stuff;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:observe/observe.dart';
|
||||
|
||||
const ITEMS = 1000;
|
||||
const ITEM_HEIGHT = 40;
|
||||
const VISIBLE_ITEMS = 17;
|
||||
|
||||
const HEIGHT = ITEMS * ITEM_HEIGHT;
|
||||
const VIEW_PORT_HEIGHT = ITEM_HEIGHT * VISIBLE_ITEMS;
|
||||
|
||||
const COMPANY_NAME_WIDTH = 100;
|
||||
const OPPORTUNITY_NAME_WIDTH = 100;
|
||||
const OFFERING_NAME_WIDTH = 100;
|
||||
const ACCOUNT_CELL_WIDTH = 50;
|
||||
const BASE_POINTS_WIDTH = 50;
|
||||
const KICKER_POINTS_WIDTH = 50;
|
||||
const STAGE_BUTTONS_WIDTH = 220;
|
||||
const BUNDLES_WIDTH = 120;
|
||||
const DUE_DATE_WIDTH = 100;
|
||||
const END_DATE_WIDTH = 100;
|
||||
const AAT_STATUS_WIDTH = 100;
|
||||
const ROW_WIDTH = COMPANY_NAME_WIDTH +
|
||||
OPPORTUNITY_NAME_WIDTH +
|
||||
OFFERING_NAME_WIDTH +
|
||||
ACCOUNT_CELL_WIDTH +
|
||||
BASE_POINTS_WIDTH +
|
||||
KICKER_POINTS_WIDTH +
|
||||
STAGE_BUTTONS_WIDTH +
|
||||
BUNDLES_WIDTH +
|
||||
DUE_DATE_WIDTH +
|
||||
END_DATE_WIDTH +
|
||||
AAT_STATUS_WIDTH;
|
||||
|
||||
const STATUS_LIST = const [
|
||||
'Planned', 'Pitched', 'Won', 'Lost'
|
||||
];
|
||||
|
||||
const AAT_STATUS_LIST = const [
|
||||
'Active', 'Passive', 'Abandoned'
|
||||
];
|
||||
|
||||
// Imitate Streamy entities.
|
||||
|
||||
class RawEntity
|
||||
extends Object
|
||||
with MapMixin<String, dynamic>
|
||||
implements ObservableMap<String, dynamic> {
|
||||
|
||||
ObservableMap _data = new ObservableMap();
|
||||
|
||||
@override
|
||||
Iterable<String> get keys => _data.keys;
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
operator[](String key) {
|
||||
if (!key.contains('.')) {
|
||||
return _data[key];
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
return target[last];
|
||||
}
|
||||
|
||||
@override
|
||||
operator[]=(String key, value) {
|
||||
if (!key.contains('.')) {
|
||||
_data[key] = value;
|
||||
return;
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
target[last] = value;
|
||||
}
|
||||
|
||||
@override
|
||||
remove(String key) {
|
||||
if (!key.contains('.')) {
|
||||
return _data.remove(key);
|
||||
}
|
||||
var pieces = key.split('.');
|
||||
var last = pieces.removeLast();
|
||||
var target = _resolve(pieces, this);
|
||||
return target.remove(last);
|
||||
}
|
||||
|
||||
_resolve(List<String> pieces, start) {
|
||||
var cur = start;
|
||||
for (var i = 0; i < pieces.length; i++) {
|
||||
cur = cur[pieces[i]];
|
||||
if (cur == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<ChangeRecord>> get changes => _data.changes;
|
||||
@override
|
||||
bool get hasObservers => _data.hasObservers;
|
||||
@override
|
||||
bool deliverChanges() => _data.deliverChanges();
|
||||
@override
|
||||
notifyPropertyChange(Symbol field, Object oldValue, Object newValue) =>
|
||||
_data.notifyPropertyChange(field, oldValue, newValue);
|
||||
@override
|
||||
void notifyChange(ChangeRecord record) {
|
||||
_data.notifyChange(record);
|
||||
}
|
||||
@override
|
||||
void observed() {
|
||||
_data.observed();
|
||||
}
|
||||
@override
|
||||
void unobserved() {
|
||||
_data.observed();
|
||||
}
|
||||
}
|
||||
|
||||
class Company extends RawEntity {
|
||||
String get name => this['name'];
|
||||
set name(String val) {
|
||||
this['name'] = val;
|
||||
}
|
||||
}
|
||||
|
||||
class Offering extends RawEntity {
|
||||
String get name => this['name'];
|
||||
set name(String val) {
|
||||
this['name'] = val;
|
||||
}
|
||||
|
||||
Company get company => this['company'];
|
||||
set company(Company val) {
|
||||
this['company'] = val;
|
||||
}
|
||||
|
||||
Opportunity get opportunity => this['opportunity'];
|
||||
set opportunity(Opportunity val) {
|
||||
this['opportunity'] = val;
|
||||
}
|
||||
|
||||
Account get account => this['account'];
|
||||
set account(Account val) {
|
||||
this['account'] = val;
|
||||
}
|
||||
|
||||
int get basePoints => this['basePoints'];
|
||||
set basePoints(int val) {
|
||||
this['basePoints'] = val;
|
||||
}
|
||||
|
||||
int get kickerPoints => this['kickerPoints'];
|
||||
set kickerPoints(int val) {
|
||||
this['kickerPoints'] = val;
|
||||
}
|
||||
|
||||
String get status => this['status'];
|
||||
set status(String val) {
|
||||
this['status'] = val;
|
||||
}
|
||||
|
||||
String get bundles => this['bundles'];
|
||||
set bundles(String val) {
|
||||
this['bundles'] = val;
|
||||
}
|
||||
|
||||
DateTime get dueDate => this['dueDate'];
|
||||
set dueDate(DateTime val) {
|
||||
this['dueDate'] = val;
|
||||
}
|
||||
|
||||
DateTime get endDate => this['endDate'];
|
||||
set endDate(DateTime val) {
|
||||
this['endDate'] = val;
|
||||
}
|
||||
|
||||
String get aatStatus => this['aatStatus'];
|
||||
set aatStatus(String val) {
|
||||
this['aatStatus'] = val;
|
||||
}
|
||||
}
|
||||
|
||||
class Opportunity extends RawEntity {
|
||||
String get name => this['name'];
|
||||
set name(String val) {
|
||||
this['name'] = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Account extends RawEntity {
|
||||
Int64 get accountId => this['accountId'];
|
||||
set accountId(Int64 val) {
|
||||
this['accountId'] = val;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
library naive_infinite_scroll;
|
||||
|
||||
import 'package:angular/angular.dart';
|
||||
import 'package:angular/application_factory.dart';
|
||||
import 'app.dart';
|
||||
import 'scroll_area.dart';
|
||||
import 'scroll_item.dart';
|
||||
import 'cells.dart';
|
||||
|
||||
class MyAppModule extends Module {
|
||||
MyAppModule() {
|
||||
bind(ResourceResolverConfig, toValue: new ResourceResolverConfig.resolveRelativeUrls(false));
|
||||
bind(App);
|
||||
bind(ScrollAreaComponent);
|
||||
bind(ScrollItemComponent);
|
||||
bind(CompanyNameComponent);
|
||||
bind(OpportunityNameComponent);
|
||||
bind(OfferingNameComponent);
|
||||
bind(AccountCellComponent);
|
||||
bind(StageButtonsComponent);
|
||||
bind(FormattedCellComponent);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
applicationFactory()
|
||||
.addModule(new MyAppModule())
|
||||
.run();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>AngularDart Scrolling Benchmark</title>
|
||||
</head>
|
||||
<body>
|
||||
<form>
|
||||
App size: <input type="text" name="appSize" value="1"></input><br>
|
||||
Iteration count: <input type="text" name="iterationCount" value="1"></input><br>
|
||||
Scroll increment: <input type="text" name="scrollIncrement" value="1"></input><br>
|
||||
</form>
|
||||
<scroll-app></scroll-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,62 @@
|
|||
library random_data;
|
||||
|
||||
import 'common.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
|
||||
List<Offering> generateOfferings(int count) =>
|
||||
new List.generate(count, generateOffering);
|
||||
|
||||
Offering generateOffering(int seed) {
|
||||
final res = new Offering();
|
||||
res.name = generateName(seed++);
|
||||
res.company = generateCompany(seed++);
|
||||
res.opportunity = generateOpportunity(seed++);
|
||||
res.account = generateAccount(seed++);
|
||||
res.basePoints = seed % 10;
|
||||
res.kickerPoints = seed % 4;
|
||||
res.status = STATUS_LIST[seed % STATUS_LIST.length];
|
||||
res.bundles = randomString(seed++);
|
||||
res.dueDate = randomDate(seed++);
|
||||
res.endDate = randomDate(seed++, minDate: res.dueDate);
|
||||
res.aatStatus = AAT_STATUS_LIST[seed % AAT_STATUS_LIST.length];
|
||||
return res;
|
||||
}
|
||||
|
||||
Company generateCompany(int seed) {
|
||||
return new Company()
|
||||
..name = generateName(seed);
|
||||
}
|
||||
|
||||
Opportunity generateOpportunity(int seed) {
|
||||
return new Opportunity()
|
||||
..name = generateName(seed);
|
||||
}
|
||||
|
||||
Account generateAccount(int seed) {
|
||||
return new Account()
|
||||
..accountId = new Int64(seed);
|
||||
}
|
||||
|
||||
String generateName(int seed) {
|
||||
const names = const [
|
||||
'Foo', 'Bar', 'Baz', 'Qux', 'Quux', 'Garply', 'Waldo', 'Fred', 'Plugh',
|
||||
'Xyzzy', 'Thud', 'Cruft', 'Stuff'
|
||||
];
|
||||
return names[seed % names.length];
|
||||
}
|
||||
|
||||
DateTime randomDate(int seed, {DateTime minDate}) {
|
||||
if (minDate == null) {
|
||||
minDate = new DateTime.now();
|
||||
}
|
||||
|
||||
const offsets = const[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
return minDate.add(new Duration(days: offsets[seed % offsets.length]));
|
||||
}
|
||||
|
||||
String randomString(int seed) {
|
||||
return new String.fromCharCodes(new List.generate(
|
||||
const[5, 7, 9, 11, 13][seed % 5],
|
||||
(i) => 'a'.codeUnitAt(0) + const[0, 1, 2, 3, 4, 5, 6, 7, 8][seed % 9] + i
|
||||
));
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
library scroll_area;
|
||||
|
||||
import 'dart:html';
|
||||
import 'dart:math' as math;
|
||||
import 'package:angular/angular.dart';
|
||||
import 'common.dart';
|
||||
import 'random_data.dart';
|
||||
|
||||
@Component(
|
||||
selector: 'scroll-area',
|
||||
templateUrl: 'scroll_area.html',
|
||||
map: const {
|
||||
'scroll-top': '=>scrollTop',
|
||||
})
|
||||
class ScrollAreaComponent implements ShadowRootAware {
|
||||
Element scrollDiv;
|
||||
List<Offering> _fullList;
|
||||
List<Offering> visibleItems = [];
|
||||
|
||||
// Init empty maps and populate later. There seems to be a bug in Angular
|
||||
// that makes it choke on pre-populated style maps.
|
||||
final Map paddingStyle = {};
|
||||
final Map innerStyle = {};
|
||||
final Map scrollDivStyle = {};
|
||||
|
||||
ScrollAreaComponent() {
|
||||
_fullList = generateOfferings(ITEMS);
|
||||
}
|
||||
|
||||
@override
|
||||
void onShadowRoot(ShadowRoot shadowRoot) {
|
||||
scrollDiv = shadowRoot.querySelector('#scrollDiv');
|
||||
onScroll();
|
||||
scrollDivStyle.addAll({
|
||||
'height': '${VIEW_PORT_HEIGHT}px',
|
||||
'width': '1000px',
|
||||
'border': '1px solid #000',
|
||||
'overflow': 'scroll',
|
||||
});
|
||||
innerStyle['width'] = '${ROW_WIDTH}px';
|
||||
}
|
||||
|
||||
set scrollTop(int value) {
|
||||
if (value == null || scrollDiv == null) return;
|
||||
scrollDiv.scrollTop = value;
|
||||
}
|
||||
|
||||
void onScroll() {
|
||||
int scrollY = scrollDiv.scrollTop;
|
||||
int iStart = scrollY == 0 ? 0 : (scrollY / ITEM_HEIGHT).floor();
|
||||
int iEnd = math.min(iStart + VISIBLE_ITEMS + 1, _fullList.length);
|
||||
int padding = iStart * ITEM_HEIGHT;
|
||||
innerStyle['height'] = '${HEIGHT - padding}px';
|
||||
paddingStyle['height'] = '${padding}px';
|
||||
visibleItems..clear()..addAll(_fullList.getRange(iStart, iEnd));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<div>
|
||||
<div id="scrollDiv"
|
||||
ng-style="scrollDivStyle"
|
||||
ng-scroll="onScroll()">
|
||||
<div ng-style="paddingStyle"></div>
|
||||
<div ng-style="innerStyle">
|
||||
<scroll-item
|
||||
ng-repeat="item in visibleItems"
|
||||
offering="item">
|
||||
</scroll-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,41 @@
|
|||
library scroll_item;
|
||||
|
||||
import 'package:angular/angular.dart';
|
||||
import 'common.dart';
|
||||
|
||||
@Component(
|
||||
selector: 'scroll-item',
|
||||
templateUrl: 'scroll_item.html',
|
||||
map: const {
|
||||
'offering': '=>offering',
|
||||
})
|
||||
class ScrollItemComponent implements ShadowRootAware {
|
||||
|
||||
Offering offering;
|
||||
|
||||
// Init empty maps and populate later. There seems to be a bug in Angular
|
||||
// that makes it choke on pre-populated style maps.
|
||||
Map itemStyle = {};
|
||||
|
||||
@override
|
||||
void onShadowRoot(_) {
|
||||
itemStyle.addAll({
|
||||
'height': '${ITEM_HEIGHT}px',
|
||||
'line-height': '${ITEM_HEIGHT}px',
|
||||
'font-size': '18px',
|
||||
'display': 'flex',
|
||||
'justify-content': 'space-between',
|
||||
});
|
||||
}
|
||||
get companyNameWidth => '${COMPANY_NAME_WIDTH}px';
|
||||
get opportunityNameWidth => '${OPPORTUNITY_NAME_WIDTH}px';
|
||||
get offeringNameWidth => '${OFFERING_NAME_WIDTH}px';
|
||||
get accountCellWidth => '${ACCOUNT_CELL_WIDTH}px';
|
||||
get basePointsWidth => '${BASE_POINTS_WIDTH}px';
|
||||
get kickerPointsWidth => '${KICKER_POINTS_WIDTH}px';
|
||||
get stageButtonsWidth => '${STAGE_BUTTONS_WIDTH}px';
|
||||
get bundlesWidth => '${BUNDLES_WIDTH}px';
|
||||
get dueDateWidth => '${DUE_DATE_WIDTH}px';
|
||||
get endDateWidth => '${END_DATE_WIDTH}px';
|
||||
get aatStatusWidth => '${AAT_STATUS_WIDTH}px';
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<div ng-style="itemStyle">
|
||||
<company-name company="offering.company"
|
||||
cell-width="companyNameWidth">
|
||||
</company-name>
|
||||
|
||||
<opportunity-name opportunity="offering.opportunity"
|
||||
cell-width="opportunityNameWidth">
|
||||
</opportunity-name>
|
||||
|
||||
<offering-name offering="offering"
|
||||
cell-width="offeringNameWidth">
|
||||
</offering-name>
|
||||
|
||||
<account-cell account="offering.account"
|
||||
cell-width="accountCellWidth">
|
||||
</account-cell>
|
||||
|
||||
<formatted-cell value="offering.basePoints"
|
||||
cell-width="basePointsWidth">
|
||||
</formatted-cell>
|
||||
|
||||
<formatted-cell value="offering.kickerPoints"
|
||||
cell-width="kickerPointsWidth">
|
||||
</formatted-cell>
|
||||
|
||||
<stage-buttons offering="offering"
|
||||
cell-width="stageButtonsWidth">
|
||||
</stage-buttons>
|
||||
|
||||
<formatted-cell value="offering.bundles"
|
||||
cell-width="bundlesWidth">
|
||||
</formatted-cell>
|
||||
|
||||
<formatted-cell value="offering.dueDate"
|
||||
cell-width="dueDateWidth">
|
||||
</formatted-cell>
|
||||
|
||||
<formatted-cell value="offering.endDate"
|
||||
cell-width="endDateWidth">
|
||||
</formatted-cell>
|
||||
|
||||
<formatted-cell value="offering.aatStatus"
|
||||
cell-width="aatStatusWidth">
|
||||
</formatted-cell>
|
||||
</div>
|
|
@ -3,10 +3,23 @@ var webdriver = require('protractor/node_modules/selenium-webdriver');
|
|||
|
||||
module.exports = {
|
||||
runClickBenchmark: runClickBenchmark,
|
||||
runBenchmark: runBenchmark,
|
||||
verifyNoBrowserErrors: benchpress.verifyNoBrowserErrors
|
||||
};
|
||||
|
||||
function runClickBenchmark(config) {
|
||||
var buttons = config.buttons.map(function(selector) {
|
||||
return $(selector);
|
||||
});
|
||||
config.work = function() {
|
||||
buttons.forEach(function(button) {
|
||||
button.click();
|
||||
});
|
||||
}
|
||||
runBenchmark(config);
|
||||
}
|
||||
|
||||
function runBenchmark(config) {
|
||||
var globalParams = browser.params;
|
||||
getScaleFactor(globalParams.benchmark.scaling).then(function(scaleFactor) {
|
||||
var params = config.params.map(function(param) {
|
||||
|
@ -23,14 +36,7 @@ function runClickBenchmark(config) {
|
|||
return param.name + '=' + param.value;
|
||||
}).join('&'));
|
||||
browser.get(url);
|
||||
var buttons = config.buttons.map(function(selector) {
|
||||
return $(selector);
|
||||
});
|
||||
benchpress.runBenchmark(benchmarkConfig, function() {
|
||||
buttons.forEach(function(button) {
|
||||
button.click();
|
||||
});
|
||||
});
|
||||
benchpress.runBenchmark(benchmarkConfig, config.work);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
var config = exports.config = require('./protractor-e2e-shared.js').config;
|
||||
config.baseUrl = 'http://localhost:8001/';
|
||||
|
||||
// TODO: remove exclusion when JS verison of scrolling benchmark is available
|
||||
config.exclude = config.exclude || [];
|
||||
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/naive_infinite_scroll_spec.js');
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
var config = exports.config = require('./protractor-perf-shared.js').config;
|
||||
config.baseUrl = 'http://localhost:8001/';
|
||||
config.params.lang = 'js';
|
||||
|
||||
// TODO: remove exclusion when JS verison of scrolling benchmark is available
|
||||
config.exclude = config.exclude || [];
|
||||
config.exclude.push('dist/cjs/e2e_test/benchmarks_external/e2e_test/naive_infinite_scroll_perf.js');
|
||||
|
|
Loading…
Reference in New Issue