Skip to content
Snippets Groups Projects
Unverified Commit fff6e35c authored by Alexander Polyankin's avatar Alexander Polyankin Committed by GitHub
Browse files

Show an error message when the temporal unit is not applicable to a dashboard card (#46983)

* Fix tests

* Add tests

* Add tests

* Fix types

* Fix types
parent 07c1e254
No related branches found
No related tags found
No related merge requests found
......@@ -187,6 +187,22 @@ const nativeUnitQuestionDetails = {
},
};
const nativeTimeQuestionDetails = {
name: "SQL time",
display: "table",
native: {
query: "SELECT CAST('10:00' AS TIME) AS TIME",
},
};
const getNativeTimeQuestionBasedQuestionDetails = card => ({
query: {
"source-table": `card__${card.id}`,
aggregation: [["count"]],
breakout: [["field", "TIME", { "base-type": "type/Time" }]],
},
});
const parameterDetails = {
id: "1",
name: "Unit of Time",
......@@ -857,6 +873,34 @@ describe("scenarios > dashboard > temporal unit parameters", () => {
resetFilterWidgetToDefault();
getDashboardCard().findByText("Created At: Year").should("be.visible");
});
it("should show an error message when an incompatible temporal unit is used", () => {
cy.log("setup dashboard with a time column");
createNativeQuestion(nativeTimeQuestionDetails).then(({ body: card }) => {
cy.createDashboardWithQuestions({
questions: [getNativeTimeQuestionBasedQuestionDetails(card)],
}).then(({ dashboard }) => {
visitDashboard(dashboard.id);
});
});
editDashboard();
addTemporalUnitParameter();
selectDashboardFilter(getDashboardCard(), "TIME");
saveDashboard();
cy.log("use an invalid temporal unit");
filterWidget().click();
popover().findByText("Year").click();
getDashboardCard().should(
"contain.text",
"This chart can not be broken out by the selected unit of time: year.",
);
cy.log("use an valid temporal unit");
filterWidget().click();
popover().findByText("Minute").click();
getDashboardCard().findByText("TIME: Minute").should("be.visible");
});
});
describe("query string parameters", () => {
......
......@@ -74,11 +74,14 @@ export interface Dataset {
row_count: number;
running_time: number;
json_query?: JsonQuery;
error?:
| string
| {
status: number; // HTTP status code
data?: string;
};
error_type?: string;
error?: {
status: number; // HTTP status code
data?: string;
};
error_is_curated?: boolean;
context?: string;
status?: string;
}
......
import type { Location } from "history";
import _ from "underscore";
import { IS_EMBED_PREVIEW } from "metabase/lib/embed";
import { SERVER_ERROR_TYPES } from "metabase/lib/errors";
import { isJWT } from "metabase/lib/utils";
import { isUuid } from "metabase/lib/uuid";
......@@ -207,7 +206,7 @@ export function getDashcardResultsError(datasets: Dataset[]) {
const isAccessRestricted = datasets.some(
s =>
s.error_type === SERVER_ERROR_TYPES.missingPermissions ||
s.error?.status === 403,
(typeof s.error === "object" && s.error?.status === 403),
);
if (isAccessRestricted) {
......@@ -217,14 +216,16 @@ export function getDashcardResultsError(datasets: Dataset[]) {
};
}
const errors = datasets.map(s => s.error).filter(Boolean);
if (errors.length > 0) {
if (IS_EMBED_PREVIEW) {
const message = errors[0]?.data || getGenericErrorMessage();
return { message, icon: "warning" as const };
}
if (datasets.some(dataset => dataset.error)) {
const curatedErrorDataset = datasets.find(
dataset => dataset.error && dataset.error_is_curated,
);
return {
message: getGenericErrorMessage(),
message:
typeof curatedErrorDataset?.error === "string"
? curatedErrorDataset.error
: getGenericErrorMessage(),
icon: "warning" as const,
};
}
......
......@@ -213,11 +213,49 @@ describe("Dashboard utils", () => {
expect(error).toStrictEqual(expectedGenericError);
});
it("should return a curated error in case it is set in the response", () => {
const error = getDashcardResultsError([
createMockDataset({}),
createMockDataset({
error: "Wrong query",
error_is_curated: true,
}),
]);
expect(error).toEqual({
icon: "warning",
message: "Wrong query",
});
});
it("should return a generic error in case the error is curated but is not a string", () => {
const error = getDashcardResultsError([
createMockDataset({}),
createMockDataset({
error: { status: 500 },
error_is_curated: true,
}),
]);
expect(error).toEqual(expectedGenericError);
});
it("should not return any errors if there are no any errors", () => {
const error = getDashcardResultsError([createMockDataset({})]);
expect(error).toBeUndefined();
});
it("should not return any errors if the error is curated but there is no error message or object set", () => {
const error = getDashcardResultsError([
createMockDataset({
error: undefined,
error_is_curated: true,
}),
]);
expect(error).toBeUndefined();
});
});
describe("getVisibleCardIds", () => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment