get rid of global notify (#5355)

* [toasts] get rid of notify globals, refactor messageToasts for use by entire app

* [remove notify] use arrow func in ajax call

* fix lint + tests

* actually fix tests from messageToast refactor

* add 'test:one' npm script

* debugger

* [toasts] convert bootstrap flash messages to toasts in explore + sqllab

* [toasts][tests] import from right file
This commit is contained in:
Chris Williams
2018-07-12 11:50:25 -07:00
committed by GitHub
parent f9352af80e
commit 19ac6e1231
72 changed files with 657 additions and 524 deletions

View File

@@ -1,31 +0,0 @@
import React from 'react';
import { describe, it } from 'mocha';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import AlertContainer from 'react-alert';
import AlertsWrapper from '../../../src/components/AlertsWrapper';
describe('AlertsWrapper', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<AlertsWrapper />);
});
it('is valid', () => {
expect(React.isValidElement(<AlertsWrapper />)).to.equal(true);
});
it('renders AlertContainer', () => {
expect(wrapper.find(AlertContainer)).to.have.length(1);
});
it('expects AlertContainer to have correct props', () => {
const alertContainerProps = wrapper.find(AlertContainer).props();
expect(alertContainerProps.offset).to.be.equal(14);
expect(alertContainerProps.position).to.be.equal('top right');
expect(alertContainerProps.theme).to.be.equal('dark');
expect(alertContainerProps.time).to.be.equal(5000);
expect(alertContainerProps.transition).to.be.equal('fade');
});
});

View File

@@ -14,23 +14,24 @@ import { sqlLabReducer } from '../../../src/SqlLab/reducers';
describe('App', () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const store = mockStore(sqlLabReducer(undefined, {}));
const store = mockStore({ sqlLab: sqlLabReducer(undefined, {}), messageToasts: [] });
let wrapper;
beforeEach(() => {
wrapper = shallow(<App />, {
context: { store },
}).dive();
wrapper = shallow(<App />, { context: { store } }).dive();
});
it('is valid', () => {
expect(React.isValidElement(<App />)).to.equal(true);
});
it('should handler resize', () => {
sinon.spy(wrapper.instance(), 'getHeight');
wrapper.instance().handleResize();
expect(wrapper.instance().getHeight.callCount).to.equal(1);
wrapper.instance().getHeight.restore();
});
it('should render', () => {
expect(wrapper.find('.SqlLab')).to.have.length(1);
expect(wrapper.find(TabbedSqlEditors)).to.have.length(1);

View File

@@ -7,7 +7,7 @@ import CopyQueryTabUrl from '../../../src/SqlLab/components/CopyQueryTabUrl';
describe('CopyQueryTabUrl', () => {
const mockedProps = {
queryEditor: initialState.queryEditors[0],
queryEditor: initialState.sqlLab.queryEditors[0],
};
it('is valid with props', () => {
expect(

View File

@@ -20,6 +20,7 @@ describe('SqlEditorLeftBar', () => {
queryEditorSetDb: sinon.stub(),
setDatabases: sinon.stub(),
addTable: sinon.stub(),
addDangerToast: sinon.stub(),
},
tables: [table],
queryEditor: defaultQueryEditor,

View File

@@ -11,7 +11,7 @@ describe('SqlEditor', () => {
const mockedProps = {
actions: {},
database: {},
queryEditor: initialState.queryEditors[0],
queryEditor: initialState.sqlLab.queryEditors[0],
latestQuery: queries[0],
tables: [table],
queries,

View File

@@ -22,10 +22,12 @@ describe('TabbedSqlEditors', () => {
'dfsadfs',
'newEditorId',
];
const tables = [Object.assign({}, table[0], {
dataPreviewQueryId: 'B1-VQU1zW',
queryEditorId: 'newEditorId',
})];
const queryEditors = [{
autorun: false,
dbId: 1,
@@ -47,8 +49,8 @@ describe('TabbedSqlEditors', () => {
databases: {},
tables: [],
queries: {},
queryEditors: initialState.queryEditors,
tabHistory: initialState.tabHistory,
queryEditors: initialState.sqlLab.queryEditors,
tabHistory: initialState.sqlLab.tabHistory,
editorHeight: '',
getHeight: () => ('100px'),
database: {},
@@ -163,7 +165,7 @@ describe('TabbedSqlEditors', () => {
wrapper.setState({ hideLeftBar: true });
const firstTab = wrapper.find(Tab).first();
expect(firstTab.props().eventKey).to.contain(initialState.queryEditors[0].id);
expect(firstTab.props().eventKey).to.contain(initialState.sqlLab.queryEditors[0].id);
expect(firstTab.find(SqlEditor)).to.have.length(1);
const lastTab = wrapper.find(Tab).last();

View File

@@ -17,17 +17,16 @@ import { VISUALIZE_VALIDATION_ERRORS } from '../../../src/SqlLab/constants';
import VisualizeModal from '../../../src/SqlLab/components/VisualizeModal';
import * as exploreUtils from '../../../src/explore/exploreUtils';
global.notify = {
info: () => {},
error: () => {},
};
describe('VisualizeModal', () => {
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const initialState = sqlLabReducer({}, {});
initialState.common = {
conf: { SUPERSET_WEBSERVER_TIMEOUT: 45 },
const initialState = {
sqlLab: {
...sqlLabReducer(undefined, {}),
common: {
conf: { SUPERSET_WEBSERVER_TIMEOUT: 45 },
},
},
};
const store = mockStore(initialState);
const mockedProps = {
@@ -277,7 +276,7 @@ describe('VisualizeModal', () => {
});
it('should build visualize advise for long query', () => {
const longQuery = Object.assign({}, queries[0], { endDttm: 1476910666798 });
const longQuery = { ...queries[0], endDttm: 1476910666798 };
const props = {
show: true,
query: longQuery,
@@ -334,29 +333,46 @@ describe('VisualizeModal', () => {
expect(spyCall.args[0].data.data).to.equal(JSON.stringify(mockOptions));
});
it('should open new window', () => {
const infoToastSpy = sinon.spy();
datasourceSpy.callsFake(() => {
const d = $.Deferred();
d.resolve('done');
return d.promise();
});
wrapper.setProps({ actions: { createDatasource: datasourceSpy } });
wrapper.setProps({
actions: {
createDatasource: datasourceSpy,
addInfoToast: infoToastSpy,
},
});
wrapper.instance().visualize();
expect(exploreUtils.exportChart.callCount).to.equal(1);
expect(exploreUtils.exportChart.getCall(0).args[0].datasource).to.equal('107__table');
expect(infoToastSpy.callCount).to.equal(1);
});
it('should notify error', () => {
it('should add error toast', () => {
const dangerToastSpy = sinon.spy();
datasourceSpy.callsFake(() => {
const d = $.Deferred();
d.reject('error message');
return d.promise();
});
wrapper.setProps({ actions: { createDatasource: datasourceSpy } });
sinon.spy(notify, 'error');
wrapper.setProps({
actions: {
createDatasource: datasourceSpy,
addDangerToast: dangerToastSpy,
},
});
wrapper.instance().visualize();
expect(exploreUtils.exportChart.callCount).to.equal(0);
expect(notify.error.callCount).to.equal(1);
expect(dangerToastSpy.callCount).to.equal(1);
});
});
});

View File

@@ -20,13 +20,15 @@ describe('async actions', () => {
describe('saveQuery', () => {
it('makes the ajax request', () => {
actions.saveQuery(query);
const thunk = actions.saveQuery(query);
thunk((/* mockDispatch */) => {});
expect(ajaxStub.calledOnce).to.be.true;
});
it('calls correct url', () => {
const url = '/savedqueryviewapi/api/create';
actions.saveQuery(query);
const thunk = actions.saveQuery(query);
thunk((/* mockDispatch */) => {});
expect(ajaxStub.getCall(0).args[0].url).to.equal(url);
});
});

View File

@@ -319,15 +319,18 @@ export const runningQuery = {
export const cachedQuery = Object.assign({}, queries[0], { cached: true });
export const initialState = {
alerts: [],
queries: {},
databases: {},
queryEditors: [defaultQueryEditor],
tabHistory: [defaultQueryEditor.id],
tables: [],
workspaceQueries: [],
queriesLastUpdate: 0,
activeSouthPaneTab: 'Results',
sqlLab: {
alerts: [],
queries: {},
databases: {},
queryEditors: [defaultQueryEditor],
tabHistory: [defaultQueryEditor.id],
tables: [],
workspaceQueries: [],
queriesLastUpdate: 0,
activeSouthPaneTab: 'Results',
},
messageToasts: [],
};
export const query = {

View File

@@ -3,12 +3,17 @@ import { expect } from 'chai';
import * as r from '../../../src/SqlLab/reducers';
import * as actions from '../../../src/SqlLab/actions';
import { alert, table, initialState } from './fixtures';
import { table, initialState as mockState } from './fixtures';
const initialState = mockState.sqlLab;
describe('sqlLabReducer', () => {
describe('CLONE_QUERY_TO_NEW_TAB', () => {
const testQuery = { sql: 'SELECT * FROM...', dbId: 1, id: 'flasj233' };
let newState = Object.assign({}, initialState, { queries: { [testQuery.id]: testQuery } });
let newState = {
...initialState,
queries: { [testQuery.id]: testQuery },
};
beforeEach(() => {
newState = r.sqlLabReducer(newState, actions.cloneQueryToNewTab(testQuery));
});
@@ -29,24 +34,12 @@ describe('sqlLabReducer', () => {
expect(newState.tabHistory[1]).to.eq(newState.queryEditors[1].id);
});
});
describe('Alerts', () => {
const state = Object.assign({}, initialState);
let newState;
it('should add one alert', () => {
newState = r.sqlLabReducer(state, actions.addAlert(alert));
expect(newState.alerts).to.have.lengthOf(1);
});
it('should remove one alert', () => {
newState = r.sqlLabReducer(newState, actions.removeAlert(newState.alerts[0]));
expect(newState.alerts).to.have.lengthOf(0);
});
});
describe('Query editors actions', () => {
let newState;
let defaultQueryEditor;
let qe;
beforeEach(() => {
newState = Object.assign({}, initialState);
newState = { ...initialState };
defaultQueryEditor = newState.queryEditors[0];
qe = Object.assign({}, defaultQueryEditor);
newState = r.sqlLabReducer(newState, actions.addQueryEditor(qe));
@@ -134,8 +127,8 @@ describe('sqlLabReducer', () => {
let query;
let newQuery;
beforeEach(() => {
newState = Object.assign({}, initialState);
newQuery = Object.assign({}, query);
newState = { ...initialState };
newQuery = { ...query };
});
it('should start a query', () => {
newState = r.sqlLabReducer(newState, actions.startQuery(newQuery));