mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[TSVB]: initial markdown test implementation (#31893)
* Improve test coverage for TSVB markdown
This commit is contained in:
parent
92559eeaf5
commit
062376368e
7 changed files with 201 additions and 97 deletions
|
@ -169,7 +169,7 @@ class MarkdownEditor extends Component {
|
|||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<table className="table">
|
||||
<table className="table" data-test-subj="tsvbMarkdownVariablesTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
|
@ -190,7 +190,7 @@ class MarkdownEditor extends Component {
|
|||
</table>
|
||||
|
||||
{rows.length === 0 && (
|
||||
<EuiTitle size="xxs" className="tvbMarkdownEditor__noVariables">
|
||||
<EuiTitle size="xxs" className="tsvbMarkdownVariablesTable__noVariables" data-test-subj="tvbMarkdownEditor__noVariables">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdownEditor.noVariablesAvailableDescription"
|
||||
|
|
|
@ -279,11 +279,12 @@ class MarkdownPanelConfigUi extends Component {
|
|||
<EuiTab
|
||||
isSelected={selectedTab === 'markdown'}
|
||||
onClick={() => this.switchTab('markdown')}
|
||||
data-test-subj="markdown-subtab"
|
||||
>
|
||||
Markdown
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="markdownDataBtn"
|
||||
data-test-subj="data-subtab"
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
|
@ -295,6 +296,7 @@ class MarkdownPanelConfigUi extends Component {
|
|||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
data-test-subj="options-subtab"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdown.optionsTab.panelOptionsButtonLabel"
|
||||
|
|
|
@ -152,58 +152,6 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
});
|
||||
|
||||
describe('markdown', () => {
|
||||
before(async () => {
|
||||
await PageObjects.visualBuilder.resetPage();
|
||||
await PageObjects.visualBuilder.clickMarkdown();
|
||||
await PageObjects.timePicker.setAbsoluteRange(
|
||||
'2015-09-22 06:00:00.000',
|
||||
'2015-09-22 11:00:00.000'
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow printing raw timestamp of data', async () => {
|
||||
await retry.try(async () => {
|
||||
await PageObjects.visualBuilder.enterMarkdown('{{ count.data.raw.[0].[0] }}');
|
||||
const text = await PageObjects.visualBuilder.getMarkdownText();
|
||||
expect(text).to.be('1442901600000');
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow printing raw value of data', async () => {
|
||||
await PageObjects.visualBuilder.enterMarkdown('{{ count.data.raw.[0].[1] }}');
|
||||
const text = await PageObjects.visualBuilder.getMarkdownText();
|
||||
expect(text).to.be('6');
|
||||
});
|
||||
|
||||
describe('allow time offsets', () => {
|
||||
before(async () => {
|
||||
await PageObjects.visualBuilder.enterMarkdown(
|
||||
'{{ count.data.raw.[0].[0] }}#{{ count.data.raw.[0].[1] }}'
|
||||
);
|
||||
await PageObjects.visualBuilder.clickMarkdownData();
|
||||
await PageObjects.visualBuilder.clickSeriesOption();
|
||||
});
|
||||
|
||||
it('allow positive time offsets', async () => {
|
||||
await PageObjects.visualBuilder.enterOffsetSeries('2h');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
const text = await PageObjects.visualBuilder.getMarkdownText();
|
||||
const [timestamp, value] = text.split('#');
|
||||
expect(timestamp).to.be('1442901600000');
|
||||
expect(value).to.be('3');
|
||||
});
|
||||
|
||||
it('allow negative time offsets', async () => {
|
||||
await PageObjects.visualBuilder.enterOffsetSeries('-2h');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
const text = await PageObjects.visualBuilder.getMarkdownText();
|
||||
const [timestamp, value] = text.split('#');
|
||||
expect(timestamp).to.be('1442901600000');
|
||||
expect(value).to.be('23');
|
||||
});
|
||||
});
|
||||
});
|
||||
// add a table sanity timestamp
|
||||
describe('table', () => {
|
||||
before(async () => {
|
||||
|
|
76
test/functional/apps/visualize/_tsvb_markdown.ts
Normal file
76
test/functional/apps/visualize/_tsvb_markdown.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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 'expect.js';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
// tslint:disable-next-line:no-default-export
|
||||
export default function({ getPageObjects }: FtrProviderContext) {
|
||||
const { visualBuilder, timePicker } = getPageObjects([
|
||||
'visualBuilder',
|
||||
'timePicker',
|
||||
'visualize',
|
||||
]);
|
||||
|
||||
describe('visual builder', function describeIndexTests() {
|
||||
describe('markdown', () => {
|
||||
before(async () => {
|
||||
await visualBuilder.resetPage();
|
||||
await visualBuilder.clickMarkdown();
|
||||
await timePicker.setAbsoluteRange('2015-09-22 06:00:00.000', '2015-09-22 11:00:00.000');
|
||||
});
|
||||
|
||||
it('should render subtabs and table variables markdown components', async () => {
|
||||
const tabs = await visualBuilder.getSubTabs();
|
||||
expect(tabs).to.have.length(3);
|
||||
|
||||
const variables = await visualBuilder.getMarkdownTableVariables();
|
||||
expect(variables).not.to.be.empty();
|
||||
expect(variables).to.have.length(5);
|
||||
});
|
||||
|
||||
it('should allow printing raw timestamp of data', async () => {
|
||||
await visualBuilder.enterMarkdown('{{ count.data.raw.[0].[0] }}');
|
||||
const text = await visualBuilder.getMarkdownText();
|
||||
expect(text).to.be('1442901600000');
|
||||
});
|
||||
|
||||
it('should allow printing raw value of data', async () => {
|
||||
await visualBuilder.enterMarkdown('{{ count.data.raw.[0].[1] }}');
|
||||
const text = await visualBuilder.getMarkdownText();
|
||||
expect(text).to.be('6');
|
||||
});
|
||||
|
||||
it('should render html as plain text', async () => {
|
||||
const html = '<h1>hello world</h1>';
|
||||
await visualBuilder.enterMarkdown(html);
|
||||
const markdownText = await visualBuilder.getMarkdownText();
|
||||
expect(markdownText).to.be(html);
|
||||
});
|
||||
|
||||
it('should render mustache list', async () => {
|
||||
const list = '{{#each _all}}\n{{ data.formatted.[0] }} {{ data.raw.[0] }}\n{{/each}}';
|
||||
const expectedRenderer = 'Sep 22, 2015 @ 06:00:00.000,6 1442901600000,6';
|
||||
await visualBuilder.enterMarkdown(list);
|
||||
const markdownText = await visualBuilder.getMarkdownText();
|
||||
expect(markdownText).to.be(expectedRenderer);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -76,6 +76,7 @@ export default function ({ getService, loadTestFile }) {
|
|||
loadTestFile(require.resolve('./_vertical_bar_chart'));
|
||||
loadTestFile(require.resolve('./_vertical_bar_chart_nontimeindex'));
|
||||
loadTestFile(require.resolve('./_tsvb_chart'));
|
||||
loadTestFile(require.resolve('./_tsvb_markdown'));
|
||||
loadTestFile(require.resolve('./_vega_chart'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -45,7 +45,6 @@ import { ShieldPageProvider } from './shield_page';
|
|||
import { TimePickerPageProvider } from './time_picker';
|
||||
// @ts-ignore not TS yet
|
||||
import { TimelionPageProvider } from './timelion_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { VisualBuilderPageProvider } from './visual_builder_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { VisualizePageProvider } from './visualize_page';
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export function VisualBuilderPageProvider({ getService, getPageObjects }) {
|
||||
import { FtrProviderContext } from '../ftr_provider_context.d';
|
||||
|
||||
export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const find = getService('find');
|
||||
const retry = getService('retry');
|
||||
const log = getService('log');
|
||||
|
@ -27,38 +29,48 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
|
|||
const PageObjects = getPageObjects(['common', 'header', 'visualize', 'timePicker']);
|
||||
|
||||
class VisualBuilderPage {
|
||||
|
||||
async resetPage() {
|
||||
const fromTime = '2015-09-19 06:31:44.000';
|
||||
const toTime = '2015-09-22 18:31:44.000';
|
||||
public async resetPage(
|
||||
fromTime = '2015-09-19 06:31:44.000',
|
||||
toTime = '2015-09-22 18:31:44.000'
|
||||
) {
|
||||
log.debug('navigateToApp visualize');
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickVisualBuilderChart');
|
||||
await PageObjects.visualize.clickVisualBuilder();
|
||||
log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
|
||||
log.debug('Set absolute time range from "' + fromTime + '" to "' + toTime + '"');
|
||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
}
|
||||
|
||||
async clickMetric() {
|
||||
public async clickMetric() {
|
||||
const button = await testSubjects.find('metricTsvbTypeBtn');
|
||||
await button.click();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async clickMarkdown() {
|
||||
public async clickMarkdown() {
|
||||
const button = await testSubjects.find('markdownTsvbTypeBtn');
|
||||
await button.click();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getMetricValue() {
|
||||
public async getMetricValue() {
|
||||
const metricValue = await find.byCssSelector('.tvbVisMetric__value--primary');
|
||||
return metricValue.getVisibleText();
|
||||
}
|
||||
|
||||
async enterMarkdown(markdown) {
|
||||
const prevRenderingCount = await PageObjects.visualize.getVisualizationRenderingCount();
|
||||
public async enterMarkdown(markdown: string) {
|
||||
const input = await find.byCssSelector('.tvbMarkdownEditor__editor textarea');
|
||||
await this.clearMarkdown();
|
||||
const prevRenderingCount = await PageObjects.visualize.getVisualizationRenderingCount();
|
||||
await input.type(markdown);
|
||||
await PageObjects.visualize.waitForVisualizationRenderingStabilized();
|
||||
await PageObjects.visualize.waitForRenderingCount(prevRenderingCount + 1);
|
||||
}
|
||||
|
||||
public async clearMarkdown() {
|
||||
const input = await find.byCssSelector('.tvbMarkdownEditor__editor textarea');
|
||||
// click for switching context(fix for "should render first table variable" test)
|
||||
// see _tsvb_markdown.js
|
||||
// Since we use ACE editor and that isn't really storing its value inside
|
||||
// a textarea we must really select all text and remove it, and cannot use
|
||||
// clearValue().
|
||||
|
@ -69,80 +81,142 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
await input.pressKeys(browser.keys.NULL); // Release modifier keys
|
||||
await input.pressKeys(browser.keys.BACK_SPACE); // Delete all content
|
||||
await input.type(markdown);
|
||||
await PageObjects.visualize.waitForRenderingCount(prevRenderingCount + 1);
|
||||
}
|
||||
|
||||
async getMarkdownText() {
|
||||
public async getMarkdownText() {
|
||||
const el = await find.byCssSelector('.tvbEditorVisualization');
|
||||
return await el.getVisibleText();
|
||||
const text = await el.getVisibleText();
|
||||
return text;
|
||||
}
|
||||
|
||||
async clickMarkdownData() {
|
||||
await testSubjects.click('markdownDataBtn');
|
||||
/**
|
||||
*
|
||||
* getting all markdown variables list which located on `table` section
|
||||
*
|
||||
* **Note**: if `table` not have variables, use `getMarkdownTableNoVariables` method instead
|
||||
* @see {getMarkdownTableNoVariables}
|
||||
* @returns {Promise<Array<{key:string, value:string, selector:any}>>}
|
||||
* @memberof VisualBuilderPage
|
||||
*/
|
||||
public async getMarkdownTableVariables(): Promise<
|
||||
Array<{ key: string; value: string; selector: any }>
|
||||
> {
|
||||
const testTableVariables = await testSubjects.find('tsvbMarkdownVariablesTable');
|
||||
const variablesSelector = 'tbody tr';
|
||||
const exists = await find.existsByDisplayedByCssSelector(variablesSelector);
|
||||
if (!exists) {
|
||||
log.debug('variable list is empty');
|
||||
return [];
|
||||
}
|
||||
const variables: any[] = await testTableVariables.findAllByCssSelector(variablesSelector);
|
||||
|
||||
const variablesKeyValueSelectorMap = await Promise.all(
|
||||
variables.map(async (variable: any) => {
|
||||
const subVars = await variable.findAllByCssSelector('td');
|
||||
const selector = await subVars[0].findByTagName('a');
|
||||
const key = await selector.getVisibleText();
|
||||
const value = await subVars[1].getVisibleText();
|
||||
log.debug(`markdown table variables table is: ${key} ${value}`);
|
||||
return { key, value, selector };
|
||||
})
|
||||
);
|
||||
return variablesKeyValueSelectorMap;
|
||||
}
|
||||
|
||||
async clickSeriesOption(nth = 0) {
|
||||
/**
|
||||
* return variable table message, if `table` is empty it will be fail
|
||||
*
|
||||
* **Note:** if `table` have variables, use `getMarkdownTableVariables` method instead
|
||||
* @see {@link VisualBuilderPage#getMarkdownTableVariables}
|
||||
* @returns
|
||||
* @memberof VisualBuilderPage
|
||||
*/
|
||||
public async getMarkdownTableNoVariables() {
|
||||
return await testSubjects.getVisibleText('tvbMarkdownEditor__noVariables');
|
||||
}
|
||||
|
||||
/**
|
||||
* get all sub-tabs count for `time series`, `metric`, `top n`, `gauge`, `markdown` or `table` tab.
|
||||
*
|
||||
* @returns {Promise<any[]>}
|
||||
* @memberof VisualBuilderPage
|
||||
*/
|
||||
public async getSubTabs() {
|
||||
return await find.allByCssSelector('[data-test-subj$="-subtab"]');
|
||||
}
|
||||
|
||||
/**
|
||||
* switch markdown sub-tab for visualization
|
||||
*
|
||||
* @param {'data' | 'options'| 'markdown'} subTab
|
||||
* @memberof VisualBuilderPage
|
||||
*/
|
||||
public async markdownSwitchSubTab(subTab: 'data' | 'options' | 'markdown') {
|
||||
const element = await testSubjects.find(`${subTab}-subtab`);
|
||||
await element.click();
|
||||
}
|
||||
|
||||
public async clickSeriesOption(nth = 0) {
|
||||
const el = await testSubjects.findAll('seriesOptions');
|
||||
await el[nth].click();
|
||||
await PageObjects.common.sleep(300);
|
||||
await PageObjects.common.sleep(500);
|
||||
}
|
||||
|
||||
async clearOffsetSeries() {
|
||||
public async clearOffsetSeries() {
|
||||
const el = await testSubjects.find('offsetTimeSeries');
|
||||
await el.clearValue();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async enterOffsetSeries(value) {
|
||||
public async enterOffsetSeries(value: string) {
|
||||
const el = await testSubjects.find('offsetTimeSeries');
|
||||
await el.clearValue();
|
||||
await el.type(value);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getRhythmChartLegendValue() {
|
||||
public async getRhythmChartLegendValue() {
|
||||
const metricValue = await find.byCssSelector('.tvbLegend__itemValue');
|
||||
await metricValue.moveMouseTo();
|
||||
return await metricValue.getVisibleText();
|
||||
}
|
||||
|
||||
async clickGauge() {
|
||||
public async clickGauge() {
|
||||
await testSubjects.click('gaugeTsvbTypeBtn');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getGaugeLabel() {
|
||||
public async getGaugeLabel() {
|
||||
const gaugeLabel = await find.byCssSelector('.tvbVisGauge__label');
|
||||
return await gaugeLabel.getVisibleText();
|
||||
}
|
||||
|
||||
async getGaugeCount() {
|
||||
public async getGaugeCount() {
|
||||
const gaugeCount = await find.byCssSelector('.tvbVisGauge__value');
|
||||
return await gaugeCount.getVisibleText();
|
||||
}
|
||||
|
||||
async clickTopN() {
|
||||
public async clickTopN() {
|
||||
await testSubjects.click('top_nTsvbTypeBtn');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getTopNLabel() {
|
||||
public async getTopNLabel() {
|
||||
const topNLabel = await find.byCssSelector('.tvbVisTopN__label');
|
||||
return await topNLabel.getVisibleText();
|
||||
}
|
||||
|
||||
async getTopNCount() {
|
||||
public async getTopNCount() {
|
||||
const gaugeCount = await find.byCssSelector('.tvbVisTopN__value');
|
||||
return await gaugeCount.getVisibleText();
|
||||
}
|
||||
|
||||
async clickTable() {
|
||||
public async clickTable() {
|
||||
await testSubjects.click('tableTsvbTypeBtn');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async createNewAgg(nth = 0) {
|
||||
public async createNewAgg(nth = 0) {
|
||||
return await retry.try(async () => {
|
||||
const elements = await testSubjects.findAll('addMetricAddBtn');
|
||||
await elements[nth].click();
|
||||
|
@ -154,55 +228,59 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) {
|
|||
});
|
||||
}
|
||||
|
||||
async selectAggType(value, nth = 0) {
|
||||
public async selectAggType(value: string | number, nth = 0) {
|
||||
const elements = await testSubjects.findAll('aggSelector');
|
||||
await comboBox.setElement(elements[nth], value);
|
||||
return await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async fillInExpression(expression, nth = 0) {
|
||||
public async fillInExpression(expression: string, nth = 0) {
|
||||
const expressions = await testSubjects.findAll('mathExpression');
|
||||
await expressions[nth].type(expression);
|
||||
return await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async fillInVariable(name = 'test', metric = 'count', nth = 0) {
|
||||
public async fillInVariable(name = 'test', metric = 'count', nth = 0) {
|
||||
const elements = await testSubjects.findAll('varRow');
|
||||
const varNameInput = await elements[nth].findByCssSelector('.tvbAggs__varName');
|
||||
await varNameInput.type(name);
|
||||
const metricSelectWrapper = await elements[nth].findByCssSelector('.tvbAggs__varMetricWrapper');
|
||||
const metricSelectWrapper = await elements[nth].findByCssSelector(
|
||||
'.tvbAggs__varMetricWrapper'
|
||||
);
|
||||
await comboBox.setElement(metricSelectWrapper, metric);
|
||||
return await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
|
||||
async selectGroupByField(fieldName) {
|
||||
public async selectGroupByField(fieldName: string) {
|
||||
await comboBox.set('groupByField', fieldName);
|
||||
}
|
||||
|
||||
async setLabelValue(value) {
|
||||
public async setLabelValue(value: string) {
|
||||
const el = await testSubjects.find('columnLabelName');
|
||||
await el.clearValue();
|
||||
await el.type(value);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async getViewTable() {
|
||||
public async getViewTable() {
|
||||
const tableView = await testSubjects.find('tableView');
|
||||
return await tableView.getVisibleText();
|
||||
}
|
||||
async clickMetricPanelOptions() {
|
||||
|
||||
public async clickMetricPanelOptions() {
|
||||
const button = await testSubjects.find('metricEditorPanelOptionsBtn');
|
||||
await button.click();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
async setIndexPatternValue(value) {
|
||||
|
||||
public async setIndexPatternValue(value: string) {
|
||||
const el = await testSubjects.find('metricsIndexPatternInput');
|
||||
await el.clearValue();
|
||||
await el.type(value);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
async selectIndexPatternTimeField(timeField) {
|
||||
|
||||
public async selectIndexPatternTimeField(timeField: string) {
|
||||
const el = await testSubjects.find('comboBoxSearchInput');
|
||||
await el.clearValue();
|
||||
await el.type(timeField);
|
Loading…
Add table
Add a link
Reference in a new issue