kibana/test/functional/page_objects/visualize_editor_page.ts
Spencer 4f4cf054de
[7.x] [ts] migrate root test dir to project refs (#99148) (#101416)
* [ts] migrate root test dir to project refs (#99148)

Co-authored-by: spalger <spalger@users.noreply.github.com>

* include schema files in telemetry ts project

Co-authored-by: spalger <spalger@users.noreply.github.com>
2021-06-04 16:22:00 -04:00

536 lines
19 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import expect from '@kbn/expect';
import { FtrService } from '../ftr_provider_context';
interface IntervalOptions {
type?: 'default' | 'numeric' | 'custom';
aggNth?: number;
append?: boolean;
}
export class VisualizeEditorPageObject extends FtrService {
private readonly find = this.ctx.getService('find');
private readonly log = this.ctx.getService('log');
private readonly retry = this.ctx.getService('retry');
private readonly browser = this.ctx.getService('browser');
private readonly testSubjects = this.ctx.getService('testSubjects');
private readonly comboBox = this.ctx.getService('comboBox');
private readonly elasticChart = this.ctx.getService('elasticChart');
private readonly common = this.ctx.getPageObject('common');
private readonly header = this.ctx.getPageObject('header');
private readonly visChart = this.ctx.getPageObject('visChart');
public async clickDataTab() {
await this.testSubjects.click('visEditorTab__data');
}
public async clickOptionsTab() {
await this.testSubjects.click('visEditorTab__options');
}
public async clickMetricsAndAxes() {
await this.testSubjects.click('visEditorTab__advanced');
}
public async clickVisEditorTab(tabName: string) {
await this.testSubjects.click(`visEditorTab__${tabName}`);
await this.header.waitUntilLoadingHasFinished();
}
public async addInputControl(type?: string) {
if (type) {
const selectInput = await this.testSubjects.find('selectControlType');
await selectInput.type(type);
}
await this.testSubjects.click('inputControlEditorAddBtn');
await this.header.waitUntilLoadingHasFinished();
}
public async inputControlClear() {
await this.testSubjects.click('inputControlClearBtn');
await this.header.waitUntilLoadingHasFinished();
}
public async inputControlSubmit() {
await this.testSubjects.clickWhenNotDisabled('inputControlSubmitBtn');
await this.visChart.waitForVisualizationRenderingStabilized();
}
public async clickGo() {
if (await this.visChart.isNewChartsLibraryEnabled()) {
await this.elasticChart.setNewChartUiDebugFlag();
}
const prevRenderingCount = await this.visChart.getVisualizationRenderingCount();
this.log.debug(`Before Rendering count ${prevRenderingCount}`);
await this.testSubjects.clickWhenNotDisabled('visualizeEditorRenderButton');
await this.visChart.waitForRenderingCount(prevRenderingCount + 1);
}
public async removeDimension(aggNth: number) {
await this.testSubjects.click(`visEditorAggAccordion${aggNth} > removeDimensionBtn`);
}
public async setFilterParams(aggNth: number, indexPattern: string, field: string) {
await this.comboBox.set(`indexPatternSelect-${aggNth}`, indexPattern);
await this.comboBox.set(`fieldSelect-${aggNth}`, field);
}
public async setFilterRange(aggNth: number, min: string, max: string) {
const control = await this.testSubjects.find(`inputControl${aggNth}`);
const inputMin = await control.findByCssSelector('[name$="minValue"]');
await inputMin.type(min);
const inputMax = await control.findByCssSelector('[name$="maxValue"]');
await inputMax.type(max);
}
public async clickSplitDirection(direction: string) {
const radioBtn = await this.find.byCssSelector(
`[data-test-subj="visEditorSplitBy-${direction}"]`
);
await radioBtn.click();
}
public async clickAddDateRange() {
await this.testSubjects.click(`visEditorAddDateRange`);
}
public async setDateRangeByIndex(index: string, from: string, to: string) {
await this.testSubjects.setValue(`visEditorDateRange${index}__from`, from);
await this.testSubjects.setValue(`visEditorDateRange${index}__to`, to);
}
/**
* Adds new bucket
* @param bucketName bucket name, like 'X-axis', 'Split rows', 'Split series'
* @param type aggregation type, like 'buckets', 'metrics'
*/
public async clickBucket(bucketName: string, type = 'buckets') {
await this.testSubjects.click(`visEditorAdd_${type}`);
await this.testSubjects.click(`visEditorAdd_${type}_${bucketName}`);
}
public async clickEnableCustomRanges() {
await this.testSubjects.click('heatmapUseCustomRanges');
}
public async clickAddRange() {
await this.testSubjects.click(`heatmapColorRange__addRangeButton`);
}
public async setCustomRangeByIndex(index: string | number, from: string, to: string) {
await this.testSubjects.setValue(`heatmapColorRange${index}__from`, from);
await this.testSubjects.setValue(`heatmapColorRange${index}__to`, to);
}
public async changeHeatmapColorNumbers(value = 6) {
await this.testSubjects.setValue('heatmapColorsNumber', `${value}`);
}
public async getBucketErrorMessage() {
const error = await this.find.byCssSelector(
'[data-test-subj="bucketsAggGroup"] [data-test-subj="defaultEditorAggSelect"] + .euiFormErrorText'
);
const errorMessage = await error.getAttribute('innerText');
this.log.debug(errorMessage);
return errorMessage;
}
public async addNewFilterAggregation() {
await this.testSubjects.click('visEditorAddFilterButton');
}
public async selectField(fieldValue: string, groupName = 'buckets', isChildAggregation = false) {
this.log.debug(`selectField ${fieldValue}`);
const selector = `
[data-test-subj="${groupName}AggGroup"]
[data-test-subj^="visEditorAggAccordion"].euiAccordion-isOpen
[data-test-subj="visAggEditorParams"]
${isChildAggregation ? '.visEditorAgg__subAgg' : ''}
[data-test-subj="visDefaultEditorField"]
`;
const fieldEl = await this.find.byCssSelector(selector);
await this.comboBox.setElement(fieldEl, fieldValue);
}
public async selectOrderByMetric(aggNth: number, metric: string) {
const sortSelect = await this.testSubjects.find(`visEditorOrderBy${aggNth}`);
const sortMetric = await sortSelect.findByCssSelector(`option[value="${metric}"]`);
await sortMetric.click();
}
public async selectCustomSortMetric(aggNth: number, metric: string, field: string) {
await this.selectOrderByMetric(aggNth, 'custom');
await this.selectAggregation(metric, 'buckets', true);
await this.selectField(field, 'buckets', true);
}
public async selectAggregation(
aggValue: string,
groupName = 'buckets',
isChildAggregation = false
) {
const comboBoxElement = await this.find.byCssSelector(`
[data-test-subj="${groupName}AggGroup"]
[data-test-subj^="visEditorAggAccordion"].euiAccordion-isOpen
${isChildAggregation ? '.visEditorAgg__subAgg' : ''}
[data-test-subj="defaultEditorAggSelect"]
`);
await this.comboBox.setElement(comboBoxElement, aggValue);
await this.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
*/
public async setFilterAggregationValue(filterValue: string, filterIndex = 0, aggregationId = 2) {
await this.testSubjects.setValue(
`visEditorFilterInput_${aggregationId}_${filterIndex}`,
filterValue
);
}
public async setValue(newValue: string) {
const input = await this.find.byCssSelector(
'[data-test-subj="visEditorPercentileRanks"] input'
);
await input.clearValue();
await input.type(newValue);
}
public async clickEditorSidebarCollapse() {
await this.testSubjects.click('collapseSideBarButton');
}
public async clickDropPartialBuckets() {
await this.testSubjects.click('dropPartialBucketsCheckbox');
}
public async expectMarkdownTextArea() {
await this.testSubjects.existOrFail('markdownTextarea');
}
public async setMarkdownTxt(markdownTxt: string) {
const input = await this.testSubjects.find('markdownTextarea');
await input.clearValue();
await input.type(markdownTxt);
}
public async isSwitchChecked(selector: string) {
const checkbox = await this.testSubjects.find(selector);
const isChecked = await checkbox.getAttribute('aria-checked');
return isChecked === 'true';
}
public async checkSwitch(selector: string) {
const isChecked = await this.isSwitchChecked(selector);
if (!isChecked) {
this.log.debug(`checking switch ${selector}`);
await this.testSubjects.click(selector);
}
}
public async uncheckSwitch(selector: string) {
const isChecked = await this.isSwitchChecked(selector);
if (isChecked) {
this.log.debug(`unchecking switch ${selector}`);
await this.testSubjects.click(selector);
}
}
public async setIsFilteredByCollarCheckbox(value = true) {
await this.retry.try(async () => {
const isChecked = await this.isSwitchChecked('isFilteredByCollarCheckbox');
if (isChecked !== value) {
await this.testSubjects.click('isFilteredByCollarCheckbox');
throw new Error('isFilteredByCollar not set correctly');
}
});
}
public async setCustomLabel(label: string, index: number | string = 1) {
const customLabel = await this.testSubjects.find(`visEditorStringInput${index}customLabel`);
customLabel.type(label);
}
public async selectYAxisAggregation(agg: string, field: string, label: string, index = 1) {
// index starts on the first "count" metric at 1
// Each new metric or aggregation added to a visualization gets the next index.
// So to modify a metric or aggregation tests need to keep track of the
// order they are added.
await this.toggleOpenEditor(index);
// select our agg
const aggSelect = await this.find.byCssSelector(
`#visEditorAggAccordion${index} [data-test-subj="defaultEditorAggSelect"]`
);
await this.comboBox.setElement(aggSelect, agg);
const fieldSelect = await this.find.byCssSelector(
`#visEditorAggAccordion${index} [data-test-subj="visDefaultEditorField"]`
);
// select our field
await this.comboBox.setElement(fieldSelect, field);
// enter custom label
await this.setCustomLabel(label, index);
}
public async getField() {
return await this.comboBox.getComboBoxSelectedOptions('visDefaultEditorField');
}
public async sizeUpEditor() {
const resizerPanel = await this.testSubjects.find('euiResizableButton');
// Drag panel 100 px left
await this.browser.dragAndDrop({ location: resizerPanel }, { location: { x: -100, y: 0 } });
}
public async toggleDisabledAgg(agg: string | number) {
await this.testSubjects.click(`visEditorAggAccordion${agg} > ~toggleDisableAggregationBtn`);
await this.header.waitUntilLoadingHasFinished();
}
public async toggleAggregationEditor(agg: string | number) {
await this.find.clickByCssSelector(
`[data-test-subj="visEditorAggAccordion${agg}"] .euiAccordion__button`
);
await this.header.waitUntilLoadingHasFinished();
}
public async toggleOtherBucket(agg: string | number = 2) {
await this.testSubjects.click(`visEditorAggAccordion${agg} > otherBucketSwitch`);
}
public async toggleMissingBucket(agg: string | number = 2) {
await this.testSubjects.click(`visEditorAggAccordion${agg} > missingBucketSwitch`);
}
public async toggleScaleMetrics() {
await this.testSubjects.click('scaleMetricsSwitch');
}
public async toggleAutoMode() {
await this.testSubjects.click('visualizeEditorAutoButton');
}
public async togglePieLegend() {
await this.testSubjects.click('visTypePieAddLegendSwitch');
}
public async togglePieNestedLegend() {
await this.testSubjects.click('visTypePieNestedLegendSwitch');
}
public async isApplyEnabled() {
const applyButton = await this.testSubjects.find('visualizeEditorRenderButton');
return await applyButton.isEnabled();
}
public async toggleAccordion(id: string, toState = 'true') {
const toggle = await this.find.byCssSelector(`button[aria-controls="${id}"]`);
const toggleOpen = await toggle.getAttribute('aria-expanded');
this.log.debug(`toggle ${id} expand = ${toggleOpen}`);
if (toggleOpen !== toState) {
this.log.debug(`toggle ${id} click()`);
await toggle.click();
}
}
public async toggleOpenEditor(index: number, toState = 'true') {
// index, see selectYAxisAggregation
await this.toggleAccordion(`visEditorAggAccordion${index}`, toState);
}
public async toggleAdvancedParams(aggId: string) {
const accordion = await this.testSubjects.find(`advancedParams-${aggId}`);
const accordionButton = await this.find.descendantDisplayedByCssSelector('button', accordion);
await accordionButton.click();
}
public async inputValueInCodeEditor(value: string) {
const codeEditor = await this.find.byCssSelector('.react-monaco-editor-container');
const textarea = await codeEditor.findByClassName('monaco-mouse-cursor-text');
await textarea.click();
await this.browser.pressKeys(value);
}
public async clickReset() {
await this.testSubjects.click('visualizeEditorResetButton');
await this.visChart.waitForVisualization();
}
public async clickYAxisOptions(axisId: string) {
await this.testSubjects.click(`toggleYAxisOptions-${axisId}`);
}
public async changeYAxisShowCheckbox(axisId: string, enabled: boolean) {
const selector = `valueAxisShow-${axisId}`;
const button = await this.testSubjects.find(selector);
const isEnabled = (await button.getAttribute('aria-checked')) === 'true';
if (enabled !== isEnabled) {
await button.click();
}
}
public async changeYAxisFilterLabelsCheckbox(axisId: string, enabled: boolean) {
const selector = `yAxisFilterLabelsCheckbox-${axisId}`;
const button = await this.testSubjects.find(selector);
const isEnabled = (await button.getAttribute('aria-checked')) === 'true';
if (enabled !== isEnabled) {
await button.click();
}
}
public async setSize(newValue: number, aggId?: number) {
const dataTestSubj = aggId
? `visEditorAggAccordion${aggId} > sizeParamEditor`
: 'sizeParamEditor';
await this.testSubjects.setValue(dataTestSubj, String(newValue));
}
public async selectChartMode(mode: string) {
const selector = await this.find.byCssSelector(`#seriesMode0 > option[value="${mode}"]`);
await selector.click();
}
public async selectYAxisScaleType(axisId: string, scaleType: string) {
const selector = await this.find.byCssSelector(
`#scaleSelectYAxis-${axisId} > option[value="${scaleType}"]`
);
await selector.click();
}
public async selectXAxisPosition(position: string) {
const option = await (await this.testSubjects.find('categoryAxisPosition')).findByCssSelector(
`option[value="${position}"]`
);
await option.click();
}
public async selectYAxisMode(mode: string) {
const selector = await this.find.byCssSelector(`#valueAxisMode0 > option[value="${mode}"]`);
await selector.click();
}
public async setAxisExtents(min: string, max: string, axisId = 'ValueAxis-1') {
await this.toggleAccordion(`yAxisAccordion${axisId}`);
await this.toggleAccordion(`yAxisOptionsAccordion${axisId}`);
await this.testSubjects.click('yAxisSetYExtents');
await this.testSubjects.setValue('yAxisYExtentsMax', max);
await this.testSubjects.setValue('yAxisYExtentsMin', min);
}
public async selectAggregateWith(fieldValue: string) {
await this.testSubjects.selectValue('visDefaultEditorAggregateWith', fieldValue);
}
public async setInterval(newValue: string | number, options: IntervalOptions = {}) {
const newValueString = `${newValue}`;
const { type = 'default', aggNth = 2, append = false } = options;
this.log.debug(`visEditor.setInterval(${newValueString}, {${type}, ${aggNth}, ${append}})`);
if (type === 'default') {
await this.comboBox.set('visEditorInterval', newValueString);
} else if (type === 'custom') {
await this.comboBox.setCustom('visEditorInterval', newValueString);
} else {
if (type === 'numeric') {
const autoMode = await this.testSubjects.getAttribute(
`visEditorIntervalSwitch${aggNth}`,
'aria-checked'
);
if (autoMode === 'true') {
await this.testSubjects.click(`visEditorIntervalSwitch${aggNth}`);
}
}
if (append) {
await this.testSubjects.append(`visEditorInterval${aggNth}`, String(newValueString));
} else {
await this.testSubjects.setValue(`visEditorInterval${aggNth}`, String(newValueString));
}
}
}
public async getInterval() {
return await this.comboBox.getComboBoxSelectedOptions('visEditorInterval');
}
public async getNumericInterval(aggNth = 2) {
return await this.testSubjects.getAttribute(`visEditorInterval${aggNth}`, 'value');
}
public async clickMetricEditor() {
await this.find.clickByCssSelector('[data-test-subj="metricsAggGroup"] .euiAccordion__button');
}
public async clickMetricByIndex(index: number) {
const metrics = await this.find.allByCssSelector(
'[data-test-subj="visualizationLoader"] .mtrVis .mtrVis__container'
);
expect(metrics.length).greaterThan(index);
await metrics[index].click();
}
public async setSelectByOptionText(selectId: string, optionText: string) {
const selectField = await this.find.byCssSelector(`#${selectId}`);
const options = await this.find.allByCssSelector(`#${selectId} > option`);
const $ = await selectField.parseDomContent();
const optionsText = $('option')
.toArray()
.map((option) => $(option).text());
const optionIndex = optionsText.indexOf(optionText);
if (optionIndex === -1) {
throw new Error(
`Unable to find option '${optionText}' in select ${selectId}. Available options: ${optionsText.join(
','
)}`
);
}
await options[optionIndex].click();
}
// point series
async clickAddAxis() {
return await this.testSubjects.click('visualizeAddYAxisButton');
}
async setAxisTitle(title: string, aggNth = 0) {
return await this.testSubjects.setValue(`valueAxisTitle${aggNth}`, title);
}
public async toggleGridCategoryLines() {
return await this.testSubjects.click('showCategoryLines');
}
public async toggleValuesOnChart() {
return await this.testSubjects.click('showValuesOnChart');
}
public async setGridValueAxis(axis: string) {
this.log.debug(`setGridValueAxis(${axis})`);
await this.find.selectValue('select#gridAxis', axis);
}
public async setSeriesAxis(seriesNth: number, axis: string) {
await this.find.selectValue(`select#seriesValueAxis${seriesNth}`, axis);
}
public async setSeriesType(seriesNth: number, type: string) {
await this.find.selectValue(`select#seriesType${seriesNth}`, type);
}
}