From 0fdefcf6a2a2c7abbb5f1fa81bebd5cd45c94d8d Mon Sep 17 00:00:00 2001
From: "metabase-bot[bot]"
 <109303359+metabase-bot[bot]@users.noreply.github.com>
Date: Wed, 10 Apr 2024 09:10:51 +0000
Subject: [PATCH] Restore tabs display for embedded dashboard without title
 (#41204) (#41238)

* Restore tabs display for embedded dashboard without title

* Add unit test

* Remove empty file

---------

Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
Co-authored-by: Mahatthana Nomsawadi <mahatthana.n@gmail.com>
---
 .../components/EmbedFrame/EmbedFrame.tsx      |  2 +-
 .../{ => PublicDashboard}/PublicDashboard.jsx |  8 +--
 .../PublicDashboard.styled.tsx                |  0
 .../PublicDashboard.unit.spec.tsx             | 57 +++++++++++++++++++
 .../containers/PublicDashboard/index.ts       |  1 +
 frontend/src/metabase/routes-embed.jsx        |  2 +-
 frontend/src/metabase/routes-public.jsx       |  2 +-
 frontend/src/metabase/routes.jsx              |  2 +-
 .../test/__support__/server-mocks/embed.ts    | 10 ++++
 9 files changed, 76 insertions(+), 8 deletions(-)
 rename frontend/src/metabase/public/containers/{ => PublicDashboard}/PublicDashboard.jsx (97%)
 rename frontend/src/metabase/public/containers/{ => PublicDashboard}/PublicDashboard.styled.tsx (100%)
 create mode 100644 frontend/src/metabase/public/containers/PublicDashboard/PublicDashboard.unit.spec.tsx
 create mode 100644 frontend/src/metabase/public/containers/PublicDashboard/index.ts
 create mode 100644 frontend/test/__support__/server-mocks/embed.ts

diff --git a/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx b/frontend/src/metabase/public/components/EmbedFrame/EmbedFrame.tsx
index d10b79a5dc8..abc00ea283d 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 6c6383f9aff..be74b15611b 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 00000000000..fc53c3c64ec
--- /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(
+    <Route path="embed/dashboard/:token" component={PublicDashboard} />,
+    {
+      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 00000000000..2272b942a45
--- /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 a686e38ab68..1098e3cf0dc 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 29ec4bb88df..d6cf1ee0582 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 93c8c4f37b6..33451470083 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 00000000000..87923276a3d
--- /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);
+}
-- 
GitLab