From 976f96bbcbfb1ca52b4b8ea771abc76d15f583ad Mon Sep 17 00:00:00 2001 From: Cal Herries <39073188+calherries@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:15:50 +0300 Subject: [PATCH] Fix corrupted dashboard parameters to have "unnamed" names and slugs (#34311) --- ...ully-deal-with-corrupted-filter.cy.spec.js | 24 ++++++++++++------- src/metabase/models/dashboard.clj | 15 ++++++++++++ test/metabase/models/dashboard_test.clj | 11 +++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/e2e/test/scenarios/dashboard-filters/reproductions/24500-gracefully-deal-with-corrupted-filter.cy.spec.js b/e2e/test/scenarios/dashboard-filters/reproductions/24500-gracefully-deal-with-corrupted-filter.cy.spec.js index 99eb88c6906..d2c4ead1fc2 100644 --- a/e2e/test/scenarios/dashboard-filters/reproductions/24500-gracefully-deal-with-corrupted-filter.cy.spec.js +++ b/e2e/test/scenarios/dashboard-filters/reproductions/24500-gracefully-deal-with-corrupted-filter.cy.spec.js @@ -44,7 +44,7 @@ const questionDetails = { const dashboardDetails = { parameters }; -describe.skip("issues 15279 and 24500", () => { +describe("issues 15279 and 24500", () => { beforeEach(() => { restore(); cy.signInAsAdmin(); @@ -110,17 +110,23 @@ describe.skip("issues 15279 and 24500", () => { // The corrupted filter is now present in the UI, but it doesn't work (as expected) // People can now easily remove it - // eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage - cy.findByText("Select…"); - editDashboard(); - filterWidget().last().find(".Icon-gear").click(); - // Uncomment the next line if we end up disabling fields for the corrupted filter - // cy.findByText("No valid fields") - // eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage - cy.findByText("Remove").click(); + cy.findByTestId("edit-dashboard-parameters-widget-container") + .findByText("unnamed") + .icon("gear") + .click(); + cy.findByRole("button", { name: "Remove" }).click(); saveDashboard(); + // Check the list filter again + filterWidget().contains("List").click(); + cy.wait("@values"); + + // Check that the search filter works + filterWidget().contains("Search").click(); + cy.findByPlaceholderText("Search by Name").type("Lora Cronin"); + cy.button("Add filter").click(); + cy.get(".DashCard") .should("contain", "Lora Cronin") .and("not.contain", "Dagmar Fay"); diff --git a/src/metabase/models/dashboard.clj b/src/metabase/models/dashboard.clj index 05a55426fbd..3c736704248 100644 --- a/src/metabase/models/dashboard.clj +++ b/src/metabase/models/dashboard.clj @@ -127,9 +127,24 @@ [dashboard] (update-dashboard-subscription-pulses! dashboard)) +(defn- migrate-parameters-list + "Update the `:parameters` list of a dashboard from legacy formats." + [dashboard] + (cond-> dashboard + (:parameters dashboard) + (update :parameters (fn [params] + (for [p params] + (cond-> p + ;; It was previously possible for parameters to have empty strings for :name and + ;; :slug, but these are now required to be non-blank strings. + (or (= (:name p) "") + (= (:slug p) "")) + (assoc :name "unnamed" :slug "unnamed"))))))) + (t2/define-after-select :model/Dashboard [dashboard] (-> dashboard + migrate-parameters-list public-settings/remove-public-uuid-if-public-sharing-is-disabled)) (defmethod serdes/hash-fields :model/Dashboard diff --git a/test/metabase/models/dashboard_test.clj b/test/metabase/models/dashboard_test.clj index 478764bfaf8..ba8b9a7d3bd 100644 --- a/test/metabase/models/dashboard_test.clj +++ b/test/metabase/models/dashboard_test.clj @@ -648,6 +648,17 @@ (is (= nil (:public_uuid dashboard)))))))) +(deftest migrate-parameters-list-test + (testing "test that a Dashboard's :parameters is selected with a non-nil name and slug" + (doseq [[name slug] [["" ""] ["" "slug"] ["name" ""]]] + (mt/with-temp [:model/Dashboard dashboard {:parameters [{:id "_CATEGORY_NAME_" + :type "category" + :name name + :slug slug}]}] + (is (=? {:name "unnamed" + :slug "unnamed"} + (first (:parameters dashboard)))))))) + (deftest post-update-test (t2.with-temp/with-temp [Collection {collection-id-1 :id} {} Collection {collection-id-2 :id} {} -- GitLab