Repository: CSCfi/rems
Pull request #1553 (2019-08-28 19:57:41)

Split previous update workflow into archived, enabled, and edit
Split previous update workflow into archived, enabled, and edit
    
There used to be a single API endpoint for all these operations. Have separate API endpoints for each.


Part of #1548

# Definition of Done / Review checklist

## Reviewability
- [x] link to issue
- [x] note if PR is on top of other PR
- [x] note if related change in rems-deploy repo
- [x] consider adding screenshots for ease of review

## API
- [x] API is documented and shows up in Swagger UI
- [x] API is backwards compatible or completely new
- [x] Events are backwards compatible

## Documentation
- [x] update changelog if necessary
- [x] add or update docstrings for namespaces and functions
- [x] components are added to guide page
- [x] documentation _at least_ for config options (i.e. docs folder)
- [x] ADR for major architectural decisions or experiments

## Different installations
- [x] new configuration options added to rems-deploy repository
- [x] instance specific translations (i.e. LBR kielivara)

## Testing
- [x] complex logic is unit tested
- [x] valuable features are integration / browser / acceptance tested automatically

## Accessibility
- [x] all icons have the aria-label attribute
- [x] all fields have a label
- [x] errors are linked to fields with aria-describedby
- [x] contrast is checked
- [x] conscious decision about where to move focus after an action

## Follow-up
- [x] new tasks are created for pending or remaining tasks
- [x] no critical TODOs left to implement



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9775b2b32..937af3c21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,11 @@ Changes since v2.4
 - API for creating catalogue item and its localizations has been changed.
   There is now a single API call that is used to create both a catalogue
   item and the localizations, namely, /api/catalogue-items/create.
+- API for editing workflow has been changed. The API endpoint for
+  editing name and handlers is now /api/workflows/edit, whereas the
+  endpoint for archiving or unarchiving workflow is /api/workflows/archived
+  and the endpoint for enabling or disabling workflow is
+  /api/workflows/enabled.
 - API endpoint for editing forms has been changed from
   /api/forms/[form-id]/edit to /api/forms/edit.
 
diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql
index 6f722f484..30cc61d84 100644
--- a/resources/sql/queries.sql
+++ b/resources/sql/queries.sql
@@ -297,14 +297,26 @@ VALUES
  /*~ (if (:workflow params) */ :workflow::jsonb /*~*/ NULL /*~ ) ~*/
 );
 
--- :name update-workflow! :!
+-- :name set-workflow-enabled! :!
+UPDATE workflow
+SET (enabled) = (:enabled)
+WHERE id = :id;
+
+-- :name set-workflow-archived! :!
+UPDATE workflow
+SET (archived) = (:archived)
+WHERE id = :id;
+
+-- :name edit-workflow! :!
 UPDATE workflow
 SET
-  id = :id
-  --~(when (contains? params :enabled) ", enabled = :enabled")
-  --~(when (contains? params :archived) ", archived = :archived")
-  --~(when (contains? params :title) ", title = :title")
-  --~(when (contains? params :workflow) ", workflowBody = :workflow::jsonb")
+/*~ (when (:title params) */
+  title = :title,
+/*~ ) ~*/
+/*~ (when (:workflow params) */
+  workflowBody = :workflow::jsonb,
+/*~ ) ~*/
+  id = id
 WHERE id = :id;
 
 -- :name create-workflow-license! :insert
diff --git a/src/clj/rems/api/schema.clj b/src/clj/rems/api/schema.clj
index 737e95b15..d0fda1214 100644
--- a/src/clj/rems/api/schema.clj
+++ b/src/clj/rems/api/schema.clj
@@ -47,11 +47,21 @@
    :end (s/maybe DateTime)
    :mail s/Str})
 
+;; TODO: Remove once all admin APIs have separate endpoints for enabled
+;;       and archived.
 (s/defschema UpdateStateCommand
   {:id s/Int
    :enabled s/Bool
    :archived s/Bool})
 
+(s/defschema EnabledCommand
+  {:id s/Int
+   :enabled s/Bool})
+
+(s/defschema ArchivedCommand
+  {:id s/Int
+   :archived s/Bool})
+
 (s/defschema SuccessResponse
   {:success s/Bool
    (s/optional-key :errors) [s/Any]})
