Skip to content

Commit

Permalink
Cypress: Add tests for Filters (#4757)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrieldutra authored May 5, 2020
1 parent 27eab28 commit 4f8d2ca
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 6 deletions.
11 changes: 7 additions & 4 deletions client/app/components/Filters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function Filters({ filters, onChange }) {
onChange = createFilterChangeHandler(filters, onChange);

return (
<div className="filters-wrapper">
<div className="filters-wrapper" data-test="Filters">
<div className="container bg-white">
<div className="row">
{map(filters, filter => {
Expand All @@ -83,7 +83,10 @@ function Filters({ filters, onChange }) {
));

return (
<div key={filter.name} className="col-sm-6 p-l-0 filter-container">
<div
key={filter.name}
className="col-sm-6 p-l-0 filter-container"
data-test={`FilterName-${filter.name}`}>
<label>{filter.friendlyName}</label>
{options.length === 0 && <Select className="w-100" disabled value="No values" />}
{options.length > 0 && (
Expand All @@ -108,11 +111,11 @@ function Filters({ filters, onChange }) {
onChange={values => onChange(filter, values)}>
{!filter.multiple && options}
{filter.multiple && [
<Select.Option key={NONE_VALUES}>
<Select.Option key={NONE_VALUES} data-test="ClearOption">
<i className="fa fa-square-o m-r-5" />
Clear
</Select.Option>,
<Select.Option key={ALL_VALUES}>
<Select.Option key={ALL_VALUES} data-test="SelectAllOption">
<i className="fa fa-check-square-o m-r-5" />
Select All
</Select.Option>,
Expand Down
5 changes: 3 additions & 2 deletions client/app/pages/dashboards/DashboardPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ function DashboardSettings({ dashboardOptions }) {
<div className="m-b-10 p-15 bg-white tiled">
<Checkbox
checked={!!dashboard.dashboard_filters_enabled}
onChange={({ target }) => updateDashboard({ dashboard_filters_enabled: target.checked })}>
onChange={({ target }) => updateDashboard({ dashboard_filters_enabled: target.checked })}
data-test="DashboardFiltersCheckbox">
Use Dashboard Level Filters
</Checkbox>
</div>
Expand Down Expand Up @@ -84,7 +85,7 @@ function DashboardComponent(props) {
</div>
)}
{!isEmpty(filters) && (
<div className="m-b-10 p-15 bg-white tiled">
<div className="m-b-10 p-15 bg-white tiled" data-test="DashboardFilters">
<Filters filters={filters} onChange={setFilters} />
</div>
)}
Expand Down
87 changes: 87 additions & 0 deletions client/cypress/integration/dashboard/filters_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { createDashboard } from "../../support/redash-api";
import { createQueryAndAddWidget, editDashboard } from "../../support/dashboard";
import { expectTableToHaveLength, expectFirstColumnToHaveMembers } from "../../support/visualizations/table";

const SQL = `
SELECT 'a' AS stage1, 'a1' AS stage2, 11 AS value UNION ALL
SELECT 'a' AS stage1, 'a2' AS stage2, 12 AS value UNION ALL
SELECT 'a' AS stage1, 'a3' AS stage2, 45 AS value UNION ALL
SELECT 'a' AS stage1, 'a4' AS stage2, 54 AS value UNION ALL
SELECT 'b' AS stage1, 'b1' AS stage2, 33 AS value UNION ALL
SELECT 'b' AS stage1, 'b2' AS stage2, 73 AS value UNION ALL
SELECT 'b' AS stage1, 'b3' AS stage2, 90 AS value UNION ALL
SELECT 'c' AS stage1, 'c1' AS stage2, 19 AS value UNION ALL
SELECT 'c' AS stage1, 'c2' AS stage2, 92 AS value UNION ALL
SELECT 'c' AS stage1, 'c3' AS stage2, 63 AS value UNION ALL
SELECT 'c' AS stage1, 'c4' AS stage2, 44 AS value\
`;

describe("Dashboard Filters", () => {
beforeEach(() => {
cy.login();

const queryData = {
name: "Query Filters",
query: `SELECT stage1 AS "stage1::filter", stage2, value FROM (${SQL}) q`,
};
createDashboard("Dashboard Filters").then(dashboard => {
createQueryAndAddWidget(dashboard.id, queryData)
.as("widget1TestId")
.then(() => createQueryAndAddWidget(dashboard.id, queryData, { position: { col: 4 } }))
.as("widget2TestId")
.then(() => cy.visit(`/dashboard/${dashboard.slug}`));
});
});

it("filters rows in a Table Visualization", function() {
editDashboard();
cy.getByTestId("DashboardFilters").should("not.exist");
cy.getByTestId("DashboardFiltersCheckbox").click();

cy.getByTestId("DashboardFilters").within(() => {
cy.getByTestId("FilterName-stage1::filter")
.find(".ant-select-selection-selected-value")
.should("have.text", "a");
});

cy.getByTestId(this.widget1TestId).within(() => {
expectTableToHaveLength(4);
expectFirstColumnToHaveMembers(["a", "a", "a", "a"]);

cy.getByTestId("FilterName-stage1::filter")
.find(".ant-select")
.click();
});

cy.contains("li.ant-select-dropdown-menu-item:visible", "b").click();

cy.getByTestId(this.widget1TestId).within(() => {
expectTableToHaveLength(3);
expectFirstColumnToHaveMembers(["b", "b", "b"]);
});

// assert that changing one widget filter doesn't affect another

cy.getByTestId(this.widget2TestId).within(() => {
expectTableToHaveLength(4);
expectFirstColumnToHaveMembers(["a", "a", "a", "a"]);
});

// assert that changing a global filter affects all widgets

cy.getByTestId("DashboardFilters").within(() => {
cy.getByTestId("FilterName-stage1::filter")
.find(".ant-select")
.click();
});

cy.contains("li.ant-select-dropdown-menu-item:visible", "c").click();

[this.widget1TestId, this.widget2TestId].forEach(widgetTestId =>
cy.getByTestId(widgetTestId).within(() => {
expectTableToHaveLength(4);
expectFirstColumnToHaveMembers(["c", "c", "c", "c"]);
})
);
});
});
109 changes: 109 additions & 0 deletions client/cypress/integration/query/filters_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { createQuery } from "../../support/redash-api";
import { expectTableToHaveLength, expectFirstColumnToHaveMembers } from "../../support/visualizations/table";

const SQL = `
SELECT 'a' AS stage1, 'a1' AS stage2, 11 AS value UNION ALL
SELECT 'a' AS stage1, 'a2' AS stage2, 12 AS value UNION ALL
SELECT 'a' AS stage1, 'a3' AS stage2, 45 AS value UNION ALL
SELECT 'a' AS stage1, 'a4' AS stage2, 54 AS value UNION ALL
SELECT 'b' AS stage1, 'b1' AS stage2, 33 AS value UNION ALL
SELECT 'b' AS stage1, 'b2' AS stage2, 73 AS value UNION ALL
SELECT 'b' AS stage1, 'b3' AS stage2, 90 AS value UNION ALL
SELECT 'c' AS stage1, 'c1' AS stage2, 19 AS value UNION ALL
SELECT 'c' AS stage1, 'c2' AS stage2, 92 AS value UNION ALL
SELECT 'c' AS stage1, 'c3' AS stage2, 63 AS value UNION ALL
SELECT 'c' AS stage1, 'c4' AS stage2, 44 AS value\
`;

describe("Query Filters", () => {
beforeEach(() => {
cy.login();
});

describe("Simple Filter", () => {
beforeEach(() => {
const queryData = {
name: "Query Filters",
query: `SELECT stage1 AS "stage1::filter", stage2, value FROM (${SQL}) q`,
};

createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
cy.getByTestId("ExecuteButton").click();
});

it("filters rows in a Table Visualization", () => {
cy.getByTestId("FilterName-stage1::filter")
.find(".ant-select-selection-selected-value")
.should("have.text", "a");

expectTableToHaveLength(4);
expectFirstColumnToHaveMembers(["a", "a", "a", "a"]);

cy.getByTestId("FilterName-stage1::filter")
.find(".ant-select")
.click();

cy.contains("li.ant-select-dropdown-menu-item", "b").click();

expectTableToHaveLength(3);
expectFirstColumnToHaveMembers(["b", "b", "b"]);
});
});

describe("Multi Filter", () => {
beforeEach(() => {
const queryData = {
name: "Query Filters",
query: `SELECT stage1 AS "stage1::multi-filter", stage2, value FROM (${SQL}) q`,
};

createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
cy.getByTestId("ExecuteButton").click();
});

function expectSelectedOptionsToHaveMembers(values) {
cy.getByTestId("FilterName-stage1::multi-filter")
.find(".ant-select-selection__choice__content")
.then($selectedOptions => Cypress.$.map($selectedOptions, item => Cypress.$(item).text()))
.then(selectedOptions => expect(selectedOptions).to.have.members(values));
}

it("filters rows in a Table Visualization", () => {
expectSelectedOptionsToHaveMembers(["a"]);
expectTableToHaveLength(4);
expectFirstColumnToHaveMembers(["a", "a", "a", "a"]);

cy.getByTestId("FilterName-stage1::multi-filter")
.find(".ant-select-selection")
.click();
cy.contains("li.ant-select-dropdown-menu-item", "b").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown

expectSelectedOptionsToHaveMembers(["a", "b"]);
expectTableToHaveLength(7);
expectFirstColumnToHaveMembers(["a", "a", "a", "a", "b", "b", "b"]);

// Clear Option

cy.getByTestId("FilterName-stage1::multi-filter")
.find(".ant-select-selection")
.click();
cy.getByTestId("ClearOption").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown

cy.getByTestId("TableVisualization").should("not.exist");

// Select All Option

cy.getByTestId("FilterName-stage1::multi-filter")
.find(".ant-select-selection")
.click();
cy.getByTestId("SelectAllOption").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown

expectSelectedOptionsToHaveMembers(["a", "b", "c"]);
expectTableToHaveLength(11);
expectFirstColumnToHaveMembers(["a", "a", "a", "a", "b", "b", "b", "c", "c", "c", "c"]);
});
});
});
12 changes: 12 additions & 0 deletions client/cypress/support/visualizations/table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function expectTableToHaveLength(length) {
cy.getByTestId("TableVisualization")
.find("tbody tr")
.should("have.length", length);
}

export function expectFirstColumnToHaveMembers(values) {
cy.getByTestId("TableVisualization")
.find("tbody tr td:first-child")
.then($cell => Cypress.$.map($cell, item => Cypress.$(item).text()))
.then(firstColumnCells => expect(firstColumnCells).to.have.members(values));
}

0 comments on commit 4f8d2ca

Please sign in to comment.