[feat] Feature flag system via config (#5960)

* [feat] Feature flag system via config

Adding a feature flag system that is driven by superset_config.py. This change includes:
- Server side changes to specify a dedicated FEATURE_FLAG dictionary for listing feature flags. E.g.
```
FEATURE_FLAGS = { 'SCOPED_FILTER': true }
```
- Pass the new feature flags to client via bootstrap-data
- Client side changes to inject feature flags into the redux state tree for dashboard, explore view and SqlLab
- Client side refactor/clean up so the feature flags can be properly tested. Also avoid modifying incoming bootstrap data when creating initial state for the redux state tree
- Re-enable tests that were previously disabled for ExploreViewContainer

* Fix lint errors.

* Remove the partial attempt to get reference to src working in tests (so we don't have to write ../../../src and such in tests). This will in a separate PR.
This commit is contained in:
Christine Chambers
2018-10-01 11:47:06 -07:00
committed by Beto Dealmeida
parent 414a4bfc6f
commit 604524b671
17 changed files with 246 additions and 113 deletions

View File

@@ -1,38 +0,0 @@
// this test must be commented out because ChartContainer is now importing files
// from visualizations/*.js which are also importing css files which breaks in the testing env.
// import React from 'react';
// import { expect } from 'chai';
// // import { shallow } from 'enzyme';
// import ExploreViewContainer
// from '../../../../src/explore/components/ExploreViewContainer';
// import QueryAndSaveBtns
// from '../../../../src/explore/components/QueryAndSaveBtns';
// import ControlPanelsContainer
// from '../../../../src/explore/components/ControlPanelsContainer';
// import ChartContainer
// from '../../../../src/explore/components/ChartContainer';
// describe('ExploreViewContainer', () => {
// it('renders', () => {
// expect(
// React.isValidElement(<ExploreViewContainer />)
// ).to.equal(true);
// });
// it('renders QueryAndSaveButtons', () => {
// const wrapper = shallow(<ExploreViewContainer />);
// expect(wrapper.find(QueryAndSaveBtns)).to.have.length(1);
// });
// it('renders ControlPanelsContainer', () => {
// const wrapper = shallow(<ExploreViewContainer />);
// expect(wrapper.find(ControlPanelsContainer)).to.have.length(1);
// });
// it('renders ChartContainer', () => {
// const wrapper = shallow(<ExploreViewContainer />);
// expect(wrapper.find(ChartContainer)).to.have.length(1);
// });
// });

View File

@@ -0,0 +1,69 @@
import React from 'react';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import getInitialState from '../../../../src/explore/reducers/getInitialState';
import ExploreViewContainer
from '../../../../src/explore/components/ExploreViewContainer';
import QueryAndSaveBtns
from '../../../../src/explore/components/QueryAndSaveBtns';
import ControlPanelsContainer
from '../../../../src/explore/components/ControlPanelsContainer';
import ChartContainer
from '../../../../src/explore/components/ExploreChartPanel';
describe('ExploreViewContainer', () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
let store;
let wrapper;
before(() => {
const bootstrapData = {
common: {
feature_flags: {
FOO_BAR: true,
},
conf: {},
},
datasource: {
columns: [],
},
form_data: {
datasource: {},
},
};
store = mockStore(getInitialState(bootstrapData), {});
});
beforeEach(() => {
wrapper = shallow(<ExploreViewContainer />, {
context: { store },
disableLifecycleMethods: true,
});
});
it('should set feature flags', () => {
expect(wrapper.prop('isFeatureEnabled')('FOO_BAR')).to.equal(true);
});
it('renders', () => {
expect(
React.isValidElement(<ExploreViewContainer />),
).to.equal(true);
});
it('renders QueryAndSaveButtons', () => {
expect(wrapper.dive().find(QueryAndSaveBtns)).to.have.length(1);
});
it('renders ControlPanelsContainer', () => {
expect(wrapper.dive().find(ControlPanelsContainer)).to.have.length(1);
});
it('renders ChartContainer', () => {
expect(wrapper.dive().find(ChartContainer)).to.have.length(1);
});
});