UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

1,023 lines (920 loc) • 35.8 kB
// (C) 2007-2020 GoodData Corporation import { VisualizationObject, AFM } from "@gooddata/typings"; import cloneDeep = require("lodash/cloneDeep"); import update = require("lodash/update"); import { VisualizationTypes } from "../../constants/visualizationTypes"; import { generateDimensions, getHeadlinesDimensions, getPivotTableDimensions, generateStackedDimensions, getGeneralDimensionsFromAFM, getGeoChartDimensions, } from "../dimensions"; import { visualizationObjects } from "../../../__mocks__/fixtures"; import { MEASURE_1, ATTRIBUTE_CITIES } from "../../../stories/data/afmComponentProps"; import { MEASURES, ATTRIBUTE, COLUMNS } from "../../constants/bucketNames"; import { MEASUREGROUP } from "../../constants/dimensions"; import { IGeoPushpinChartProps } from "../../interfaces/GeoChart"; import { attribute, measure } from "../../helpers/model"; import { getBuckets } from "../../components/GeoPushpinChart"; function getVisualization(name: string): VisualizationObject.IVisualizationObjectContent { const uri = `/gdc/md/myproject/obj/${name}`; const visObj = visualizationObjects.find(chart => chart.visualizationObject.meta.uri === uri); if (!visObj) { throw new Error(`Unknown uri ${uri}`); } return visObj.visualizationObject.content; } function getVisualizationBucket( newVis: VisualizationObject.IVisualizationObjectContent, bucketName: string, ): VisualizationObject.IBucket { let bucketIndex = newVis.buckets.findIndex(bucket => bucket.localIdentifier === bucketName); if (bucketIndex < 0) { update(newVis, ["buckets"], (buckets: VisualizationObject.IBucket[]) => { buckets.push({ localIdentifier: bucketName, items: [], }); return buckets; }); bucketIndex = newVis.buckets.length - 1; } return newVis.buckets[bucketIndex]; } function addMeasure( visualization: VisualizationObject.IVisualizationObjectContent, index: number, ): VisualizationObject.IVisualizationObjectContent { const newVis: VisualizationObject.IVisualizationObjectContent = cloneDeep(visualization); const measure = { measure: { localIdentifier: `m${index}`, title: `# Users Opened AD ${index}`, definition: { measureDefinition: { item: { uri: `/gdc/md/myproject/obj/150${index}`, }, }, }, }, }; return update(newVis, ["buckets", 0, "items"], (measures: VisualizationObject.IMeasure[]) => { measures.push(measure); return measures; }); } function addAttribute( visualization: VisualizationObject.IVisualizationObjectContent, index: number, bucketName: string, ): VisualizationObject.IVisualizationObjectContent { const newVis = cloneDeep(visualization); const visualizationAttribute = { visualizationAttribute: { localIdentifier: `a${index}`, displayForm: { uri: `/gdc/md/myproject/obj/400${index}`, }, }, }; const bucket = getVisualizationBucket(newVis, bucketName); bucket.items.push(visualizationAttribute); return newVis; } function addTotals( visualization: VisualizationObject.IVisualizationObjectContent, bucketName: string, newTotals: VisualizationObject.IVisualizationTotal[], ): VisualizationObject.IVisualizationObjectContent { const newVis: VisualizationObject.IVisualizationObjectContent = cloneDeep(visualization); const bucket = getVisualizationBucket(newVis, bucketName); if (!bucket.totals) { bucket.totals = []; } newTotals.forEach(total => { bucket.totals.push(total); }); return newVis; } describe("getHeadlinesDimensions", () => { it("should always return just one dimension with a measureGroup", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, ]; expect(getHeadlinesDimensions()).toEqual(expectedDimensions); }); }); describe("getPivotTableDimensions", () => { // tslint:disable-next-line:max-line-length it("should return row attributes in the first dimensions, column attributes and measureGroup in second dimension", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["a2", "measureGroup"], }, ]; const buckets = [ { localIdentifier: MEASURES, items: [ { measure: { localIdentifier: "m1", title: "# Accounts with AD Query", definition: { measureDefinition: { item: { uri: "/gdc/md/myproject/obj/m1", }, }, }, }, }, ], }, { // ATTRIBUTE for backwards compatibility with Table component. Actually ROWS localIdentifier: ATTRIBUTE, items: [ { visualizationAttribute: { localIdentifier: "a1", displayForm: { uri: "/gdc/md/myproject/obj/a1", }, }, }, ], }, { localIdentifier: COLUMNS, items: [ { visualizationAttribute: { localIdentifier: "a2", displayForm: { uri: "/gdc/md/myproject/obj/a2", }, }, }, ], }, ]; expect(getPivotTableDimensions(buckets)).toEqual(expectedDimensions); }); }); describe("generateDimensions", () => { describe("column/bar chart", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: [], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.COLUMN)).toEqual( expectedDimensions, ); expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.BAR)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "view"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.COLUMN)).toEqual( expectedDimensions, ); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.BAR)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithStackAttribute = addAttribute(visualization, 1, "stack"); expect(generateDimensions(visualizationWithStackAttribute, VisualizationTypes.COLUMN)).toEqual( expectedDimensions, ); expect(generateDimensions(visualizationWithStackAttribute, VisualizationTypes.BAR)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure, view attribute and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["a1", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAndStackAttribute = addAttribute( addAttribute(visualization, 1, "view"), 2, "stack", ); expect( generateDimensions(visualizationWithViewAndStackAttribute, VisualizationTypes.COLUMN), ).toEqual(expectedDimensions); expect( generateDimensions(visualizationWithViewAndStackAttribute, VisualizationTypes.BAR), ).toEqual(expectedDimensions); }); }); describe("area chart", () => { it("should generate dimensions for area with one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: [], }, ]; const dimensions = generateDimensions(getVisualization("onemeasure"), VisualizationTypes.AREA); expect(dimensions).toEqual(expectedDimensions); }); it("should generate dimensions for area with one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "view"); const dimensions = generateDimensions(visualizationWithViewAttribute, VisualizationTypes.AREA); expect(dimensions).toEqual(expectedDimensions); }); it("should generate dimensions for area with one measure and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithStackAttribute = addAttribute(visualization, 1, "stack"); const dimensions = generateDimensions(visualizationWithStackAttribute, VisualizationTypes.AREA); expect(dimensions).toEqual(expectedDimensions); }); it("should generate dimensions for area with one measure, view attribute and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["a1", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAndStackAttribute = addAttribute( addAttribute(visualization, 1, "view"), 2, "stack", ); const dimensions = generateDimensions( visualizationWithViewAndStackAttribute, VisualizationTypes.AREA, ); expect(dimensions).toEqual(expectedDimensions); }); it("should generate dimensions for area with one measure, two view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["a1", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithTwoViewAttributes = addAttribute( addAttribute(visualization, 1, "view"), 2, "view", ); const dimensions = generateDimensions( visualizationWithTwoViewAttributes, VisualizationTypes.AREA, ); expect(dimensions).toEqual(expectedDimensions); }); }); describe("heatmap", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.HEATMAP)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "view"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.HEATMAP)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["a1", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithStackAttribute = addAttribute(visualization, 1, "stack"); expect(generateDimensions(visualizationWithStackAttribute, VisualizationTypes.HEATMAP)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure, view attribute and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["a2", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAndStackAttribute = addAttribute( addAttribute(visualization, 1, "view"), 2, "stack", ); expect( generateDimensions(visualizationWithViewAndStackAttribute, VisualizationTypes.HEATMAP), ).toEqual(expectedDimensions); }); }); describe("line chart", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: [], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.LINE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "trend"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.LINE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "segment"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.LINE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure, view attribute and stack attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["a1", "measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAndStackAttribute = addAttribute( addAttribute(visualization, 1, "trend"), 2, "segment", ); expect( generateDimensions(visualizationWithViewAndStackAttribute, VisualizationTypes.LINE), ).toEqual(expectedDimensions); }); }); describe("pie chart", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.PIE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "view"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.PIE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and 2 view attributes", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1", "a2"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWith2ViewAttributes = addAttribute( addAttribute(visualization, 1, "view"), 2, "view", ); expect(generateDimensions(visualizationWith2ViewAttributes, VisualizationTypes.PIE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for two measures", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWith2Measures = addMeasure(visualization, 2); expect(generateDimensions(visualizationWith2Measures, VisualizationTypes.PIE)).toEqual( expectedDimensions, ); }); }); describe("treemap", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.TREEMAP)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and view attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["measureGroup"], }, { itemIdentifiers: ["a1"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithViewAttribute = addAttribute(visualization, 1, "view"); expect(generateDimensions(visualizationWithViewAttribute, VisualizationTypes.TREEMAP)).toEqual( expectedDimensions, ); }); it("should generate dimensions for two measures", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWith2Measures = addMeasure(visualization, 2); expect(generateDimensions(visualizationWith2Measures, VisualizationTypes.TREEMAP)).toEqual( expectedDimensions, ); }); }); describe("table", () => { it("should generate dimensions for one measure", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; expect(generateDimensions(getVisualization("onemeasure"), VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: [], }, ]; expect(generateDimensions(getVisualization("oneattribute"), VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and attribute", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWithAttribute = addAttribute(visualization, 1, "attribute"); expect(generateDimensions(visualizationWithAttribute, VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for one measure and 2 attributes", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a1", "a2"], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWith2Attributes = addAttribute( addAttribute(visualization, 1, "attribute"), 2, "attribute", ); expect(generateDimensions(visualizationWith2Attributes, VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); it("should generate dimensions for two measures", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("onemeasure"); const visualizationWith2Measures = addMeasure(visualization, 2); expect(generateDimensions(visualizationWith2Measures, VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); it("should generate dimensions with totals", () => { const expectedTotals: AFM.ITotalItem[] = [ { measureIdentifier: "m1", attributeIdentifier: "a1", type: "sum", }, { measureIdentifier: "m2", attributeIdentifier: "a1", type: "sum", }, { measureIdentifier: "m1", attributeIdentifier: "a1", type: "nat", }, ]; const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], totals: expectedTotals, }, { itemIdentifiers: ["measureGroup"], }, ]; const visualization = getVisualization("1"); const visualizationWithTotals = addTotals(visualization, "attribute", [ { measureIdentifier: "m1", attributeIdentifier: "a1", type: "sum", alias: "Sum", }, { measureIdentifier: "m2", attributeIdentifier: "a1", type: "sum", }, { measureIdentifier: "m1", attributeIdentifier: "a1", type: "nat", }, ]); expect(generateDimensions(visualizationWithTotals, VisualizationTypes.TABLE)).toEqual( expectedDimensions, ); }); }); }); describe("generateStackedDimensions", () => { it("measure and stack by only", () => { const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["measureGroup"], }, ]; const buckets = [ { localIdentifier: "measures", items: [ { measure: { localIdentifier: "m1", title: "# Accounts with AD Query", definition: { measureDefinition: { item: { uri: "/gdc/md/myproject/obj/m1", }, }, }, }, }, ], }, { localIdentifier: "stack", items: [ { visualizationAttribute: { localIdentifier: "a2", displayForm: { uri: "/gdc/md/myproject/obj/a2", }, }, }, ], }, ]; expect(generateStackedDimensions(buckets)).toEqual(expectedDimensions); }); it("should return 2 attributes along with measureGroup", () => { const buckets = [ { localIdentifier: "measures", items: [ { measure: { localIdentifier: "m1", definition: { measureDefinition: { item: { uri: "/gdc/md/storybook/obj/1", }, }, }, }, }, ], }, { localIdentifier: "attribute", items: [ { visualizationAttribute: { displayForm: { uri: "/gdc/md/storybook/obj/1.df", }, localIdentifier: "a1", }, }, { visualizationAttribute: { displayForm: { uri: "/gdc/md/storybook/obj/2.df", }, localIdentifier: "a2", }, }, ], }, { localIdentifier: "stack", items: [], }, ]; const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [], }, { itemIdentifiers: ["a1", "a2", "measureGroup"], }, ]; expect(generateStackedDimensions(buckets)).toEqual(expectedDimensions); }); it("should return 2 attributes along with measureGroup and return 1 stack attribute", () => { const buckets = [ { localIdentifier: "measures", items: [ { measure: { localIdentifier: "m1", definition: { measureDefinition: { item: { uri: "/gdc/md/storybook/obj/1", }, }, }, }, }, ], }, { localIdentifier: "attribute", items: [ { visualizationAttribute: { displayForm: { uri: "/gdc/md/storybook/obj/1.df", }, localIdentifier: "a1", }, }, { visualizationAttribute: { displayForm: { uri: "/gdc/md/storybook/obj/3.df", }, localIdentifier: "a3", }, }, ], }, { localIdentifier: "stack", items: [ { visualizationAttribute: { displayForm: { uri: "/gdc/md/storybook/obj/2.df", }, localIdentifier: "a2", }, }, ], }, ]; const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["a2"], }, { itemIdentifiers: ["a1", "a3", "measureGroup"], }, ]; expect(generateStackedDimensions(buckets)).toEqual(expectedDimensions); }); }); describe("getGeneralDimensionsFromAFM", () => { it("should return resultSpec dimensions for AFM with both measures and attributes", () => { const afm = { measures: [MEASURE_1], attributes: [ATTRIBUTE_CITIES], }; const expectedDimensions = [{ itemIdentifiers: ["a1"] }, { itemIdentifiers: ["measureGroup"] }]; expect(getGeneralDimensionsFromAFM(afm)).toEqual(expectedDimensions); }); it("should return resultSpec dimensions for AFM with measures only", () => { const afm = { measures: [MEASURE_1], }; const expectedDimensions = [{ itemIdentifiers: ["measureGroup"] }]; expect(getGeneralDimensionsFromAFM(afm)).toEqual(expectedDimensions); }); it("should return resultSpec dimensions for AFM with attributes only", () => { const afm = { attributes: [ATTRIBUTE_CITIES], }; const expectedDimensions = [{ itemIdentifiers: ["a1"] }]; expect(getGeneralDimensionsFromAFM(afm)).toEqual(expectedDimensions); }); }); describe("getGeoChartDimensions", () => { it("should return dimensions without measureGroup", () => { const pushpinProps: IGeoPushpinChartProps = { location: attribute("location").localIdentifier("location"), projectId: "test", }; const buckets: VisualizationObject.IBucket[] = getBuckets(pushpinProps); const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: ["location"], }, ]; expect(getGeoChartDimensions(buckets)).toEqual(expectedDimensions); }); it("should return dimensions with measureGroup Array and Attributes array have 2 items", () => { const pushpinProps: IGeoPushpinChartProps = { location: attribute("location").localIdentifier("location"), size: measure("size").localIdentifier("size"), segmentBy: attribute("segmentBy").localIdentifier("segmentBy"), projectId: "test", }; const buckets: VisualizationObject.IBucket[] = getBuckets(pushpinProps); const expectedDimensions: AFM.IDimension[] = [ { itemIdentifiers: [MEASUREGROUP], }, { itemIdentifiers: ["location", "segmentBy"], }, ]; expect(getGeoChartDimensions(buckets)).toEqual(expectedDimensions); }); });