@gooddata/react-components
Version:
GoodData.UI - A powerful JavaScript library for building analytical applications
395 lines (364 loc) • 12.6 kB
text/typescript
// (C) 2007-2020 GoodData Corporation
import {
getIdsFromUri,
sanitizeField,
getRowNodeId,
getGridIndex,
indexOfTreeNode,
getTreeLeaves,
getSubtotalStyles,
cellRenderer,
generateAgGridComponentKey,
getParsedFields,
sanitizeFingerprint,
getMappingHeaderMeasureItemLocalIdentifier,
} from "../agGridUtils";
import cloneDeep = require("lodash/cloneDeep");
import identity = require("lodash/identity");
import { AFM } from "@gooddata/typings";
import { IGridHeader } from "../agGridTypes";
import { getFakeColumn } from "./agGridMock";
import { IMappingHeader } from "../../../../interfaces/MappingHeader";
describe("getIdsFromUri", () => {
it("should return array of attribute id and attribute value id", () => {
expect(getIdsFromUri("/gdc/md/storybook/obj/123/elements?id=456")).toEqual(["123", "456"]);
});
it("should return null as attribute value id if supplied with attribute uri", () => {
expect(getIdsFromUri("/gdc/md/storybook/obj/123")).toEqual(["123", null]);
});
it("should work with non standard ids and sanitize them", () => {
expect(getIdsFromUri("/gdc/md/storybook/obj/123_ABC.DEF/elements?id=456_GHI.789")).toEqual([
"123UNDERSCOREABCDOTDEF",
"456UNDERSCOREGHIDOT789",
]);
});
it("should return unsanitized ids if sanitize: false", () => {
expect(getIdsFromUri("/gdc/md/storybook/obj/123_ABC.DEF/elements?id=456_GHI.789", false)).toEqual([
"123_ABC.DEF",
"456_GHI.789",
]);
});
});
describe("sanitizeField", () => {
it("should replace [.], [_] and [-] characters with placeholders", () => {
expect(sanitizeField("field.with-replacement_")).toBe("fieldDOTwithDASHreplacementUNDERSCORE");
});
});
describe("getRowNodeId", () => {
it("should return correct id for row item", () => {
const item = {
headerItemMap: {
a_1027: {
attributeHeaderItem: {
name: "Direct Sales",
uri: "/gdc/md/ux8xk21n3al4qr1akoz7j6xkl5dt1dqj/obj/1026/elements?id=1226",
},
},
a_1094: { totalHeaderItem: { name: "nat", type: "nat" } },
a_64727: {
attributeHeaderItem: {
name: "Exclude",
uri: "/gdc/md/ux8xk21n3al4qr1akoz7j6xkl5dt1dqj/obj/64726/elements?id=966650",
},
},
},
};
expect(getRowNodeId(item)).toEqual("a_1027_1226-a_1094_nat-a_64727_966650");
});
});
describe("getGridIndex", () => {
const gridDistance = 20;
it.each([["100", 100, 5], ["110", 110, 5], ["99", 99, 4]])(
"should return correct row index when scrolltop is %s",
(_: string, scrollTop: number, expectedRowIndex: number) => {
expect(getGridIndex(scrollTop, gridDistance)).toEqual(expectedRowIndex);
},
);
});
describe("cellRenderer", () => {
it("should escape value", () => {
const fakeParams: any = {
formatValue: identity,
value: "<button>xss</button>",
node: {
rowPinned: false,
},
};
const value = cellRenderer(fakeParams);
expect(value).toEqual('<span class="s-value"><button>xss</button></span>');
});
});
describe("getSubtotalStyles", () => {
it("should return empty array if no totals are present", () => {
const dimension: AFM.IDimension = {
itemIdentifiers: ["a1", "a2", "a3"],
};
const resultSubtotalStyles = getSubtotalStyles(dimension);
expect(resultSubtotalStyles).toEqual([]);
});
it("should return null on first attribute", () => {
const dimension: AFM.IDimension = {
itemIdentifiers: ["a1", "a2"],
totals: [
{
attributeIdentifier: "a1",
type: "sum",
measureIdentifier: "m1",
},
{
attributeIdentifier: "a2",
type: "sum",
measureIdentifier: "m1",
},
],
};
const resultSubtotalStyles = getSubtotalStyles(dimension);
expect(resultSubtotalStyles).toEqual([null, "even"]);
});
it("should alternate subtotal style", () => {
const dimension: AFM.IDimension = {
itemIdentifiers: ["a1", "a2", "a3", "a4", "a5"],
totals: [
{
attributeIdentifier: "a2",
type: "sum",
measureIdentifier: "m1",
},
{
attributeIdentifier: "a4",
type: "sum",
measureIdentifier: "m1",
},
{
attributeIdentifier: "a5",
type: "sum",
measureIdentifier: "m1",
},
],
};
const resultSubtotalStyles = getSubtotalStyles(dimension);
expect(resultSubtotalStyles).toEqual([null, "even", null, "odd", "even"]);
});
});
const tree: any = {
name: "A",
children: [
{
name: "A.A",
},
{
name: "A.B",
children: [
{
name: "A.B.A",
},
{
name: "A.B.B",
},
{
name: "A.B.C",
},
],
},
{
name: "A.C",
},
],
};
describe("getTreeleaves", () => {
it("should return tree nodes that have no children", () => {
expect(getTreeLeaves(tree)).toEqual([
{
name: "A.A",
},
{
name: "A.C",
},
{
name: "A.B.A",
},
{
name: "A.B.B",
},
{
name: "A.B.C",
},
]);
});
});
describe("indexOfTreeNode", () => {
it("should return an array of indexes that define a matiching node in a tree structure", () => {
const node: any = tree.children[1].children[2];
expect(indexOfTreeNode(node, tree)).toEqual([0, 1, 2]);
});
it("should return indexes with custom matchNode function", () => {
const clonedTree: any = cloneDeep(tree);
const node: any = tree.children[1].children[2];
expect(
indexOfTreeNode(node, clonedTree, (nodeA, nodeB) => nodeA.name && nodeA.name === nodeB.name),
).toEqual([0, 1, 2]);
});
it("should return return null if the node is not found", () => {
const node = {};
expect(indexOfTreeNode(node, tree)).toEqual(null);
});
});
describe("generateAgGridComponentKey", () => {
it("should generate agGrid component key from AFM without nativeTotals", () => {
const afm: AFM.IAfm = {
measures: [],
attributes: [],
filters: [],
nativeTotals: [],
};
const key = generateAgGridComponentKey(afm, 1);
const expectedKey = 'agGridKey-{"attributes":[],"filters":[],"measures":[]}-1';
expect(key).toEqual(expectedKey);
});
});
describe("getParsedFields", () => {
it("should return last parsed field from colId", () => {
expect(getParsedFields("a_2009")).toEqual([["a", "2009"]]);
expect(getParsedFields("a_2009_4-a_2071_12")).toEqual([["a", "2009", "4"], ["a", "2071", "12"]]);
expect(getParsedFields("a_2009_4-a_2071_12-m_3")).toEqual([
["a", "2009", "4"],
["a", "2071", "12"],
["m", "3"],
]);
});
});
describe("sanitizeFingerprint", () => {
const correctFingerprintMock = JSON.stringify({
afm: {
measures: [
{
alias: "lost",
localIdentifier: "1",
},
],
},
bucketItemsPositionSignature: [
{
items: ["123"],
localIdentifier: "measure",
},
],
});
const incorrectFingerprintMock = JSON.stringify({
afm: {
attributes: [],
measures: [
{
alias: "lost",
localIdentifier: "1",
},
],
filters: [],
nativeTotals: [],
},
bucketItemsPositionSignature: [
{
items: ["123"],
localIdentifier: "measure",
},
],
});
it("should return correctly sanitized fingerprint", () => {
expect(sanitizeFingerprint(incorrectFingerprintMock)).toEqual(correctFingerprintMock);
});
it("should not change correct fingerprint", () => {
expect(sanitizeFingerprint(correctFingerprintMock)).toEqual(correctFingerprintMock);
});
it("should return original fingerprint when fingerprint parse fails", () => {
const incorrectStringToParse = '{a": 1}}';
expect(sanitizeFingerprint(incorrectStringToParse)).toEqual(incorrectStringToParse);
});
});
describe("getMappingHeaderMeasureItemLocalIdentifier", () => {
const getColumnDef = (type: string, drillItems: IMappingHeader[]): IGridHeader => ({
drillItems,
headerName: "Amount",
field: "colId",
colId: "colId",
type,
measureIndex: 0,
index: 1,
});
it("should return undefined if it is not measure column", () => {
const columnDef: IGridHeader = getColumnDef("ROW_ATTRIBUTE_COLUMN", [
{
measureHeaderItem: {
identifier: "1",
uri: "/gdc/md/storybook/obj/1",
localIdentifier: "m1",
format: "#,##0.00",
name: "Amount",
},
},
]);
expect(getMappingHeaderMeasureItemLocalIdentifier(columnDef)).toBeUndefined();
});
it("should return undefined if drillItems missing", () => {
const columnDef: IGridHeader = getColumnDef("MEASURE_COLUMN", []);
expect(getMappingHeaderMeasureItemLocalIdentifier(columnDef)).toBeUndefined();
});
it("should return localIdentifier of first measure", () => {
const columnDef: IGridHeader = getColumnDef("MEASURE_COLUMN", [
{
attributeHeaderItem: {
uri: "/gdc/md/storybook/obj/5/elements?id=3",
name: "high",
},
},
{
measureHeaderItem: {
identifier: "1",
uri: "/gdc/md/storybook/obj/1",
localIdentifier: "m1",
format: "#,##0.00",
name: "Amount",
},
},
{
measureHeaderItem: {
identifier: "2",
uri: "/gdc/md/storybook/obj/2",
localIdentifier: "m2",
format: "#,##0.00",
name: "Big Amount",
},
},
]);
expect(getMappingHeaderMeasureItemLocalIdentifier(columnDef)).toBe("m1");
});
it("should work with column object", () => {
const columnDef: IGridHeader = getColumnDef("MEASURE_COLUMN", [
{
attributeHeaderItem: {
uri: "/gdc/md/storybook/obj/5/elements?id=3",
name: "high",
},
},
{
measureHeaderItem: {
identifier: "1",
uri: "/gdc/md/storybook/obj/1",
localIdentifier: "m1",
format: "#,##0.00",
name: "Amount",
},
},
{
measureHeaderItem: {
identifier: "2",
uri: "/gdc/md/storybook/obj/2",
localIdentifier: "m2",
format: "#,##0.00",
name: "Big Amount",
},
},
]);
const column = getFakeColumn(columnDef);
expect(getMappingHeaderMeasureItemLocalIdentifier(column)).toBe("m1");
});
});