+2016-05-04 Dewei Zhu <dewei_zhu@apple.com>
+
+ Summary page should show warnings when current or baseline data is missing.
+ https://bugs.webkit.org/show_bug.cgi?id=157339
+
+ Reviewed by Ryosuke Niwa.
+
+ Set summary page to be the default page of v3 UI.
+ Show warning icon when either baseline or current data is missing.
+ Make fetchBetween returns a promise.
+ Update unit tests for MeasurementSet.fetchBetween since it returns a promise now.
+ Add a workaround to skip some platform and metric configurations.
+
+ * public/v3/components/ratio-bar-graph.js:
+ (RatioBarGraph):
+ (RatioBarGraph.prototype.update): Add showWarningIcon flag to indicate whether we should show warning icon.
+ (RatioBarGraph.prototype.render): Show warning icon when showWarningIcon is true.
+ (RatioBarGraph.cssTemplate): Add style for warning icon.
+ * public/v3/components/warning-icon.js: Add warning icon.
+ (WarningIcon):
+ (WarningIcon.cssTemplate):
+ * public/v3/index.html:
+ * public/v3/main.js:
+ (main): Set summary page to be the default page of v3 UI.
+ * public/v3/models/measurement-set.js:
+ (MeasurementSet):
+ (MeasurementSet.prototype.fetchBetween): Returns a promise. Fix the bug in previous implementation that we miss
+ some callbacks sometimes. Basically, we will fetch primary cluster first, then secondary clusters. For each
+ secondary cluster fetch, we will always invoke callback even when it fails.
+ (MeasurementSet.prototype._fetchSecondaryClusters): Deleted.
+ (MeasurementSet.prototype._fetch.else.url.api.measurement.set platform): Deleted.
+ * public/v3/pages/summary-page.js:
+ (SummaryPage): Add a variable for excluded configurations.
+ (SummaryPage.prototype._createConfigurationGroup): Pass excluded configurations while building config groups.
+ (SummaryPage.prototype._constructTable): Remove the logic for unified header since it breaks consistency of the table appearance.
+ (SummaryPage.prototype.this._renderQueue.push): Show warning message when baseline/current data is missing.
+ (SummaryPageConfigurationGroup): Add a variable to keep track of the warnings while computing summary.
+ (SummaryPageConfigurationGroup.prototype.warnings): A getter for warnings.
+ (SummaryPageConfigurationGroup._computeSummary): Fix a bug in calculating ratios. We should always use
+ current/baseline for ratio and present the difference between ratio and 1 in the summary page.
+ (SummaryPageConfigurationGroup.set then): Deleted.
+ (SummaryPageConfigurationGroup.set var): Deleted.
+ * unit-tests/measurement-set-tests.js: Add a helper function to wait for fetchBetween. Update unit tests since fetchBetween returns a promise now.
+ (promise.set fetchBetween):
+ (set MeasurementSet):
+ (set fetchBetween): Deleted.
+
2016-04-26 Ryosuke Niwa <rniwa@webkit.org>
Chart status should always be computed against prior values
constructor()
{
super('ratio-bar-graph');
- this._ratio = 0;
+ this._ratio = null;
this._label = null;
this._shouldRender = true;
- this._bar = this.content().querySelector('.bar');
- this._labelContainer = this.content().querySelector('.label');
+ this._ratioBarGraph = this.content().querySelector('.ratio-bar-graph');
}
- update(ratio, label)
+ update(ratio, label, showWarningIcon)
{
- console.assert(ratio >= -1 && ratio <= 1);
+ console.assert(isNaN(ratio) || (ratio >= -1 && ratio <= 1));
this._ratio = ratio;
this._label = label;
+ this._showWarningIcon = showWarningIcon;
this._shouldRender = true;
}
{
if (!this._shouldRender)
return;
+ this._shouldRender = false;
+ var element = ComponentBase.createElement;
- var percent = Math.abs(this._ratio * 100);
- this._labelContainer.textContent = this._label;
- this._bar.style.width = Math.min(percent, 50) + '%';
- this._bar.parentNode.className = 'ratio-bar-graph ' + (this._ratio > 0 ? 'better' : 'worse');
+ var children = [element('div', {class: 'separator'})];
+ if (this._showWarningIcon) {
+ if (this._ratio && this._ratio < -0.4)
+ this._ratioBarGraph.classList.add('warning-on-right');
+ else
+ this._ratioBarGraph.classList.remove('warning-on-right');
+ children.push(new WarningIcon);
+ }
- this._shouldRender = false;
+ var barClassName = 'bar';
+ var labelClassName = 'label';
+ if (this._ratio) {
+ var ratioType = this._ratio > 0 ? 'better' : 'worse';
+ barClassName = [barClassName, ratioType].join(' ');
+ labelClassName = [labelClassName, ratioType].join(' ');
+ children.push(element('div', {class: barClassName, style: 'width:' + Math.min(Math.abs(this._ratio * 100), 50) + '%'}));
+ }
+ if (this._label)
+ children.push(element('div', {class: labelClassName}, this._label));
+
+ this.renderReplace(this._ratioBarGraph, children);
}
static htmlTemplate()
{
- return `<div class="ratio-bar-graph"><div class="seperator"></div><div class="bar"></div><div class="label"></div></div>`;
+ return `<div class="ratio-bar-graph"></div>`;
}
static cssTemplate()
text-decoration: none;
color: black;
}
- .ratio-bar-graph .seperator {
+ .ratio-bar-graph warning-icon {
+ position: absolute;
+ display: block;
+ top: 0;
+ }
+ .ratio-bar-graph:not(.warning-on-right) warning-icon {
+ left: 0;
+ }
+ .ratio-bar-graph.warning-on-right warning-icon {
+ transform: scaleX(-1);
+ right: 0;
+ }
+ .ratio-bar-graph .separator {
position: absolute;
left: 50%;
width: 0px;
height: calc(100% - 1rem);
background: #ccc;
}
- .ratio-bar-graph.worse .bar {
+ .ratio-bar-graph .bar.worse {
transform: translateX(-100%);
background: #c33;
}
- .ratio-bar-graph.better .bar {
+ .ratio-bar-graph .bar.better {
background: #3c3;
}
.ratio-bar-graph .label {
position: absolute;
line-height: 2.5rem;
}
- .ratio-bar-graph.worse .label {
+ .ratio-bar-graph .label.worse {
text-align: left;
left: calc(50% + 0.2rem);
}
- .ratio-bar-graph.better .label {
+ .ratio-bar-graph .label.better {
text-align: right;
right: calc(50% + 0.2rem);
}
--- /dev/null
+
+class WarningIcon extends ButtonBase {
+ constructor()
+ {
+ super('warning-icon');
+ }
+
+ static cssTemplate()
+ {
+ return super.cssTemplate() + `
+ .button {
+ display: block;
+ width: 0.7rem;
+ height: 0.7rem;
+ }
+ .button svg {
+ display: block;
+ }
+ `;
+ }
+
+ static htmlTemplate()
+ {
+ return `<a class="button" href="#"><svg viewBox="0 0 100 100">
+ <g stroke="#9f6000" fill="#9f6000" stroke-width="7">
+ <polygon points="0,0, 100,0, 0,100" />
+ </g>
+ </svg></a>`;
+ }
+
+}
+
+ComponentBase.defineElement('warning-icon', WarningIcon);
<script src="components/base.js"></script>
<script src="components/spinner-icon.js"></script>
<script src="components/button-base.js"></script>
+ <script src="components/warning-icon.js"></script>
<script src="components/close-button.js"></script>
<script src="components/commit-log-viewer.js"></script>
<script src="components/editable-text.js"></script>
var router = new PageRouter();
var chartsToolbar = new ChartsToolbar;
- var summaryPage = new SummaryPage(manifest.summary);
+ var summaryPage = manifest.summary ? new SummaryPage(manifest.summary) : null;
var chartsPage = new ChartsPage(chartsToolbar);
var analysisCategoryPage = new AnalysisCategoryPage();
analysisTaskPage.setParentPage(analysisCategoryPage);
var heading = new Heading(manifest.siteTitle);
- heading.addPageGroup([summaryPage, chartsPage, analysisCategoryPage]);
+ heading.addPageGroup([summaryPage, chartsPage, analysisCategoryPage].filter(function (page) { return page; }));
heading.setTitle(manifest.siteTitle);
heading.addPageGroup(dashboardPages);
var router = new PageRouter();
- router.addPage(summaryPage);
+ if(summaryPage)
+ router.addPage(summaryPage);
router.addPage(chartsPage);
router.addPage(createAnalysisTaskPage);
router.addPage(analysisTaskPage);
for (var page of dashboardPages)
router.addPage(page);
- if (dashboardPages)
+ if (summaryPage)
+ router.setDefaultPage(summaryPage);
+ else if (dashboardPages)
router.setDefaultPage(dashboardPages[0]);
else
router.setDefaultPage(chartsPage);
this._metricId = metricId;
this._lastModified = +lastModified;
- this._waitingForPrimaryCluster = null;
- this._fetchedPrimary = false;
- this._endTimeToCallback = {};
-
this._sortedClusters = [];
this._primaryClusterEndTime = null;
this._clusterCount = null;
this._clusterStart = null;
this._clusterSize = null;
+ this._allFetches = {};
+ this._primaryClusterPromise = null;
}
+ platformId() { return this._platformId; }
+
static findSet(platformId, metricId, lastModified)
{
if (!this._set)
{
var clusterStart = this._clusterStart;
var clusterSize = this._clusterSize;
- console.assert(clusterStart && clusterSize);
function computeClusterStart(time) {
var diff = time - clusterStart;
fetchBetween(startTime, endTime, callback)
{
- if (!this._fetchedPrimary) {
- var primaryFetchHadFailed = this._waitingForPrimaryCluster === false;
- if (primaryFetchHadFailed) {
- callback();
- return;
- }
-
- var shouldStartPrimaryFetch = !this._waitingForPrimaryCluster;
- if (shouldStartPrimaryFetch)
- this._waitingForPrimaryCluster = [];
-
- this._waitingForPrimaryCluster.push({startTime: startTime, endTime: endTime, callback: callback});
-
- if (shouldStartPrimaryFetch)
- this._fetch(null, true);
-
- return;
- }
-
- this._fetchSecondaryClusters(startTime, endTime, callback);
+ if (!this._primaryClusterPromise)
+ this._primaryClusterPromise = this._fetchPrimaryCluster();
+ var self = this;
+ this._primaryClusterPromise.catch(callback);
+ return this._primaryClusterPromise.then(function () {
+ var promiseList = [];
+ self.findClusters(startTime, endTime).map(function (clusterEndTime) {
+ if(!self._allFetches[clusterEndTime])
+ self._allFetches[clusterEndTime] = self._fetchSecondaryCluster(clusterEndTime);
+ self._allFetches[clusterEndTime].then(callback, callback);
+ promiseList.push(self._allFetches[clusterEndTime]);
+ });
+ return Promise.all(promiseList);
+ });
}
- _fetchSecondaryClusters(startTime, endTime, callback)
+ _constructUrl(useCache, clusterEndTime)
{
- console.assert(this._fetchedPrimary);
- console.assert(this._clusterStart && this._clusterSize);
- console.assert(this._sortedClusters.length);
-
- var clusters = this.findClusters(startTime, endTime);
- var shouldInvokeCallackNow = false;
- for (var endTime of clusters) {
- var isPrimaryCluster = endTime == this._primaryClusterEndTime;
- var shouldStartFetch = !isPrimaryCluster && !(endTime in this._endTimeToCallback);
- if (shouldStartFetch)
- this._endTimeToCallback[endTime] = [];
-
- var callbackList = this._endTimeToCallback[endTime];
- if (isPrimaryCluster || callbackList === true)
- shouldInvokeCallackNow = true;
- else if (!callbackList.includes(callback))
- callbackList.push(callback);
-
- if (shouldStartFetch)
- this._fetch(endTime, true);
+ if (!useCache) {
+ return `../api/measurement-set?platform=${this._platformId}&metric=${this._metricId}`;
}
-
- if (shouldInvokeCallackNow)
- callback();
- }
-
- _fetch(clusterEndTime, useCache)
- {
- console.assert(!clusterEndTime || useCache);
-
var url;
- if (useCache) {
- url = `../data/measurement-set-${this._platformId}-${this._metricId}`;
- if (clusterEndTime)
- url += '-' + +clusterEndTime;
- url += '.json';
- } else
- url = `../api/measurement-set?platform=${this._platformId}&metric=${this._metricId}`;
+ url = `../data/measurement-set-${this._platformId}-${this._metricId}`;
+ if (clusterEndTime)
+ url += '-' + +clusterEndTime;
+ url += '.json';
+ return url;
+ }
+ _fetchPrimaryCluster() {
var self = this;
+ return RemoteAPI.getJSONWithStatus(self._constructUrl(true, null)).then(function (data) {
+ if (+data['lastModified'] < self._lastModified)
+ return RemoteAPI.getJSONWithStatus(self._constructUrl(false, null));
+ return data;
+ }).catch(function (error) {
+ if(error == 404)
+ return RemoteAPI.getJSONWithStatus(self._constructUrl(false, null));
+ return Promise.reject(error);
+ }).then(function (data) {
+ self._didFetchJSON(true, data);
+ self._allFetches[self._primaryClusterEndTime] = self._primaryClusterPromise;
+ });
+ }
- return RemoteAPI.getJSONWithStatus(url).then(function (data) {
- if (!clusterEndTime && useCache && +data['lastModified'] < self._lastModified)
- self._fetch(clusterEndTime, false);
- else
- self._didFetchJSON(!clusterEndTime, data);
- }, function (error, xhr) {
- if (!clusterEndTime && error == 404 && useCache)
- self._fetch(clusterEndTime, false);
- else
- self._failedToFetchJSON(clusterEndTime, error);
+ _fetchSecondaryCluster(endTime) {
+ var self = this;
+ return RemoteAPI.getJSONWithStatus(self._constructUrl(true, endTime)).then(function (data) {
+ self._didFetchJSON(false, data);
});
}
_didFetchJSON(isPrimaryCluster, response, clusterEndTime)
{
- console.assert(isPrimaryCluster || this._fetchedPrimary);
+ console.assert(isPrimaryCluster);
if (isPrimaryCluster) {
this._primaryClusterEndTime = response['endTime'];
console.assert(this._primaryClusterEndTime);
this._addFetchedCluster(new MeasurementCluster(response));
-
- console.assert(this._waitingForPrimaryCluster);
- if (!isPrimaryCluster) {
- this._invokeCallbacks(response.endTime);
- return;
- }
- console.assert(this._waitingForPrimaryCluster instanceof Array);
-
- this._fetchedPrimary = true;
- for (var entry of this._waitingForPrimaryCluster)
- this._fetchSecondaryClusters(entry.startTime, entry.endTime, entry.callback);
- this._waitingForPrimaryCluster = true;
- }
-
- _failedToFetchJSON(clusterEndTime, error)
- {
- if (clusterEndTime) {
- this._invokeCallbacks(clusterEndTime, error || true);
- return;
- }
-
- console.assert(!this._fetchedPrimary);
- console.assert(this._waitingForPrimaryCluster instanceof Array);
- for (var entry of this._waitingForPrimaryCluster)
- entry.callback(error || true);
- this._waitingForPrimaryCluster = false;
- }
-
- _invokeCallbacks(clusterEndTime, error)
- {
- var callbackList = this._endTimeToCallback[clusterEndTime];
- for (var callback of callbackList)
- callback(error);
- this._endTimeToCallback[clusterEndTime] = true;
}
_addFetchedCluster(cluster)
this._shouldConstructTable = true;
this._renderQueue = [];
this._configGroups = [];
+ this._excludedConfigurations = summarySettings.excludedConfigurations;
for (var metricGroup of summarySettings.metricGroups) {
var group = {name: metricGroup.name, rows: []};
{
var platforms = platformIdList.map(function (id) { return Platform.findById(id); }).filter(function (obj) { return !!obj; });
var metrics = metricIdList.map(function (id) { return Metric.findById(id); }).filter(function (obj) { return !!obj; });
- var configGroup = new SummaryPageConfigurationGroup(platforms, metrics);
+ var configGroup = new SummaryPageConfigurationGroup(platforms, metrics, this._excludedConfigurations);
this._configGroups.push(configGroup);
return configGroup;
}
this._table.groups.map(function (rowGroup) {
return rowGroup.rows.map(function (row, rowIndex) {
var headings;
- if (rowGroup.rows.length == 1)
- headings = [element('th', {class: 'unifiedHeader', colspan: 2}, row.name)];
- else {
- headings = [element('th', {class: 'minorHeader'}, row.name)];
- if (!rowIndex)
- headings.unshift(element('th', {class: 'majorHeader', rowspan: rowGroup.rows.length}, rowGroup.name));
- }
+ headings = [element('th', {class: 'minorHeader'}, row.name)];
+ if (!rowIndex)
+ headings.unshift(element('th', {class: 'majorHeader', rowspan: rowGroup.rows.length}, rowGroup.name));
return element('tr', [headings, row.cells.map(self._constructRatioGraph.bind(self))]);
});
}),
{
var element = ComponentBase.createElement;
var link = ComponentBase.createLink;
+ var configurationList = configurationGroup.configurationList();
var ratioGraph = new RatioBarGraph();
+ var state = ChartsPage.createStateForConfigurationList(configurationList);
+ var anchor = link(ratioGraph, this.router().url('charts', state));
this._renderQueue.push(function () {
- ratioGraph.update(configurationGroup.ratio(), configurationGroup.label());
+ var warnings = configurationGroup.warnings();
+ var warningText = '';
+ for (var type in warnings) {
+ var platformString = Array.from(warnings[type]).map(function (platform) { return platform.name(); }).join(', ');
+ warningText += `Missing ${type} for following platform(s): ${platformString}`;
+ }
+
+ anchor.title = warningText || 'Open charts';
+ ratioGraph.update(configurationGroup.ratio(), configurationGroup.label(), !!warningText);
ratioGraph.render();
});
+ if (configurationList.length == 0)
+ return element('td', ratioGraph);
- var state = ChartsPage.createStateForConfigurationList(configurationGroup.configurationList());
- return element('td', link(ratioGraph, 'Open charts', this.router().url('charts', state)));
+ return element('td', anchor);
}
static htmlTemplate()
}
class SummaryPageConfigurationGroup {
- constructor(platforms, metrics)
+ constructor(platforms, metrics, excludedConfigurations)
{
this._measurementSets = [];
this._configurationList = [];
this._setToRatio = new Map;
this._ratio = null;
this._label = null;
- this._changeType = null;
+ this._warnings = {};
this._smallerIsBetter = metrics.length ? metrics[0].isSmallerBetter() : null;
for (var platform of platforms) {
console.assert(metric instanceof Metric);
console.assert(this._smallerIsBetter == metric.isSmallerBetter());
metric.isSmallerBetter();
+
+ if (excludedConfigurations && platform.id() in excludedConfigurations && excludedConfigurations[platform.id()].includes(+metric.id()))
+ continue;
if (platform.hasMetric(metric)) {
this._measurementSets.push(MeasurementSet.findSet(platform.id(), metric.id(), platform.lastModified(metric)));
this._configurationList.push([platform.id(), metric.id()]);
ratio() { return this._ratio; }
label() { return this._label; }
+ warnings() { return this._warnings; }
changeType() { return this._changeType; }
configurationList() { return this._configurationList; }
}
var averageRatio = Statistics.mean(ratios);
- if (isNaN(averageRatio)) {
- this._summary = '-';
- this._changeType = null;
- return;
- }
-
- if (Math.abs(averageRatio - 1) < 0.001) { // Less than 0.1% difference.
- this._summary = 'No change';
- this._changeType = null;
+ if (isNaN(averageRatio))
return;
- }
var currentIsSmallerThanBaseline = averageRatio < 1;
var changeType = this._smallerIsBetter == currentIsSmallerThanBaseline ? 'better' : 'worse';
- if (currentIsSmallerThanBaseline)
- averageRatio = 1 / averageRatio;
+ averageRatio = Math.abs(averageRatio - 1);
- this._ratio = (averageRatio - 1) * (changeType == 'better' ? 1 : -1);
- this._label = ((averageRatio - 1) * 100).toFixed(1) + '%';
+ this._ratio = averageRatio * (changeType == 'better' ? 1 : -1);
+ this._label = (averageRatio * 100).toFixed(1) + '%';
this._changeType = changeType;
}
_fetchAndComputeRatio(set, timeRange)
{
var setToRatio = this._setToRatio;
- return SummaryPageConfigurationGroup._fetchData(set, timeRange).then(function () {
+ var self = this;
+ return set.fetchBetween(timeRange[0], timeRange[1]).then(function () {
var baselineTimeSeries = set.fetchedTimeSeries('baseline', false, false);
var currentTimeSeries = set.fetchedTimeSeries('current', false, false);
var baselineMedian = SummaryPageConfigurationGroup._medianForTimeRange(baselineTimeSeries, timeRange);
var currentMedian = SummaryPageConfigurationGroup._medianForTimeRange(currentTimeSeries, timeRange);
+ var platform = Platform.findById(set.platformId());
+ if (!baselineMedian) {
+ if(!('baseline' in self._warnings))
+ self._warnings['baseline'] = new Set;
+ self._warnings['baseline'].add(platform);
+ }
+ if (!currentMedian) {
+ if(!('current' in self._warnings))
+ self._warnings['current'] = new Set;
+ self._warnings['current'].add(platform);
+ }
+
setToRatio.set(set, currentMedian / baselineMedian);
}).catch(function () {
setToRatio.set(set, NaN);
var points = timeSeries.dataBetweenPoints(startPoint, endPoint).map(function (point) { return point.value; });
return Statistics.median(points);
}
-
- static _fetchData(set, timeRange)
- {
- // FIXME: Make fetchBetween return a promise.
- var done = false;
- return new Promise(function (resolve, reject) {
- set.fetchBetween(timeRange[0], timeRange[1], function (error) {
- if (done)
- return;
- if (error)
- reject(null);
- else if (set.hasFetchedRange(timeRange[0], timeRange[1]))
- resolve();
- done = true;
- });
- });
- }
}
it('should invoke the callback when the up-to-date cached primary cluster is fetched and it matches the requested range', function (done) {
var set = MeasurementSet.findSet(1, 1, 3000);
var callCount = 0;
- set.fetchBetween(2000, 3000, function () {
+ var promise = set.fetchBetween(2000, 3000, function () {
callCount++;
});
assert.equal(requests.length, 1);
'clusterCount': 2,
'status': 'OK'});
- requests[0].promise.then(function () {
+ promise.then(function () {
assert.equal(callCount, 1);
assert.equal(requests.length, 1);
done();
});
});
- it('should invoke the callback and fetch a secondary cluster'
- + 'when the cached primary cluster is up-to-date and within in the requested range', function (done) {
+ function waitForMeasurementSet()
+ {
+ return Promise.resolve().then(function () {
+ return Promise.resolve();
+ }).then(function () {
+ return Promise.resolve();
+ });
+ }
+
+ it('should invoke the callback and fetch a secondary cluster when the cached primary cluster is up-to-date and within in the requested range', function (done) {
var set = MeasurementSet.findSet(1, 1, 3000);
var callCount = 0;
- set.fetchBetween(1000, 3000, function () {
+ var promise = set.fetchBetween(1000, 3000, function () {
callCount++;
});
assert.equal(requests.length, 1);
'clusterCount': 2,
'status': 'OK'});
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(callCount, 1);
assert.equal(requests.length, 2);
assert.equal(requests[1].url, '../data/measurement-set-1-1-2000.json');
'clusterCount': 3,
'status': 'OK'});
- Promise.resolve().then(function () {
+ var callCount = 0;
+ waitForMeasurementSet().then(function () {
assert.equal(requests.length, 2);
assert.equal(requests[1].url, '../data/measurement-set-1-1-3000.json');
- var callCount = 0;
set.fetchBetween(0, 7000, function () { callCount++; });
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCount, 1);
assert.equal(requests.length, 4);
assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
'clusterCount': 3,
'status': 'OK'});
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(requests.length, 3);
assert.equal(requests[1].url, '../data/measurement-set-1-1-3000.json');
assert.equal(requests[2].url, '../data/measurement-set-1-1-4000.json');
'clusterCount': 3,
'status': 'OK'});
- Promise.resolve().then(function () {
+ var callCount = 0;
+ waitForMeasurementSet().then(function () {
assert.equal(requests.length, 2);
assert.equal(requests[1].url, '../data/measurement-set-1-1-4000.json');
-
- var callCount = 0;
set.fetchBetween(1207, 1293, function () { callCount++; });
-
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCount, 0);
assert.equal(requests.length, 3);
assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
-
set.fetchBetween(1964, 3401, function () { callCount++; });
-
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCount, 0);
assert.equal(requests.length, 4);
assert.equal(requests[3].url, '../data/measurement-set-1-1-3000.json');
-
done();
}).catch(function (error) {
done(error);
requests[0].reject(500);
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(callCount, 1);
assert.equal(requests.length, 1);
done();
requests[0].reject(404);
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(callCount, 0);
assert.equal(requests.length, 2);
assert.equal(requests[1].url, '../api/measurement-set?platform=1&metric=1');
'clusterCount': 2,
'status': 'OK'});
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(callCount, 1);
assert.equal(alternativeCallCount, 1);
assert.equal(requests.length, 1);
var callCountFor4000To5000 = 0;
var callCountFor2000 = 0;
var callCountFor2000To4000 = 0;
- Promise.resolve().then(function () {
+ waitForMeasurementSet().then(function () {
assert.equal(callCountFor4000, 0);
assert.equal(requests.length, 2);
assert.equal(requests[1].url, '../data/measurement-set-1-1-4000.json');
set.fetchBetween(3708, 4800, function () { callCountFor4000To5000++; });
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCountFor4000To5000, 1);
assert.equal(requests.length, 2);
set.fetchBetween(1207, 1293, function () { callCountFor2000++; });
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCountFor2000, 0);
assert.equal(requests.length, 3);
assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
'endTime': 2000,
'lastModified': 5000,
'status': 'OK'});
+ return waitForMeasurementSet();
}).then(function () {
assert.equal(requests.length, 3);
assert.equal(callCountFor4000, 0);
assert.equal(callCountFor2000, 1);
set.fetchBetween(1964, 3401, function () { callCountFor2000To4000++; });
-
+ return waitForMeasurementSet();
+ }).then(function () {
assert.equal(callCountFor2000To4000, 1);
assert.equal(requests.length, 4);
assert.equal(requests[3].url, '../data/measurement-set-1-1-3000.json');
'endTime': 3000,
'lastModified': 5000,
'status': 'OK'});
+ return waitForMeasurementSet();
}).then(function () {
assert.equal(callCountFor4000, 0);
assert.equal(callCountFor4000To5000, 1);
'endTime': 4000,
'lastModified': 5000,
'status': 'OK'});
+ return waitForMeasurementSet();
}).then(function () {
assert.equal(callCountFor4000, 1);
assert.equal(callCountFor4000To5000, 2);
});
-});
\ No newline at end of file
+});