Newer
Older
Oisin Coveney
committed
import { within } from "@testing-library/react";
import {
setupAlertsEndpoints,
setupCardEndpoints,
setupCardQueryEndpoints,
setupCardQueryMetadataEndpoint,
Oisin Coveney
committed
setupDatabaseEndpoints,
setupTableEndpoints,
setupUnauthorizedCardEndpoints,
} from "__support__/server-mocks";
import {
Oisin Coveney
committed
renderWithProviders,
screen,
waitForLoaderToBeRemoved,
} from "__support__/ui";
Phoomparin Mano
committed
import { InteractiveQuestionResult } from "embedding-sdk/components/private/InteractiveQuestionResult";
import { createMockAuthProviderUriConfig } from "embedding-sdk/test/mocks/config";
Oisin Coveney
committed
import { setupSdkState } from "embedding-sdk/test/server-mocks/sdk-init";
github-automation-metabase
committed
import type { SdkQuestionTitleProps } from "embedding-sdk/types/question";
Oisin Coveney
committed
import {
createMockCard,
Oisin Coveney
committed
createMockColumn,
createMockDatabase,
createMockDataset,
createMockDatasetData,
createMockTable,
createMockUser,
} from "metabase-types/api/mocks";
import { useInteractiveQuestionContext } from "../../private/InteractiveQuestion/context";
import { InteractiveQuestion } from "./InteractiveQuestion";
Oisin Coveney
committed
const TEST_USER = createMockUser();
const TEST_DB_ID = 1;
const TEST_DB = createMockDatabase({ id: TEST_DB_ID });
const TEST_TABLE_ID = 1;
const TEST_TABLE = createMockTable({ id: TEST_TABLE_ID, db_id: TEST_DB_ID });
const TEST_COLUMN = createMockColumn({
display_name: "Test Column",
name: "Test Column",
});
Phoomparin Mano
committed
Oisin Coveney
committed
const TEST_DATASET = createMockDataset({
data: createMockDatasetData({
cols: [TEST_COLUMN],
rows: [["Test Row"]],
}),
});
Phoomparin Mano
committed
// Provides a button to re-run the query
github-automation-metabase
committed
function InteractiveQuestionCustomLayout({
title,
}: {
title?: SdkQuestionTitleProps;
}) {
Phoomparin Mano
committed
const { resetQuestion } = useInteractiveQuestionContext();
return (
<div>
<button onClick={resetQuestion}>Run Query</button>
github-automation-metabase
committed
<InteractiveQuestionResult title={title} />
Phoomparin Mano
committed
</div>
);
}
Oisin Coveney
committed
const setup = ({
isValidCard = true,
github-automation-metabase
committed
title,
github-automation-metabase
committed
withCustomLayout = false,
withChartTypeSelector = false,
Oisin Coveney
committed
}: {
isValidCard?: boolean;
github-automation-metabase
committed
title?: SdkQuestionTitleProps;
github-automation-metabase
committed
withCustomLayout?: boolean;
withChartTypeSelector?: boolean;
Oisin Coveney
committed
} = {}) => {
const { state } = setupSdkState({
currentUser: TEST_USER,
});
github-automation-metabase
committed
const TEST_CARD = createMockCard({ name: "My Question" });
Oisin Coveney
committed
if (isValidCard) {
setupCardEndpoints(TEST_CARD);
setupCardQueryMetadataEndpoint(
TEST_CARD,
createMockCardQueryMetadata({
databases: [TEST_DB],
}),
);
Oisin Coveney
committed
} else {
setupUnauthorizedCardEndpoints(TEST_CARD);
}
setupAlertsEndpoints(TEST_CARD, []);
setupDatabaseEndpoints(TEST_DB);
setupTableEndpoints(TEST_TABLE);
setupCardQueryEndpoints(TEST_CARD, TEST_DATASET);
Mahatthana (Kelvin) Nomsawadi
committed
return renderWithProviders(
github-automation-metabase
committed
<InteractiveQuestion
questionId={TEST_CARD.id}
github-automation-metabase
committed
title={title}
github-automation-metabase
committed
withChartTypeSelector={withChartTypeSelector}
>
{withCustomLayout ? <InteractiveQuestionCustomLayout /> : undefined}
Phoomparin Mano
committed
</InteractiveQuestion>,
Mahatthana (Kelvin) Nomsawadi
committed
{
mode: "sdk",
sdkProviderProps: {
config: createMockAuthProviderUriConfig({
authProviderUri: "http://TEST_URI/sso/metabase",
Mahatthana (Kelvin) Nomsawadi
committed
storeInitialState: state,
},
);
Oisin Coveney
committed
};
describe("InteractiveQuestion", () => {
it("should initially render with a loader", async () => {
setup();
expect(screen.getByTestId("loading-indicator")).toBeInTheDocument();
Oisin Coveney
committed
});
Phoomparin Mano
committed
it("should render loading state when rerunning the query", async () => {
github-automation-metabase
committed
setup({ withCustomLayout: true });
Mahatthana (Kelvin) Nomsawadi
committed
await waitForLoaderToBeRemoved();
expect(
await within(screen.getByTestId("TableInteractive-root")).findByText(
Mahatthana (Kelvin) Nomsawadi
committed
TEST_COLUMN.display_name,
),
).toBeInTheDocument();
expect(
await within(screen.getByRole("gridcell")).findByText("Test Row"),
Mahatthana (Kelvin) Nomsawadi
committed
).toBeInTheDocument();
expect(screen.queryByTestId("loading-indicator")).not.toBeInTheDocument();
Phoomparin Mano
committed
// Simulate drilling down by re-running the query again
act(() => screen.getByText("Run Query").click());
Mahatthana (Kelvin) Nomsawadi
committed
expect(screen.queryByText("Question not found")).not.toBeInTheDocument();
expect(screen.getByTestId("loading-indicator")).toBeInTheDocument();
Mahatthana (Kelvin) Nomsawadi
committed
expect(
within(await screen.findByRole("gridcell")).getByText("Test Row"),
).toBeInTheDocument();
});
it("should render when question is valid", async () => {
setup();
await waitForLoaderToBeRemoved();
expect(
within(screen.getByTestId("TableInteractive-root")).getByText(
TEST_COLUMN.display_name,
),
).toBeInTheDocument();
expect(
within(screen.getByRole("gridcell")).getByText("Test Row"),
).toBeInTheDocument();
});
Mahatthana (Kelvin) Nomsawadi
committed
it("should not render an error if a question isn't found before the question loaded", async () => {
setup();
await waitForLoaderToBeRemoved();
expect(screen.queryByText("Error")).not.toBeInTheDocument();
expect(screen.queryByText("Question not found")).not.toBeInTheDocument();
});
Oisin Coveney
committed
it("should render an error if a question isn't found", async () => {
setup({ isValidCard: false });
await waitForLoaderToBeRemoved();
expect(screen.getByText("Question not found")).toBeInTheDocument();
});
github-automation-metabase
committed
github-automation-metabase
committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
it.each([
// shows the question title by default
[undefined, "My Question"],
// hides the question title when title={false}
[false, null],
// shows the default question title when title={true}
[true, "My Question"],
// customizes the question title via strings
["Foo Bar", "Foo Bar"],
// customizes the question title via React elements
[<h1 key="foo">Foo Bar</h1>, "Foo Bar"],
// customizes the question title via React components.
[() => <h1>Foo Bar</h1>, "Foo Bar"],
])(
"shows the question title according to the title prop",
async (titleProp, expectedTitle) => {
setup({ title: titleProp });
await waitForLoaderToBeRemoved();
const element = screen.queryByText(expectedTitle ?? "My Question");
expect(element?.textContent ?? null).toBe(expectedTitle);
},
);
github-automation-metabase
committed
it("should show a chart type selector button if withChartTypeSelector is true", async () => {
setup({ withChartTypeSelector: true });
await waitForLoaderToBeRemoved();
expect(
screen.getByTestId("chart-type-selector-button"),
).toBeInTheDocument();
});
it("should not show a chart type selector button if withChartTypeSelector is false", async () => {
setup({ withChartTypeSelector: false });
await waitForLoaderToBeRemoved();
expect(
screen.queryByTestId("chart-type-selector-button"),
).not.toBeInTheDocument();
});