[cypress] add SQL lab tests (#5974)

* [cypress] add sqllab/sourcePanel integration tests

* [cypress] add tests for SQL Lab query panel

* [cypress] add selectors/

* [cypress] add tests for SQL Lab tabs

* [cypress][sqllab] remove nested assertions where possible, update to single test index file

* [cypress][sqllab] try force click

* [cypress][sqllab] wait for saved query to load

* [cypress][sqllab] unnest, use visit for href

* [cypress][sqllab] try 1s wait :O

* [cypress][sqllab] wait for savedquery api response

* [cypress][sqllab] fix wait syntax

* [cypress][sqllab] add route wait in sourcepanel for flakiness

* [cypress] use *.test.js pattern for tests

* [cypress] fix paths

* [cypress][sqllab] actually try running lint

* [cypress][dashboards] use *.test.js pattern for tests

* [cypress][sqllab] combine tests, remove nesting

* [cypress][sqllab] explicitly wait for query results
This commit is contained in:
Chris Williams 2018-10-09 14:28:11 -07:00 committed by GitHub
parent ee472af14d
commit 9b4cf856dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 277 additions and 51 deletions

View File

@ -1,9 +1,6 @@
{
"baseUrl": "http://localhost:8081",
"videoUploadOnPasses": false,
"ignoreTestFiles": [
"_*.js",
"*.helper.js"
],
"ignoreTestFiles": ["**/!(*.test.js)"],
"projectId": "fbf96q"
}

View File

@ -1,11 +0,0 @@
import DashboardControlsTest from './_controls';
import DashboardEditModeTest from './_edit_mode';
import DashboardFilterTest from './_filter';
import DashboardLoadTest from './_load';
describe('Dashboard', () => {
DashboardControlsTest();
DashboardEditModeTest();
DashboardFilterTest();
DashboardLoadTest();
});

View File

@ -0,0 +1,11 @@
import DashboardControlsTest from './controls';
import DashboardEditModeTest from './edit_mode';
import DashboardFilterTest from './filter';
import DashboardLoadTest from './load';
describe('Dashboard', () => {
DashboardControlsTest();
DashboardEditModeTest();
DashboardFilterTest();
DashboardLoadTest();
});

View File

@ -1,35 +0,0 @@
import AreaTest from './_area';
import BigNumberTest from './_big_number';
import BigNumberTotalTest from './_big_number_total';
import BubbleTest from './_bubble';
import CompareTest from './_compare';
import DistBarTest from './_dist_bar';
import DualLineTest from './_dual_line';
import HistogramTest from './_histogram';
import LineTest from './_line';
import PieTest from './_pie';
import PivotTableTest from './_pivot_table';
import SankeyTest from './_sankey';
import SunburstTest from './_sunburst';
import TableTest from './_table';
import TreemapTest from './_treemap';
import WorldMapTest from './_world_map';
describe('All Visualizations', () => {
AreaTest();
BigNumberTest();
BigNumberTotalTest();
BubbleTest();
CompareTest();
DistBarTest();
DualLineTest();
HistogramTest();
LineTest();
PieTest();
PivotTableTest();
SankeyTest();
SunburstTest();
TableTest();
TreemapTest();
WorldMapTest();
});

View File

@ -0,0 +1,35 @@
import AreaTest from './area';
import BigNumberTest from './big_number';
import BigNumberTotalTest from './big_number_total';
import BubbleTest from './bubble';
import CompareTest from './compare';
import DistBarTest from './dist_bar';
import DualLineTest from './dual_line';
import HistogramTest from './histogram';
import LineTest from './line';
import PieTest from './pie';
import PivotTableTest from './pivot_table';
import SankeyTest from './sankey';
import SunburstTest from './sunburst';
import TableTest from './table';
import TreemapTest from './treemap';
import WorldMapTest from './world_map';
describe('All Visualizations', () => {
AreaTest();
BigNumberTest();
BigNumberTotalTest();
BubbleTest();
CompareTest();
DistBarTest();
DualLineTest();
HistogramTest();
LineTest();
PieTest();
PivotTableTest();
SankeyTest();
SunburstTest();
TableTest();
TreemapTest();
WorldMapTest();
});

View File

@ -0,0 +1,9 @@
import queryTests from './query';
import sourcePanelTests from './sourcePanel';
import tabsTests from './tabs';
describe('All SqlLab tests', () => {
queryTests();
sourcePanelTests();
tabsTests();
});

View File

@ -0,0 +1,103 @@
import shortid from 'shortid';
import { selectResultsTab, assertSQLLabResultsAreEqual } from './sqllab.helper';
export default () => {
describe('SqlLab query panel', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
cy.route('POST', '/superset/sql_json/**').as('sqlLabQuery');
});
it('supports entering and running a query', () => {
// row limit has to be < ~10 for us to be able to determine how many rows
// are fetched below (because React _Virtualized_ does not render all rows)
const rowLimit = 3;
cy.get('#brace-editor textarea').type(
`{selectall}{backspace}SELECT ds, gender, name, num FROM main.birth_names LIMIT ${rowLimit}`,
{ force: true },
);
cy.get('#js-sql-toolbar button')
.eq(0)
.click();
cy.wait('@sqlLabQuery');
cy.get('.SouthPane .ReactVirtualized__Table')
.eq(0) // ensures results tab in case preview tab exists
.then((tableNodes) => {
const [header, bodyWrapper] = tableNodes[0].childNodes;
const body = bodyWrapper.childNodes[0];
const expectedColCount = header.childNodes.length;
const expectedRowCount = body.childNodes.length;
expect(expectedColCount).to.equal(4);
expect(expectedRowCount).to.equal(rowLimit);
});
});
it('successfully saves a query', () => {
cy.route('savedqueryviewapi/**').as('getSavedQuery');
const query = 'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
const savedQueryTitle = `CYPRESS TEST QUERY ${shortid.generate()}`;
// we will assert that the results of the query we save, and the saved query are the same
let initialResultsTable = null;
let savedQueryResultsTable = null;
cy.get('#brace-editor textarea')
.type(`{selectall}{backspace}${query}`, { force: true })
.focus() // focus => blur is required for updating the query that is to be saved
.blur();
// ctrl + r also runs query
cy.get('#brace-editor textarea').type('{ctrl}r', { force: true });
cy.wait('@sqlLabQuery');
// Save results to check agains below
selectResultsTab().then((resultsA) => {
initialResultsTable = resultsA[0];
});
cy.get('#js-sql-toolbar button')
.eq(1) // save query
.click();
// Enter name + save into modal
cy.get('.modal-sm input').type(`{selectall}{backspace}${savedQueryTitle}`, {
force: true,
});
cy.get('.modal-sm .modal-body button')
.eq(0) // save
.click();
// visit saved queries
cy.visit('/sqllab/my_queries/');
// first row contains most recent link, follow back to SqlLab
cy.get('table tr:first-child a[href*="savedQueryId"').click();
// will timeout without explicitly waiting here
cy.wait('@getSavedQuery');
// run the saved query
cy.get('#js-sql-toolbar button')
.eq(0) // run query
.click();
cy.wait('@sqlLabQuery');
// assert the results of the saved query match the initial results
selectResultsTab().then((resultsB) => {
savedQueryResultsTable = resultsB[0];
assertSQLLabResultsAreEqual(initialResultsTable, savedQueryResultsTable);
});
});
});
};

View File

@ -0,0 +1,57 @@
import { selectResultsTab } from './sqllab.helper';
export default () => {
describe('SqlLab datasource panel', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
});
it('creates a table schema and preview when a database, schema, and table are selected', () => {
cy.route('/superset/table/**').as('tableMetadata');
// it should have dropdowns to select database, schema, and table
cy.get('.sql-toolbar .Select').should('have.length', 3);
cy.get('.sql-toolbar .table-schema').should('not.exist');
cy.get('.SouthPane .tab-content .filterable-table-container').should('not.exist');
cy.get('.sql-toolbar .Select')
.eq(0) // database select
.within(() => {
// note: we have to set force: true because the input is invisible / cypress throws
cy.get('input').type('main{enter}', { force: true });
});
cy.get('.sql-toolbar .Select')
.eq(1) // schema select
.within(() => {
cy.get('input').type('main{enter}', { force: true });
});
cy.get('.sql-toolbar .Select')
.eq(2) // table select
.within(() => {
cy.get('input').type('birth_names{enter}', { force: true });
});
cy.wait('@tableMetadata');
cy.get('.sql-toolbar .table-schema').should('have.length', 1);
selectResultsTab().should('have.length', 1);
// add another table and check for added schema + preview
cy.get('.sql-toolbar .Select')
.eq(2)
.within(() => {
cy.get('input').type('logs{enter}', { force: true });
});
cy.wait('@tableMetadata');
cy.get('.sql-toolbar .table-schema').should('have.length', 2);
selectResultsTab().should('have.length', 2);
});
});
};

View File

@ -0,0 +1,22 @@
export const selectResultsTab = () => cy.get('.SouthPane .ReactVirtualized__Table');
// this function asserts that the result set for two SQL lab table results are equal
export const assertSQLLabResultsAreEqual = (resultsA, resultsB) => {
const [headerA, bodyWrapperA] = resultsA.childNodes;
const bodyA = bodyWrapperA.childNodes[0];
const [headerB, bodyWrapperB] = resultsB.childNodes;
const bodyB = bodyWrapperB.childNodes[0];
expect(headerA.childNodes.length).to.equal(headerB.childNodes.length);
expect(bodyA.childNodes.length).to.equal(bodyB.childNodes.length);
bodyA.childNodes.forEach((rowA, rowIndex) => {
const rowB = bodyB.childNodes[rowIndex];
rowA.childNodes.forEach((cellA, columnIndex) => {
const cellB = rowB.childNodes[columnIndex];
expect(cellA.innerText).to.equal(cellB.innerText);
});
});
};

View File

@ -0,0 +1,38 @@
export default () => {
describe('SqlLab query tabs', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
});
it('allows you to create a tab', () => {
cy.get('#a11y-query-editor-tabs > ul > li').then((tabList) => {
const initialTabCount = tabList.length;
// add tab
cy.get('#a11y-query-editor-tabs > ul > li')
.last()
.click();
cy.get('#a11y-query-editor-tabs > ul > li').should('have.length', initialTabCount + 1);
});
});
it('allows you to close a tab', () => {
cy.get('#a11y-query-editor-tabs > ul > li').then((tabListA) => {
const initialTabCount = tabListA.length;
// open the tab dropdown to remove
cy.get('#a11y-query-editor-tabs > ul > li:first button').click();
// first item is close
cy.get('#a11y-query-editor-tabs > ul > li:first ul li a')
.eq(0)
.click();
cy.get('#a11y-query-editor-tabs > ul > li').should('have.length', initialTabCount - 1);
});
});
});
};

View File

@ -216,7 +216,7 @@ class TableElement extends React.PureComponent {
transitionAppear
onExited={this.removeFromStore.bind(this)}
>
<div className="TableElement m-b-10">
<div className="TableElement table-schema m-b-10">
{this.renderHeader()}
<div>
{this.renderBody()}