Skip to content
Snippets Groups Projects
Unverified Commit c179c422 authored by Ngoc Khuat's avatar Ngoc Khuat Committed by GitHub
Browse files

Rendering link cards for subscription (#28528)

parent 70281b79
No related merge requests found
......@@ -522,6 +522,7 @@
metabase.api.user-test/with-temp-user-email hooks.common/with-one-binding
metabase.async.streaming-response-test/with-start-execution-chan hooks.common/with-one-binding
metabase.db.schema-migrations-test.impl/test-migrations hooks.metabase.db.schema-migrations-test.impl/test-migrations
metabase.dashboard-subscription-test/with-link-card-fixture-for-dashboard hooks.common/let-second
metabase.models.collection-test/with-collection-hierarchy hooks.common/let-one-with-optional-value
metabase.models.collection-test/with-personal-and-impersonal-collections hooks.common/with-two-bindings
metabase.models.dashboard-test/with-dash-in-collection hooks.common/with-three-bindings
......
......@@ -200,6 +200,36 @@
body))]
{:node node*}))
(defn- let-second-inner [body bindings]
(let [binding-infos (for [[model {[binding value] :children}] (partition 2 bindings)]
{:model model
:binding binding
:value (or value
(hooks/token-node 'nil))})]
(-> (hooks/vector-node
[(hooks/vector-node (map :model binding-infos))
(-> (hooks/list-node (list* (hooks/token-node `let)
(hooks/vector-node (mapcat (juxt :binding :value) binding-infos))
body))
(with-meta (meta body)))])
(with-meta (meta body)))))
(defn let-second
"Helper for macros that have a shape like
(my-macro x [y]
...)
where the let is for second arg.
=>
(let [y nil]
...)"
[{:keys [node]}]
(let [[_ first-arg-ref binding+opts & body] (:children node)]
{:node (let-second-inner body [first-arg-ref binding+opts])}))
(defn let-with-optional-value-for-last-binding
"This is exactly like [[clojure.core/let]] but the right-hand side of the *last* binding, `value`, is optional.
......
......@@ -3,6 +3,10 @@
-----
These paths represent the current canonical icon set for Metabase.
Some of these icons are used in BE to render subscriptions and defined in src/metabase/pulse/render/js_svg.clj
so if you update icons here please make sure you update icons there as well.
*/
export const ICON_PATHS: Record<string, any> = {
add: "M12.4285714,12.4285714 L12.4285714,0 L19.5714286,0 L19.5714286,12.4285714 L32,12.4285714 L32,19.5714286 L19.5714286,19.5714286 L19.5714286,32 L12.4285714,32 L12.4285714,19.5714286 L0,19.5714286 L0,12.4285714 L12.4285714,12.4285714 Z",
......
......@@ -68,6 +68,9 @@
;; :else url
(defn- icon-bundle
"Bundle an icon.
The available icons are defined in [[js-svg/icon-paths]]."
[icon-name]
(let [color (style/primary-color)
png-bytes (js-svg/icon icon-name color)]
......
......@@ -282,18 +282,21 @@
(def ^:private link-card-models
(set (keys serdes.util/link-card-model->toucan-model)))
(defn- link-card-info-query-for-model
[[model ids]]
(defn link-card-info-query-for-model
"Return a honeysql query that is used to fetch info for a linkcard."
[model id-or-ids]
{:select (select-clause-for-link-card-model model)
:from (t2/table-name (serdes.util/link-card-model->toucan-model model))
:where [:in :id ids]})
:where (if (coll? id-or-ids)
[:in :id id-or-ids]
[:= :id id-or-ids])})
(defn- link-card-info-query
[link-card-model->ids]
(if (= 1 (count link-card-model->ids))
(link-card-info-query-for-model (first link-card-model->ids))
(apply link-card-info-query-for-model (first link-card-model->ids))
{:select [:*]
:from [[{:union-all (map link-card-info-query-for-model link-card-model->ids)}
:from [[{:union-all (map #(apply link-card-info-query-for-model %) link-card-model->ids)}
:alias_is_required_by_sql_but_not_needed_here]]}))
(mi/define-batched-hydration-method dashcard-linkcard-info
......@@ -321,8 +324,6 @@
(if (mi/can-read? (t2/instance (serdes.util/link-card-model->toucan-model model) instance))
instance
{:restricted true}))))]
(map (fn [card]
(if-let [model-info (->> (get-in card entity-path)
((juxt :model :id))
......
......@@ -2,16 +2,18 @@
"Public API for sending Pulses."
(:require
[clojure.string :as str]
[metabase.api.common :as api]
[metabase.config :as config]
[metabase.email :as email]
[metabase.email.messages :as messages]
[metabase.integrations.slack :as slack]
[metabase.models.card :refer [Card]]
[metabase.models.dashboard :refer [Dashboard]]
[metabase.models.dashboard-card :refer [DashboardCard]]
[metabase.models.dashboard-card :as dashboard-card :refer [DashboardCard]]
[metabase.models.database :refer [Database]]
[metabase.models.interface :as mi]
[metabase.models.pulse :as pulse :refer [Pulse]]
[metabase.models.serialization.util :as serdes.util]
[metabase.models.setting :as setting :refer [defsetting]]
[metabase.public-settings :as public-settings]
[metabase.pulse.markdown :as markdown]
......@@ -29,7 +31,8 @@
[metabase.util.ui-logic :as ui-logic]
[metabase.util.urls :as urls]
[schema.core :as s]
[toucan.db :as db])
[toucan.db :as db]
[toucan2.core :as t2])
(:import
(clojure.lang ExceptionInfo)))
......@@ -48,12 +51,15 @@
(dissoc parameter :default))))
(defn- execute-dashboard-subscription-card
[owner-id dashboard dashcard card-or-id parameters]
"Returns subscription result for a card.
This function should be executed under pulse's creator permissions."
[dashboard dashcard card-or-id parameters]
(assert api/*current-user-id* "Makes sure you wrapped this with a `with-current-user`.")
(try
(let [card-id (u/the-id card-or-id)
card (db/select-one Card :id card-id)
result (mw.session/with-current-user owner-id
(qp.dashboard/run-query-for-dashcard-async
result (qp.dashboard/run-query-for-dashcard-async
:dashboard-id (u/the-id dashboard)
:card-id card-id
:dashcard-id (u/the-id dashcard)
......@@ -65,7 +71,7 @@
:run (fn [query info]
(qp/process-query-and-save-with-max-results-constraints!
(assoc query :async? false)
info))))]
info)))]
{:card card
:dashcard dashcard
:result result})
......@@ -80,21 +86,65 @@
(compare (:row dashcard-1) (:row dashcard-2))
(compare (:col dashcard-1) (:col dashcard-2))))
(defn- virtual-card-of-type?
"Check if dashcard is a virtual with type `ttype`.
(defn virtual-card-of-type?
"Check if dashcard is a virtual with type `ttype`, if `true` returns the dashcard, else returns `nil`.
There are currently 3 types of virtual card: text, action, link."
There are currently 3 types of virtual card: \"text\", \"action\", \"link\"."
[dashcard ttype]
(and (map? dashcard)
(= ttype (get-in dashcard [:visualization_settings :virtual_card :display]))))
(when (= ttype (get-in dashcard [:visualization_settings :virtual_card :display]))
dashcard))
(defn- link-card-entity->url
[{:keys [db_id id model] :as _entity}]
(case model
"card" (urls/card-url id)
"dataset" (urls/card-url id)
"collection" (urls/collection-url id)
"dashboard" (urls/dashboard-url id)
"database" (urls/database-url id)
"table" (urls/table-url db_id id)))
(defn- link-card->text
[{:keys [entity url] :as _link-card}]
(let [url-link-card? (some? url)]
{:text (str (format
"### [%s](%s)"
(if url-link-card? url (:name entity))
(if url-link-card? url (link-card-entity->url entity)))
(when-let [description (if url-link-card? nil (:description entity))]
(format "\n%s" description)))}))
(defn- dashcard-link-card->content
"Convert a dashcard that is a link card to pulse content.
This function should be executed under pulse's creator permissions."
[dashcard]
(assert api/*current-user-id* "Makes sure you wrapped this with a `with-current-user`.")
(let [link-card (get-in dashcard [:visualization_settings :link])]
(cond
(some? (:url link-card))
(link-card->text link-card)
;; if link card link to an entity, update the setting because
;; the info in viz-settings might be out-of-date
(some? (:entity link-card))
(let [{:keys [model id]} (:entity link-card)
instance (t2/select-one
(serdes.util/link-card-model->toucan-model model)
(dashboard-card/link-card-info-query-for-model model id))]
(when (mi/can-read? instance)
(link-card->text (assoc link-card :entity instance)))))))
(defn- dashcard->content
"Given a dashcard returns its content based on its type."
[dashcard {pulse-creator-id :creator_id, :as pulse} dashboard]
"Given a dashcard returns its content based on its type.
The result will follow the pulse's creator permissions."
[dashcard pulse dashboard]
(assert api/*current-user-id* "Makes sure you wrapped this with a `with-current-user`.")
(cond
(:card_id dashcard)
(let [parameters (merge-default-values (params/parameters pulse dashboard))]
(execute-dashboard-subscription-card pulse-creator-id dashboard dashcard (:card_id dashcard) parameters))
(execute-dashboard-subscription-card dashboard dashcard (:card_id dashcard) parameters))
;; actions
(virtual-card-of-type? dashcard "action")
......@@ -102,7 +152,7 @@
;; link cards
(virtual-card-of-type? dashcard "link")
nil
(dashcard-link-card->content dashcard)
;; text cards has existed for a while and I'm not sure if all existing text cards
;; will have virtual_card.display = "text", so assume everything else is a text card
......@@ -113,15 +163,18 @@
:visualization_settings))))
(defn- execute-dashboard
"Fetch all the dashcards in a dashboard for a Pulse, and execute non-text cards"
[pulse dashboard & {:as _options}]
"Fetch all the dashcards in a dashboard for a Pulse, and execute non-text cards.
The gerenerated contents will follow the pulse's creator permissions."
[{pulse-creator-id :creator_id, :as pulse} dashboard & {:as _options}]
(let [dashboard-id (u/the-id dashboard)
dashcards (db/select DashboardCard :dashboard_id dashboard-id)
ordered-dashcards (sort dashcard-comparator dashcards)]
(for [dashcard ordered-dashcards
:let [content (dashcard->content dashcard pulse dashboard)]
:when (some? content)]
content)))
(mw.session/with-current-user pulse-creator-id
(doall (for [dashcard ordered-dashcards
:let [content (dashcard->content dashcard pulse dashboard)]
:when (some? content)]
content)))))
(defn- database-id [card]
(or (:database_id card)
......@@ -155,7 +208,7 @@
(str "…"))
mrkdwn))
(defn create-slack-attachment-data
(defn- create-slack-attachment-data
"Returns a seq of slack attachment data structures, used in `create-and-upload-slack-attachments!`"
[card-results]
(let [channel-id (slack/files-channel)]
......
......@@ -27,6 +27,20 @@
[^Integer id]
(format "%s/question/%d" (site-url) id))
(defn database-url
"Returns an appropriate URL to view a database.
(database-url 4) -> \"http://localhost:3000/browse/4\""
[^Integer db-id]
(format "%s/browse/%d" (site-url) db-id))
(defn table-url
"Returns an appropriate URL to view a table.
(table-url 1 10) -> \"http://localhost:3000/question?db=1&table=10\""
[^Integer db-id ^Integer table-id]
(format "%s/question?db=%d&table=%d" (site-url) db-id table-id))
(defn public-card-prefix
"URL prefix for a public Cards. Get the complete URL by adding the UUID to the end."
[]
......@@ -44,8 +58,8 @@
(defn collection-url
"Return an appropriate URL for a `Collection` with ID or nil for root.
(collection-url 10) -> \"http://localhost:3000/question/10\"
(collection-url nil) -> \"http://localhost:3000/question/root\""
(collection-url 10) -> \"http://localhost:3000/collection/10\"
(collection-url nil) -> \"http://localhost:3000/collection/root\""
[collection-id-or-nil]
(format "%s/collection/%s" (site-url) (or collection-id-or-nil "root")))
......
......@@ -10,12 +10,12 @@
[metabase.api.common :as api]
[metabase.api.dashboard :as api.dashboard]
[metabase.api.pivots :as api.pivots]
[metabase.dashboard-subscription-test :as dashboard-subscription-test]
[metabase.http-client :as client]
[metabase.models
:refer [Action
Card
Collection
Database
Dashboard
DashboardCard
DashboardCardSeries
......@@ -324,71 +324,42 @@
(dashboard-response (mt/user-http-request :rasta :get 200 (format "dashboard/%d" dashboard-id)))))))))
(testing "a dashboard that has link cards on it"
(let [link-card-viz-setting (fn [model id]
{:virtual_card {:display "link"}
:link {:entity {:id id
:model model}}})
link-card-info-from-resp (fn [resp]
(->> resp
:ordered_cards
(map #(get-in % [:visualization_settings :link :entity]))))
crowberto-pc-id (db/select-one-field :id Collection :personal_owner_id (mt/user->id :crowberto))]
(let [link-card-info-from-resp
(fn [resp]
(->> resp
:ordered_cards
(map (fn [dashcard] (or (get-in dashcard [:visualization_settings :link :entity])
;; get for link card
(get-in dashcard [:visualization_settings :link]))))))]
(t2.with-temp/with-temp
[Collection {coll-id :id} {:name "Linked collection"
:description "Linked collection desc"
:location (format "/%d/" crowberto-pc-id)}
Database {db-id :id} {:name "Linked database"
:description "Linked database desc"}
Table {table-id :id} {:db_id db-id
:name "Linked table"
:display_name "Linked table dname"
:description "Linked table desc"}
Card {card-id :id} {:name "Linked card"
:description "Linked card desc"
:display "bar"
:collection_id crowberto-pc-id}
Card {model-id :id} {:dataset true
:name "Linked model"
:description "Linked model desc"
:display "table"
:collection_id crowberto-pc-id}
Dashboard {dash-id :id} {:name "Linked Dashboard"
:description "Linked Dashboard desc"
:collection_id crowberto-pc-id}
Dashboard {dashboard-id :id} {:name "Test Dashboard"}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "collection" coll-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "database" db-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "table" table-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "dashboard" dash-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "card" card-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "dataset" model-id)}]
(is (= [{:id coll-id :model "collection":name "Linked collection" :description "Linked collection desc" :display nil
:db_id nil :collection_id nil}
{:id db-id :model "database" :name "Linked database" :description "Linked database desc" :display nil
:db_id nil :collection_id nil}
{:id table-id :model "table" :name "Linked table dname" :description "Linked table desc" :display nil
:db_id db-id :collection_id nil}
{:id dash-id :model "dashboard" :name "Linked Dashboard" :description "Linked Dashboard desc" :display nil
:db_id nil :collection_id crowberto-pc-id}
{:id card-id :model "card" :name "Linked card" :description "Linked card desc" :display "bar"
:db_id nil :collection_id crowberto-pc-id}
{:id model-id :model "dataset" :name "Linked model" :description "Linked model desc" :display "table"
:db_id nil :collection_id crowberto-pc-id}]
(link-card-info-from-resp
(mt/user-http-request :crowberto :get 200 (format "dashboard/%d" dashboard-id)))))
(testing "should return restricted if user doesn't have permission to view it"
(perms/revoke-data-perms! (perms-group/all-users) db-id)
(is (= #{{:restricted true}}
(set (link-card-info-from-resp
(mt/user-http-request :rasta :get 200 (format "dashboard/%d" dashboard-id))))))))))
[Dashboard dashboard {:name "Test Dashboard"}]
(dashboard-subscription-test/with-link-card-fixture-for-dashboard dashboard [{:keys [collection-id
database-id
table-id
dashboard-id
card-id
model-id]}]
(is (= [{:id collection-id :model "collection":name "Linked collection name" :description "Linked collection desc" :display nil
:db_id nil :collection_id nil}
{:id database-id :model "database" :name "Linked database name" :description "Linked database desc" :display nil
:db_id nil :collection_id nil}
{:id table-id :model "table" :name "Linked table dname" :description "Linked table desc" :display nil
:db_id database-id :collection_id nil}
{:id dashboard-id :model "dashboard" :name "Linked Dashboard name" :description "Linked Dashboard desc" :display nil
:db_id nil :collection_id collection-id}
{:id card-id :model "card" :name "Linked card name" :description "Linked card desc" :display "bar"
:db_id nil :collection_id collection-id}
{:id model-id :model "dataset" :name "Linked model name" :description "Linked model desc" :display "table"
:db_id nil :collection_id collection-id}
{:url "https://metabase.com"}]
(link-card-info-from-resp
(mt/user-http-request :crowberto :get 200 (format "dashboard/%d" (:id dashboard))))))
(testing "should return restricted if user doesn't have permission to view the models"
(perms/revoke-data-perms! (perms-group/all-users) database-id)
(is (= #{{:restricted true} {:url "https://metabase.com"}}
(set (link-card-info-from-resp
(mt/user-http-request :lucky :get 200 (format "dashboard/%d" (:id dashboard))))))))))))
(testing "fetch a dashboard with a param in it"
(mt/with-temp* [Table [{table-id :id} {}]
......
......@@ -3,20 +3,25 @@
[clojure.test :refer :all]
[metabase.models
:refer [Card
Collection
Database
Dashboard
DashboardCard
Pulse
PulseCard
PulseChannel
PulseChannelRecipient
Table
User]]
[metabase.models.pulse :as pulse]
[metabase.public-settings :as public-settings]
[metabase.pulse]
[metabase.pulse.render.body :as body]
[metabase.pulse.test-util :as pulse.test-util]
[metabase.test :as mt]
[metabase.util :as u]
[schema.core :as s]
[toucan2.core :as t2]
[toucan2.tools.with-temp :as t2.with-temp]))
(defn- do-with-dashboard-sub-for-card
......@@ -138,6 +143,69 @@
pulse.test-util/png-attachment]}
email)))
(defn do-with-dashboard-fixture-for-dashboard
"Impl for [[with-link-card-fixture-for-dashboard]]."
[dashboard thunk]
(let [dashboard-id (:id dashboard)
link-card-viz-setting (fn [model id]
{:virtual_card {:display "link"}
:link {:entity {:id id
:model model}}})
rasta-pc-id (t2/select-one-fn :id Collection :personal_owner_id (mt/user->id :rasta))]
(t2.with-temp/with-temp
[Collection {coll-id :id} {:name "Linked collection name"
:description "Linked collection desc"
:location (format "/%d/" rasta-pc-id)}
Database {db-id :id} {:name "Linked database name"
:description "Linked database desc"}
Table {table-id :id} {:db_id db-id
:name "Linked table name"
:display_name "Linked table dname"
:description "Linked table desc"}
Card {card-id :id} {:name "Linked card name"
:description "Linked card desc"
:display "bar"
:collection_id coll-id}
Card {model-id :id} {:dataset true
:name "Linked model name"
:description "Linked model desc"
:display "table"
:collection_id coll-id}
Dashboard {dash-id :id} {:name "Linked Dashboard name"
:description "Linked Dashboard desc"
:collection_id coll-id}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "collection" coll-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "database" db-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "table" table-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "dashboard" dash-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "card" card-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings (link-card-viz-setting "dataset" model-id)}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings {:virtual_card {:display "link"}
:link {:url "https://metabase.com"}}}]
(thunk {:collection-owner-id rasta-pc-id
:collection-id coll-id
:database-id db-id
:table-id table-id
:card-id card-id
:model-id model-id
:dashboard-id dash-id
:url "https://metabase.com"}))))
(defmacro with-link-card-fixture-for-dashboard
"Given a dashboard, prepare a list of linkcards that connected to it and execute the body."
{:style/indent 2}
[dashboard [binding] & body]
`(do-with-dashboard-fixture-for-dashboard
~dashboard
(fn [~binding] ~@body)))
;;; +----------------------------------------------------------------------------------------------------------------+
;;; | Tests |
;;; +----------------------------------------------------------------------------------------------------------------+
......@@ -345,6 +413,107 @@
"?state=CA&state=NY&state=NJ&quarter_and_year=Q1-2021|*Sent from Metabase Test*>")}]}]}]}
(pulse.test-util/thunk->boolean pulse-results)))))}})))
(deftest dashboard-with-link-card-test
(tests {:pulse {:skip_if_empty false}
:dashboard pulse.test-util/test-dashboard}
"Dashboard that has link cards should render correctly"
{:card (pulse.test-util/checkins-query-card {})
:fixture
(fn [{dashboard-id :dashboard-id} thunk]
(with-link-card-fixture-for-dashboard (t2/select-one Dashboard :id dashboard-id) [_]
(thunk)))
:assert
{:email
(fn [_ _]
(is (every?
true?
(-> (mt/summarize-multipart-email
#"https://metabase\.com/testmb/collection/\d+"
#"Linked collection name"
#"Linked collection desc"
#"https://metabase\.com/testmb/browse/\d+"
#"Linked database name"
#"Linked database desc"
#"https://metabase\.com/testmb/question\?db=\d+&amp;table=\d+"
#"Linked table dname"
#"Linked table desc"
#"https://metabase\.com/testmb/question/\d+"
#"Linked card name"
#"Linked card desc"
#"https://metabase\.com/testmb/question/\d+"
#"Linked model name"
#"Linked model desc"
#"https://metabase\.com/testmb/dashboard/\d+"
#"Linked Dashboard name"
#"Linked Dashboard desc")
(get "rasta@metabase.com")
first
:body
first
vals))))
:slack
(fn [_ [pulse-results]]
(is (=? {:channel-id "#general",
:attachments
[{:blocks
[{:type "header", :text {:type "plain_text", :text "Aviary KPIs", :emoji true}}
{:type "section",
:fields
[{:type "mrkdwn", :text "*State*\nCA, NY, and NJ"}
{:type "mrkdwn", :text "*Quarter and Year*\nQ1, 2021"}]}
{:type "section", :fields [{:type "mrkdwn", :text "Sent by Rasta Toucan"}]}]}
{:title "Test card",
:rendered-info {:attachments false, :content true, :render/text true},
:title_link #"https://metabase.com/testmb/question/.+",
:attachment-name "image.png",
:channel-id "FOO",
:fallback "Test card"}
{:blocks
[{:type "section",
:text
{:type "mrkdwn",
:text #"\*<https://metabase\.com/testmb/collection/\d+\|Linked collection name>\*\nLinked collection desc"}}]}
{:blocks
[{:type "section",
:text
{:type "mrkdwn", :text #"\*<https://metabase\.com/testmb/browse/\d+\|Linked database name>\*\nLinked database desc"}}]}
{:blocks
[{:type "section",
:text
{:type "mrkdwn",
:text #"\*<https://metabase\.com/testmb/question\?db=\d+&table=\d+\|Linked table dname>\*\nLinked table desc"}}]}
{:blocks
[{:type "section",
:text
{:type "mrkdwn",
:text #"\*<https://metabase\.com/testmb/dashboard/\d+\|Linked Dashboard name>\*\nLinked Dashboard desc"}}]}
{:blocks
[{:type "section",
:text {:type "mrkdwn", :text #"\*<https://metabase\.com/testmb/question/\d+\|Linked card name>\*\nLinked card desc"}}]}
{:blocks
[{:type "section",
:text
{:type "mrkdwn", :text #"\*<https://metabase\.com/testmb/question/\d+\|Linked model name>\*\nLinked model desc"}}]}
{:blocks
[{:type "section", :text {:type "mrkdwn", :text "*<https://metabase.com|https://metabase.com>*"}}]}
{:blocks
[{:type "divider"}
{:type "context",
:elements
[{:type "mrkdwn",
:text
#"<https://metabase\.com/testmb/dashboard/\d+\?state=CA&state=NY&state=NJ&quarter_and_year=Q1-2021\|\*Sent from Metabase Test\*>"}]}]}]}
(pulse.test-util/thunk->boolean pulse-results))))}}))
(deftest mrkdwn-length-limit-test
(with-redefs [metabase.pulse/block-text-length-limit 10]
(tests {:pulse {:skip_if_empty false}, :dashcard {:row 0, :col 0}}
......@@ -451,8 +620,8 @@
(is (= [{:text "Doohickey and Gizmo"}]
(@#'metabase.pulse/execute-dashboard {:creator_id (mt/user->id :rasta)} dashboard))))))
(deftest link-cards-and-actions-are-skipped-test
(testing "Actions and link cards should be filtered out"
(deftest actions-are-skipped-test
(testing "Actions should be filtered out"
(t2.with-temp/with-temp
[Dashboard {dashboard-id :id
:as dashboard} {:name "Dashboard"}
......@@ -460,10 +629,42 @@
:visualization_settings {:text "Markdown"}}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings {:virtual_card {:display "link"}
:link {:entity {:id dashboard-id
:model "dashboard"}}}}
:link {:url "https://metabase.com"}}}
DashboardCard _ {:dashboard_id dashboard-id
:visualization_settings {:virtual_card {:display "action"}}}]
(is (= [{:text "Markdown"}]
(@#'metabase.pulse/execute-dashboard {:creator_id (mt/user->id :rasta)} dashboard))))))
(is (= [{:text "Markdown"}
{:text "### [https://metabase.com](https://metabase.com)"}]
(@#'metabase.pulse/execute-dashboard {:creator_id (mt/user->id :rasta)} dashboard)))))
(testing "Link cards are returned and info should be newly fetched"
(t2.with-temp/with-temp [Dashboard dashboard {:name "Test Dashboard"}]
(with-link-card-fixture-for-dashboard dashboard [{:keys [collection-owner-id
collection-id
database-id
table-id
card-id
model-id
dashboard-id]}]
(let [site-url (public-settings/site-url)]
(testing "should returns all link cards and name are newly fetched"
(doseq [[model id] [[Card card-id]
[Table table-id]
[Database database-id]
[Dashboard dashboard-id]
[Collection collection-id]
[Card model-id]]]
(t2/update! model id {:name (format "New %s name" (name model))}))
(is (=? [{:text (format "### [New Collection name](%s/collection/%d)\nLinked collection desc" site-url collection-id)}
{:text (format "### [New Database name](%s/browse/%d)\nLinked database desc" site-url database-id)}
{:text (format "### [Linked table dname](%s/question?db=%d&table=%d)\nLinked table desc" site-url database-id table-id)}
{:text (format "### [New Dashboard name](%s/dashboard/%d)\nLinked Dashboard desc" site-url dashboard-id)}
{:text (format "### [New Card name](%s/question/%d)\nLinked card desc" site-url card-id)}
{:text (format "### [New Card name](%s/question/%d)\nLinked model desc" site-url model-id)}
{:text (format "### [https://metabase.com](https://metabase.com)")}]
(@#'metabase.pulse/execute-dashboard {:creator_id collection-owner-id} dashboard))))
(testing "it should filter out models that current users does not have permission to read"
(is (=? [{:text (format "### [New Database name](%s/browse/%d)\nLinked database desc" site-url database-id)}
{:text (format "### [Linked table dname](%s/question?db=%d&table=%d)\nLinked table desc" site-url database-id table-id)}
{:text (format "### [https://metabase.com](https://metabase.com)")}]
(@#'metabase.pulse/execute-dashboard {:creator_id (mt/user->id :lucky)} dashboard)))))))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment