diff --git a/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
index dc129613b9..576304a4e4 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/AdhocFilters.test.ts
@@ -40,7 +40,7 @@ describe('AdhocFilters', () => {
cy.get('button').contains('Save').click();
});
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@postJson',
chartSelector: 'svg',
@@ -63,7 +63,7 @@ describe('AdhocFilters', () => {
cy.get('button').contains('Save').click();
});
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@postJson',
chartSelector: 'svg',
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
index 59722a0e67..5dfd741d77 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts
@@ -48,7 +48,7 @@ describe('AdhocMetrics', () => {
cy.get('.metrics-select .metric-option').contains(metricName);
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@postJson',
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
@@ -77,7 +77,7 @@ describe('AdhocMetrics', () => {
.type('/COUNT(DISTINCT name)', { force: true });
cy.get('#metrics-edit-popover').find('button').contains('Save').click();
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
const metric = 'SUM(num)/COUNT(DISTINCT name)';
cy.verifySliceSuccess({
@@ -103,7 +103,7 @@ describe('AdhocMetrics', () => {
cy.get('button').contains('Save').click();
});
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
const metric = 'SUM(num)';
cy.verifySliceSuccess({
@@ -124,7 +124,7 @@ describe('AdhocMetrics', () => {
});
const metric = 'AVG(sum_boys)';
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@postJson',
querySubstring: `${metric} AS "${metric}"`,
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
index 624bac63a7..31291e365d 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
@@ -43,7 +43,7 @@ describe('Advanced analytics', () => {
.find('.Select__multi-value__label')
.contains('364 days');
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.wait('@postJson');
cy.reload();
cy.verifySliceSuccess({
@@ -90,7 +90,7 @@ describe('Annotations', () => {
cy.get('button').contains('OK').click();
});
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@postJson',
chartSelector: 'svg',
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
index f90695805d..7a08611497 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
@@ -78,7 +78,7 @@ describe('Groupby control', () => {
cy.get('.Select__control').click();
cy.get('input[type=text]').type('state{enter}');
});
- cy.get('button.query').click();
+ cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({ waitAlias: '@postJson', chartSelector: 'svg' });
});
});
diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json
index 18da52a5ce..ecc9c29ce6 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -34830,16 +34830,14 @@
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/polished/-/polished-3.6.5.tgz",
"integrity": "sha512-VwhC9MlhW7O5dg/z7k32dabcAFW1VI2+7fSe8cE/kXcfL7mVdoa5UxciYGW2sJU78ldDLT6+ROEKIZKFNTnUXQ==",
- "dev": true,
"requires": {
"@babel/runtime": "^7.9.2"
},
"dependencies": {
"@babel/runtime": {
- "version": "7.10.5",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
- "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
- "dev": true,
+ "version": "7.11.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
+ "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index cb003287d2..4302995bf7 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -145,6 +145,7 @@
"mousetrap": "^1.6.1",
"mustache": "^2.2.1",
"omnibar": "^2.1.1",
+ "polished": "^3.6.5",
"prop-types": "^15.7.2",
"re-resizable": "^4.3.1",
"react": "^16.13.1",
diff --git a/superset-frontend/spec/helpers/theming.ts b/superset-frontend/spec/helpers/theming.ts
index cf1b4626f2..7f83165635 100644
--- a/superset-frontend/spec/helpers/theming.ts
+++ b/superset-frontend/spec/helpers/theming.ts
@@ -51,5 +51,5 @@ export function styledShallow(
theme: supersetTheme,
...options?.wrappingComponentProps,
},
- });
+ }).dive();
}
diff --git a/superset-frontend/spec/javascripts/addSlice/AddSliceContainer_spec.tsx b/superset-frontend/spec/javascripts/addSlice/AddSliceContainer_spec.tsx
index 5db740d279..4af7fec71e 100644
--- a/superset-frontend/spec/javascripts/addSlice/AddSliceContainer_spec.tsx
+++ b/superset-frontend/spec/javascripts/addSlice/AddSliceContainer_spec.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
-import { Button } from 'react-bootstrap';
+import Button from 'src/components/Button';
import Select from 'src/components/Select';
import AddSliceContainer, {
AddSliceContainerProps,
@@ -58,9 +58,9 @@ describe('AddSliceContainer', () => {
});
it('renders a disabled button if no datasource is selected', () => {
- expect(
- wrapper.find(Button).dive().find('.btn[disabled=true]'),
- ).toHaveLength(1);
+ expect(wrapper.find(Button).dive().find({ disabled: true })).toHaveLength(
+ 1,
+ );
});
it('renders an enabled button if datasource is selected', () => {
@@ -70,9 +70,9 @@ describe('AddSliceContainer', () => {
datasourceId: datasourceValue.split('__')[0],
datasourceType: datasourceValue.split('__')[1],
});
- expect(
- wrapper.find(Button).dive().find('.btn[disabled=false]'),
- ).toHaveLength(1);
+ expect(wrapper.find(Button).dive().find({ disabled: true })).toHaveLength(
+ 0,
+ );
});
it('formats explore url', () => {
diff --git a/superset-frontend/spec/javascripts/components/ConfirmStatusChange_spec.jsx b/superset-frontend/spec/javascripts/components/ConfirmStatusChange_spec.jsx
index a9e027d28f..4b002637b6 100644
--- a/superset-frontend/spec/javascripts/components/ConfirmStatusChange_spec.jsx
+++ b/superset-frontend/spec/javascripts/components/ConfirmStatusChange_spec.jsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { mount } from 'enzyme';
-import { Button } from 'react-bootstrap';
+import Button from 'src/components/Button';
import { supersetTheme, ThemeProvider } from '@superset-ui/style';
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
import Modal from 'src/components/Modal';
@@ -33,7 +33,7 @@ describe('ConfirmStatusChange', () => {
{confirm => (
<>
-
+
>
)}
,
@@ -44,7 +44,7 @@ describe('ConfirmStatusChange', () => {
);
it('opens a confirm modal', () => {
- wrapper.find('#btn1').props().onClick('foo');
+ wrapper.find('#btn1').first().props().onClick('foo');
wrapper.update();
diff --git a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx
index 0d072558b7..059de56689 100644
--- a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx
+++ b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx
@@ -18,7 +18,7 @@
*/
import { Provider } from 'react-redux';
import React from 'react';
-import { mount } from 'enzyme';
+import { styledMount as mount } from 'spec/helpers/theming';
import sinon from 'sinon';
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
diff --git a/superset-frontend/spec/javascripts/datasource/DatasourceModal_spec.jsx b/superset-frontend/spec/javascripts/datasource/DatasourceModal_spec.jsx
index be5111c84b..f8bf0c0a98 100644
--- a/superset-frontend/spec/javascripts/datasource/DatasourceModal_spec.jsx
+++ b/superset-frontend/spec/javascripts/datasource/DatasourceModal_spec.jsx
@@ -83,7 +83,10 @@ describe('DatasourceModal', () => {
it('saves on confirm', async () => {
act(() => {
- wrapper.find('[className="m-r-5"]').props().onClick();
+ wrapper
+ .find('button[data-test="datasource-modal-save"]')
+ .props()
+ .onClick();
});
await waitForComponentToPaint(wrapper);
act(() => {
diff --git a/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx b/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
index 022ee1dcaa..652c16288a 100644
--- a/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
@@ -20,7 +20,8 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import { Button, Popover, Tab, Tabs } from 'react-bootstrap';
+import { Popover, Tab, Tabs } from 'react-bootstrap';
+import Button from 'src/components/Button';
import AdhocFilter, {
EXPRESSION_TYPES,
@@ -117,9 +118,9 @@ describe('AdhocFilterEditPopover', () => {
it('highlights save if changes are present', () => {
const { wrapper } = setup();
- expect(wrapper.find(Button).find({ bsStyle: 'primary' })).not.toExist();
+ expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).not.toExist();
wrapper.instance().onAdhocFilterChange(sqlAdhocFilter);
- expect(wrapper.find(Button).find({ bsStyle: 'primary' })).toExist();
+ expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).toExist();
});
it('will initiate a drag when clicked', () => {
diff --git a/superset-frontend/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx b/superset-frontend/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
index f2e9ffe434..118ef329e8 100644
--- a/superset-frontend/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
@@ -19,7 +19,7 @@
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
-import { shallow } from 'enzyme';
+import { styledShallow as shallow } from 'spec/helpers/theming';
import { OverlayTrigger } from 'react-bootstrap';
import Label from 'src/components/Label';
@@ -46,7 +46,7 @@ function setup(overrides) {
datasource: {},
...overrides,
};
- const wrapper = shallow();
+ const wrapper = shallow().dive();
return { wrapper };
}
diff --git a/superset-frontend/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx b/superset-frontend/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
index e66f6ae8a9..2f15017c7b 100644
--- a/superset-frontend/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
@@ -20,7 +20,8 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import { Button, FormGroup, Popover } from 'react-bootstrap';
+import { FormGroup, Popover } from 'react-bootstrap';
+import Button from 'src/components/Button';
import AdhocMetric, { EXPRESSION_TYPES } from 'src/explore/AdhocMetric';
import AdhocMetricEditPopover from 'src/explore/components/AdhocMetricEditPopover';
@@ -117,9 +118,9 @@ describe('AdhocMetricEditPopover', () => {
it('highlights save if changes are present', () => {
const { wrapper } = setup();
- expect(wrapper.find(Button).find({ bsStyle: 'primary' })).not.toExist();
+ expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).not.toExist();
wrapper.instance().onColumnChange({ column: columns[1] });
- expect(wrapper.find(Button).find({ bsStyle: 'primary' })).toExist();
+ expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).toExist();
});
it('will initiate a drag when clicked', () => {
diff --git a/superset-frontend/spec/javascripts/explore/components/AdhocMetricOption_spec.jsx b/superset-frontend/spec/javascripts/explore/components/AdhocMetricOption_spec.jsx
index 0612f6cbfd..5b23da24f5 100644
--- a/superset-frontend/spec/javascripts/explore/components/AdhocMetricOption_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/AdhocMetricOption_spec.jsx
@@ -19,7 +19,7 @@
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
-import { shallow } from 'enzyme';
+import { styledShallow as shallow } from 'spec/helpers/theming';
import { OverlayTrigger } from 'react-bootstrap';
import Label from 'src/components/Label';
@@ -46,7 +46,7 @@ function setup(overrides) {
columns,
...overrides,
};
- const wrapper = shallow();
+ const wrapper = shallow().dive();
return { wrapper, onMetricEdit };
}
diff --git a/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx b/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
index 5a93af1ac6..693c86950c 100644
--- a/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/DateFilterControl_spec.jsx
@@ -20,7 +20,7 @@
import React from 'react';
import sinon from 'sinon';
import { styledMount as mount } from 'spec/helpers/theming';
-import { Button } from 'react-bootstrap';
+import Button from 'src/components/Button';
import Label from 'src/components/Label';
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
diff --git a/superset-frontend/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx b/superset-frontend/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
index 21262653a9..7c32361233 100644
--- a/superset-frontend/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
@@ -54,7 +54,7 @@ describe('QueryAndSaveButtons', () => {
});
it('calls onQuery when query button is clicked', () => {
- const queryButton = wrapper.find('.query');
+ const queryButton = wrapper.find('[data-test="run-query-button"]');
queryButton.simulate('click');
expect(defaultProps.onQuery.called).toBe(true);
});
diff --git a/superset-frontend/spec/javascripts/explore/components/SaveModal_spec.jsx b/superset-frontend/spec/javascripts/explore/components/SaveModal_spec.jsx
index 4348b9b491..b419a7bbce 100644
--- a/superset-frontend/spec/javascripts/explore/components/SaveModal_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/SaveModal_spec.jsx
@@ -21,8 +21,10 @@ import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { bindActionCreators } from 'redux';
-import { shallow, mount } from 'enzyme';
-import { FormControl, Modal, Button, Radio } from 'react-bootstrap';
+import { shallow } from 'enzyme';
+import { styledMount as mount } from 'spec/helpers/theming';
+import { FormControl, Modal, Radio } from 'react-bootstrap';
+import Button from 'src/components/Button';
import sinon from 'sinon';
import fetchMock from 'fetch-mock';
diff --git a/superset-frontend/spec/javascripts/sqllab/QuerySearch_spec.jsx b/superset-frontend/spec/javascripts/sqllab/QuerySearch_spec.jsx
index 5d853dc1dd..68ae9e8067 100644
--- a/superset-frontend/spec/javascripts/sqllab/QuerySearch_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/QuerySearch_spec.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { Button } from 'react-bootstrap';
+import Button from 'src/components/Button';
import { shallow } from 'enzyme';
import sinon from 'sinon';
diff --git a/superset-frontend/spec/javascripts/sqllab/SouthPane_spec.jsx b/superset-frontend/spec/javascripts/sqllab/SouthPane_spec.jsx
index 64f0164295..75a85192f6 100644
--- a/superset-frontend/spec/javascripts/sqllab/SouthPane_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/SouthPane_spec.jsx
@@ -78,7 +78,7 @@ describe('SouthPane', () => {
const getWrapper = () =>
shallow(, {
context: { store },
- }).dive();
+ });
let wrapper;
diff --git a/superset-frontend/src/CRUD/CollectionTable.tsx b/superset-frontend/src/CRUD/CollectionTable.tsx
index dfa89b0dc8..11d3105adc 100644
--- a/superset-frontend/src/CRUD/CollectionTable.tsx
+++ b/superset-frontend/src/CRUD/CollectionTable.tsx
@@ -19,7 +19,7 @@
import React, { ReactNode } from 'react';
import shortid from 'shortid';
import { t } from '@superset-ui/translation';
-import Button from '../components/Button';
+import Button from 'src/components/Button';
import Fieldset from './Fieldset';
import { recurseReactClone } from './utils';
import './crud.less';
@@ -167,7 +167,7 @@ export default class CRUDCollection extends React.PureComponent<
{allowDeletes && !allowAddItem &&
}
{allowAddItem && (
-
diff --git a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton.jsx b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton.jsx
index 9de78089a3..69d0095c69 100644
--- a/superset-frontend/src/SqlLab/components/EstimateQueryCostButton.jsx
+++ b/superset-frontend/src/SqlLab/components/EstimateQueryCostButton.jsx
@@ -22,7 +22,7 @@ import { Table } from 'reactable-arc';
import { Alert } from 'react-bootstrap';
import { t } from '@superset-ui/translation';
-import Button from '../../components/Button';
+import Button from 'src/components/Button';
import Loading from '../../components/Loading';
import ModalTrigger from '../../components/ModalTrigger';
@@ -85,8 +85,8 @@ class EstimateQueryCostButton extends React.PureComponent {
modalBody={this.renderModalBody()}
triggerNode={
diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx
index 8ecec6fa56..9a8cef6db9 100644
--- a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx
+++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx
@@ -25,11 +25,11 @@ import { Alert } from 'react-bootstrap';
import Dialog from 'react-bootstrap-dialog';
import { t } from '@superset-ui/translation';
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
-
import shortid from 'shortid';
+
+import Button from 'src/components/Button';
import { exploreChart } from '../../explore/exploreUtils';
import * as actions from '../actions/sqlLab';
-import Button from '../../components/Button';
const propTypes = {
actions: PropTypes.object.isRequired,
@@ -213,7 +213,7 @@ class ExploreResultsButton extends React.PureComponent {
return (
<>
{t('Search')}
diff --git a/superset-frontend/src/SqlLab/components/QueryTable.jsx b/superset-frontend/src/SqlLab/components/QueryTable.jsx
index 6c3ec8029b..969bed805d 100644
--- a/superset-frontend/src/SqlLab/components/QueryTable.jsx
+++ b/superset-frontend/src/SqlLab/components/QueryTable.jsx
@@ -24,6 +24,7 @@ import { ProgressBar, Well } from 'react-bootstrap';
import Label from 'src/components/Label';
import { t } from '@superset-ui/translation';
+import Button from 'src/components/Button';
import Link from '../../components/Link';
import ResultSet from './ResultSet';
import ModalTrigger from '../../components/ModalTrigger';
@@ -99,31 +100,34 @@ class QueryTable extends React.PureComponent {