Fetch options for input control child select boxes (#38148)
This commit is contained in:
parent
cc372800ab
commit
8dbfbddb53
|
@ -85,11 +85,13 @@ class ListControl extends Control {
|
|||
}
|
||||
|
||||
const ancestorValues = this.getAncestorValues();
|
||||
if (_.isEqual(ancestorValues, this.lastAncestorValues)) {
|
||||
if (_.isEqual(ancestorValues, this.lastAncestorValues)
|
||||
&& _.isEqual(query, this.lastQuery)) {
|
||||
// short circuit to avoid fetching options list for same ancestor values
|
||||
return;
|
||||
}
|
||||
this.lastAncestorValues = ancestorValues;
|
||||
this.lastQuery = query;
|
||||
|
||||
ancestorFilters = this.getAncestorFilters();
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./_experimental_vis'));
|
||||
loadTestFile(require.resolve('./_gauge_chart'));
|
||||
loadTestFile(require.resolve('./_heatmap_chart'));
|
||||
loadTestFile(require.resolve('./_input_control_vis'));
|
||||
loadTestFile(require.resolve('./input_control_vis'));
|
||||
loadTestFile(require.resolve('./_histogram_request_start'));
|
||||
loadTestFile(require.resolve('./_metric_chart'));
|
||||
});
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const filterBar = getService('filterBar');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
describe('chained controls', () => {
|
||||
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('visualize');
|
||||
await PageObjects.visualize.loadSavedVisualization('chained input control', { navigateToVisualize: false });
|
||||
});
|
||||
|
||||
it('should disable child control when parent control is not set', async () => {
|
||||
const parentControlMenu = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(parentControlMenu.trim().split('\n').join()).to.equal('BD,BR,CN,ID,IN,JP,NG,PK,RU,US');
|
||||
|
||||
const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input');
|
||||
const isDisabled = await childControlInput.getProperty('disabled');
|
||||
expect(isDisabled).to.equal(true);
|
||||
});
|
||||
|
||||
it('should filter child control options by parent control value', async () => {
|
||||
await comboBox.set('listControlSelect0', 'BR');
|
||||
|
||||
const childControlMenu = await comboBox.getOptionsList('listControlSelect1');
|
||||
expect(childControlMenu.trim().split('\n').join()).to.equal('14.61.182.136,3.174.21.181,6.183.121.70,71.241.97.89,9.69.255.135');
|
||||
});
|
||||
|
||||
it('should create a seperate filter pill for parent control and child control', async () => {
|
||||
await comboBox.set('listControlSelect1', '14.61.182.136');
|
||||
|
||||
await PageObjects.visualize.inputControlSubmit();
|
||||
|
||||
const hasParentControlFilter = await filterBar.hasFilter('geo.src', 'BR');
|
||||
expect(hasParentControlFilter).to.equal(true);
|
||||
|
||||
const hasChildControlFilter = await filterBar.hasFilter('clientip', '14.61.182.136');
|
||||
expect(hasChildControlFilter).to.equal(true);
|
||||
});
|
||||
|
||||
it('should clear child control dropdown when parent control value is removed', async () => {
|
||||
await comboBox.clear('listControlSelect0');
|
||||
await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire
|
||||
|
||||
const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input');
|
||||
const isDisabled = await childControlInput.getProperty('disabled');
|
||||
expect(isDisabled).to.equal(true);
|
||||
|
||||
await testSubjects.click('inputControlCancelBtn');
|
||||
});
|
||||
|
||||
it('should clear child control dropdown when parent control filter pill removed', async () => {
|
||||
await filterBar.removeFilter('geo.src');
|
||||
await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire
|
||||
|
||||
const hasValue = await comboBox.doesComboBoxHaveSelectedOptions('listControlSelect0');
|
||||
expect(hasValue).to.equal(false);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']);
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
describe('dynamic options', () => {
|
||||
|
||||
describe('without chained controls', () => {
|
||||
beforeEach(async () => {
|
||||
await PageObjects.common.navigateToApp('visualize');
|
||||
await PageObjects.visualize.loadSavedVisualization('dynamic options input control', { navigateToVisualize: false });
|
||||
});
|
||||
|
||||
it('should fetch new options when string field is filtered', async () => {
|
||||
const initialOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(initialOptions.trim().split('\n').join()).to.equal('BD,BR,CN,ID,IN,JP,NG,PK,RU,US');
|
||||
|
||||
await comboBox.filterOptionsList('listControlSelect0', 'R');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const updatedOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(updatedOptions.trim().split('\n').join()).to.equal('AR,BR,FR,GR,IR,KR,RO,RU,RW,TR');
|
||||
});
|
||||
|
||||
it('should not fetch new options when non-string is filtered', async () => {
|
||||
await comboBox.set('fieldSelect-0', 'clientip');
|
||||
await PageObjects.visualize.clickGo();
|
||||
|
||||
const initialOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(initialOptions.trim().split('\n').join()).to.equal(
|
||||
'135.206.117.161,177.194.175.66,18.55.141.62,243.158.217.196,32.146.206.24');
|
||||
|
||||
await comboBox.filterOptionsList('listControlSelect0', '17');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const updatedOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(updatedOptions.trim().split('\n').join()).to.equal('135.206.117.161,177.194.175.66,243.158.217.196');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with chained controls', () => {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('visualize');
|
||||
await PageObjects.visualize.loadSavedVisualization('chained input control with dynamic options', { navigateToVisualize: false });
|
||||
await comboBox.set('listControlSelect0', 'win 7');
|
||||
});
|
||||
|
||||
it('should fetch new options when string field is filtered', async () => {
|
||||
const initialOptions = await comboBox.getOptionsList('listControlSelect1');
|
||||
expect(initialOptions.trim().split('\n').join()).to.equal('BD,BR,CN,ID,IN,JP,MX,NG,PK,US');
|
||||
|
||||
await comboBox.filterOptionsList('listControlSelect1', 'R');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const updatedOptions = await comboBox.getOptionsList('listControlSelect1');
|
||||
expect(updatedOptions.trim().split('\n').join()).to.equal('AR,BR,FR,GR,IR,KR,RO,RS,RU,TR');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
26
test/functional/apps/visualize/input_control_vis/index.js
Normal file
26
test/functional/apps/visualize/input_control_vis/index.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export default function ({ loadTestFile }) {
|
||||
describe('input controls', function () {
|
||||
loadTestFile(require.resolve('./input_control_options'));
|
||||
loadTestFile(require.resolve('./dynamic_options'));
|
||||
loadTestFile(require.resolve('./chained_controls'));
|
||||
});
|
||||
}
|
|
@ -29,7 +29,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
const FIELD_NAME = 'machine.os.raw';
|
||||
|
||||
describe('input control visualization', () => {
|
||||
describe('input control options', () => {
|
||||
|
||||
before(async () => {
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
|
@ -183,112 +183,5 @@ export default function ({ getService, getPageObjects }) {
|
|||
expect(menu.trim().split('\n').join()).to.equal('osx,win 7,win 8,win xp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('dynamic options', () => {
|
||||
beforeEach(async () => {
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
await PageObjects.visualize.clickInputControlVis();
|
||||
await PageObjects.visualize.clickVisEditorTab('controls');
|
||||
|
||||
await PageObjects.visualize.addInputControl();
|
||||
await comboBox.set('indexPatternSelect-0', 'logstash- ');
|
||||
await comboBox.set('fieldSelect-0', 'geo.src');
|
||||
|
||||
await PageObjects.visualize.clickGo();
|
||||
});
|
||||
|
||||
it('should fetch new options when string field is filtered', async () => {
|
||||
const initialOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(initialOptions.trim().split('\n').join()).to.equal('BD,BR,CN,ID,IN,JP,NG,PK,RU,US');
|
||||
|
||||
await comboBox.filterOptionsList('listControlSelect0', 'R');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const updatedOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(updatedOptions.trim().split('\n').join()).to.equal('AR,BR,FR,GR,IR,KR,RO,RU,RW,TR');
|
||||
});
|
||||
|
||||
it('should not fetch new options when non-string is filtered', async () => {
|
||||
await comboBox.set('fieldSelect-0', 'clientip');
|
||||
await PageObjects.visualize.clickGo();
|
||||
|
||||
const initialOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(initialOptions.trim().split('\n').join()).to.equal(
|
||||
'135.206.117.161,177.194.175.66,18.55.141.62,243.158.217.196,32.146.206.24');
|
||||
|
||||
await comboBox.filterOptionsList('listControlSelect0', '17');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const updatedOptions = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(updatedOptions.trim().split('\n').join()).to.equal('135.206.117.161,177.194.175.66,243.158.217.196');
|
||||
});
|
||||
});
|
||||
|
||||
describe('chained controls', () => {
|
||||
|
||||
before(async () => {
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
await PageObjects.visualize.clickInputControlVis();
|
||||
await PageObjects.visualize.clickVisEditorTab('controls');
|
||||
|
||||
await PageObjects.visualize.addInputControl();
|
||||
await comboBox.set('indexPatternSelect-0', 'logstash- ');
|
||||
await comboBox.set('fieldSelect-0', 'geo.src');
|
||||
|
||||
await PageObjects.visualize.addInputControl();
|
||||
await comboBox.set('indexPatternSelect-1', 'logstash- ');
|
||||
await comboBox.set('fieldSelect-1', 'clientip');
|
||||
await PageObjects.visualize.setSelectByOptionText('parentSelect-1', 'geo.src');
|
||||
|
||||
await PageObjects.visualize.clickGo();
|
||||
});
|
||||
|
||||
it('should disable child control when parent control is not set', async () => {
|
||||
const parentControlMenu = await comboBox.getOptionsList('listControlSelect0');
|
||||
expect(parentControlMenu.trim().split('\n').join()).to.equal('BD,BR,CN,ID,IN,JP,NG,PK,RU,US');
|
||||
|
||||
const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input');
|
||||
const isDisabled = await childControlInput.getProperty('disabled');
|
||||
expect(isDisabled).to.equal(true);
|
||||
});
|
||||
|
||||
it('should filter child control options by parent control value', async () => {
|
||||
await comboBox.set('listControlSelect0', 'BR');
|
||||
|
||||
const childControlMenu = await comboBox.getOptionsList('listControlSelect1');
|
||||
expect(childControlMenu.trim().split('\n').join()).to.equal('14.61.182.136,3.174.21.181,6.183.121.70,71.241.97.89,9.69.255.135');
|
||||
});
|
||||
|
||||
it('should create a seperate filter pill for parent control and child control', async () => {
|
||||
await comboBox.set('listControlSelect1', '14.61.182.136');
|
||||
|
||||
await PageObjects.visualize.inputControlSubmit();
|
||||
|
||||
const hasParentControlFilter = await filterBar.hasFilter('geo.src', 'BR');
|
||||
expect(hasParentControlFilter).to.equal(true);
|
||||
|
||||
const hasChildControlFilter = await filterBar.hasFilter('clientip', '14.61.182.136');
|
||||
expect(hasChildControlFilter).to.equal(true);
|
||||
});
|
||||
|
||||
it('should clear child control dropdown when parent control value is removed', async () => {
|
||||
await comboBox.clear('listControlSelect0');
|
||||
await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire
|
||||
|
||||
const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input');
|
||||
const isDisabled = await childControlInput.getProperty('disabled');
|
||||
expect(isDisabled).to.equal(true);
|
||||
|
||||
await testSubjects.click('inputControlCancelBtn');
|
||||
});
|
||||
|
||||
it('should clear child control dropdown when parent control filter pill removed', async () => {
|
||||
await filterBar.removeFilter('geo.src');
|
||||
await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire
|
||||
|
||||
const hasValue = await comboBox.doesComboBoxHaveSelectedOptions('listControlSelect0');
|
||||
expect(hasValue).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
176
test/functional/fixtures/es_archiver/visualize/data.json
Normal file
176
test/functional/fixtures/es_archiver/visualize/data.json
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -239,6 +239,34 @@
|
|||
"number_of_replicas": "1",
|
||||
"number_of_shards": "1"
|
||||
}
|
||||
},
|
||||
"migrationVersion": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"index-pattern": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"references": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue