From a5a944c41ed030e94080e48efcc21a64c8266e44 Mon Sep 17 00:00:00 2001
From: Alexander Polyankin <alexander.polyankin@metabase.com>
Date: Mon, 10 Jul 2023 11:35:49 +0300
Subject: [PATCH] Fix embedding plugins init (#32138)

---
 .../EmbeddingAppOriginDescription.tsx         | 31 +++++++
 .../EmbeddingAppOriginDescription/index.ts    |  1 +
 .../metabase-enterprise/embedding/index.js    | 81 +++++++------------
 frontend/src/metabase/admin/routes.jsx        |  4 +-
 .../SettingsEditor/SettingsEditor.jsx}        | 14 ++--
 .../app/components/SettingsEditor/index.ts    |  1 +
 .../SettingsEditor/tests/common.unit.spec.tsx | 25 ++++++
 .../tests/enterprise.unit.spec.tsx            | 32 ++++++++
 .../tests/premium.unit.spec.tsx               | 39 +++++++++
 .../components/SettingsEditor/tests/setup.tsx | 58 +++++++++++++
 .../EmbeddingCustomizationInfo.tsx            | 33 --------
 .../EmbeddingCustomizationInfo/index.ts       |  2 -
 .../EmbeddingCustomizationWidget.tsx          | 21 +++++
 ...mbeddingCustomizationWidget.unit.spec.tsx} |  6 +-
 .../EmbeddingCustomizationWidget/index.ts     |  1 +
 .../FullAppEmbeddingLinkWidget.tsx            | 24 ++----
 .../FullAppEmbeddingLinkWidget.unit.spec.tsx  |  2 +-
 .../FullAppEmbeddingLinkWidget/index.ts       |  3 +-
 .../src/metabase/admin/settings/selectors.js  | 28 ++++---
 frontend/src/metabase/plugins/index.ts        |  4 +
 frontend/test/__support__/enterprise.js       |  7 ++
 21 files changed, 289 insertions(+), 128 deletions(-)
 create mode 100644 enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/EmbeddingAppOriginDescription.tsx
 create mode 100644 enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/index.ts
 rename frontend/src/metabase/admin/settings/{containers/SettingsEditorApp.jsx => app/components/SettingsEditor/SettingsEditor.jsx} (96%)
 create mode 100644 frontend/src/metabase/admin/settings/app/components/SettingsEditor/index.ts
 create mode 100644 frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/common.unit.spec.tsx
 create mode 100644 frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/enterprise.unit.spec.tsx
 create mode 100644 frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/premium.unit.spec.tsx
 create mode 100644 frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/setup.tsx
 delete mode 100644 frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.tsx
 delete mode 100644 frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/index.ts
 create mode 100644 frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.tsx
 rename frontend/src/metabase/admin/settings/components/widgets/{EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.unit.spec.tsx => EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.unit.spec.tsx} (63%)
 create mode 100644 frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/index.ts

diff --git a/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/EmbeddingAppOriginDescription.tsx b/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/EmbeddingAppOriginDescription.tsx
new file mode 100644
index 00000000000..295660bccab
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/EmbeddingAppOriginDescription.tsx
@@ -0,0 +1,31 @@
+import { jt, t } from "ttag";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import MetabaseSettings from "metabase/lib/settings";
+
+export const EmbeddingAppOriginDescription = () => {
+  return (
+    <div>
+      {jt`With this Pro/Enterprise feature you can embed the full Metabase app. Enable your users to drill-through to charts, browse collections, and use the graphical query builder. ${(
+        <ExternalLink
+          key="learn-more"
+          href={MetabaseSettings.learnUrl(
+            "embedding/multi-tenant-self-service-analytics",
+          )}
+        >
+          {t`Learn more.`}
+        </ExternalLink>
+      )}`}
+      <div className="my4">
+        <strong className="block text-dark mb1">{t`Authorized origins`}</strong>
+        {jt`Enter the origins for the websites or web apps where you want to allow embedding, separated by a space. Here are the ${(
+          <ExternalLink
+            key="specs"
+            href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors"
+          >
+            {t`exact specifications`}
+          </ExternalLink>
+        )} for what can be entered.`}
+      </div>
+    </div>
+  );
+};
diff --git a/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/index.ts b/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/index.ts
new file mode 100644
index 00000000000..0c22012cb56
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/embedding/components/EmbeddingAppOriginDescription/index.ts
@@ -0,0 +1 @@
+export { EmbeddingAppOriginDescription } from "./EmbeddingAppOriginDescription";
diff --git a/enterprise/frontend/src/metabase-enterprise/embedding/index.js b/enterprise/frontend/src/metabase-enterprise/embedding/index.js
index bbeae11f569..e97cad21627 100644
--- a/enterprise/frontend/src/metabase-enterprise/embedding/index.js
+++ b/enterprise/frontend/src/metabase-enterprise/embedding/index.js
@@ -1,55 +1,34 @@
-import { jt, t } from "ttag";
-import { updateIn } from "icepick";
-
-import MetabaseSettings from "metabase/lib/settings";
+import { t } from "ttag";
 import { hasPremiumFeature } from "metabase-enterprise/settings";
