From b4cbd8998f34220e526ecb227cf8bb649e77b7b6 Mon Sep 17 00:00:00 2001 From: Noa Nutkevitch Date: Mon, 12 Dec 2016 03:31:39 -0800 Subject: [PATCH] Add support for basic filter wiuth values as array of tuples --- package.json | 2 +- src/models.ts | 22 +++++++++++++++++----- src/schemas/basicFilter.json | 2 +- test/models.spec.ts | 24 ++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 790e3bd..48e8ec2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "powerbi-models", - "version": "0.10.2", + "version": "0.10.3", "description": "Contains JavaScript & TypeScript object models for Microsoft Power BI JavaScript SDK. For each model there is a TypeScript interface, a json schema definitions, and a validation function to ensure and object is valid.", "main": "dist/models.js", "typings": "dist/models.d.ts", diff --git a/src/models.ts b/src/models.ts index ebaf215..a17e428 100644 --- a/src/models.ts +++ b/src/models.ts @@ -124,6 +124,7 @@ export interface IBaseFilterTarget { export interface IFilterColumnTarget extends IBaseFilterTarget { column: string; + keys?: string[]; } export interface IFilterHierarchyTarget extends IBaseFilterTarget { @@ -144,7 +145,7 @@ export interface IFilter { export interface IBasicFilter extends IFilter { operator: BasicFilterOperators; - values: (string | number | boolean)[]; + values: (string | number | boolean)[] | (string | number | boolean)[][]; } export type BasicFilterOperators = "In" | "NotIn" | "All"; @@ -221,12 +222,12 @@ export abstract class Filter { export class BasicFilter extends Filter { static schemaUrl: string = "http://powerbi.com/product/schema#basic"; operator: BasicFilterOperators; - values: (string | number | boolean)[]; + values: (string | number | boolean)[] | (string | number | boolean)[][]; constructor( target: IFilterTarget, operator: BasicFilterOperators, - ...values: ((string | number | boolean) | (string | number | boolean)[])[] + ...values: ((string | number | boolean) | (string | number | boolean)[] | (string | number | boolean)[][])[] ) { super(target); this.operator = operator; @@ -242,10 +243,21 @@ export class BasicFilter extends Filter { * new BasicFilter('a', 'b', [1,2]); */ if (Array.isArray(values[0])) { - this.values = <(string | number | boolean)[]>values[0]; + this.values = <(string | number | boolean)[] | (string | number | boolean)[][]>values[0]; } else { - this.values = <(string | number | boolean)[]>values; + this.values = <(string | number | boolean)[] | (string | number | boolean)[][]>values; + } + let numberOfKeys = (target).keys ? (target).keys.length : 0; + + for (let i = 0 ; i < this.values.length ; i++) { + if (this.values[i] && Array.isArray(this.values[i])) { + let lengthOfArray = (<(string | number | boolean)[]>this.values[i]).length; + if (lengthOfArray !== numberOfKeys) { + throw new Error(`Each tuple of values should contain a value for each of the key columns. You passed: ${lengthOfArray} values and ${numberOfKeys} key columns`); + } + } + } } diff --git a/src/schemas/basicFilter.json b/src/schemas/basicFilter.json index 480b229..dedb6f9 100644 --- a/src/schemas/basicFilter.json +++ b/src/schemas/basicFilter.json @@ -31,7 +31,7 @@ "values": { "type": "array", "items": { - "type": ["string", "boolean", "number"] + "type": ["string", "boolean", "number", "array"] } } }, diff --git a/test/models.spec.ts b/test/models.spec.ts index 69ab540..791ee92 100644 --- a/test/models.spec.ts +++ b/test/models.spec.ts @@ -512,6 +512,28 @@ describe("Unit | Filters", function () { expect(basicFilter.values).toEqual(values); }); + it("should accept values as an array of tuples", function () { + // Arrange + const values = [[1, 2], [3,4]]; + + // Act + const basicFilter = new models.BasicFilter({ table: "t", column: "c" , keys: ["1", "2"]}, "In", values); + + // Assert + expect(basicFilter.values).toEqual(values); + }); + + it("should throw an exception when values are an array of tupples, but tuples length is different than keys length", function () { + // Arrange + const values = [[1, 2], [3,4]]; + + // Act + const attemptToCreateFilter = () => { + return new models.BasicFilter({ table: "t", column: "c" , keys: ["1"]}, "In", values); + }; + expect(attemptToCreateFilter).toThrowError(); + }); + it("should return valid json format when toJSON is called", function () { // Arrange const expectedFilter: models.IBasicFilter = { @@ -684,6 +706,7 @@ describe("Unit | Filters", function () { // Arrange const testData = { basicFilter: new models.BasicFilter({ table: "a", column: "b" }, "In", ["x", "y"]), + basicFilterWithKeys: new models.BasicFilter({ table: "a", column: "b", keys: ["1", "2"] }, "In", [["x1", 1], ["y2",2]]), advancedFilter: new models.AdvancedFilter({ table: "a", column: "b" }, "And", { operator: "Contains", value: "x" }, { operator: "Contains", value: "x" } @@ -695,6 +718,7 @@ describe("Unit | Filters", function () { // Assert expect(models.getFilterType(testData.basicFilter.toJSON())).toBe(models.FilterType.Basic); + expect(models.getFilterType(testData.basicFilterWithKeys.toJSON())).toBe(models.FilterType.Basic); expect(models.getFilterType(testData.advancedFilter.toJSON())).toBe(models.FilterType.Advanced); expect(models.getFilterType(testData.nonFilter)).toBe(models.FilterType.Unknown); });