// (C) 2007-2020 GoodData Corporation import { ExecuteAFM as AFM } from "@gooddata/typings"; import { IMockProject } from "../../../../model/MockProject"; import { buildProject } from "../../../../schema/builder"; import { schema } from "../../../../schema/fixtures/dummySchema"; import { AFMBuilder } from "../../../../utils/AFMBuilder/AFMBuilder"; import { DataResultBuilder, IRandomDataResult } from "../dataResult"; import { IErrorResponse } from "../../executeAfm"; describe("New Data result", () => { const currentDate = new Date("2015-12-31"); const random = (params: { row: number; column: number }) => `${(params.row + 1) * (params.column + 1)}`; const tableFactory = ( project: IMockProject, execution: AFM.IExecution, ): IRandomDataResult | IErrorResponse => { return DataResultBuilder.forProject(project) .withGenerator(random) .atDate(currentDate) .forAfmAndResultSpec(execution) .build(); }; const project = buildProject(schema); const JOHN = { attributeHeaderItem: { name: "John Doe", uri: "/gdc/md/mockproject/obj/attr.employee/elements?id=1", }, }; const JANE = { attributeHeaderItem: { name: "Jane Doe", uri: "/gdc/md/mockproject/obj/attr.employee/elements?id=2", }, }; const JIM = { attributeHeaderItem: { name: "Jim Doe", uri: "/gdc/md/mockproject/obj/attr.employee/elements?id=3", }, }; const MEASURE_A = { measureHeaderItem: { name: "Simple metric", order: 0, }, }; const MEASURE_B = { measureHeaderItem: { name: "Simple metric 2", order: 1, }, }; const MEASURE_C = { measureHeaderItem: { name: "Count of Employee", order: 2, }, }; const COMPANY_A = { attributeHeaderItem: { name: "Company A", uri: "/gdc/md/mockproject/obj/1234/elements?id=1", }, }; const COMPANY_B = { attributeHeaderItem: { name: "Company B", uri: "/gdc/md/mockproject/obj/1234/elements?id=2", }, }; const DIM_Y: AFM.IDimension = { itemIdentifiers: ["measureGroup"], }; const DIM_X: AFM.IDimension = { itemIdentifiers: ["a0"], }; const DIM_EMPTY: AFM.IDimension = { itemIdentifiers: [], }; describe("unidimensional", () => { describe("single metric", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addResultSpec({ dimensions: [DIM_Y], }) .build(); const table = tableFactory(project, execution) as IRandomDataResult; it("should convert to data with single value", () => { expect(table.data).toEqual(["1"]); }); it("should convert to attribute header items with empty arrays", () => { expect(table.headerItems).toEqual([[[MEASURE_A]]]); }); }); describe("multiple metrics", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addMeasure() .addResultSpec({ dimensions: [DIM_Y], }) .build(); const table = tableFactory(project, execution) as IRandomDataResult; it("should convert to data with multiple values", () => { expect(table.data).toEqual(["1", "2"]); }); it("should convert to attribute header items with empty arrays", () => { expect(table.headerItems).toEqual([[[MEASURE_A, MEASURE_B]]]); }); }); }); describe("bidimensional", () => { describe("second dimension is empty", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addMeasure() .addResultSpec({ dimensions: [DIM_Y, DIM_EMPTY], }) .build(); const table = tableFactory(project, execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([["1"], ["2"]]); }); it("should convert to header items", () => { expect(table.headerItems).toEqual([ [[MEASURE_A, MEASURE_B]], [], // empty array => empty 1-st dimension ]); }); }); describe("measureGroup first", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addMeasure() .addAttribute() .addResultSpec({ dimensions: [DIM_Y, DIM_X], }) .build(); const table = tableFactory(buildProject(schema), execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([["1", "2", "3"], ["2", "4", "6"]]); }); it("should convert to attribute header items in the second dimension", () => { expect(table.headerItems).toEqual([[[MEASURE_A, MEASURE_B]], [[JOHN, JANE, JIM]]]); }); }); describe("measureGroup second", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addMeasure() .addResultSpec({ dimensions: [DIM_EMPTY, DIM_Y], }) .build(); const table = tableFactory(buildProject(schema), execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([["1", "2"]]); }); it("should convert to attribute header items", () => { expect(table.headerItems).toEqual([[], [[MEASURE_A, MEASURE_B]]]); }); }); describe("measureGroup with attribute based measure", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addMeasure() .addAttributeBasedMeasure() .addResultSpec({ dimensions: [DIM_Y, DIM_EMPTY], }) .build(); const table = tableFactory(buildProject(schema), execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([["1"], ["2"], ["3"]]); }); it("should convert to attribute header items in the second dimension", () => { expect(table.headerItems).toEqual([[[MEASURE_A, MEASURE_B, MEASURE_C]], []]); }); }); describe("single attribute, empty row resultSpec", () => { const execution = AFMBuilder.buildFromSchema(schema) .addAttribute() .addResultSpec({ dimensions: [DIM_EMPTY, DIM_X], }) .build(); const table = tableFactory(buildProject(schema), execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([]); }); it("should convert to attribute header items in the second dimension", () => { expect(table.headerItems).toEqual([[], [[JOHN, JANE, JIM]]]); }); }); describe("single attribute, empty col resultSpec", () => { const execution = AFMBuilder.buildFromSchema(schema) .addAttribute() .addResultSpec({ dimensions: [DIM_X, DIM_EMPTY], }) .build(); const table = tableFactory(buildProject(schema), execution) as IRandomDataResult; it("should convert to data", () => { expect(table.data).toEqual([]); }); it("should convert to attribute header items in the first dimension", () => { expect(table.headerItems).toEqual([[[JOHN, JANE, JIM]], []]); }); }); }); describe("stacking", () => { it("should support simple stacking", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addResultSpec({ dimensions: [ { itemIdentifiers: ["measureGroup", "a0"], }, ], }) .build(); const result = tableFactory(buildProject(schema), execution) as IRandomDataResult; expect(result.data).toEqual(["1", "2", "3"]); expect(result.headerItems).toEqual([[[MEASURE_A, MEASURE_A, MEASURE_A], [JOHN, JANE, JIM]]]); }); it("should support two levels of stacking", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addAttribute() .addResultSpec({ dimensions: [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a0", "a1"], }, ], }) .build(); const result = tableFactory(buildProject(schema), execution) as IRandomDataResult; expect(result.data).toEqual([["1", "2", "3", "4", "5", "6"]]); expect(result.headerItems).toEqual([ [[MEASURE_A]], [ [JOHN, JOHN, JANE, JANE, JIM, JIM], [COMPANY_A, COMPANY_B, COMPANY_A, COMPANY_B, COMPANY_A, COMPANY_B], ], ]); }); it("should support sort by attribute", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addAttribute() .addResultSpec({ dimensions: [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a0", "a1"], }, ], }) .addSortByAttribute(0, "asc") .build(); const result = tableFactory(buildProject(schema), execution) as IRandomDataResult; expect(result.data).toEqual([["3", "4", "5", "6", "1", "2"]]); expect(result.headerItems).toEqual([ [[MEASURE_A]], [ [JANE, JANE, JIM, JIM, JOHN, JOHN], [COMPANY_A, COMPANY_B, COMPANY_A, COMPANY_B, COMPANY_A, COMPANY_B], ], ]); }); }); describe("measure value filter", () => { it("should apply measure value filter on generated result", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addFilter({ measureValueFilter: { measure: { localIdentifier: "m0", }, condition: { comparison: { operator: "GREATER_THAN_OR_EQUAL_TO", value: 2, }, }, }, }) .build(); const result = tableFactory(buildProject(schema), execution) as IRandomDataResult; expect(result.data).toEqual([["2", "3"]]); }); it("should return error response when measure value filter is invalid", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addFilter({ measureValueFilter: { measure: { localIdentifier: "measure-not-in-afm", }, condition: { comparison: { operator: "GREATER_THAN", value: 400, }, }, }, }) .build(); const result = tableFactory(buildProject(schema), execution) as IErrorResponse; expect(result.error.statusCode).toBe(400); }); }); describe("ranking filter", () => { it("should apply ranking filter on generated result", () => { const execution = AFMBuilder.buildFromSchema(schema) .addMeasure() .addAttribute() .addFilter({ rankingFilter: { measures: [ { localIdentifier: "m0", }, ], operator: "BOTTOM", value: 2, }, }) .build(); const result = tableFactory(buildProject(schema), execution) as IRandomDataResult; expect(result.data).toEqual([["1", "2"]]); }); }); });