-import { PLUGIN_ADMIN_SETTINGS_UPDATES } from "metabase/plugins";
-import ExternalLink from "metabase/core/components/ExternalLink";
+import {
+  PLUGIN_ADMIN_SETTINGS_UPDATES,
+  PLUGIN_EMBEDDING,
+} from "metabase/plugins";
+import { EmbeddingAppOriginDescription } from "./components/EmbeddingAppOriginDescription";
 
-if (hasPremiumFeature("embedding")) {
-  MetabaseSettings.hideEmbedBranding = () => true;
-}
+const SLUG = "embedding-in-other-applications/full-app";
 
-const APP_ORIGIN_SETTING = {
-  key: "embedding-app-origin",
-  display_name: t`Embedding the entire Metabase app`,
-  description: (
-    <>
-      {jt`With this Pro/Enterprise feature you can embed the full Metabase app. Enable your users to drill-through to charts, browse collections, and use the graphical query builder. ${(
-        <ExternalLink
-          key="learn-more"
-          href={MetabaseSettings.learnUrl(
-            "embedding/multi-tenant-self-service-analytics",
-          )}
-        >
-          {t`Learn more.`}
-        </ExternalLink>
-      )}`}
-      <div className="my4">
-        <strong className="block text-dark mb1">{t`Authorized origins`}</strong>
-        {jt`Enter the origins for the websites or web apps where you want to allow embedding, separated by a space. Here are the ${(
-          <ExternalLink
-            key="specs"
-            href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors"
-          >
-            {t`exact specifications`}
-          </ExternalLink>
-        )} for what can be entered.`}
-      </div>
-    </>
-  ),
-  placeholder: "https://*.example.com",
-  type: "string",
-  getHidden: settings =>
-    !settings["enable-embedding"] || !MetabaseSettings.isEnterprise(),
-};
+if (hasPremiumFeature("embedding")) {
+  PLUGIN_EMBEDDING.isEnabled = () => true;
 
-PLUGIN_ADMIN_SETTINGS_UPDATES.push(sections =>
-  updateIn(
-    sections,
-    ["embedding-in-other-applications/full-app", "settings"],
-    settings => {
-      return [...settings, APP_ORIGIN_SETTING];
-    },
-  ),
-);
+  PLUGIN_ADMIN_SETTINGS_UPDATES.push(sections => {
+    return {
+      ...sections,
+      [SLUG]: {
+        ...sections[SLUG],
+        settings: [
+          ...sections[SLUG]["settings"],
+          {
+            key: "embedding-app-origin",
+            display_name: t`Embedding the entire Metabase app`,
+            description: <EmbeddingAppOriginDescription />,
+            placeholder: "https://*.example.com",
+            type: "string",
+            getHidden: (_, derivedSettings) =>
+              !derivedSettings["enable-embedding"],
+          },
+        ],
+      },
+    };
+  });
+}
diff --git a/frontend/src/metabase/admin/routes.jsx b/frontend/src/metabase/admin/routes.jsx
index 0e0c592a222..786812520cd 100644
--- a/frontend/src/metabase/admin/routes.jsx
+++ b/frontend/src/metabase/admin/routes.jsx
@@ -27,7 +27,7 @@ import EditUserModal from "metabase/admin/people/containers/EditUserModal";
 import UserActivationModal from "metabase/admin/people/containers/UserActivationModal";
 
 // Settings
