mirror of https://github.com/apache/superset.git
fix: chart validation error not cleared on control value update (#10224)
This commit is contained in:
parent
f7a024d7de
commit
700429f431
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.
|
||||
*/
|
||||
describe('AdhocFilters', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Set simple adhoc filter', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=adhoc_filters]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('name{enter}');
|
||||
});
|
||||
cy.get('#filter-edit-popover').within(() => {
|
||||
cy.get('[data-test=adhoc-filter-simple-value]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('Any{enter}');
|
||||
});
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Set custom adhoc filter', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=adhoc_filters]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('name{enter}');
|
||||
});
|
||||
|
||||
cy.get('#filter-edit-popover').within(() => {
|
||||
cy.get('#adhoc-filter-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type("'Amy' OR name = 'Bob'");
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.
|
||||
*/
|
||||
describe('AdhocMetrics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Clear metric and set simple adhoc metric', () => {
|
||||
const metric = 'sum(sum_girls)';
|
||||
const metricName = 'Girl Births';
|
||||
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__clear-indicator').click();
|
||||
cy.get('.Select__control input').type('sum_girls');
|
||||
cy.get('.Select__option--is-focused').trigger('mousedown').click();
|
||||
});
|
||||
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('.popover-title').within(() => {
|
||||
cy.get('span').click();
|
||||
cy.get('input').type(metricName);
|
||||
});
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
cy.get('.Select__multi-value__label').contains(metricName);
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Switch from simple to custom sql', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
// select column "num"
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__clear-indicator').click();
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('.Select__control input').type('num');
|
||||
cy.get('.option-label').contains(/^num$/).click();
|
||||
});
|
||||
|
||||
// add custom SQL
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type('/COUNT(DISTINCT name)', { force: true });
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
|
||||
const metric = 'SUM(num)/COUNT(DISTINCT name)';
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Switch from custom sql tabs to simple', () => {
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__dropdown-indicator').click();
|
||||
cy.get('input[type=text]').type('sum_girls{enter}');
|
||||
});
|
||||
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_identifier').contains('sum_girls');
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type('{selectall}{backspace}SUM(num)');
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SIMPLE').click();
|
||||
cy.get('.Select__single-value').contains(/^num$/);
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
|
||||
const metric = 'SUM(num)';
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Typing starts with aggregate function name', () => {
|
||||
// select column "num"
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__dropdown-indicator').click();
|
||||
cy.get('.Select__control input[type=text]').type('avg(');
|
||||
cy.get('.Select__option').contains('ds');
|
||||
cy.get('.Select__option').contains('name');
|
||||
cy.get('.Select__option').contains('sum_boys').click();
|
||||
});
|
||||
|
||||
const metric = 'AVG(sum_boys)';
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.
|
||||
*/
|
||||
describe('Advanced analytics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Create custom time compare', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('.panel-title').contains('Advanced Analytics').click();
|
||||
|
||||
cy.get('[data-test=time_compare]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('28 days{enter}');
|
||||
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('364 days{enter}');
|
||||
cy.get('.Select__multi-value__label').contains('364 days');
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.wait('@postJson');
|
||||
cy.reload();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
|
||||
cy.get('[data-test=time_compare]').within(() => {
|
||||
cy.get('.Select__multi-value__label').contains('364 days');
|
||||
cy.get('.Select__multi-value__label').contains('28 days');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Annotations', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Create formula annotation y-axis goal line', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=annotation_layers]').within(() => {
|
||||
cy.get('button').click();
|
||||
});
|
||||
|
||||
cy.get('.popover-content').within(() => {
|
||||
cy.get('[data-test=annotation-layer-name-header]')
|
||||
.siblings()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('input').type('Goal line');
|
||||
});
|
||||
cy.get('[data-test=annotation-layer-value-header]')
|
||||
.siblings()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('input').type('y=1400000');
|
||||
});
|
||||
cy.get('button').contains('OK').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
|
||||
cy.get('.nv-legend-text').should('have.length', 2);
|
||||
});
|
||||
});
|
|
@ -40,255 +40,6 @@ describe('Groupby', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('AdhocMetrics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Clear metric and set simple adhoc metric', () => {
|
||||
const metric = 'sum(sum_girls)';
|
||||
const metricName = 'Girl Births';
|
||||
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__clear-indicator').click();
|
||||
cy.get('.Select__control input').type('sum_girls');
|
||||
cy.get('.Select__option--is-focused').trigger('mousedown').click();
|
||||
});
|
||||
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('.popover-title').within(() => {
|
||||
cy.get('span').click();
|
||||
cy.get('input').type(metricName);
|
||||
});
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
cy.get('.Select__multi-value__label').contains(metricName);
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Switch from simple to custom sql', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
// select column "num"
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__clear-indicator').click();
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('.Select__control input').type('num');
|
||||
cy.get('.option-label').contains(/^num$/).click();
|
||||
});
|
||||
|
||||
// add custom SQL
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type('/COUNT(DISTINCT name)', { force: true });
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
|
||||
const metric = 'SUM(num)/COUNT(DISTINCT name)';
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Switch from custom sql tabs to simple', () => {
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__dropdown-indicator').click();
|
||||
cy.get('input[type=text]').type('sum_girls{enter}');
|
||||
});
|
||||
|
||||
cy.get('#metrics-edit-popover').within(() => {
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_identifier').contains('sum_girls');
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type('{selectall}{backspace}SUM(num)');
|
||||
cy.get('#adhoc-metric-edit-tabs-tab-SIMPLE').click();
|
||||
cy.get('.Select__single-value').contains(/^num$/);
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
|
||||
const metric = 'SUM(num)';
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Typing starts with aggregate function name', () => {
|
||||
// select column "num"
|
||||
cy.get('[data-test=metrics]').within(() => {
|
||||
cy.get('.Select__dropdown-indicator').click();
|
||||
cy.get('.Select__control input[type=text]').type('avg(');
|
||||
cy.get('.Select__option').contains('ds');
|
||||
cy.get('.Select__option').contains('name');
|
||||
cy.get('.Select__option').contains('sum_boys').click();
|
||||
});
|
||||
|
||||
const metric = 'AVG(sum_boys)';
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AdhocFilters', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Set simple adhoc filter', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=adhoc_filters]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('name{enter}');
|
||||
});
|
||||
cy.get('#filter-edit-popover').within(() => {
|
||||
cy.get('[data-test=adhoc-filter-simple-value]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('Any{enter}');
|
||||
});
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
|
||||
it('Set custom adhoc filter', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=adhoc_filters]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('name{enter}');
|
||||
});
|
||||
|
||||
cy.get('#filter-edit-popover').within(() => {
|
||||
cy.get('#adhoc-filter-edit-tabs-tab-SQL').click();
|
||||
cy.get('.ace_content').click();
|
||||
cy.get('.ace_text-input').type("'Amy' OR name = 'Bob'");
|
||||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Advanced analytics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Create custom time compare', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('.panel-title').contains('Advanced Analytics').click();
|
||||
|
||||
cy.get('[data-test=time_compare]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('28 days{enter}');
|
||||
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('364 days{enter}');
|
||||
cy.get('.Select__multi-value__label').contains('364 days');
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.wait('@postJson');
|
||||
cy.reload();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
|
||||
cy.get('[data-test=time_compare]').within(() => {
|
||||
cy.get('.Select__multi-value__label').contains('364 days');
|
||||
cy.get('.Select__multi-value__label').contains('28 days');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Annotations', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.server();
|
||||
cy.route('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.route('POST', '/superset/explore_json/**').as('postJson');
|
||||
});
|
||||
|
||||
it('Create formula annotation y-axis goal line', () => {
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
|
||||
cy.get('[data-test=annotation_layers]').within(() => {
|
||||
cy.get('button').click();
|
||||
});
|
||||
|
||||
cy.get('.popover-content').within(() => {
|
||||
cy.get('[data-test=annotation-layer-name-header]')
|
||||
.siblings()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('input').type('Goal line');
|
||||
});
|
||||
cy.get('[data-test=annotation-layer-value-header]')
|
||||
.siblings()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get('input').type('y=1400000');
|
||||
});
|
||||
cy.get('button').contains('OK').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
});
|
||||
|
||||
cy.get('.nv-legend-text').should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Time range filter', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
|
|
|
@ -27,9 +27,26 @@ describe('Visualization > Line', () => {
|
|||
cy.route('POST', '/superset/explore_json/**').as('getJson');
|
||||
});
|
||||
|
||||
it('should show validator error when no metric', () => {
|
||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [] };
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.get('.alert-warning').contains(`"Metrics" cannot be empty`);
|
||||
});
|
||||
|
||||
it('should not show validator error when metric added', () => {
|
||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [] };
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.get('.alert-warning').contains(`"Metrics" cannot be empty`);
|
||||
cy.get('.text-danger').contains('Metrics');
|
||||
cy.get('.metrics-select .Select__input input:eq(0)')
|
||||
.focus()
|
||||
.type('SUM(num){enter}');
|
||||
cy.get('.text-danger').should('not.exist');
|
||||
cy.get('.alert-warning').should('not.exist');
|
||||
});
|
||||
|
||||
it('should work with adhoc metric', () => {
|
||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
||||
});
|
||||
|
|
|
@ -30,9 +30,7 @@ describe('Visualization > Table', () => {
|
|||
});
|
||||
|
||||
it('Test table with adhoc metric', () => {
|
||||
const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC };
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.visitChartByParams({ ...VIZ_DEFAULTS, metrics: NUM_METRIC });
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@getJson',
|
||||
querySubstring: NUM_METRIC.label,
|
||||
|
@ -41,16 +39,14 @@ describe('Visualization > Table', () => {
|
|||
});
|
||||
|
||||
it('Test table with groupby', () => {
|
||||
const formData = {
|
||||
cy.visitChartByParams({
|
||||
...VIZ_DEFAULTS,
|
||||
metrics: NUM_METRIC,
|
||||
groupby: ['name'],
|
||||
};
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
});
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@getJson',
|
||||
querySubstring: formData.groupby[0],
|
||||
querySubstring: /groupby.*name/,
|
||||
chartSelector: 'table',
|
||||
});
|
||||
});
|
||||
|
@ -62,7 +58,6 @@ describe('Visualization > Table', () => {
|
|||
metrics: [],
|
||||
groupby: ['name'],
|
||||
};
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
|
||||
});
|
||||
|
@ -74,23 +69,19 @@ describe('Visualization > Table', () => {
|
|||
groupby: ['name'],
|
||||
order_desc: true,
|
||||
};
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
|
||||
});
|
||||
|
||||
it('Test table with groupby and limit', () => {
|
||||
const limit = 10;
|
||||
|
||||
const formData = {
|
||||
...VIZ_DEFAULTS,
|
||||
metrics: NUM_METRIC,
|
||||
groupby: ['name'],
|
||||
row_limit: limit,
|
||||
};
|
||||
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
|
||||
cy.wait('@getJson').then(async xhr => {
|
||||
cy.verifyResponseCodes(xhr);
|
||||
cy.verifySliceContainer('table');
|
|
@ -30,6 +30,10 @@ declare namespace Cypress {
|
|||
*/
|
||||
login(): void;
|
||||
|
||||
visitChartByParams(params: string | object): cy;
|
||||
visitChartByName(name: string): cy;
|
||||
visitChartById(id: number): cy;
|
||||
|
||||
/**
|
||||
* Verify a waitXHR response and parse response JSON.
|
||||
*/
|
||||
|
@ -46,14 +50,10 @@ declare namespace Cypress {
|
|||
/**
|
||||
* Verify slice successfully loaded.
|
||||
*/
|
||||
verifySliceSuccess({
|
||||
waitAlias,
|
||||
querySubString,
|
||||
chartSelector,
|
||||
}: {
|
||||
verifySliceSuccess(options: {
|
||||
waitAlias: string;
|
||||
querySubString: string;
|
||||
chartSelector: JQuery.Selector;
|
||||
querySubstring?: string | RegExp;
|
||||
chartSelector?: JQuery.Selector;
|
||||
}): cy;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@ Cypress.Commands.add('visitChartById', chartId => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add('visitChartByParams', params => {
|
||||
return cy.visit(`${BASE_EXPLORE_URL}${params}`);
|
||||
const queryString =
|
||||
typeof params === 'string' ? params : JSON.stringify(params);
|
||||
return cy.visit(`${BASE_EXPLORE_URL}${queryString}`);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('verifyResponseCodes', (xhr: XMLHttpRequest, callback) => {
|
||||
|
@ -78,17 +80,21 @@ Cypress.Commands.add(
|
|||
chartSelector,
|
||||
}: {
|
||||
waitAlias: string;
|
||||
querySubstring: string;
|
||||
chartSelector: JQuery.Selector;
|
||||
querySubstring?: string | RegExp;
|
||||
}) => {
|
||||
cy.wait(waitAlias).then(xhr => {
|
||||
cy.verifySliceContainer(chartSelector);
|
||||
cy.verifyResponseCodes(xhr, responseBody => {
|
||||
if (querySubstring) {
|
||||
type QueryResponse = { query: string };
|
||||
expect(
|
||||
responseBody && (responseBody as QueryResponse).query,
|
||||
).contains(querySubstring);
|
||||
const query = responseBody
|
||||
? (responseBody as { query: string }).query
|
||||
: '';
|
||||
if (querySubstring instanceof RegExp) {
|
||||
expect(query).to.match(querySubstring);
|
||||
} else {
|
||||
expect(query).to.contain(querySubstring);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -189,15 +189,15 @@ describe('controlUtils', () => {
|
|||
it('removes the mapStateToProps key from the object', () => {
|
||||
let control = getControlConfig('all_columns', 'table');
|
||||
control = applyMapStateToPropsToControl(control, state);
|
||||
expect(control.mapStateToProps).toBe(undefined);
|
||||
expect(control.mapStateToProps[0]).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getControlState', () => {
|
||||
it('to be function free', () => {
|
||||
const control = getControlState('all_columns', 'table', state, ['a']);
|
||||
expect(control.mapStateToProps).toBe(undefined);
|
||||
expect(control.validators).toBe(undefined);
|
||||
it('to still have the functions', () => {
|
||||
const control = getControlState('metrics', 'table', state, ['a']);
|
||||
expect(typeof control.mapStateToProps).toBe('function');
|
||||
expect(typeof control.validators[0]).toBe('function');
|
||||
});
|
||||
|
||||
it('to fix multi with non-array values', () => {
|
||||
|
|
|
@ -76,13 +76,6 @@ class ControlPanelsContainer extends React.Component {
|
|||
// apply current value in formData
|
||||
value: formData[name],
|
||||
};
|
||||
const { mapStateToProps: mapFn } = controlData;
|
||||
if (mapFn) {
|
||||
Object.assign(
|
||||
controlData,
|
||||
mapFn(exploreState, controlData, actions) || {},
|
||||
);
|
||||
}
|
||||
const {
|
||||
validationErrors,
|
||||
provideFormDataToProps,
|
||||
|
|
|
@ -45,7 +45,6 @@ export function validateControl(control, processedState) {
|
|||
validationErrors.push(v);
|
||||
}
|
||||
});
|
||||
delete validatedControl.validators;
|
||||
return { ...validatedControl, validationErrors };
|
||||
}
|
||||
return control;
|
||||
|
@ -95,7 +94,6 @@ export function applyMapStateToPropsToControl(control, state) {
|
|||
if (state) {
|
||||
Object.assign(appliedControl, control.mapStateToProps(state, control));
|
||||
}
|
||||
delete appliedControl.mapStateToProps;
|
||||
return appliedControl;
|
||||
}
|
||||
return control;
|
||||
|
@ -141,6 +139,7 @@ export function getControlStateFromControlConfig(controlConfig, state, value) {
|
|||
// If a choice control went from multi=false to true, wrap value in array
|
||||
const controlValue =
|
||||
controlConfig.multi && value && !Array.isArray(value) ? [value] : value;
|
||||
|
||||
controlState.value =
|
||||
typeof controlValue === 'undefined' ? controlState.default : controlValue;
|
||||
|
||||
|
|
|
@ -99,24 +99,34 @@ export default function exploreReducer(state = {}, action) {
|
|||
},
|
||||
[actions.SET_FIELD_VALUE]() {
|
||||
const new_form_data = state.form_data;
|
||||
new_form_data[action.controlName] = action.value;
|
||||
const { controlName, value, validationErrors } = action;
|
||||
new_form_data[controlName] = value;
|
||||
|
||||
// These errors are reported from the Control components
|
||||
let errors = action.validationErrors || [];
|
||||
const vizType = new_form_data.viz_type;
|
||||
|
||||
// Use the processed control config (with overrides and everything)
|
||||
// if `controlName` does not existing in current controls,
|
||||
const controlConfig =
|
||||
state.controls[action.controlName] ||
|
||||
getControlConfig(action.controlName, vizType) ||
|
||||
{};
|
||||
|
||||
// will call validators again
|
||||
const control = {
|
||||
...getControlStateFromControlConfig(controlConfig, state, action.value),
|
||||
};
|
||||
|
||||
// These errors are based on control config `validators`
|
||||
errors = errors.concat(control.validationErrors || []);
|
||||
// combine newly detected errors with errors from `onChange` event of
|
||||
// each control component (passed via reducer action).
|
||||
const errors = control.validationErrors || [];
|
||||
(validationErrors || []).forEach(err => {
|
||||
// skip duplicated errors
|
||||
if (!errors.includes(err)) {
|
||||
errors.push(err);
|
||||
}
|
||||
});
|
||||
const hasErrors = errors && errors.length > 0;
|
||||
|
||||
return {
|
||||
...state,
|
||||
form_data: new_form_data,
|
||||
|
|
Loading…
Reference in New Issue