@@ -170,6 +170,124 @@ defmodule Phoenix.ComponentUnitTest do
170170 end
171171 end
172172
173+ describe "assign_new with dependencies" do
174+ test "recomputes value when dependencies change" do
175+ socket =
176+ @ socket
177+ |> assign ( user_id: 123 )
178+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
179+
180+ assert socket . assigns . user == "User 123"
181+
182+ # Change a dependency
183+ socket =
184+ socket
185+ |> Utils . clear_changed ( )
186+ |> assign ( user_id: 456 )
187+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
188+
189+ assert socket . assigns . user == "User 456"
190+ assert changed? ( socket , :user )
191+ end
192+
193+ test "doesn't recompute when dependencies don't change" do
194+ socket =
195+ @ socket
196+ |> assign ( user_id: 123 , counter: 0 )
197+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
198+
199+ assert socket . assigns . user == "User 123"
200+
201+ # Change an unrelated assign
202+ socket =
203+ socket
204+ |> Utils . clear_changed ( )
205+ |> assign ( counter: 1 )
206+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
207+
208+ assert socket . assigns . user == "User 123"
209+ refute changed? ( socket , :user )
210+ end
211+
212+ test "works with zero-arity functions" do
213+ socket =
214+ @ socket
215+ |> assign ( user_id: 123 )
216+ |> assign_new ( :random_value , [ :user_id ] , fn -> :rand . uniform ( 100 ) end )
217+
218+ assert is_integer ( socket . assigns . random_value )
219+ assert socket . assigns . random_value > 0 && socket . assigns . random_value <= 100
220+
221+ # Change a dependency
222+ socket =
223+ socket
224+ |> Utils . clear_changed ( )
225+ |> assign ( user_id: 456 )
226+ |> assign_new ( :random_value , [ :user_id ] , fn -> :rand . uniform ( 100 ) end )
227+
228+ # Value should be recomputed
229+ assert is_integer ( socket . assigns . random_value )
230+ assert socket . assigns . random_value > 0 && socket . assigns . random_value <= 100
231+ # It's theoretically possible but extremely unlikely that we'd get the same random number
232+ assert changed? ( socket , :random_value )
233+ end
234+
235+ test "works with multiple dependencies" do
236+ socket =
237+ @ socket
238+ |> assign ( first_name: "John" , last_name: "Doe" )
239+ |> assign_new ( :full_name , [ :first_name , :last_name ] , fn % { first_name: first , last_name: last } ->
240+ "#{ first } #{ last } "
241+ end )
242+
243+ assert socket . assigns . full_name == "John Doe"
244+
245+ # Change first dependency
246+ socket =
247+ socket
248+ |> Utils . clear_changed ( )
249+ |> assign ( first_name: "Jane" )
250+ |> assign_new ( :full_name , [ :first_name , :last_name ] , fn % { first_name: first , last_name: last } ->
251+ "#{ first } #{ last } "
252+ end )
253+
254+ assert socket . assigns . full_name == "Jane Doe"
255+ assert changed? ( socket , :full_name )
256+
257+ # Change second dependency
258+ socket =
259+ socket
260+ |> Utils . clear_changed ( )
261+ |> assign ( last_name: "Smith" )
262+ |> assign_new ( :full_name , [ :first_name , :last_name ] , fn % { first_name: first , last_name: last } ->
263+ "#{ first } #{ last } "
264+ end )
265+
266+ assert socket . assigns . full_name == "Jane Smith"
267+ assert changed? ( socket , :full_name )
268+ end
269+
270+ test "behaves like assign_new when key doesn't exist" do
271+ socket =
272+ @ socket
273+ |> assign ( user_id: 123 )
274+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
275+
276+ assert socket . assigns . user == "User 123"
277+ assert changed? ( socket , :user )
278+ end
279+
280+ test "uses parent assigns when present" do
281+ socket =
282+ put_in ( @ socket . private [ :assign_new ] , { % { user_id: 999 } , [ ] } )
283+ |> assign ( user_id: 123 )
284+ |> assign_new ( :user , [ :user_id ] , fn % { user_id: user_id } -> "User #{ user_id } " end )
285+
286+ assert socket . assigns . user == "User 123"
287+ assert changed? ( socket , :user )
288+ end
289+ end
290+
173291 describe "assign_new with assigns" do
174292 test "tracks changes" do
175293 assigns = assign_new ( @ assigns_changes , :key , fn -> raise "won't be invoked" end )
0 commit comments