-import SettingsEditorApp from "metabase/admin/settings/containers/SettingsEditorApp";
+import { SettingsEditor } from "metabase/admin/settings/app/components/SettingsEditor";
 import PremiumEmbeddingLicensePage from "metabase/admin/settings/containers/PremiumEmbeddingLicensePage";
 
 //  DB Add / list
@@ -174,7 +174,7 @@ const getRoutes = (store, CanAccessSettings, IsAdmin) => (
             path="premium-embedding-license"
             component={PremiumEmbeddingLicensePage}
           />
-          <Route path="*" component={SettingsEditorApp} />
+          <Route path="*" component={SettingsEditor} />
         </Route>
       </Route>
 
diff --git a/frontend/src/metabase/admin/settings/containers/SettingsEditorApp.jsx b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/SettingsEditor.jsx
similarity index 96%
rename from frontend/src/metabase/admin/settings/containers/SettingsEditorApp.jsx
rename to frontend/src/metabase/admin/settings/app/components/SettingsEditor/SettingsEditor.jsx
index 8776d345c13..54c45d29457 100644
--- a/frontend/src/metabase/admin/settings/containers/SettingsEditorApp.jsx
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/SettingsEditor.jsx
@@ -16,7 +16,7 @@ import { NotFound } from "metabase/containers/ErrorPages";
 
 import { prepareAnalyticsValue } from "metabase/admin/settings/utils";
 import ErrorBoundary from "metabase/ErrorBoundary";
-import SettingsSetting from "../components/SettingsSetting";
+import SettingsSetting from "../../../components/SettingsSetting";
 
 import {
   getSettings,
@@ -26,8 +26,12 @@ import {
   getActiveSection,
   getActiveSectionName,
   getNewVersionAvailable,
-} from "../selectors";
-import { initializeSettings, updateSetting, reloadSettings } from "../settings";
+} from "../../../selectors";
+import {
+  initializeSettings,
+  updateSetting,
+  reloadSettings,
+} from "../../../settings";
 
 const mapStateToProps = (state, props) => {
   return {
@@ -53,7 +57,7 @@ const mapDispatchToProps = dispatch => ({
   dispatch,
 });
 
-class SettingsEditorApp extends Component {
+class SettingsEditor extends Component {
   layout = null; // the reference to AdminLayout
 
   static propTypes = {
@@ -272,4 +276,4 @@ class SettingsEditorApp extends Component {
 export default _.compose(
   connect(mapStateToProps, mapDispatchToProps),
   title(({ activeSection }) => activeSection && activeSection.name),
-)(SettingsEditorApp);
+)(SettingsEditor);
diff --git a/frontend/src/metabase/admin/settings/app/components/SettingsEditor/index.ts b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/index.ts
new file mode 100644
index 00000000000..dd18d9993ef
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/index.ts
@@ -0,0 +1 @@
+export { default as SettingsEditor } from "./SettingsEditor";
diff --git a/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/common.unit.spec.tsx b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/common.unit.spec.tsx
new file mode 100644
index 00000000000..dadf102edfe
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/common.unit.spec.tsx
@@ -0,0 +1,25 @@
+import {
+  createMockSettingDefinition,
+  createMockSettings,
+} from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+const FULL_APP_EMBEDDING_URL =
+  "/admin/settings/embedding-in-other-applications/full-app";
+
+describe("SettingsEditor", () => {
+  describe("full-app embedding", () => {
+    it("should show info about full app embedding", async () => {
+      setup({
+        settings: [createMockSettingDefinition({ key: "enable-embedding" })],
+        settingValues: createMockSettings({ "enable-embedding": true }),
+        initialRoute: FULL_APP_EMBEDDING_URL,
+      });
+
+      expect(await screen.findByText("Full-app embedding")).toBeInTheDocument();
+      expect(screen.getByText(/some of our paid plans/)).toBeInTheDocument();
+      expect(screen.queryByText("Authorized origins")).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/enterprise.unit.spec.tsx b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/enterprise.unit.spec.tsx
new file mode 100644
index 00000000000..96c15561d6d
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/enterprise.unit.spec.tsx
@@ -0,0 +1,32 @@
+import {
+  createMockSettingDefinition,
+  createMockSettings,
+} from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup, SetupOpts } from "./setup";
+
+const setupEnterprise = (opts?: SetupOpts) => {
+  setup({ ...opts, hasEnterprisePlugins: true });
+};
+
+const FULL_APP_EMBEDDING_URL =
+  "/admin/settings/embedding-in-other-applications/full-app";
+
+describe("SettingsEditor", () => {
+  describe("full-app embedding", () => {
+    it("should show info about full app embedding", async () => {
+      setupEnterprise({
+        settings: [
+          createMockSettingDefinition({ key: "enable-embedding" }),
+          createMockSettingDefinition({ key: "embedding-app-origin" }),
+        ],
+        settingValues: createMockSettings({ "enable-embedding": true }),
+        initialRoute: FULL_APP_EMBEDDING_URL,
+      });
+
+      expect(await screen.findByText("Full-app embedding")).toBeInTheDocument();
+      expect(screen.getByText(/some of our paid plans/)).toBeInTheDocument();
+      expect(screen.queryByText("Authorized origins")).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/premium.unit.spec.tsx b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/premium.unit.spec.tsx
new file mode 100644
index 00000000000..e6344fd6534
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/premium.unit.spec.tsx
@@ -0,0 +1,39 @@
+import {
+  createMockSettingDefinition,
+  createMockSettings,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup, SetupOpts } from "./setup";
+
+const setupPremium = (opts?: SetupOpts) => {
+  setup({
+    ...opts,
+    tokenFeatures: createMockTokenFeatures({ embedding: true }),
+    hasEnterprisePlugins: true,
+  });
+};
+
+const FULL_APP_EMBEDDING_URL =
+  "/admin/settings/embedding-in-other-applications/full-app";
+
+describe("SettingsEditor", () => {
+  describe("full-app embedding", () => {
+    it("should allow to configure the origin for full-app embedding", async () => {
+      setupPremium({
+        settings: [
+          createMockSettingDefinition({ key: "enable-embedding" }),
+          createMockSettingDefinition({ key: "embedding-app-origin" }),
+        ],
+        settingValues: createMockSettings({ "enable-embedding": true }),
+        initialRoute: FULL_APP_EMBEDDING_URL,
+      });
+
+      expect(await screen.findByText("Full-app embedding")).toBeInTheDocument();
+      expect(screen.getByText("Authorized origins")).toBeInTheDocument();
+      expect(
+        screen.queryByText(/some of our paid plans/),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/setup.tsx b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/setup.tsx
new file mode 100644
index 00000000000..0f5bb85a42f
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/app/components/SettingsEditor/tests/setup.tsx
@@ -0,0 +1,58 @@
+/* istanbul ignore file */
+import { IndexRedirect, Route } from "react-router";
+import { SettingDefinition, Settings, TokenFeatures } from "metabase-types/api";
+import {
+  createMockSettings,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import {
+  setupPropertiesEndpoints,
+  setupSettingsEndpoints,
+} from "__support__/server-mocks";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import SettingsEditor from "../SettingsEditor";
+
+export interface SetupOpts {
+  initialRoute?: string;
+  settings?: SettingDefinition[];
+  settingValues?: Settings;
+  tokenFeatures?: TokenFeatures;
+  hasEnterprisePlugins?: boolean;
+}
+
+export const setup = ({
+  initialRoute = "/admin/settings",
+  settings = [],
+  settingValues = createMockSettings(),
+  tokenFeatures = createMockTokenFeatures(),
+  hasEnterprisePlugins = false,
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      ...settingValues,
+      "token-features": tokenFeatures,
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  setupSettingsEndpoints(settings);
+  setupPropertiesEndpoints(settingValues);
+
+  renderWithProviders(
+    <Route path="/admin/settings">
+      <IndexRedirect to="general" />
+      <Route path="*" component={SettingsEditor} />
+    </Route>,
+    {
+      storeInitialState: state,
+      withRouter: true,
+      initialRoute,
+    },
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.tsx b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.tsx
deleted file mode 100644
index 863ffbae168..00000000000
--- a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { connect } from "react-redux";
-import { t, jt } from "ttag";
-import ExternalLink from "metabase/core/components/ExternalLink";
-import { getUpgradeUrl } from "metabase/selectors/settings";
-import { State } from "metabase-types/store";
-import SettingHeader from "../../SettingHeader";
-
-interface StateProps {
-  upgradeUrl: string;
-}
-
-type EmbeddingCustomizationInfoProps = StateProps;
-
-const mapStateToProps = (state: State): StateProps => ({
-  upgradeUrl: getUpgradeUrl(state, { utm_media: "embed_standalone" }),
-});
-
-const EmbeddingCustomizationInfo = ({
-  upgradeUrl,
-}: EmbeddingCustomizationInfoProps) => {
-  const setting = {
-    description: jt`In order to remove the Metabase logo from embeds, you can always upgrade to ${(
-      <ExternalLink key="upgrade-link" href={upgradeUrl}>
-        {t`one of our paid plans.`}
-      </ExternalLink>
-    )}`,
-  };
-
-  return <SettingHeader id="embedding-customization-info" setting={setting} />;
-};
-
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export default connect(mapStateToProps)(EmbeddingCustomizationInfo);
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/index.ts b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/index.ts
deleted file mode 100644
index 60d840d1189..00000000000
--- a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export { default } from "./EmbeddingCustomizationInfo";
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.tsx b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.tsx
new file mode 100644
index 00000000000..e074f92b82f
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.tsx
@@ -0,0 +1,21 @@
+import { jt, t } from "ttag";
+import { useSelector } from "metabase/lib/redux";
+import { getUpgradeUrl } from "metabase/selectors/settings";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import SettingHeader from "../../SettingHeader";
+
+export const EmbeddingCustomizationWidget = () => {
+  const upgradeUrl = useSelector(state =>
+    getUpgradeUrl(state, { utm_media: "embed_standalone" }),
+  );
+
+  const setting = {
+    description: jt`In order to remove the Metabase logo from embeds, you can always upgrade to ${(
+      <ExternalLink key="upgrade-link" href={upgradeUrl}>
+        {t`one of our paid plans.`}
+      </ExternalLink>
+    )}`,
+  };
+
+  return <SettingHeader id="embedding-customization-info" setting={setting} />;
+};
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.unit.spec.tsx b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.unit.spec.tsx
similarity index 63%
rename from frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.unit.spec.tsx
rename to frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.unit.spec.tsx
index c0fde1dcfdb..18be5a9e76d 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo/EmbeddingCustomizationInfo.unit.spec.tsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/EmbeddingCustomizationWidget.unit.spec.tsx
@@ -1,11 +1,11 @@
 import { renderWithProviders, screen } from "__support__/ui";
-import EmbeddingCustomizationInfo from "./EmbeddingCustomizationInfo";
+import { EmbeddingCustomizationWidget } from "./EmbeddingCustomizationWidget";
 
 const setup = () => {
-  renderWithProviders(<EmbeddingCustomizationInfo />);
+  renderWithProviders(<EmbeddingCustomizationWidget />);
 };
 
-describe("EmbeddingCustomizationInfo", () => {
+describe("EmbeddingCustomizationWidget", () => {
   it("should add utm_media to the upgrade link", () => {
     setup();
 
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/index.ts b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/index.ts
new file mode 100644
index 00000000000..7b60db353b6
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationWidget/index.ts
@@ -0,0 +1 @@
+export { EmbeddingCustomizationWidget } from "./EmbeddingCustomizationWidget";
diff --git a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.tsx b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.tsx
index 13435825fe8..75b72dddafe 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.tsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.tsx
@@ -1,23 +1,14 @@
-import { connect } from "react-redux";
 import { jt, t } from "ttag";
-import ExternalLink from "metabase/core/components/ExternalLink";
+import { useSelector } from "metabase/lib/redux";
 import { getUpgradeUrl } from "metabase/selectors/settings";
-import { State } from "metabase-types/store";
+import ExternalLink from "metabase/core/components/ExternalLink";
 import SettingHeader from "../../SettingHeader";
 
-interface StateProps {
-  upgradeUrl: string;
-}
-
-type FullAppEmbeddingLinkWidgetProps = StateProps;
+export const FullAppEmbeddingLinkWidget = () => {
+  const upgradeUrl = useSelector(state =>
+    getUpgradeUrl(state, { utm_media: "embed_fullapp" }),
+  );
 
-const mapStateToProps = (state: State): StateProps => ({
-  upgradeUrl: getUpgradeUrl(state, { utm_media: "embed_fullapp" }),
-});
-
-const FullAppEmbeddingLinkWidget = ({
-  upgradeUrl,
-}: FullAppEmbeddingLinkWidgetProps) => {
   const setting = {
     display_name: t`embedding the entire metabase app`,
     description: jt`With ${(
@@ -29,6 +20,3 @@ const FullAppEmbeddingLinkWidget = ({
 
   return <SettingHeader id="embedding-customization-info" setting={setting} />;
 };
-
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export default connect(mapStateToProps)(FullAppEmbeddingLinkWidget);
diff --git a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.unit.spec.tsx b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.unit.spec.tsx
index 998f8a2bf8f..3ba7216a97b 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.unit.spec.tsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/FullAppEmbeddingLinkWidget.unit.spec.tsx
@@ -1,5 +1,5 @@
 import { renderWithProviders, screen } from "__support__/ui";
-import FullAppEmbeddingLinkWidget from "./FullAppEmbeddingLinkWidget";
+import { FullAppEmbeddingLinkWidget } from "./FullAppEmbeddingLinkWidget";
 
 const setup = () => {
   renderWithProviders(<FullAppEmbeddingLinkWidget />);
diff --git a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/index.ts b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/index.ts
index 75e642ed5cc..e00852d69bd 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/index.ts
+++ b/frontend/src/metabase/admin/settings/components/widgets/FullAppEmbeddingLinkWidget/index.ts
@@ -1,2 +1 @@
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export { default } from "./FullAppEmbeddingLinkWidget";
+export { FullAppEmbeddingLinkWidget } from "./FullAppEmbeddingLinkWidget";
diff --git a/frontend/src/metabase/admin/settings/selectors.js b/frontend/src/metabase/admin/settings/selectors.js
index f924278a212..e8a6f670e38 100644
--- a/frontend/src/metabase/admin/settings/selectors.js
+++ b/frontend/src/metabase/admin/settings/selectors.js
@@ -5,7 +5,10 @@ import ExternalLink from "metabase/core/components/ExternalLink";
 
 import MetabaseSettings from "metabase/lib/settings";
 import { PersistedModelsApi, UtilApi } from "metabase/services";
-import { PLUGIN_ADMIN_SETTINGS_UPDATES } from "metabase/plugins";
+import {
+  PLUGIN_ADMIN_SETTINGS_UPDATES,
+  PLUGIN_EMBEDDING,
+} from "metabase/plugins";
 import { getUserIsAdmin } from "metabase/selectors/user";
 import Breadcrumbs from "metabase/components/Breadcrumbs";
 import { DashboardSelector } from "metabase/components/DashboardSelector";
@@ -18,7 +21,7 @@ import { UploadSettings } from "./components/UploadSettings";
 import SettingsLicense from "./components/SettingsLicense";
 import SiteUrlWidget from "./components/widgets/SiteUrlWidget";
 import HttpsOnlyWidget from "./components/widgets/HttpsOnlyWidget";
-import EmbeddingCustomizationInfo from "./components/widgets/EmbeddingCustomizationInfo";
+import { EmbeddingCustomizationWidget } from "./components/widgets/EmbeddingCustomizationWidget";
 import {
   PublicLinksDashboardListing,
   PublicLinksQuestionListing,
@@ -29,7 +32,7 @@ import {
 import SecretKeyWidget from "./components/widgets/SecretKeyWidget";
 import EmbeddingLegalese from "./components/widgets/EmbeddingLegalese";
 import FormattingWidget from "./components/widgets/FormattingWidget";
-import FullAppEmbeddingLinkWidget from "./components/widgets/FullAppEmbeddingLinkWidget";
+import { FullAppEmbeddingLinkWidget } from "./components/widgets/FullAppEmbeddingLinkWidget";
 import ModelCachingScheduleWidget from "./components/widgets/ModelCachingScheduleWidget";
 import SectionDivider from "./components/widgets/SectionDivider";
 
@@ -67,7 +70,7 @@ function updateSectionsWithPlugins(sections) {
   }
 }
 
-const SECTIONS = updateSectionsWithPlugins({
+const SECTIONS = {
   setup: {
     name: t`Setup`,
     order: 10,
@@ -521,10 +524,9 @@ const SECTIONS = updateSectionsWithPlugins({
         getHidden: (_, derivedSettings) => !derivedSettings["enable-embedding"],
       },
       {
-        widget: EmbeddingCustomizationInfo,
+        widget: EmbeddingCustomizationWidget,
         getHidden: (_, derivedSettings) =>
-          !derivedSettings["enable-embedding"] ||
-          MetabaseSettings.isEnterprise(),
+          !derivedSettings["enable-embedding"] || PLUGIN_EMBEDDING.isEnabled(),
       },
       {
         widget: () => (
@@ -555,8 +557,7 @@ const SECTIONS = updateSectionsWithPlugins({
       {
         widget: FullAppEmbeddingLinkWidget,
         getHidden: (_, derivedSettings) =>
-          !derivedSettings["enable-embedding"] ||
-          MetabaseSettings.isEnterprise(),
+          !derivedSettings["enable-embedding"] || PLUGIN_EMBEDDING.isEnabled(),
       },
       {
         widget: () => (
@@ -702,7 +703,11 @@ const SECTIONS = updateSectionsWithPlugins({
       },
     ],
   },
-});
+};
+
+const getSectionsWithPlugins = _.once(() =>
+  updateSectionsWithPlugins(SECTIONS),
+);
 
 export const getSettings = createSelector(
   state => state.admin.settings.settings,
@@ -741,9 +746,10 @@ export const getSections = createSelector(
       return {};
     }
 
+    const sections = getSectionsWithPlugins();
     const settingsByKey = _.groupBy(settings, "key");
     const sectionsWithAPISettings = {};
-    for (const [slug, section] of Object.entries(SECTIONS)) {
+    for (const [slug, section] of Object.entries(sections)) {
       const isHidden = section.getHidden?.(derivedSettingValues);
 
       if (isHidden || (section.adminOnly && !isAdmin)) {
diff --git a/frontend/src/metabase/plugins/index.ts b/frontend/src/metabase/plugins/index.ts
index 60c8a96dc2c..2f47681eb44 100644
--- a/frontend/src/metabase/plugins/index.ts
+++ b/frontend/src/metabase/plugins/index.ts
@@ -281,3 +281,7 @@ export const PLUGIN_MODEL_PERSISTENCE = {
   ModelCacheControl: PluginPlaceholder as any,
   getMenuItems: (question?: any, onChange?: any) => ({}),
 };
+
+export const PLUGIN_EMBEDDING = {
+  isEnabled: () => false,
+};
diff --git a/frontend/test/__support__/enterprise.js b/frontend/test/__support__/enterprise.js
index e28e6514798..7b6082b0f4b 100644
--- a/frontend/test/__support__/enterprise.js
+++ b/frontend/test/__support__/enterprise.js
@@ -1,7 +1,14 @@
+/**
+ * @deprecated use setupEnterprisePlugins with settings set via mockSettings
+ */
 export function setupEnterpriseTest() {
   jest.mock("metabase-enterprise/settings", () => ({
     hasPremiumFeature: jest.fn().mockReturnValue(true),
   }));
 
+  setupEnterprisePlugins();
+}
+
+export function setupEnterprisePlugins() {
   require("metabase-enterprise/plugins");
 }
-- 
GitLab