mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* Fix missing check on empty response * Fix test order and remove applying on each entered filter * Change quotes on addNewFilterAggregation testsubject * Rename test hasPieChartError method to expectPieChartError * Refactor piechart zero-value slices data cleaning. The previous implementation used to remove zero-value slices by mutating the vis data from the legend logic. We moved the logic of "cleaning" the zero-value slices before rendering the piechart and/or the legend, so now piechart and legends are rendering themselves with the same data structure. * Reverting _validatePieData method to the old one
This commit is contained in:
parent
e400a9e49d
commit
0f677d87e8
6 changed files with 119 additions and 15 deletions
|
@ -28,6 +28,7 @@
|
|||
|
||||
<div class="form-group">
|
||||
<input
|
||||
data-test-subj="visEditorFilterInput_{{agg.id}}_{{$index}}"
|
||||
id="visEditorFilterInput{{agg.id}}"
|
||||
parse-query
|
||||
ng-model="filter.input.query"
|
||||
|
@ -58,6 +59,7 @@
|
|||
</div>
|
||||
|
||||
<button
|
||||
data-test-subj="visEditorAddFilterButton"
|
||||
click-focus="'filter'+(agg.params.filters.length-1)"
|
||||
ng-click="agg.params.filters.push({input:{}})"
|
||||
class="kuiButton kuiButton--primary kuiButton--fullWidth"
|
||||
|
|
|
@ -45,7 +45,7 @@ export function VislibLibDataProvider(Private) {
|
|||
this.uiState = uiState;
|
||||
this.data = this.copyDataObj(data);
|
||||
this.type = this.getDataType();
|
||||
|
||||
this._cleanVisData();
|
||||
this.labels = this._getLabels(this.data);
|
||||
this.color = this.labels ? color(this.labels, uiState.get('vis.colors')) : undefined;
|
||||
this._normalizeOrdered();
|
||||
|
@ -96,7 +96,10 @@ export function VislibLibDataProvider(Private) {
|
|||
}
|
||||
|
||||
_getLabels(data) {
|
||||
return this.type === 'series' ? getLabels(data) : this.pieNames();
|
||||
if (this.type === 'series') {
|
||||
return getLabels(data);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
getDataType() {
|
||||
|
@ -345,19 +348,42 @@ export function VislibLibDataProvider(Private) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Removes zeros from pie chart data
|
||||
* Clean visualization data from missing/wrong values.
|
||||
* Currently used only to clean remove zero slices from
|
||||
* pie chart.
|
||||
*/
|
||||
_cleanVisData() {
|
||||
const visData = this.getVisData();
|
||||
if (this.type === 'slices') {
|
||||
this._cleanPieChartData(visData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutate the current pie chart vis data to remove slices with
|
||||
* zero values.
|
||||
* @param {Array} data
|
||||
*/
|
||||
_cleanPieChartData(data) {
|
||||
_.forEach(data, (obj) => {
|
||||
obj.slices = this._removeZeroSlices(obj.slices);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes zeros from pie chart data, mutating the passed values.
|
||||
* @param slices
|
||||
* @returns {*}
|
||||
*/
|
||||
_removeZeroSlices(slices) {
|
||||
const self = this;
|
||||
|
||||
if (!slices.children) return slices;
|
||||
if (!slices.children) {
|
||||
return slices;
|
||||
}
|
||||
|
||||
slices = _.clone(slices);
|
||||
slices.children = slices.children.reduce(function (children, child) {
|
||||
slices.children = slices.children.reduce((children, child) => {
|
||||
if (child.size !== 0) {
|
||||
children.push(self._removeZeroSlices(child));
|
||||
return [...children, this._removeZeroSlices(child)];
|
||||
}
|
||||
return children;
|
||||
}, []);
|
||||
|
@ -378,8 +404,6 @@ export function VislibLibDataProvider(Private) {
|
|||
|
||||
_.forEach(data, function (obj) {
|
||||
const columns = obj.raw ? obj.raw.columns : undefined;
|
||||
obj.slices = self._removeZeroSlices(obj.slices);
|
||||
|
||||
_.forEach(self.getNames(obj, columns), function (name) {
|
||||
names.push(name);
|
||||
});
|
||||
|
|
|
@ -217,7 +217,8 @@ export function VisHandlerProvider(Private) {
|
|||
.append('div')
|
||||
// class name needs `chart` in it for the polling checkSize function
|
||||
// to continuously call render on resize
|
||||
.attr('class', 'visualize-error chart error');
|
||||
.attr('class', 'visualize-error chart error')
|
||||
.attr('data-test-subj', 'visLibVisualizeError');
|
||||
|
||||
if (message === 'No results found') {
|
||||
div.append('div')
|
||||
|
|
|
@ -48,10 +48,8 @@ export function VislibVisualizationsPieChartProvider(Private) {
|
|||
class PieChart extends Chart {
|
||||
constructor(handler, chartEl, chartData) {
|
||||
super(handler, chartEl, chartData);
|
||||
|
||||
const charts = this.handler.data.getVisData();
|
||||
this._validatePieData(charts);
|
||||
|
||||
this._attr = _.defaults(handler.visConfig.get('chart', {}), defaults);
|
||||
}
|
||||
|
||||
|
@ -61,7 +59,7 @@ export function VislibVisualizationsPieChartProvider(Private) {
|
|||
* If so, an error is thrown.
|
||||
*/
|
||||
_validatePieData(charts) {
|
||||
const isAllZeros = charts.every(function (chart) {
|
||||
const isAllZeros = charts.every((chart) => {
|
||||
return chart.slices.children.length === 0;
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ export default function ({ getService, getPageObjects }) {
|
|||
describe('pie chart', async function () {
|
||||
const vizName1 = 'Visualization PieChart';
|
||||
before(async function () {
|
||||
|
||||
log.debug('navigateToApp visualize');
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickPieChart');
|
||||
|
@ -170,5 +169,63 @@ export default function ({ getService, getPageObjects }) {
|
|||
expect(pieData).to.eql(expectedTableData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('empty time window', () => {
|
||||
it('should show no data message when no data on selected timerange', async function () {
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickPieChart');
|
||||
await PageObjects.visualize.clickPieChart();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
|
||||
await PageObjects.header.setAbsoluteRange(fromTime, toTime);
|
||||
log.debug('select bucket Split Slices');
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
log.debug('Click aggregation Filters');
|
||||
await PageObjects.visualize.selectAggregation('Filters');
|
||||
log.debug('Set the 1st filter value');
|
||||
await PageObjects.visualize.setFilterAggregationValue('geo.dest:"US"');
|
||||
log.debug('Add new filter');
|
||||
await PageObjects.visualize.addNewFilterAggregation();
|
||||
log.debug('Set the 2nd filter value');
|
||||
await PageObjects.visualize.setFilterAggregationValue('geo.dest:"CN"', 1);
|
||||
await PageObjects.visualize.clickGo();
|
||||
const emptyFromTime = '2016-09-19 06:31:44.000';
|
||||
const emptyToTime = '2016-09-23 18:31:44.000';
|
||||
log.debug('Switch to a different time range from \"' + emptyFromTime + '\" to \"' + emptyToTime + '\"');
|
||||
await PageObjects.header.setAbsoluteRange(emptyFromTime, emptyToTime);
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.expectPieChartError();
|
||||
});
|
||||
});
|
||||
describe('multi series slice', () => {
|
||||
it('should still showing pie chart when a subseries have zero data', async function () {
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickPieChart');
|
||||
await PageObjects.visualize.clickPieChart();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
|
||||
await PageObjects.header.setAbsoluteRange(fromTime, toTime);
|
||||
log.debug('select bucket Split Slices');
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
log.debug('Click aggregation Filters');
|
||||
await PageObjects.visualize.selectAggregation('Filters');
|
||||
log.debug('Set the 1st filter value');
|
||||
await PageObjects.visualize.setFilterAggregationValue('geo.dest:"US"');
|
||||
log.debug('Toggle previous editor');
|
||||
await PageObjects.visualize.toggleAggegationEditor(2);
|
||||
log.debug('Add a new series');
|
||||
await PageObjects.visualize.clickAddBucket();
|
||||
log.debug('select bucket Split Slices');
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
log.debug('Click aggregation Filters');
|
||||
await PageObjects.visualize.selectAggregation('Filters');
|
||||
log.debug('Set the 1st filter value of the aggregation id 3');
|
||||
await PageObjects.visualize.setFilterAggregationValue('geo.dest:"UX"', 0, 3);
|
||||
await PageObjects.visualize.clickGo();
|
||||
const legends = await PageObjects.visualize.getLegendEntries();
|
||||
const expectedLegends = ['geo.dest:"US"', 'geo.dest:"UX"'];
|
||||
expect(legends).to.eql(expectedLegends);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -509,6 +509,21 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
await PageObjects.common.sleep(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the test for a filter aggregation.
|
||||
* @param {*} filterValue the string value of the filter
|
||||
* @param {*} filterIndex used when multiple filters are configured on the same aggregation
|
||||
* @param {*} aggregationId the ID if the aggregation. On Tests, it start at from 2
|
||||
*/
|
||||
async setFilterAggregationValue(filterValue, filterIndex = 0, aggregationId = 2) {
|
||||
const inputField = await testSubjects.find(`visEditorFilterInput_${aggregationId}_${filterIndex}`);
|
||||
await inputField.type(filterValue);
|
||||
}
|
||||
|
||||
async addNewFilterAggregation() {
|
||||
return await testSubjects.click('visEditorAddFilterButton');
|
||||
}
|
||||
|
||||
async toggleOpenEditor(index, toState = 'true') {
|
||||
// index, see selectYAxisAggregation
|
||||
const toggle = await find.byCssSelector(`button[aria-controls="visAggEditorParams${index}"]`);
|
||||
|
@ -653,6 +668,10 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
await testSubjects.click(`aggregationEditor${agg} disableAggregationBtn`);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
async toggleAggegationEditor(agg) {
|
||||
await testSubjects.click(`aggregationEditor${agg} toggleEditor`);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async toggleOtherBucket() {
|
||||
return await find.clickByCssSelector('input[name="showOther"]');
|
||||
|
@ -922,6 +941,9 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('data-label'));
|
||||
return await Promise.all(getChartTypesPromises);
|
||||
}
|
||||
async expectPieChartError() {
|
||||
return await testSubjects.existOrFail('visLibVisualizeError');
|
||||
}
|
||||
|
||||
async getChartAreaWidth() {
|
||||
const rect = await retry.try(async () => find.byCssSelector('clipPath rect'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue