11defmodule Cinder.Integration.AsyncLoadTest do
22 @ moduledoc """
3- Covers the async data-loading path end-to-end .
3+ Covers opt-in server-rendered initial data with async loading enabled .
44
55 Every other integration test loads data synchronously (see `Cinder.ConnCase`)
6- for simplicity. This test opts back into Cinder's default `start_async` loading
7- to prove the full async cycle works: the view mounts, the async query runs in a
8- separate task, replies, and the rows appear on re-render.
6+ for simplicity. This test opts back into Cinder's default async mode and
7+ verifies the global and per-collection SSR settings.
98 """
109 use Cinder.ConnCase , async: false
10+ import Phoenix.ConnTest , only: [ get: 2 , html_response: 2 ]
1111
1212 # Opt back into async loading for this test (ConnCase's setup disabled it).
1313 setup { Cinder.TestHelpers , :enable_async_loading }
1414
15- defp album_collection ( assigns ) do
15+ defp restore_ssr_config ( nil ) , do: Application . delete_env ( :cinder , :ssr )
16+ defp restore_ssr_config ( value ) , do: Application . put_env ( :cinder , :ssr , value )
17+
18+ defp ssr_album_collection ( assigns ) do
19+ ~H"""
20+ < Cinder . collection resource = { Cinder.Integration.Album } url_state = { @ url_state } ssr >
21+ <: col :let = { album } field = "title " sort > { album . title } </: col >
22+ </ Cinder . collection >
23+ """
24+ end
25+
26+ defp default_album_collection ( assigns ) do
1627 ~H"""
1728 < Cinder . collection resource = { Cinder.Integration.Album } url_state = { @ url_state } >
1829 <: col :let = { album } field = "title " sort > { album . title } </: col >
1930 </ Cinder . collection >
2031 """
2132 end
2233
34+ defp async_album_collection ( assigns ) do
35+ ~H"""
36+ < Cinder . collection resource = { Cinder.Integration.Album } url_state = { @ url_state } ssr = { false } >
37+ <: col :let = { album } field = "title " sort > { album . title } </: col >
38+ </ Cinder . collection >
39+ """
40+ end
41+
42+ defp failing_ssr_assigns do
43+ % {
44+ id: "failing-ssr-collection" ,
45+ query: Cinder.Integration.Album ,
46+ action: :missing_read_action ,
47+ actor: nil ,
48+ tenant: nil ,
49+ page_size_config: Cinder.PageSize . parse ( nil ) ,
50+ theme: Cinder.Theme . default ( ) ,
51+ url_raw_params: % { } ,
52+ query_opts: [ ] ,
53+ ssr: true ,
54+ on_state_change: nil ,
55+ col: [ ] ,
56+ query_columns: [ ] ,
57+ search_fn: nil
58+ }
59+ end
60+
2361 setup do
2462 artist = generate ( artist ( name: "Async Artist" ) )
2563 generate ( album ( title: "Async Album" , genre: :rock , artist_id: artist . id ) )
@@ -29,14 +67,76 @@ defmodule Cinder.Integration.AsyncLoadTest do
2967 Ash . bulk_destroy! ( Cinder.Integration.Artist , :destroy , % { } )
3068 end )
3169
32- % { path: Cinder.TestLive.Fixture . register ( & album_collection / 1 ) }
70+ % {
71+ ssr_path: Cinder.TestLive.Fixture . register ( & ssr_album_collection / 1 ) ,
72+ default_path: Cinder.TestLive.Fixture . register ( & default_album_collection / 1 ) ,
73+ async_path: Cinder.TestLive.Fixture . register ( & async_album_collection / 1 )
74+ }
75+ end
76+
77+ test "ssr=true includes collection data in the initial HTTP response" , % {
78+ conn: conn ,
79+ ssr_path: path
80+ } do
81+ html =
82+ conn
83+ |> get ( path )
84+ |> html_response ( 200 )
85+
86+ assert html =~ "Async Album"
3387 end
3488
35- test "rows appear after the async query resolves" , % { conn: conn , path: path } do
89+ test "SSR is disabled by default" , % { conn: conn , default_path: path } do
90+ html =
91+ conn
92+ |> get ( path )
93+ |> html_response ( 200 )
94+
95+ refute html =~ "Async Album"
96+ end
97+
98+ test "the default async load still delivers collection data" , % { conn: conn , default_path: path } do
3699 conn
37100 |> visit ( path )
38- # The data is not present on the first synchronous render; it arrives only
39- # after the start_async task replies, so we wait for it with a timeout.
40101 |> assert_has ( "td" , text: "Async Album" , timeout: 1000 )
41102 end
103+
104+ test "SSR can be enabled globally" , % { conn: conn , default_path: path } do
105+ original = Application . get_env ( :cinder , :ssr )
106+ Application . put_env ( :cinder , :ssr , true )
107+ on_exit ( fn -> restore_ssr_config ( original ) end )
108+
109+ html =
110+ conn
111+ |> get ( path )
112+ |> html_response ( 200 )
113+
114+ assert html =~ "Async Album"
115+ end
116+
117+ test "a collection setting overrides the global setting" , % { conn: conn , async_path: path } do
118+ original = Application . get_env ( :cinder , :ssr )
119+ Application . put_env ( :cinder , :ssr , true )
120+ on_exit ( fn -> restore_ssr_config ( original ) end )
121+
122+ html =
123+ conn
124+ |> get ( path )
125+ |> html_response ( 200 )
126+
127+ refute html =~ "Async Album"
128+ end
129+
130+ test "a retry is asynchronous after the initial SSR query fails" do
131+ { :ok , socket } = Cinder.LiveComponent . mount ( % Phoenix.LiveView.Socket { } )
132+ { :ok , socket } = Cinder.LiveComponent . update ( failing_ssr_assigns ( ) , socket )
133+
134+ assert socket . assigns . error
135+ assert socket . assigns . page == nil
136+
137+ { :noreply , socket } = Cinder.LiveComponent . handle_event ( "refresh" , % { } , socket )
138+
139+ assert socket . assigns . loading
140+ refute socket . assigns . error
141+ end
42142end
0 commit comments