[TSVB]: initial markdown test implementation (#31893)

* Improve test coverage for TSVB markdown
This commit is contained in:
Vitali Haradkou 2019-03-05 12:15:44 +03:00 committed by GitHub
parent 92559eeaf5
commit 062376368e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 201 additions and 97 deletions

View file

@ -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"

View file

@ -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"

View file

@ -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 () => {

View 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);
});
});
});
}

View file

@ -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'));
});
});

View file

@ -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';

View file

@ -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);