diff --git a/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx b/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx index d10b79a5dc848..abc00ea283d32 100644 --- a/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx +++ b/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx @@ -164,7 +164,7 @@ function EmbedFrame({ : []; const hasVisibleParameters = visibleParameters.length > 0; - const hasHeader = Boolean(finalName || hasParameters); + const hasHeader = Boolean(finalName || dashboardTabs); const isParameterPanelSticky = !!dashboard && theme !== "transparent" && // https://github.com/metabase/metabase/pull/38766#discussion_r1491549200 diff --git a/frontend/src/metabase/public/containers/PublicDashboard.jsx b/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.jsx similarity index 97% rename from frontend/src/metabase/public/containers/PublicDashboard.jsx rename to frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.jsx index 6c6383f9affd0..be74b15611b24 100644 --- a/frontend/src/metabase/public/containers/PublicDashboard.jsx +++ b/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.jsx @@ -32,7 +32,7 @@ import { } from "metabase/services"; import { PublicMode } from "metabase/visualizations/click-actions/modes/PublicMode"; -import EmbedFrame from "../components/EmbedFrame"; +import EmbedFrame from "../../components/EmbedFrame"; import { DashboardContainer } from "./PublicDashboard.styled"; @@ -57,7 +57,7 @@ const mapDispatchToProps = { onChangeLocation: push, }; -class PublicDashboard extends Component { +class PublicDashboardInner extends Component { _initialize = async () => { const { initialize, @@ -206,8 +206,8 @@ class PublicDashboard extends Component { } } -export default _.compose( +export const PublicDashboard = _.compose( connect(mapStateToProps, mapDispatchToProps), title(({ dashboard }) => dashboard && dashboard.name), DashboardControls, -)(PublicDashboard); +)(PublicDashboardInner); diff --git a/frontend/src/metabase/public/containers/PublicDashboard.styled.tsx b/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.styled.tsx similarity index 100% rename from frontend/src/metabase/public/containers/PublicDashboard.styled.tsx rename to frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.styled.tsx diff --git a/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.unit.spec.tsx b/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.unit.spec.tsx new file mode 100644 index 0000000000000..fc53c3c64ecbf --- /dev/null +++ b/frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.unit.spec.tsx @@ -0,0 +1,57 @@ +import { Route } from "react-router"; + +import { setupEmbedDashboardEndpoints } from "__support__/server-mocks/embed"; +import { renderWithProviders, screen } from "__support__/ui"; +import { + createMockDashboard, + createMockDashboardTab, +} from "metabase-types/api/mocks"; +import { createMockState } from "metabase-types/store/mocks"; + +import { PublicDashboard } from "./PublicDashboard"; + +const MOCK_TOKEN = + "eyJhbGciOiJIUzI1NiJ9.eyJyZXNvdXJjZSI6eyJkYXNoYm9hcmQiOjExfSwicGFyYW1zIjp7fSwiaWF0IjoxNzEyNjg0NTA1LCJfZW1iZWRkaW5nX3BhcmFtcyI6e319.WbZTB-cQYh4gjh61ZzoLOcFbJ6j6RlOY3GS4fwzv3W4"; +const DASHBOARD_TITLE = '"My test dash"'; + +const DASHBOARD_WITH_TABS = createMockDashboard({ + id: 1, + name: DASHBOARD_TITLE, + parameters: [], + dashcards: [], + tabs: [ + createMockDashboardTab({ id: 1, name: "Tab 1" }), + createMockDashboardTab({ id: 2, name: "Tab 2" }), + ], +}); + +describe("PublicDashboard", () => { + it("should display dashboard tabs", async () => { + await setup(); + + expect(screen.getByText("Tab 1")).toBeInTheDocument(); + expect(screen.getByText("Tab 2")).toBeInTheDocument(); + }); + + it("should display dashboard tabs if title is disabled (metabase#41195)", async () => { + await setup({ hash: "titled=false" }); + + expect(screen.getByText("Tab 1")).toBeInTheDocument(); + expect(screen.getByText("Tab 2")).toBeInTheDocument(); + }); +}); + +async function setup({ hash }: { hash?: string } = {}) { + setupEmbedDashboardEndpoints(MOCK_TOKEN, DASHBOARD_WITH_TABS); + + renderWithProviders( + , + { + storeInitialState: createMockState(), + withRouter: true, + initialRoute: `embed/dashboard/${MOCK_TOKEN}${hash ? "#" + hash : ""}`, + }, + ); + + expect(await screen.findByTestId("dashboard-grid")).toBeInTheDocument(); +} diff --git a/frontend/src/metabase/public/containers/PublicDashboard/index.ts b/frontend/src/metabase/public/containers/PublicDashboard/index.ts new file mode 100644 index 0000000000000..2272b942a4572 --- /dev/null +++ b/frontend/src/metabase/public/containers/PublicDashboard/index.ts @@ -0,0 +1 @@ +export { PublicDashboard } from "./PublicDashboard"; diff --git a/frontend/src/metabase/routes-embed.jsx b/frontend/src/metabase/routes-embed.jsx index a686e38ab684a..1098e3cf0dc76 100644 --- a/frontend/src/metabase/routes-embed.jsx +++ b/frontend/src/metabase/routes-embed.jsx @@ -2,7 +2,7 @@ import { Route } from "react-router"; import PublicNotFound from "metabase/public/components/PublicNotFound"; import PublicApp from "metabase/public/containers/PublicApp"; -import PublicDashboard from "metabase/public/containers/PublicDashboard"; +import { PublicDashboard } from "metabase/public/containers/PublicDashboard"; import { PublicQuestion } from "metabase/public/containers/PublicQuestion"; export const getRoutes = store => ( diff --git a/frontend/src/metabase/routes-public.jsx b/frontend/src/metabase/routes-public.jsx index 29ec4bb88dfee..d6cf1ee0582d2 100644 --- a/frontend/src/metabase/routes-public.jsx +++ b/frontend/src/metabase/routes-public.jsx @@ -2,7 +2,7 @@ import { Route } from "metabase/hoc/Title"; import PublicNotFound from "metabase/public/components/PublicNotFound"; import PublicAction from "metabase/public/containers/PublicAction"; import PublicApp from "metabase/public/containers/PublicApp"; -import PublicDashboard from "metabase/public/containers/PublicDashboard"; +import { PublicDashboard } from "metabase/public/containers/PublicDashboard"; import { PublicQuestion } from "metabase/public/containers/PublicQuestion"; import { getApplicationName } from "./selectors/whitelabel"; diff --git a/frontend/src/metabase/routes.jsx b/frontend/src/metabase/routes.jsx index 93c8c4f37b67b..33451470083dd 100644 --- a/frontend/src/metabase/routes.jsx +++ b/frontend/src/metabase/routes.jsx @@ -35,7 +35,7 @@ import ModelMetabotApp from "metabase/metabot/containers/ModelMetabotApp"; import NewModelOptions from "metabase/models/containers/NewModelOptions"; import { getRoutes as getModelRoutes } from "metabase/models/routes"; import { PLUGIN_LANDING_PAGE } from "metabase/plugins"; -import PublicDashboard from "metabase/public/containers/PublicDashboard"; +import { PublicDashboard } from "metabase/public/containers/PublicDashboard"; import { PublicQuestion } from "metabase/public/containers/PublicQuestion"; import QueryBuilder from "metabase/query_builder/containers/QueryBuilder"; import { loadCurrentUser } from "metabase/redux/user"; diff --git a/frontend/test/__support__/server-mocks/embed.ts b/frontend/test/__support__/server-mocks/embed.ts new file mode 100644 index 0000000000000..87923276a3dfc --- /dev/null +++ b/frontend/test/__support__/server-mocks/embed.ts @@ -0,0 +1,10 @@ +import fetchMock from "fetch-mock"; + +import type { Dashboard } from "metabase-types/api"; + +export function setupEmbedDashboardEndpoints( + uuid: string, + dashboard: Dashboard, +) { + fetchMock.get(`path:/api/embed/dashboard/${uuid}`, dashboard); +}