diff --git a/frontend/src/metabase/lib/query/field_ref.js b/frontend/src/metabase/lib/query/field_ref.js index 44332da6e42f75b05d649f2f5163a743cab98427..b3523d3a210e36f90437bd1fe41d0fb6a385528c 100644 --- a/frontend/src/metabase/lib/query/field_ref.js +++ b/frontend/src/metabase/lib/query/field_ref.js @@ -62,7 +62,7 @@ export function isValidField(field) { (isAggregateField(field) && typeof field[1] === "number") || (isJoinedField(field) && typeof field[1] === "string" && - isValidField(field[0])) || + isValidField(field[2])) || isFieldLiteral(field) ); } diff --git a/frontend/src/metabase/lib/query/filter.js b/frontend/src/metabase/lib/query/filter.js index d85ee86c7ad0464a9cc585865ab212cd503fd160..552c558797055e4c51068063f2157ddcc953898e 100644 --- a/frontend/src/metabase/lib/query/filter.js +++ b/frontend/src/metabase/lib/query/filter.js @@ -70,7 +70,7 @@ export function canAddFilter(filter: ?FilterClause): boolean { export function isStandard(filter: FilterClause): boolean { return ( Array.isArray(filter) && - STANDARD_FILTERS.has(filter[0]) && + (STANDARD_FILTERS.has(filter[0]) || filter[0] === null) && (filter[1] === undefined || isValidField(filter[1])) ); } diff --git a/frontend/test/metabase-lib/lib/queries/structured/Filter.unit.spec.js b/frontend/test/metabase-lib/lib/queries/structured/Filter.unit.spec.js index 734d0525fc07abee9a47545c1543bb16ab2c41d5..379fa29508211d402c52db223dfcb1799326ab79 100644 --- a/frontend/test/metabase-lib/lib/queries/structured/Filter.unit.spec.js +++ b/frontend/test/metabase-lib/lib/queries/structured/Filter.unit.spec.js @@ -1,6 +1,6 @@ import Filter from "metabase-lib/lib/queries/structured/Filter"; -import { ORDERS } from "__support__/sample_dataset_fixture"; +import { ORDERS, PEOPLE } from "__support__/sample_dataset_fixture"; const query = ORDERS.query(); @@ -72,5 +72,38 @@ describe("Filter", () => { filter(["segment", 1]).setDimension(["field-id", ORDERS.TOTAL.id]), ).toEqual([null, ["field-id", ORDERS.TOTAL.id]]); }); + it("should set joined-field for new filter clause", () => { + const q = ORDERS.query().join({ + alias: "foo", + "source-table": PEOPLE.id, + }); + const f = new Filter([], 0, q); + expect( + f.setDimension(["joined-field", "foo", ["field-id", PEOPLE.EMAIL.id]], { + useDefaultOperator: true, + }), + ).toEqual([ + "=", + ["joined-field", "foo", ["field-id", PEOPLE.EMAIL.id]], + undefined, + ]); + }); }); + + const CASES = [ + ["isStandard", ["=", ["field-id", 1]]], + ["isStandard", [null, ["field-id", 1]]], // assume null operator is standard + ["isSegment", ["segment", 1]], + ["isCustom", ["or", ["=", ["field-id", 1], 42]]], + ]; + for (const method of ["isStandard", "isSegment", "isCustom"]) { + describe(method, () => { + for (const [method_, mbql] of CASES) { + const expected = method_ === method; + it(`should return ${expected} for ${JSON.stringify(mbql)}`, () => { + expect(filter(mbql)[method]()).toEqual(expected); + }); + } + }); + } }); diff --git a/frontend/test/metabase/lib/query/field_ref.unit.spec.js b/frontend/test/metabase/lib/query/field_ref.unit.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..d58fd540f469d925e2aec4a53cdc545c64c5ac98 --- /dev/null +++ b/frontend/test/metabase/lib/query/field_ref.unit.spec.js @@ -0,0 +1,18 @@ +import { isValidField } from "metabase/lib/query/field_ref"; + +describe("field_ref", () => { + describe("isValidField", () => { + it("should be valid for field id", () => { + expect(isValidField(["field-id", 1])).toBe(true); + }); + it("should be valid for fk", () => { + expect(isValidField(["fk->", ["field-id", 1], ["field-id", 2]])).toBe( + true, + ); + }); + it("should be valid for joined-field", () => { + expect(isValidField(["joined-field", "foo", ["field-id", 1]])).toBe(true); + }); + // TODO: remaininng field types + }); +}); diff --git a/frontend/test/metabase/support/join_filter.cy.spec.js b/frontend/test/metabase/support/join_filter.cy.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..bb0ba3eb1967f29d873b15ce2a905b7cac9eb061 --- /dev/null +++ b/frontend/test/metabase/support/join_filter.cy.spec.js @@ -0,0 +1,26 @@ +import { restore, signInAsNormalUser } from "__support__/cypress"; + +describe("support > join filter (metabase#12221)", () => { + before(restore); + before(signInAsNormalUser); + + it.skip("can filter by a joined table", () => { + cy.visit("/question/new"); + cy.contains("Custom question").click(); + cy.contains("Sample Dataset").click(); + cy.contains("Orders").click(); + cy.get(".Icon-join_left_outer ").click(); + cy.contains("People").click(); + cy.contains("Orders + People"); + cy.contains("Visualize").click(); + cy.contains("Showing first 2,000"); + + cy.contains("Filter").click(); + cy.contains("Email").click(); + cy.contains("People – Email"); + cy.get('[placeholder="Search by Email"]').type("wolf."); + cy.contains("wolf.dina@yahoo.com").click(); + cy.contains("Add filter").click(); + cy.contains("Showing 1 row"); + }); +});