diff --git a/src/clj/rems/api/services/workflow.clj b/src/clj/rems/api/services/workflow.clj
index cf00f2c8d..7bf99f329 100644
--- a/src/clj/rems/api/services/workflow.clj
+++ b/src/clj/rems/api/services/workflow.clj
@@ -32,7 +32,19 @@
      result
      {:success (not (nil? (:id result)))})))
 
-(defn update-workflow! [{:keys [id] :as command}]
+(defn edit-workflow! [command]
+  (db/edit-workflow!
+   (merge (select-keys command [:id :title])
+          (when-let [handlers (:handlers command)]
+            {:workflow (json/generate-string {:type :workflow/dynamic
+                                              :handlers handlers})})))
+  {:success true})
+
+(defn set-workflow-enabled! [command]
+  (db/set-workflow-enabled! (select-keys command [:id :enabled]))
+  {:success true})
+
+(defn set-workflow-archived! [{:keys [id archived]}]
   (let [workflow (workflow/get-workflow id)
         archived-licenses (filter :archived (:licenses workflow))
         catalogue-items
@@ -40,23 +52,20 @@
                                                        :archived false})
              (map #(select-keys % [:id :title :localizations])))]
     (cond
-      (and (:archived command) (seq catalogue-items))
+      (and archived (seq catalogue-items))
       {:success false
        :errors [{:type :t.administration.errors/workflow-in-use
                  :catalogue-items catalogue-items}]}
 
-      (and (not (:archived command)) (seq archived-licenses))
+      (and (not archived) (seq archived-licenses))
       {:success false
        :errors [{:type :t.administration.errors/license-archived
                  :licenses archived-licenses}]}
 
       :else
       (do
-        (db/update-workflow!
-         (merge (select-keys command [:id :enabled :archived :title])
-                (when-let [handlers (:handlers command)]
-                  {:workflow (json/generate-string {:type :workflow/dynamic
-                                                    :handlers handlers})})))
+        (db/set-workflow-archived! {:id id
+                                    :archived archived})
         {:success true}))))
 
 (defn get-workflow [id] (workflow/get-workflow id))
diff --git a/src/clj/rems/api/workflows.clj b/src/clj/rems/api/workflows.clj
index e7886e24f..f4f36d5d6 100644
--- a/src/clj/rems/api/workflows.clj
+++ b/src/clj/rems/api/workflows.clj
@@ -1,7 +1,7 @@
 (ns rems.api.workflows
   (:require [compojure.api.sweet :refer :all]
             [rems.api.applications :refer [User]]
-            [rems.api.schema :refer [SuccessResponse UserId Workflow]]
+            [rems.api.schema :refer [SuccessResponse ArchivedCommand EnabledCommand UserId Workflow]]
             [rems.api.services.workflow :as workflow]
             [rems.api.util] ; required for route :roles
             [rems.util :refer [getx-user-id]]
@@ -14,13 +14,11 @@
    :type s/Keyword
    (s/optional-key :handlers) [UserId]})
 
-(s/defschema UpdateWorkflowCommand
+(s/defschema EditWorkflowCommand
   {:id s/Int
-   (s/optional-key :title) s/Str
-   (s/optional-key :handlers) [UserId]
    ;; type can't change
-   (s/optional-key :enabled) s/Bool
-   (s/optional-key :archived) s/Bool})
+   (s/optional-key :title) s/Str
+   (s/optional-key :handlers) [UserId]})
 
 (s/defschema CreateWorkflowResponse
   {:success s/Bool
@@ -52,12 +50,26 @@
       :return CreateWorkflowResponse
       (ok (workflow/create-workflow! (assoc command :user-id (getx-user-id)))))
 
-    (PUT "/update" []
-      :summary "Update workflow"
+    (PUT "/edit" []
+      :summary "Edit workflow title and handlers"
+      :roles #{:owner}
+      :body [command EditWorkflowCommand]
+      :return SuccessResponse
+      (ok (workflow/edit-workflow! command)))
+
+    (PUT "/archived" []
+      :summary "Archive or unarchive workflow"
+      :roles #{:owner}
+      :body [command ArchivedCommand]
+      :return SuccessResponse
+      (ok (workflow/set-workflow-archived! command)))
+
+    (PUT "/enabled" []
+      :summary "Enable or disable workflow"
       :roles #{:owner}
-      :body [command UpdateWorkflowCommand]
+      :body [command EnabledCommand]
       :return SuccessResponse
-      (ok (workflow/update-workflow! command)))
+      (ok (workflow/set-workflow-enabled! command)))
 
     (GET "/actors" []
       :summary "List of available actors"
diff --git a/src/cljs/rems/administration/create_workflow.cljs b/src/cljs/rems/administration/create_workflow.cljs
index 779cfe81b..aaf19bde6 100644
--- a/src/cljs/rems/administration/create_workflow.cljs
+++ b/src/cljs/rems/administration/create_workflow.cljs
@@ -71,16 +71,16 @@
     (when (valid-create-request? request)
       request)))
 
