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

feat: SIP-34 explore save modal #10355

Merged
merged 12 commits into from
Jul 23, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@
// Tests for links in the explore UI
// ***********************************************

import rison from 'rison';
import shortid from 'shortid';
import { HEALTH_POP_FORM_DATA_DEFAULTS } from './visualizations/shared.helper';

const apiURL = (endpoint, queryObject) => {
return `${endpoint}?q=${rison.encode(queryObject)}`;
};

describe('Test explore links', () => {
beforeEach(() => {
cy.login();
Expand Down Expand Up @@ -73,98 +79,120 @@ describe('Test explore links', () => {
});
});

xit('Test chart save as', () => {
it('Test chart save as AND overwrite', () => {
const formData = {
...HEALTH_POP_FORM_DATA_DEFAULTS,
viz_type: 'table',
metrics: ['sum__SP_POP_TOTL'],
groupby: ['country_name'],
};
const newChartName = 'Test chart';
const newChartName = `Test chart [${shortid.generate()}]`;

cy.visitChartByParams(JSON.stringify(formData));
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.url().then(url => {
cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('#saveas-radio').check();
cy.get('input[name=new_slice_name]').type(newChartName);
cy.get('button#btn_modal_save').click();
});
cy.url().should('eq', url);

cy.visitChartByName(newChartName);
cy.verifySliceSuccess({ waitAlias: '@postJson' });
});
});

xit('Test chart save', () => {
const chartName = 'Test chart';
cy.visitChartByName(chartName);
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.visitChartByName(newChartName);

cy.get('[data-test=groupby]').within(() => {
cy.get('.Select__clear-indicator').click();
});
cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('button#btn_modal_save').click();
// Overwriting!
cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('#overwrite-radio').check();
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
const query = {
filters: [
{
col: 'slice_name',
opr: 'eq',
value: newChartName,
},
],
};
cy.request(apiURL('/api/v1/chart/', query)).then(response => {
expect(response.body.count).equals(1);
cy.request('DELETE', `/api/v1/chart/${response.body.ids[0]}`);
});
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then(
response => {
cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
},
);
});

it('Test chart save as and add to new dashboard', () => {
cy.visitChartByName('Growth Rate');
const chartName = 'Growth Rate';
const newChartName = `${chartName} [${shortid.generate()}]`;
const dashboardTitle = `Test dashboard [${shortid.generate()}]`;

cy.visitChartByName(chartName);
cy.verifySliceSuccess({ waitAlias: '@postJson' });

const dashboardTitle = 'Test dashboard';
cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('input[name=new_slice_name]').type('New Growth Rate');
cy.get('input[data-test=add-to-new-dashboard]').check();
cy.get('input[placeholder="[dashboard name]"]').type(dashboardTitle);
cy.get('#saveas-radio').check();
cy.get('input[name=new_slice_name]').click().clear().type(newChartName);
// Add a new option using the "CreatableSelect" feature
cy.get('#dashboard-creatable-select').type(
`${dashboardTitle}{enter}{enter}`,
);
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.request(
`/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`,
).then(response => {
expect(response.body.pks[0]).not.equals(null);
let query = {
filters: [
{
col: 'dashboard_title',
opr: 'eq',
value: dashboardTitle,
},
],
};
cy.request(apiURL('/api/v1/dashboard/', query)).then(response => {
expect(response.body.count).equals(1);
});
});

it('Test chart save as and add to existing dashboard', () => {
cy.visitChartByName('Most Populated Countries');
cy.visitChartByName(newChartName);
cy.verifySliceSuccess({ waitAlias: '@postJson' });
const chartName = 'New Most Populated Countries';
const dashboardTitle = 'Test dashboard';

cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('input[name=new_slice_name]').type(chartName);
cy.get('input[data-test=add-to-existing-dashboard]').check();
cy.get('.save-modal-selector')
.click()
.within(() => {
cy.get('input').type(dashboardTitle);
cy.get('.Select__option--is-focused').trigger('mousedown');
});
cy.get('#overwrite-radio').check();
cy.get('input[name=new_slice_name]').click().clear().type(newChartName);
// This time around, typing the same dashboard name
// will select the existing one
cy.get('#dashboard-creatable-select').type(
`${dashboardTitle}{enter}{enter}`,
);
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then(
response => {
cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
},
);
cy.request(
`/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`,
).then(response => {
cy.request('DELETE', `/dashboard/api/delete/${response.body.pks[0]}`);
query = {
filters: [
{
col: 'slice_name',
opr: 'eq',
value: chartName,
},
],
};
cy.request(apiURL('/api/v1/chart/', query)).then(response => {
expect(response.body.count).equals(1);
});
query = {
filters: [
{
col: 'dashboard_title',
opr: 'eq',
value: dashboardTitle,
},
],
};
cy.request(apiURL('/api/v1/dashboard/', query)).then(response => {
expect(response.body.count).equals(1);
});
});
});
5 changes: 5 additions & 0 deletions superset-frontend/cypress-base/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions superset-frontend/cypress-base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
"author": "Apcahe",
"license": "Apache-2.0",
"dependencies": {
"shortid": "^2.2.15",
"@cypress/code-coverage": "^3.8.1"
"@cypress/code-coverage": "^3.8.1",
"rison": "^0.1.1",
"shortid": "^2.2.15"
},
"devDependencies": {
"cypress": "4.9.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import thunk from 'redux-thunk';
import { bindActionCreators } from 'redux';

import { shallow, mount } from 'enzyme';
import { Modal, Button, Radio } from 'react-bootstrap';
import { FormControl, Modal, Button, Radio } from 'react-bootstrap';
import sinon from 'sinon';
import fetchMock from 'fetch-mock';

Expand Down Expand Up @@ -65,27 +65,26 @@ describe('SaveModal', () => {
target: {
value: 'mock event target',
},
value: 'mock value',
value: 10,
};

const getWrapper = () =>
shallow(<SaveModal {...defaultProps} />, {
context: { store },
}).dive();

it('renders a Modal with 7 inputs and 2 buttons', () => {
it('renders a Modal with the right set of components', () => {
const wrapper = getWrapper();
expect(wrapper.find(Modal)).toHaveLength(1);
expect(wrapper.find('input')).toHaveLength(2);
expect(wrapper.find(Button)).toHaveLength(2);
expect(wrapper.find(Radio)).toHaveLength(5);
expect(wrapper.find(FormControl)).toHaveLength(1);
expect(wrapper.find(Button)).toHaveLength(3);
expect(wrapper.find(Radio)).toHaveLength(2);
});

it('does not show overwrite option for new slice', () => {
const wrapperNewSlice = getWrapper();
wrapperNewSlice.setProps({ slice: null });
expect(wrapperNewSlice.find('#overwrite-radio')).toHaveLength(0);
expect(wrapperNewSlice.find('#saveas-radio')).toHaveLength(1);
it('overwrite radio button is disabled for new slice', () => {
const wrapper = getWrapper();
wrapper.setProps({ slice: null });
expect(wrapper.find('#overwrite-radio').prop('disabled')).toBe(true);
});

it('disable overwrite option for non-owner', () => {
Expand Down Expand Up @@ -128,14 +127,11 @@ describe('SaveModal', () => {
it('onChange', () => {
const wrapper = getWrapper();

wrapper.instance().onChange('newSliceName', mockEvent);
wrapper.instance().onSliceNameChange(mockEvent);
expect(wrapper.state().newSliceName).toBe(mockEvent.target.value);

wrapper.instance().onChange('saveToDashboardId', mockEvent);
wrapper.instance().onDashboardSelectChange(mockEvent);
expect(wrapper.state().saveToDashboardId).toBe(mockEvent.value);

wrapper.instance().onChange('newDashboardName', mockEvent);
expect(wrapper.state().newDashboardName).toBe(mockEvent.target.value);
});

describe('saveOrOverwrite', () => {
Expand All @@ -145,7 +141,7 @@ describe('SaveModal', () => {
sinon.stub(defaultProps.actions, 'saveSlice').callsFake(() =>
Promise.resolve({
data: {
dashboard: '/mock_dashboard/',
dashboard_url: 'http://localhost/mock_dashboard/',
slice: { slice_url: '/mock_slice/' },
},
}),
Expand All @@ -168,10 +164,6 @@ describe('SaveModal', () => {
const wrapper = getWrapper();
const saveToDashboardId = 100;

wrapper.setState({ addToDash: 'existing' });
wrapper.instance().saveOrOverwrite(true);
expect(wrapper.state().alert).toBe('Please select a dashboard');

wrapper.setState({ saveToDashboardId });
wrapper.instance().saveOrOverwrite(true);
const args = defaultProps.actions.saveSlice.getCall(0).args;
Expand All @@ -182,10 +174,6 @@ describe('SaveModal', () => {
const wrapper = getWrapper();
const newDashboardName = 'new dashboard name';

wrapper.setState({ addToDash: 'new' });
wrapper.instance().saveOrOverwrite(true);
expect(wrapper.state().alert).toBe('Please enter a dashboard name');

wrapper.setState({ newDashboardName });
wrapper.instance().saveOrOverwrite(true);
const args = defaultProps.actions.saveSlice.getCall(0).args;
Expand Down
Loading