Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a React-based table editor #5186

Merged
merged 6 commits into from
Aug 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions superset/assets/spec/javascripts/CRUD/CollectionTable_spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import { shallow } from 'enzyme';

import CollectionTable from '../../../src/CRUD/CollectionTable';
import mockDatasource from '../../fixtures/mockDatasource';

const props = {
collection: mockDatasource['7__table'].columns,
tableColumns: ['column_name', 'type', 'groupby'],
};

describe('CollectionTable', () => {

let wrapper;
let el;

beforeEach(() => {
el = <CollectionTable {...props} />;
wrapper = shallow(el);
});

it('is valid', () => {
expect(React.isValidElement(el)).to.equal(true);
});

it('renders a table', () => {
const length = mockDatasource['7__table'].columns.length;
expect(wrapper.find('table')).to.have.lengthOf(1);
expect(wrapper.find('tbody tr.row')).to.have.lengthOf(length);
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import DashboardBuilder from '../../../../src/dashboard/containers/DashboardBuil

// mock data
import chartQueries, { sliceId as chartId } from '../fixtures/mockChartQueries';
import datasources from '../fixtures/mockDatasource';
import datasources from '../../../fixtures/mockDatasource';
import dashboardInfo from '../fixtures/mockDashboardInfo';
import { dashboardLayout } from '../fixtures/mockDashboardLayout';
import dashboardState from '../fixtures/mockDashboardState';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Chart from '../../../../../src/dashboard/components/gridComponents/Chart'
import SliceHeader from '../../../../../src/dashboard/components/SliceHeader';
import ChartContainer from '../../../../../src/chart/ChartContainer';

import mockDatasource from '../../fixtures/mockDatasource';
import mockDatasource from '../../../../fixtures/mockDatasource';
import {
sliceEntitiesForChart as sliceEntities,
sliceId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { datasourceId } from './mockDatasource';
import { datasourceId } from '../../../fixtures/mockDatasource';

export const sliceId = 18;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { sliceId as id } from './mockChartQueries';
import { datasourceId } from './mockDatasource';
import { datasourceId } from '../../../fixtures/mockDatasource';

export const sliceId = id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { dashboardLayout } from './mockDashboardLayout';
import dashboardInfo from './mockDashboardInfo';
import dashboardState from './mockDashboardState';
import messageToasts from '../../messageToasts/mockMessageToasts';
import datasources from './mockDatasource';
import datasources from '../../../fixtures/mockDatasource';
import sliceEntities from './mockSliceEntities';

export default {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';
import { Tabs } from 'react-bootstrap';
import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import { shallow } from 'enzyme';
import configureStore from 'redux-mock-store';
import $ from 'jquery';
import sinon from 'sinon';

import DatasourceEditor from '../../../src/datasource/DatasourceEditor';
import mockDatasource from '../../fixtures/mockDatasource';

const props = {
datasource: mockDatasource['7__table'],
addSuccessToast: () => {},
addDangerToast: () => {},
onChange: sinon.spy(),
};
const extraColumn = {
column_name: 'new_column',
type: 'VARCHAR(10)',
description: null,
filterable: true,
verbose_name: null,
is_dttm: false,
expression: '',
groupby: true,
};

describe('DatasourceEditor', () => {
const mockStore = configureStore([]);
const store = mockStore({});

let wrapper;
let el;
let ajaxStub;
let inst;

beforeEach(() => {
ajaxStub = sinon.stub($, 'ajax');
el = <DatasourceEditor {...props} />;
wrapper = shallow(el, { context: { store } }).dive();
inst = wrapper.instance();
});

afterEach(() => {
ajaxStub.restore();
});

it('is valid', () => {
expect(React.isValidElement(el)).to.equal(true);
});

it('renders Tabs', () => {
expect(wrapper.find(Tabs)).to.have.lengthOf(1);
});

it('makes an async request', () => {
wrapper.setState({ activeTabKey: 2 });
const syncButton = wrapper.find('.sync-from-source');
expect(syncButton).to.have.lengthOf(1);
syncButton.simulate('click');
expect(ajaxStub.calledOnce).to.equal(true);
});

it('merges columns', () => {
const numCols = props.datasource.columns.length;
expect(inst.state.databaseColumns.length).to.equal(numCols);
inst.mergeColumns([extraColumn]);
expect(inst.state.databaseColumns.length).to.equal(numCols + 1);
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';
import { Modal } from 'react-bootstrap';
import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import configureStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import $ from 'jquery';
import sinon from 'sinon';

import DatasourceModal from '../../../src/datasource/DatasourceModal';
import DatasourceEditor from '../../../src/datasource/DatasourceEditor';
import mockDatasource from '../../fixtures/mockDatasource';

const props = {
datasource: mockDatasource['7__table'],
addSuccessToast: () => {},
addDangerToast: () => {},
onChange: sinon.spy(),
show: true,
onHide: () => {},
};

describe('DatasourceModal', () => {
const mockStore = configureStore([]);
const store = mockStore({});

let wrapper;
let el;
let ajaxStub;
let inst;

beforeEach(() => {
ajaxStub = sinon.stub($, 'ajax');
el = <DatasourceModal {...props} />;
wrapper = shallow(el, { context: { store } }).dive();
inst = wrapper.instance();
});

afterEach(() => {
ajaxStub.restore();
});

it('is valid', () => {
expect(React.isValidElement(el)).to.equal(true);
});

it('renders a Modal', () => {
expect(wrapper.find(Modal)).to.have.lengthOf(1);
});

it('renders a DatasourceEditor', () => {
expect(wrapper.find(DatasourceEditor)).to.have.lengthOf(1);
});

it('saves on confirm', () => {
inst.onConfirmSave();
expect(ajaxStub.calledOnce).to.equal(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import configureStore from 'redux-mock-store';
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { shallow } from 'enzyme';
import { Modal } from 'react-bootstrap';
import DatasourceModal from '../../../../src/datasource/DatasourceModal';
import DatasourceControl from '../../../../src/explore/components/controls/DatasourceControl';

const defaultProps = {
Expand Down Expand Up @@ -35,6 +35,6 @@ describe('DatasourceControl', () => {

it('renders a Modal', () => {
const wrapper = setup();
expect(wrapper.find(Modal)).to.have.lengthOf(1);
expect(wrapper.find(DatasourceModal)).to.have.lengthOf(1);
});
});
67 changes: 1 addition & 66 deletions superset/assets/spec/javascripts/explore/exploreActions_spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
/* eslint-disable no-unused-expressions */
import { it, describe } from 'mocha';
import { expect } from 'chai';
import sinon from 'sinon';
import $ from 'jquery';
import * as chartActions from '../../../src/chart/chartAction';
import * as actions from '../../../src/explore/actions/exploreActions';
import { defaultState } from '../../../src/explore/store';
import exploreReducer from '../../../src/explore/reducers/exploreReducer';
import * as actions from '../../../src/explore/actions/exploreActions';

describe('reducers', () => {
it('sets correct control value given a key and value', () => {
Expand All @@ -20,65 +17,3 @@ describe('reducers', () => {
expect(newState.controls.show_legend.value).to.equal(true);
});
});

describe('fetching actions', () => {
let dispatch;
let request;
let ajaxStub;

beforeEach(() => {
dispatch = sinon.spy();
ajaxStub = sinon.stub($, 'ajax');
});
afterEach(() => {
ajaxStub.restore();
});

describe('fetchDatasourceMetadata', () => {
const datasourceKey = '1__table';

const makeRequest = (alsoTriggerQuery = false) => {
request = actions.fetchDatasourceMetadata(datasourceKey, alsoTriggerQuery);
request(dispatch);
};

it('calls fetchDatasourceStarted', () => {
makeRequest();
expect(dispatch.args[0][0].type).to.equal(actions.FETCH_DATASOURCE_STARTED);
});

it('makes the ajax request', () => {
makeRequest();
expect(ajaxStub.calledOnce).to.be.true;
});

it('calls correct url', () => {
const url = `/superset/fetch_datasource_metadata?datasourceKey=${datasourceKey}`;
makeRequest();
expect(ajaxStub.getCall(0).args[0].url).to.equal(url);
});

it('calls correct actions on error', () => {
ajaxStub.yieldsTo('error', { responseJSON: { error: 'error text' } });
makeRequest();
expect(dispatch.callCount).to.equal(2);
expect(dispatch.getCall(1).args[0].type).to.equal(actions.FETCH_DATASOURCE_FAILED);
});

it('calls correct actions on success', () => {
ajaxStub.yieldsTo('success', { data: '' });
makeRequest();
expect(dispatch.callCount).to.equal(4);
expect(dispatch.getCall(1).args[0].type).to.equal(actions.SET_DATASOURCE);
expect(dispatch.getCall(2).args[0].type).to.equal(actions.FETCH_DATASOURCE_SUCCEEDED);
expect(dispatch.getCall(3).args[0].type).to.equal(actions.RESET_FIELDS);
});

it('triggers query if flag is set', () => {
ajaxStub.yieldsTo('success', { data: '' });
makeRequest(true);
expect(dispatch.callCount).to.equal(5);
expect(dispatch.getCall(4).args[0].type).to.equal(chartActions.TRIGGER_QUERY);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { describe, it } from 'mocha';
import { expect } from 'chai';
import { user } from './fixtures';
import CreatedContent from '../../../src/profile/components/CreatedContent';
import TableLoader from '../../../src/profile/components/TableLoader';
import TableLoader from '../../../src/components/TableLoader';


describe('CreatedContent', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { expect } from 'chai';

import { user } from './fixtures';
import Favorites from '../../../src/profile/components/Favorites';
import TableLoader from '../../../src/profile/components/TableLoader';
import TableLoader from '../../../src/components/TableLoader';

describe('Favorites', () => {
const mockedProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { expect } from 'chai';

import { user } from './fixtures';
import RecentActivity from '../../../src/profile/components/RecentActivity';
import TableLoader from '../../../src/profile/components/TableLoader';
import TableLoader from '../../../src/components/TableLoader';


describe('RecentActivity', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import { table, defaultQueryEditor, databases, tables } from './fixtures';
import SqlEditorLeftBar from '../../../src/SqlLab/components/SqlEditorLeftBar';
import TableElement from '../../../src/SqlLab/components/TableElement';

global.notify = {
error: () => {},
};

describe('SqlEditorLeftBar', () => {
const mockedProps = {
actions: {
Expand Down
Loading