mirror of
https://github.com/penpot/penpot.git
synced 2026-08-31 17:19:11 +00:00
🐛 Prevent nil theme in profile updates
Omit nil optional profile fields before frontend schema validation and RPC persistence. Preserve omitted language and theme values in backend updates, and add regression coverage for partial profile saves. AI-assisted-by: gpt-5.6-luna
This commit is contained in:
parent
d745dc4a3c
commit
5b4a5776cb
@ -166,8 +166,12 @@
|
|||||||
;; the same row/object.
|
;; the same row/object.
|
||||||
(let [profile (get-profile conn profile-id ::db/for-update true)
|
(let [profile (get-profile conn profile-id ::db/for-update true)
|
||||||
fullname (d/normalize-string fullname)
|
fullname (d/normalize-string fullname)
|
||||||
lang (d/normalize-string lang)
|
lang (if (contains? params :lang)
|
||||||
theme (d/normalize-string theme)
|
(d/normalize-string lang)
|
||||||
|
(:lang profile))
|
||||||
|
theme (if (contains? params :theme)
|
||||||
|
(d/normalize-string theme)
|
||||||
|
(:theme profile))
|
||||||
;; Update the profile map with direct params
|
;; Update the profile map with direct params
|
||||||
profile (-> profile
|
profile (-> profile
|
||||||
(assoc :fullname fullname)
|
(assoc :fullname fullname)
|
||||||
|
|||||||
@ -125,6 +125,17 @@
|
|||||||
(t/is (= "en" (:lang result)))
|
(t/is (= "en" (:lang result)))
|
||||||
(t/is (= "dark" (:theme result))))))
|
(t/is (= "dark" (:theme result))))))
|
||||||
|
|
||||||
|
(t/testing "update profile preserves omitted optional fields"
|
||||||
|
(let [data {::th/type :update-profile
|
||||||
|
::rpc/profile-id (:id profile)
|
||||||
|
:fullname "Updated Name"}
|
||||||
|
out (th/command! data)]
|
||||||
|
|
||||||
|
(t/is (nil? (:error out)))
|
||||||
|
(t/is (= "Updated Name" (get-in out [:result :fullname])))
|
||||||
|
(t/is (= "en" (get-in out [:result :lang])))
|
||||||
|
(t/is (= "dark" (get-in out [:result :theme])))))
|
||||||
|
|
||||||
(t/testing "update photo"
|
(t/testing "update photo"
|
||||||
(let [data {::th/type :update-profile-photo
|
(let [data {::th/type :update-profile-photo
|
||||||
::rpc/profile-id (:id profile)
|
::rpc/profile-id (:id profile)
|
||||||
|
|||||||
@ -122,6 +122,10 @@
|
|||||||
|
|
||||||
;; --- Update Profile
|
;; --- Update Profile
|
||||||
|
|
||||||
|
(defn profile-update-params
|
||||||
|
[profile]
|
||||||
|
(d/without-nils (select-keys profile [:fullname :lang :theme])))
|
||||||
|
|
||||||
(defn persist-profile
|
(defn persist-profile
|
||||||
[& {:as opts}]
|
[& {:as opts}]
|
||||||
(ptk/reify ::persist-profile
|
(ptk/reify ::persist-profile
|
||||||
@ -130,7 +134,7 @@
|
|||||||
(let [on-success (:on-success opts identity)
|
(let [on-success (:on-success opts identity)
|
||||||
on-error (:on-error opts rx/throw)
|
on-error (:on-error opts rx/throw)
|
||||||
profile (:profile state)
|
profile (:profile state)
|
||||||
params (select-keys profile [:fullname :lang :theme])]
|
params (profile-update-params profile)]
|
||||||
(->> (rp/cmd! :update-profile params)
|
(->> (rp/cmd! :update-profile params)
|
||||||
(rx/tap on-success)
|
(rx/tap on-success)
|
||||||
(rx/map set-profile)
|
(rx/map set-profile)
|
||||||
@ -143,7 +147,7 @@
|
|||||||
props"
|
props"
|
||||||
[profile]
|
[profile]
|
||||||
|
|
||||||
(let [profile (check-profile profile)]
|
(let [profile (check-profile (d/without-nils profile))]
|
||||||
(ptk/reify ::update-profile
|
(ptk/reify ::update-profile
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
|
|||||||
30
frontend/test/frontend_tests/data/profile_test.cljs
Normal file
30
frontend/test/frontend_tests/data/profile_test.cljs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||||
|
|
||||||
|
(ns frontend-tests.data.profile-test
|
||||||
|
(:require
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.data.profile :as dprof]
|
||||||
|
[cljs.test :as t :include-macros true]))
|
||||||
|
|
||||||
|
(t/deftest profile-update-params-omits-nil-values
|
||||||
|
(t/is (= {:fullname "Updated Name"}
|
||||||
|
(dprof/profile-update-params {:fullname "Updated Name"
|
||||||
|
:lang nil
|
||||||
|
:theme nil}))))
|
||||||
|
|
||||||
|
(t/deftest profile-update-params-preserves-present-values
|
||||||
|
(t/is (= {:fullname "Updated Name"
|
||||||
|
:lang "en"
|
||||||
|
:theme "dark"}
|
||||||
|
(dprof/profile-update-params {:fullname "Updated Name"
|
||||||
|
:lang "en"
|
||||||
|
:theme "dark"}))))
|
||||||
|
|
||||||
|
(t/deftest update-profile-accepts-nil-optional-values
|
||||||
|
(t/is (some? (dprof/update-profile {:id uuid/zero
|
||||||
|
:fullname "Updated Name"
|
||||||
|
:theme nil}))))
|
||||||
@ -11,6 +11,7 @@
|
|||||||
[frontend-tests.data.dashboard-test]
|
[frontend-tests.data.dashboard-test]
|
||||||
[frontend-tests.data.exports-assets-test]
|
[frontend-tests.data.exports-assets-test]
|
||||||
[frontend-tests.data.nitrate-test]
|
[frontend-tests.data.nitrate-test]
|
||||||
|
[frontend-tests.data.profile-test]
|
||||||
[frontend-tests.data.repo-test]
|
[frontend-tests.data.repo-test]
|
||||||
[frontend-tests.data.store-test]
|
[frontend-tests.data.store-test]
|
||||||
[frontend-tests.data.uploads-test]
|
[frontend-tests.data.uploads-test]
|
||||||
@ -106,6 +107,7 @@
|
|||||||
'frontend-tests.copy-as-svg-test
|
'frontend-tests.copy-as-svg-test
|
||||||
'frontend-tests.data.dashboard-test
|
'frontend-tests.data.dashboard-test
|
||||||
'frontend-tests.data.nitrate-test
|
'frontend-tests.data.nitrate-test
|
||||||
|
'frontend-tests.data.profile-test
|
||||||
'frontend-tests.data.repo-test
|
'frontend-tests.data.repo-test
|
||||||
'frontend-tests.data.store-test
|
'frontend-tests.data.store-test
|
||||||
'frontend-tests.data.exports-assets-test
|
'frontend-tests.data.exports-assets-test
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user