-(defn- valid-update-request? [request]
+(defn- valid-edit-request? [request]
   (and (number? (:id request))
        (seq (:handlers request))
        (not (str/blank? (:title request)))))
 
-(defn build-update-request [id form]
+(defn build-edit-request [id form]
   (let [request {:id id
                  :title (:title form)
                  :handlers (map :userid (:handlers form))}]
-    (when (valid-update-request? request)
+    (when (valid-edit-request? request)
       request)))
 
 (rf/reg-event-fx
@@ -94,10 +94,10 @@
    {}))
 
 (rf/reg-event-fx
- ::update-workflow
+ ::edit-workflow
  (fn [_ [_ request]]
    (let [description (text :t.administration/edit-workflow)]
-     (put! "/api/workflows/update"
+     (put! "/api/workflows/edit"
            {:params request
             :handler (flash-message/default-success-handler description #(dispatch! (str "#/administration/workflows/" (:id request))))
             :error-handler (flash-message/default-error-handler description)}))
@@ -153,15 +153,15 @@
   (let [form @(rf/subscribe [::form])
         id @(rf/subscribe [::workflow-id])
         request (if id
-                  (build-update-request id form)
+                  (build-edit-request id form)
                   (build-create-request form))]
     [:button.btn.btn-primary
      {:type :button
       :on-click (fn []
                   (rf/dispatch [:rems.spa/user-triggered-navigation])
                   (if id
-                    (rf/dispatch [::update-workflow (build-update-request id form)])
-                    (rf/dispatch [::create-workflow (build-create-request form)])))
+                    (rf/dispatch [::edit-workflow request])
+                    (rf/dispatch [::create-workflow request])))
       :disabled (nil? request)}
      (text :t.administration/save)]))
 
diff --git a/src/cljs/rems/administration/workflow.cljs b/src/cljs/rems/administration/workflow.cljs
index 64765e34f..d11e46ee1 100644
--- a/src/cljs/rems/administration/workflow.cljs
+++ b/src/cljs/rems/administration/workflow.cljs
@@ -70,8 +70,8 @@
      [:div.col.commands
       [back-button]
       [edit-button id]
-      [status-flags/enabled-toggle workflow #(rf/dispatch [:rems.administration.workflows/update-workflow %1 %2 [::enter-page id]])]
-      [status-flags/archived-toggle workflow #(rf/dispatch [:rems.administration.workflows/update-workflow %1 %2 [::enter-page id]])]])])
+      [status-flags/enabled-toggle workflow #(rf/dispatch [:rems.administration.workflows/set-workflow-enabled %1 %2 [::enter-page id]])]
+      [status-flags/archived-toggle workflow #(rf/dispatch [:rems.administration.workflows/set-workflow-archived %1 %2 [::enter-page id]])]])])
 
 (defn workflow-page []
   (let [workflow (rf/subscribe [::workflow])
diff --git a/src/cljs/rems/administration/workflows.cljs b/src/cljs/rems/administration/workflows.cljs
index c077c1caf..6ce181010 100644
--- a/src/cljs/rems/administration/workflows.cljs
+++ b/src/cljs/rems/administration/workflows.cljs
@@ -37,10 +37,19 @@
 (rf/reg-sub ::loading? (fn [db _] (::loading? db)))
 
 (rf/reg-event-fx
- ::update-workflow
+ ::set-workflow-archived
  (fn [_ [_ item description dispatch-on-finished]]
-   (put! "/api/workflows/update"
-         {:params (select-keys item [:id :enabled :archived])
+   (put! "/api/workflows/archived"
+         {:params (select-keys item [:id :archived])
+          :handler (flash-message/status-update-handler description #(rf/dispatch dispatch-on-finished))
+          :error-handler (flash-message/default-error-handler description)})
+   {}))
+
+(rf/reg-event-fx
+ ::set-workflow-enabled
+ (fn [_ [_ item description dispatch-on-finished]]
+   (put! "/api/workflows/enabled"
+         {:params (select-keys item [:id :enabled])
           :handler (flash-message/status-update-handler description #(rf/dispatch dispatch-on-finished))
           :error-handler (flash-message/default-error-handler description)})
    {}))
@@ -84,8 +93,8 @@
            :commands {:td [:td.commands
                            [to-view-workflow (:id workflow)]
                            [workflow/edit-button (:id workflow)]
-                           [status-flags/enabled-toggle workflow #(rf/dispatch [::update-workflow %1 %2 [::fetch-workflows]])]
-                           [status-flags/archived-toggle workflow #(rf/dispatch [::update-workflow %1 %2 [::fetch-workflows]])]]}})
+                           [status-flags/enabled-toggle workflow #(rf/dispatch [::set-workflow-enabled %1 %2 [::fetch-workflows]])]
+                           [status-flags/archived-toggle workflow #(rf/dispatch [::set-workflow-archived %1 %2 [::fetch-workflows]])]]}})
         workflows)))
 
 (defn- workflows-list []


Test patch:
diff --git a/test/clj/rems/api/services/test_catalogue.clj b/test/clj/rems/api/services/test_catalogue.clj
index 502baec01..f7963b530 100644
--- a/test/clj/rems/api/services/test_catalogue.clj
+++ b/test/clj/rems/api/services/test_catalogue.clj
@@ -39,9 +39,8 @@
         archive-resource! #(resource/update-resource! {:id res-id
                                                        :enabled true
                                                        :archived %})
-        archive-workflow! #(workflow/update-workflow! {:id workflow-id
-                                                       :enabled true
-                                                       :archived %})]
+        archive-workflow! #(workflow/set-workflow-archived! {:id workflow-id
+                                                             :archived %})]
     (testing "new catalogue items are enabled and not archived"
       (is (= {:enabled true
               :archived false}
diff --git a/test/clj/rems/api/test_administration.clj b/test/clj/rems/api/test_administration.clj
index ab591c29d..0967dff7f 100644
--- a/test/clj/rems/api/test_administration.clj
+++ b/test/clj/rems/api/test_administration.clj
@@ -61,12 +61,15 @@
                                      :archived archived}
                                     api-key user-id))
 
-        update-workflow! (fn [{:keys [enabled archived]}]
-                           (api-call :put "/api/workflows/update"
+        workflow-archived! #(api-call :put "/api/workflows/archived"
+                                      {:id workflow-id
+                                       :archived %}
+                                      api-key user-id)
+
+        workflow-enabled! #(api-call :put "/api/workflows/enabled"
                                      {:id workflow-id
-                                      :enabled enabled
-                                      :archived archived}
-                                     api-key user-id))]
+                                      :enabled %}
+                                     api-key user-id)]
     (is license-id)
     (is resource-id)
     (is form-id)
@@ -97,10 +100,10 @@
                (:errors resp)))))
 
     (testing "can disable a workflow"
-      (is (:success (update-workflow! {:enabled false :archived false}))))
+      (is (:success (workflow-enabled! false))))
 
     (testing "can't archive a workflow that's in use"
-      (let [resp (update-workflow! {:enabled true :archived true})]
+      (let [resp (workflow-archived! true)]
         (is (false? (:success resp)))
         (is (= [{:type "t.administration.errors/workflow-in-use"
                  :catalogue-items [{:id catalogue-id :localizations {}}]}]
@@ -127,7 +130,7 @@
       (is (:success (update-form! {:enabled true :archived true}))))
 
     (testing "can archive a workflow that's not in use"
-      (is (:success (update-workflow! {:enabled true :archived true}))))
+      (is (:success (workflow-archived! true))))
 
     (testing "can archive a license that's not in use"
       (is (= {:success true} (update-license! {:enabled true :archived true}))))
diff --git a/test/clj/rems/api/test_workflows.clj b/test/clj/rems/api/test_workflows.clj
index dd5072e37..cc8af54a9 100644
--- a/test/clj/rems/api/test_workflows.clj
+++ b/test/clj/rems/api/test_workflows.clj
@@ -14,6 +14,26 @@
   :once
   api-fixture)
 
+;; this is a subset of what we expect to get from the api
+(def ^:private expected
+  {:organization "abc"
+   :title "dynamic workflow"
+   :workflow {:type "workflow/dynamic"
+              :handlers [{:userid "bob" :email "bob@example.com" :name "Bob Approver"}
+                         {:userid "carl" :email "carl@example.com" :name "Carl Reviewer"}]}
+   :enabled true
+   :expired false
+   :archived false})
+
+(defn- fetch [api-key user-id wfid]
+  (let [wfs (-> (request :get "/api/workflows" {:archived true :expired true :disabled true})
+                (authenticate api-key user-id)
+                handler
+                read-ok-body)]
+    (select-keys
+     (first (filter #(= wfid (:id %)) wfs))
+     (keys expected))))
+
 (deftest workflows-api-test
   (testing "list"
     (let [data (-> (request :get "/api/workflows")
@@ -62,23 +82,10 @@
       (is (< 0 id))
       (sync-with-database-time)
       (testing "and fetch"
-        (let [workflows (-> (request :get "/api/workflows")
-                            (authenticate "42" "owner")
-                            handler
-                            assert-response-is-ok
-                            read-body)
-              workflow (first (filter #(= id (:id %)) workflows))]
-          (is (= {:id id
-                  :organization "abc"
-                  :title "dynamic workflow"
-                  :workflow {:type "workflow/dynamic"
-                             :handlers [{:userid "bob" :email "bob@example.com" :name "Bob Approver"}
-                                        {:userid "carl" :email "carl@example.com" :name "Carl Reviewer"}]}
-                  :enabled true
-                  :archived false}
-                 (select-keys workflow [:id :organization :title :workflow :enabled :archived]))))))))
+        (is (= expected
+               (fetch "42" "owner" id)))))))
 
-(deftest workflows-update-test
+(deftest workflows-enabled-archived-test
   (let [api-key "42"
         user-id "owner"
         wfid (test-data/create-dynamic-workflow! {:organization "abc"
@@ -87,76 +94,84 @@
         lic-id (test-data/create-license! {})
         _ (db/create-workflow-license! {:wfid wfid :licid lic-id})
 
+        fetch #(fetch api-key user-id wfid)
         archive-license! #(licenses/update-license! {:id lic-id
                                                      :enabled true
                                                      :archived %})
-
-        ;; this is a subset of what we expect to get from the api
-        expected {:id wfid
-                  :organization "abc"
-                  :title "dynamic workflow"
-                  :workflow {:type "workflow/dynamic"
-                             :handlers [{:userid "bob" :email "bob@example.com" :name "Bob Approver"}
-                                        {:userid "carl" :email "carl@example.com" :name "Carl Reviewer"}]}
-                  :enabled true
-                  :expired false
-                  :archived false}
-        fetch (fn []
-                (let [wfs (-> (request :get "/api/workflows" {:archived true :expired true :disabled true})
-                              (authenticate api-key user-id)
-                              handler
-                              read-ok-body)]
-                  (select-keys
-                   (first (filter #(= wfid (:id %)) wfs))
-                   (keys expected))))
-        update! #(-> (request :put "/api/workflows/update")
-                     (json-body (merge {:id wfid} %))
-                     (authenticate api-key user-id)
-                     handler
-                     read-ok-body)]
+        set-enabled! #(-> (request :put "/api/workflows/enabled")
+                          (json-body {:id wfid
+                                      :enabled %})
+                          (authenticate api-key user-id)
+                          handler
+                          read-ok-body)
+        set-archived! #(-> (request :put "/api/workflows/archived")
+                           (json-body {:id wfid
+                                       :archived %})
+                           (authenticate api-key user-id)
+                           handler
+                           read-ok-body)]
     (sync-with-database-time)
     (testing "before changes"
       (is (= expected (fetch))))
     (testing "disable and archive"
-      (is (:success (update! {:enabled false :archived true})))
+      (is (:success (set-enabled! false)))
+      (is (:success (set-archived! true)))
       (is (= (assoc expected
                     :enabled false
                     :archived true)
              (fetch))))
     (testing "re-enable"
-      (is (:success (update! {:enabled true})))
+      (is (:success (set-enabled! true)))
       (is (= (assoc expected
                     :archived true)
              (fetch))))
     (testing "unarchive"
-      (is (:success (update! {:archived false})))
+      (is (:success (set-archived! false)))
       (is (= expected
              (fetch))))
+    (testing "cannot unarchive if license is archived"
+      (set-archived! true)
+      (archive-license! true)
+      (is (not (:success (set-archived! false))))
+      (archive-license! false)
+      (is (:success (set-archived! false))))))
+
+(deftest workflows-edit-test
+  (let [api-key "42"
+        user-id "owner"
+        wfid (test-data/create-dynamic-workflow! {:organization "abc"
+                                                  :title "dynamic workflow"
+                                                  :handlers ["bob" "carl"]})
+        fetch #(fetch api-key user-id wfid)
+        edit! #(-> (request :put "/api/workflows/edit")
+                   (json-body (merge {:id wfid} %))
+                   (authenticate api-key user-id)
+                   handler
+                   read-ok-body)]
+    (sync-with-database-time)
     (testing "change title"
-      (is (:success (update! {:title "x"})))
+      (is (:success (edit! {:title "x"})))
       (is (= (assoc expected
                     :title "x")
              (fetch))))
     (testing "change handlers"
-      (is (:success (update! {:handlers ["owner" "alice"]})))
+      (is (:success (edit! {:handlers ["owner" "alice"]})))
       (is (= (assoc expected
                     :title "x"
                     :workflow {:type "workflow/dynamic"
-                               :handlers [{:email "owner@example.com" :name "Owner" :userid "owner"}
-                                          {:email "alice@example.com" :name "Alice Applicant" :userid "alice"}]})
-             (fetch))))
-    (testing "cannot unarchive if license is archived"
-      (update! {:archived true})
-      (archive-license! true)
-      (is (not (:success (update! {:archived false}))))
-      (archive-license! false)
-      (is (:success (update! {:archived false}))))))
+                               :handlers [{:email "owner@example.com"
+                                           :name "Owner"
+                                           :userid "owner"}
+                                          {:email "alice@example.com"
+                                           :name "Alice Applicant"
+                                           :userid "alice"}]})
+             (fetch))))))
 
 (deftest workflows-api-filtering-test
   (let [enabled-wf (test-data/create-dynamic-workflow! {})
         disabled-wf (test-data/create-dynamic-workflow! {})
-        _ (workflow/update-workflow! {:id disabled-wf
-                                      :enabled false})
+        _ (workflow/set-workflow-enabled! {:id disabled-wf
+                                           :enabled false})
         enabled-and-disabled-wfs (set (map :id (-> (request :get "/api/workflows" {:disabled true})
                                                    (authenticate "42" "owner")
                                                    handler
diff --git a/test/cljs/rems/administration/test_create_workflow.cljs b/test/cljs/rems/administration/test_create_workflow.cljs
index 264ea58ab..9d5e7ce2d 100644
--- a/test/cljs/rems/administration/test_create_workflow.cljs
+++ b/test/cljs/rems/administration/test_create_workflow.cljs
@@ -1,6 +1,6 @@
 (ns rems.administration.test-create-workflow
   (:require [cljs.test :refer-macros [deftest is testing]]
-            [rems.administration.create-workflow :refer [build-create-request build-update-request]]))
+            [rems.administration.create-workflow :refer [build-create-request build-edit-request]]))
 
 (deftest build-create-request-test
   (testing "all workflows"
@@ -43,9 +43,9 @@
       (testing "missing handlers"
         (is (nil? (build-create-request (assoc-in form [:handlers] []))))))))
 
-(deftest build-update-request-test
+(deftest build-edit-request-test
   (is (= {:id 3 :title "t" :handlers ["a" "b"]}
-         (build-update-request 3 {:title "t" :handlers [{:userid "a"} {:userid "b"}]})))
-  (is (nil? (build-update-request nil {:title "t" :handlers [{:userid "a"} {:userid "b"}]})))
-  (is (nil? (build-update-request 3 {:title "" :handlers [{:userid "a"} {:userid "b"}]})))
-  (is (nil? (build-update-request 3 {:title "t" :handlers []}))))
+         (build-edit-request 3 {:title "t" :handlers [{:userid "a"} {:userid "b"}]})))
+  (is (nil? (build-edit-request nil {:title "t" :handlers [{:userid "a"} {:userid "b"}]})))
+  (is (nil? (build-edit-request 3 {:title "" :handlers [{:userid "a"} {:userid "b"}]})))
+  (is (nil? (build-edit-request 3 {:title "t" :handlers []}))))