diff --git a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx index 24646561558..cb72da6dec3 100644 --- a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx +++ b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx @@ -75,7 +75,7 @@ class SqlEditorLeftBar extends React.PureComponent { if (dbId && schema) { this.setState({ tableLoading: true, tableOptions: [] }); const url = `/superset/tables/${dbId}/${schema}/${substr}/`; - $.get(url, (data) => { + $.get(url).done((data) => { const filterOptions = createFilterOptions({ options: data.options }); this.setState({ filterOptions, @@ -121,7 +121,7 @@ class SqlEditorLeftBar extends React.PureComponent { if (actualDbId) { this.setState({ schemaLoading: true }); const url = `/superset/schemas/${actualDbId}/`; - $.get(url, (data) => { + $.get(url).done((data) => { const schemaOptions = data.schemas.map(s => ({ value: s, label: s })); this.setState({ schemaOptions, schemaLoading: false }); }) diff --git a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx index cc3cc3ac8f3..ed10859c1a3 100644 --- a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx @@ -1,9 +1,11 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; +import sinon from 'sinon'; import { expect } from 'chai'; -import { table, defaultQueryEditor } from './fixtures'; +import $ from 'jquery'; +import { table, defaultQueryEditor, databases, tables } from './fixtures'; import SqlEditorLeftBar from '../../../javascripts/SqlLab/components/SqlEditorLeftBar'; import TableElement from '../../../javascripts/SqlLab/components/TableElement'; @@ -13,17 +15,168 @@ global.notify = { describe('SqlEditorLeftBar', () => { const mockedProps = { + actions: { + queryEditorSetSchema: sinon.stub(), + queryEditorSetDb: sinon.stub(), + setDatabases: sinon.stub(), + addTable: sinon.stub(), + }, tables: [table], queryEditor: defaultQueryEditor, height: 0, }; + + let wrapper; + let ajaxStub; + beforeEach(() => { + ajaxStub = sinon.stub($, 'get'); + wrapper = shallow(); + }); + afterEach(() => { + ajaxStub.restore(); + }); + it('is valid', () => { expect( React.isValidElement(), ).to.equal(true); }); it('renders a TableElement', () => { - const wrapper = mount(); expect(wrapper.find(TableElement)).to.have.length(1); }); + describe('onDatabaseChange', () => { + it('should fetch tables', () => { + sinon.stub(wrapper.instance(), 'fetchTables'); + sinon.stub(wrapper.instance(), 'fetchSchemas'); + wrapper.instance().onDatabaseChange({ value: 1, label: 'main' }); + + expect(wrapper.instance().fetchTables.getCall(0).args[0]).to.equal(1); + expect(wrapper.instance().fetchSchemas.getCall(0).args[0]).to.equal(1); + wrapper.instance().fetchTables.restore(); + wrapper.instance().fetchSchemas.restore(); + }); + it('should clear tableOptions', () => { + wrapper.instance().onDatabaseChange(); + expect(wrapper.state().tableOptions).to.deep.equal([]); + }); + }); + describe('getTableNamesBySubStr', () => { + it('should handle empty', () => ( + wrapper.instance().getTableNamesBySubStr('') + .then((data) => { + expect(data).to.deep.equal({ options: [] }); + }) + )); + it('should handle table name', () => { + const queryEditor = Object.assign({}, defaultQueryEditor, + { + dbId: 1, + schema: 'main', + }); + const mockTableOptions = { options: [table] }; + wrapper.setProps({ queryEditor }); + ajaxStub.callsFake(() => { + const d = $.Deferred(); + d.resolve(mockTableOptions); + return d.promise(); + }); + + return wrapper.instance().getTableNamesBySubStr('my table') + .then((data) => { + expect(ajaxStub.getCall(0).args[0]).to.equal('/superset/tables/1/main/my table'); + expect(data).to.deep.equal(mockTableOptions); + }); + }); + }); + it('dbMutator should build databases options', () => { + const options = wrapper.instance().dbMutator(databases); + expect(options).to.deep.equal([ + { value: 188, label: 'main' }, + { value: 208, label: 'Presto - Gold' }, + ]); + }); + describe('fetchTables', () => { + it('should clear table options', () => { + wrapper.instance().fetchTables(1); + expect(wrapper.state().tableOptions).to.deep.equal([]); + expect(wrapper.state().filterOptions).to.be.a('null'); + }); + it('should fetch table options', () => { + ajaxStub.callsFake(() => { + const d = $.Deferred(); + d.resolve(tables); + return d.promise(); + }); + wrapper.instance().fetchTables(1, 'main', 'birth_names'); + + expect(ajaxStub.getCall(0).args[0]).to.equal('/superset/tables/1/main/birth_names/'); + expect(wrapper.state().tableLength).to.equal(3); + }); + it('should handle error', () => { + ajaxStub.callsFake(() => { + const d = $.Deferred(); + d.reject('error message'); + return d.promise(); + }); + wrapper.instance().fetchTables(1, 'main', 'birth_names'); + expect(wrapper.state().tableOptions).to.deep.equal([]); + expect(wrapper.state().tableLength).to.equal(0); + }); + }); + describe('fetchSchemas', () => { + it('should fetch schema options', () => { + const schemaOptions = { + schemas: ['main', 'erf', 'superset'], + }; + ajaxStub.callsFake(() => { + const d = $.Deferred(); + d.resolve(schemaOptions); + return d.promise(); + }); + wrapper.instance().fetchSchemas(1); + expect(ajaxStub.getCall(0).args[0]).to.equal('/superset/schemas/1/'); + expect(wrapper.state().schemaOptions).to.have.length(3); + }); + it('should handle error', () => { + ajaxStub.callsFake(() => { + const d = $.Deferred(); + d.reject('error message'); + return d.promise(); + }); + wrapper.instance().fetchSchemas(123); + expect(wrapper.state().schemaOptions).to.deep.equal([]); + }); + }); + describe('changeTable', () => { + beforeEach(() => { + sinon.stub(wrapper.instance(), 'fetchTables'); + }); + afterEach(() => { + wrapper.instance().fetchTables.restore(); + }); + it('test 1', () => { + wrapper.instance().changeTable({ + value: 'birth_names', + label: 'birth_names', + }); + expect(wrapper.state().tableName).to.equal('birth_names'); + }); + it('test 2', () => { + wrapper.instance().changeTable({ + value: 'main.my_table', + label: 'my_table', + }); + expect(wrapper.instance().fetchTables.getCall(0).args[1]).to.equal('main'); + }); + }); + it('changeSchema', () => { + sinon.stub(wrapper.instance(), 'fetchTables'); + + wrapper.instance().changeSchema({ label: 'main', value: 'main' }); + expect(wrapper.instance().fetchTables.getCall(0).args[1]).to.equal('main'); + wrapper.instance().changeSchema(); + expect(wrapper.instance().fetchTables.getCall(1).args[1]).to.be.a('null'); + + wrapper.instance().fetchTables.restore(); + }); }); diff --git a/superset/assets/spec/javascripts/sqllab/fixtures.js b/superset/assets/spec/javascripts/sqllab/fixtures.js index c6654dc6072..5f86d860416 100644 --- a/superset/assets/spec/javascripts/sqllab/fixtures.js +++ b/superset/assets/spec/javascripts/sqllab/fixtures.js @@ -257,6 +257,40 @@ export const queries = [ results: null, }, ]; +export const databases = { + result: [{ + allow_ctas: true, + allow_dml: true, + allow_run_async: false, + allow_run_sync: true, + database_name: 'main', + expose_in_sqllab: true, + force_ctas_schema: '', + id: 188, + }, { + allow_ctas: true, + allow_dml: false, + allow_run_async: true, + allow_run_sync: true, + database_name: 'Presto - Gold', + expose_in_sqllab: true, + force_ctas_schema: 'tmp', + id: 208, + }], +}; +export const tables = { + tableLength: 3, + options: [{ + value: 'birth_names', + label: 'birth_names', + }, { + value: 'energy_usage', + label: 'energy_usage', + }, { + value: 'wb_health_population', + label: 'wb_health_population', + }], +}; export const stoppedQuery = { dbId: 1,