@gooddata/react-components
Version:
GoodData.UI - A powerful JavaScript library for building analytical applications
269 lines (230 loc) • 9.1 kB
text/typescript
// (C) 2007-2019 GoodData Corporation
import * as HttpStatusCodes from "http-status-codes";
import {
convertErrors,
generateErrorMap,
hasDuplicateIdentifiers,
isEmptyResult,
checkEmptyResult,
} from "../errorHandlers";
import { ApiResponseError } from "@gooddata/gooddata-js";
import "isomorphic-fetch";
import {
emptyResponse,
emptyResponseWithNull,
attributeOnlyResponse,
} from "../../execution/fixtures/ExecuteAfm.fixtures";
import { ErrorCodes, ErrorStates } from "../../constants/errorStates";
import { RuntimeError } from "../../errors/RuntimeError";
import "jest";
import { VisualizationObject } from "@gooddata/typings/dist";
async function createMockedError(status: number, body: string = "{}") {
const response = new Response(body, { status });
// In gooddata-js, the response body is always read before the rejectio with ApiResponseError,
// see https://github.com/gooddata/gooddata-js/blob/c5c985e9070d20ac359b988244b7bb1155661473/src/xhr.ts#L154-L155
const responseBody = await response.text();
return new ApiResponseError("Response error", response, responseBody);
}
async function createTypeError() {
return new TypeError("TypeError message");
}
describe("convertErrors", () => {
it("should return RuntimeError with message when error type is not ApiResponseError", async () => {
const e = convertErrors(await createTypeError());
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual("TypeError message");
});
it("should return `NO_DATA` error", async () => {
const e = convertErrors(await createMockedError(204));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.NO_DATA);
});
it("should return `DATA_TOO_LARGE_TO_COMPUTE` error", async () => {
const e = convertErrors(await createMockedError(HttpStatusCodes.REQUEST_TOO_LONG));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.DATA_TOO_LARGE_TO_COMPUTE);
});
it("should return `BAD_REQUEST` error", async () => {
const e = convertErrors(await createMockedError(HttpStatusCodes.BAD_REQUEST));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.BAD_REQUEST);
});
it("should return `UNAUTHORIZED` error", async () => {
const e = convertErrors(await createMockedError(HttpStatusCodes.UNAUTHORIZED));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.UNAUTHORIZED);
});
it("should return `NOT_FOUND` error", async () => {
const e = convertErrors(await createMockedError(HttpStatusCodes.NOT_FOUND));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.NOT_FOUND);
});
it("should return `PROTECTED_REPORT` error", async () => {
const protectedErrorBody = `{
"error": {
"message": "Attempt to execute protected report unsafely"
}
}`;
const e = convertErrors(await createMockedError(HttpStatusCodes.BAD_REQUEST, protectedErrorBody));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.PROTECTED_REPORT);
});
it("should return `EMPTY_AFM` error", async () => {
const e = convertErrors(await createMockedError(ErrorCodes.EMPTY_AFM));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.EMPTY_AFM);
});
it("should return `INVALID_BUCKETS` error", async () => {
const e = convertErrors(await createMockedError(ErrorCodes.INVALID_BUCKETS));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.INVALID_BUCKETS);
});
it("should return `UNKNOWN_ERROR` error", async () => {
const e = convertErrors(await createMockedError(0));
expect(e).toBeInstanceOf(RuntimeError);
expect(e.message).toEqual(ErrorStates.UNKNOWN_ERROR);
});
});
describe("isEmptyResult", () => {
it("should return true if executionResult does not contain any data", () => {
expect.hasAssertions();
expect(isEmptyResult(emptyResponse)).toBe(true);
});
it("should return true if executionResult is null", () => {
expect.hasAssertions();
expect(isEmptyResult(emptyResponseWithNull)).toBe(true);
});
it("should return false if executionResult does not contain any data, but contain headers", () => {
expect(isEmptyResult(attributeOnlyResponse)).toBe(false);
});
});
describe("checkEmptyResult", () => {
it("should throw 204 if executionResult does not contain any data", () => {
expect.hasAssertions();
try {
checkEmptyResult(emptyResponse);
} catch (obj) {
expect(obj.response.status).toEqual(204);
}
});
it("should throw 204 if executionResult is null", () => {
expect.hasAssertions();
try {
checkEmptyResult(emptyResponseWithNull);
} catch (obj) {
expect(obj.response.status).toEqual(204);
}
});
it("should not throw 204 if executionResult does not contain any data, but contain headers", () => {
expect(() => checkEmptyResult(attributeOnlyResponse)).not.toThrow();
});
it("should forward the response if executionResult is empty", async () => {
expect.hasAssertions();
try {
checkEmptyResult(emptyResponse);
} catch (obj) {
const expected = await obj.response.json();
expect(expected).toEqual(emptyResponse);
}
});
});
describe("generateErrorMap", () => {
it("should generate map", () => {
const intlMock = {
formatMessage: ({ id }: { id: string }) => id,
};
const map = generateErrorMap(intlMock as any);
expect(map).toMatchSnapshot();
});
});
describe("hasDuplicateIdentifiers", () => {
const buckets: VisualizationObject.IBucket[] = [
{
localIdentifier: "measures",
items: [
{
measure: {
localIdentifier: "abc",
definition: {
measureDefinition: {
item: {
identifier: "aaEGaXAEgB7U",
},
},
},
},
},
{
measure: {
localIdentifier: "def",
definition: {
measureDefinition: {
item: {
identifier: "aabHeqImaK0d",
},
},
},
},
},
],
},
{
localIdentifier: "rows",
items: [
{
visualizationAttribute: {
localIdentifier: "ghi",
displayForm: {
identifier: "label.restaurantlocation.locationstate",
},
},
},
{
visualizationAttribute: {
localIdentifier: "jkl",
displayForm: {
identifier: "label.restaurantlocation.locationname",
},
},
},
{
visualizationAttribute: {
localIdentifier: "abc",
displayForm: {
identifier: "label.menuitem.menucategory",
},
},
},
],
},
{
localIdentifier: "columns",
items: [
{
visualizationAttribute: {
localIdentifier: "def",
displayForm: {
identifier: "date.aam81lMifn6q",
},
},
},
{
visualizationAttribute: {
localIdentifier: "xyz",
displayForm: {
identifier: "date.abm81lMifn6q",
},
},
},
],
},
];
it("should return true if there are duplicate identifiers", () => {
const hasDuplicates = hasDuplicateIdentifiers(buckets);
expect(hasDuplicates).toBe(true);
});
it("should return false if there are duplicate identifiers", () => {
const hasDuplicates = hasDuplicateIdentifiers(buckets.slice(1));
expect(hasDuplicates).toBe(false);
});
});