diff --git a/project.clj b/project.clj index b4f632a6..3090728f 100644 --- a/project.clj +++ b/project.clj @@ -35,7 +35,7 @@ [org.cyverse/async-tasks-client "0.0.3"] [org.cyverse/clj-icat-direct "2.9.0"] [org.cyverse/clj-jargon "2.8.9"] - [org.cyverse/clojure-commons "3.0.5"] + [org.cyverse/clojure-commons "3.0.6-SNAPSHOT"] [org.cyverse/cyverse-groups-client "0.1.8"] [org.cyverse/common-cfg "2.8.1"] [org.cyverse/common-cli "2.8.1"] @@ -53,7 +53,8 @@ [swank-clojure "1.4.2" :exclusions [org.clojure/clojure]] [test2junit "1.2.2"] [jonase/eastwood "0.3.10"]] - :profiles {:dev {:resource-paths ["conf/test"]} + :profiles {:dev {:dependencies [[clj-http-fake "1.0.3"]] + :resource-paths ["conf/test" "test-resources"]} :uberjar {:aot :all}} :main ^:skip-aot terrain.core :ring {:handler terrain.core/dev-handler diff --git a/src/terrain/clients/notifications.clj b/src/terrain/clients/notifications.clj index 39b553e9..32f9906d 100644 --- a/src/terrain/clients/notifications.clj +++ b/src/terrain/clients/notifications.clj @@ -15,11 +15,11 @@ (build-url-with-query (notificationagent-base-url) (add-current-user-to-map query) relative-url))) -(def ^:private last-ten-messages-params +(def last-ten-messages-params {:limit 10 :offset 0 - :sort-field :timestamp - :sort-dir :desc}) + :sort-field "timestamp" + :sort-dir "desc"}) (defn last-ten-messages [] diff --git a/src/terrain/util/config.clj b/src/terrain/util/config.clj index b1910056..67b5bccd 100644 --- a/src/terrain/util/config.clj +++ b/src/terrain/util/config.clj @@ -174,7 +174,7 @@ (cc/defprop-optstr notificationagent-base-url "The base URL to use when connecting to the notification agent." [props config-valid configs notification-routes-enabled] - "terrain.notificationagent.base-url" "http://notification-agent") + "terrain.notificationagent.base-url" "http://notifications") (cc/defprop-optstr ipg-base "The base URL for the iplant-groups service." @@ -601,3 +601,10 @@ (cc/log-config props :filters [#"irods\.user" #"icat\.user" #"oauth\.pem"]) (validate-config) (ce/register-filters (exception-filters))) + +(defn load-config-from-map + "Loads the configuration settings from a Clojure map. This function is used for unit testing." + [config-map] + (cc/load-config-from-map config-map props) + (validate-config) + (ce/register-filters (exception-filters))) diff --git a/test-resources/notifications.json b/test-resources/notifications.json new file mode 100644 index 00000000..78a05718 --- /dev/null +++ b/test-resources/notifications.json @@ -0,0 +1,228 @@ +{ + "total": "77", + "unseen_total": "27", + "messages": [ + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "analyses": [ + { + "analysis_id": "431dd792-2118-11eb-92bd-008cfa5ae621", + "analysis_name": "Discovery_Environment_Alpha_Testing_App_analysis1", + "category_id": "" + } + ] + }, + "email_template": null, + "type": "analysis", + "seen": false, + "user": "ipcdev", + "subject": "meidanis has shared 1 analysis with you.", + "message": { + "id": "1DE61363-0BAC-4544-9E96-6FDC6F0B31CD", + "timestamp": "1604767802096", + "text": "meidanis has shared the following analysis with you: Discovery_Environment_Alpha_Testing_App_analysis1" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "paths": [ + "/iplant/home/meidanis/analyses/main.pdf" + ] + }, + "email_template": null, + "type": "data", + "seen": false, + "user": "ipcdev", + "subject": "meidanis has shared 1 file(s)/folder(s) with you.", + "message": { + "id": "CA937B14-79C7-4027-99D2-E671B81E4A11", + "timestamp": "1604765984400", + "text": "meidanis has shared the following file(s)/folder(s) with you: main.pdf" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "analyses": [ + { + "analysis_id": "5f0a6572-205c-11eb-aa57-008cfa5ae621", + "analysis_name": "DE_Word_Count_analysis1", + "category_id": "" + } + ] + }, + "email_template": null, + "type": "analysis", + "seen": false, + "user": "ipcdev", + "subject": "sriram has shared 1 analysis with you.", + "message": { + "id": "174B4C96-FF28-4715-9093-5DA9A4D99F26", + "timestamp": "1604686886421", + "text": "sriram has shared the following analysis with you: DE_Word_Count_analysis1" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "paths": [ + "/iplant/home/sriram/1KB.zip", + "/iplant/home/sriram/.chirp.config" + ] + }, + "email_template": null, + "type": "data", + "seen": false, + "user": "ipcdev", + "subject": "sriram has shared 2 file(s)/folder(s) with you.", + "message": { + "id": "1B536A4B-C449-4F78-ADEB-6787A07912C1", + "timestamp": "1604686883552", + "text": "sriram has shared the following file(s)/folder(s) with you: 1KB.zip, .chirp.config" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "apps": [ + { + "app_id": "5b52c412-6b8e-11e9-81f7-008cfa5ae621", + "app_name": "Austria Demo", + "category_id": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee" + } + ] + }, + "email_template": null, + "type": "apps", + "seen": false, + "user": "ipcdev", + "subject": "sriram has shared 1 app with you.", + "message": { + "id": "B3038CE5-8D1E-4976-98E9-9F8ADBCACFC3", + "timestamp": "1604686881340", + "text": "sriram has shared the following app with you: Austria Demo" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "analyses": [ + { + "analysis_id": "3c9825f0-2017-11eb-8f93-008cfa5ae621", + "analysis_name": "JupyterLab-with-sql-1.0.9_analysis1", + "category_id": "" + } + ] + }, + "email_template": null, + "type": "analysis", + "seen": false, + "user": "ipcdev", + "subject": "kcklang has shared 1 analysis with you.", + "message": { + "id": "FA1EF3A4-DC6E-47A0-9124-0A2A21915770", + "timestamp": "1604657381801", + "text": "kcklang has shared the following analysis with you: JupyterLab-with-sql-1.0.9_analysis1" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "paths": [ + "/iplant/home/kcklang/test/TEST-Sonora-06112020.txt" + ] + }, + "email_template": null, + "type": "data", + "seen": false, + "user": "ipcdev", + "subject": "kcklang has shared 1 file(s)/folder(s) with you.", + "message": { + "id": "E37FBD1C-9CD6-4D93-82EB-A35AE325C486", + "timestamp": "1604656088396", + "text": "kcklang has shared the following file(s)/folder(s) with you: TEST-Sonora-06112020.txt" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "paths": [ + "/iplant/home/ryank/inputfile.txt" + ] + }, + "email_template": null, + "type": "data", + "seen": false, + "user": "ipcdev", + "subject": "ryank has shared 1 file(s)/folder(s) with you.", + "message": { + "id": "957BB6FE-F2CB-4114-A970-91BC5AC1243A", + "timestamp": "1604593562152", + "text": "ryank has shared the following file(s)/folder(s) with you: inputfile.txt" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "analyses": [ + { + "analysis_id": "4f1d4b64-1a3c-11eb-8e14-008cfa5ae621", + "analysis_name": "ten-rules-jupyter_analysis1", + "category_id": "" + } + ] + }, + "email_template": null, + "type": "analysis", + "seen": false, + "user": "ipcdev", + "subject": "sriram has shared 1 analysis with you.", + "message": { + "id": "5AA1FBED-2AAC-45E8-AA08-03EAF1FE4876", + "timestamp": "1604523356160", + "text": "sriram has shared the following analysis with you: ten-rules-jupyter_analysis1" + } + }, + { + "deleted": false, + "email": false, + "payload": { + "action": "share", + "paths": [ + "/iplant/home/sriram/bulk/ten-rules-jupyter_analysis1-2020-10-29-23-13-08.1/ten-rules-jupyter" + ] + }, + "email_template": null, + "type": "data", + "seen": false, + "user": "ipcdev", + "subject": "sriram has shared 1 file(s)/folder(s) with you.", + "message": { + "id": "CFC94232-5FDC-4F74-9F3A-9E575A606E0F", + "timestamp": "1604523354527", + "text": "sriram has shared the following file(s)/folder(s) with you: ten-rules-jupyter" + } + } + ], + "system-messages": [] +} diff --git a/test/terrain/notifications_test.clj b/test/terrain/notifications_test.clj new file mode 100644 index 00000000..7eee8b5d --- /dev/null +++ b/test/terrain/notifications_test.clj @@ -0,0 +1,32 @@ +(ns terrain.notifications-test + (:require [cemerick.url :as curl] + [clj-http.fake :refer [with-fake-routes-in-isolation]] + [clojure.java.io :refer [resource]] + [clojure.test :refer :all] + [medley.core :refer [map-vals]] + [terrain.clients.notifications :as nc] + [terrain.test-fixtures :as test-fixtures] + [terrain.util.config :as config] + [terrain.util.transformers :refer [add-current-user-to-map]])) + +(use-fixtures :once test-fixtures/with-test-config test-fixtures/with-test-user) + +(defn- notification-url [& components] + (str (apply curl/url (config/notificationagent-base-url) components))) + +(deftest last-ten-messages + (with-fake-routes-in-isolation + {{:address (notification-url "messages") + :query-params (map-vals str (add-current-user-to-map nc/last-ten-messages-params))} + (fn [req] + {:status 200 + :headers {"Content-Type" "application/json"} + :body (slurp (resource "notifications.json"))})} + + (let [response (nc/last-ten-messages)] + (testing "unaltered fields in response" + (is (= (:total response) "77")) + (is (= (:unseen_total response) "27")) + (is (= (count (:messages response)) 10))) + (testing "reversed sort order for notification listing" + (is (apply < (map (comp #(Long/parseLong %) :timestamp :message) (:messages response)))))))) diff --git a/test/terrain/test_fixtures.clj b/test/terrain/test_fixtures.clj new file mode 100644 index 00000000..9dd9e78f --- /dev/null +++ b/test/terrain/test_fixtures.clj @@ -0,0 +1,27 @@ +(ns terrain.test-fixtures + (:require [terrain.auth.user-attributes :as user-attributes] + [terrain.util.config :as config])) + +(def test-config + {:terrain.uid.domain "iplantcollaborative.org" + :terrain.email.tool-request-dest "tool-request-dest@example.org" + :terrain.email.tool-request-src "tool-request-src@example.org" + :terrain.email.perm-id-req.dest "perm-id-request-dest@example.org" + :terrain.email.perm-id-req.src "perm-id-request-src@example.org" + :terrain.email.support-email-dest "support-email-dest@example.org" + :terrain.permanent-id.target-base-url "http://perm-id-target-base-url" + :terrain.keycloak.client-id "keycloak-client-id" + :terrain.keycloak.client-secret "keycloak-client-secret"}) + +(defn with-test-config [f] + (config/load-config-from-map test-config) + (f)) + +(def test-user + {"uid" "ipcdev" + "email" "ipcdev@cyverse.org" + "firstName" "Ipc" + "lastName" "Dev"}) + +(defn with-test-user [f] + (user-attributes/with-user [test-user] (f)))