22// Licensed under the Apache License Version 2.0 that can be found in the
33// LICENSE file in the root directory of this source tree.
44
5+ #define private public
6+ #define protected public
7+
58#include < memory>
69#include < unordered_map>
710#include < utility>
1316#include " core/renderer/dom/fiber/component_element.h"
1417#include " core/renderer/dom/fiber/list_element.h"
1518#include " core/renderer/tasm/react/testing/mock_painting_context.h"
16- #include " core/renderer/ui_component/list/default_list_adapter.h"
1719#include " core/renderer/ui_component/list/list_container_impl.h"
1820#include " core/renderer/ui_component/list/testing/mock_diff_result.h"
1921#include " core/renderer/ui_component/list/testing/mock_list_element.h"
@@ -36,9 +38,8 @@ class ListAdapterTest : public ::testing::Test {
3638 std::unique_ptr<lynx::tasm::ElementManager> manager;
3739 std::shared_ptr<::testing::NiceMock<test::MockTasmDelegate>> tasm_mediator;
3840 fml::RefPtr<list::MockListElement> list_element_ref;
39- std::unique_ptr<DefaultListAdapter> default_list_adapter;
4041 std::unique_ptr<ListContainerImpl> list_container;
41- std::unique_ptr< ListChildrenHelper> list_children_helper;
42+ ListChildrenHelper* list_children_helper;
4243
4344 protected:
4445 ListAdapterTest () = default ;
@@ -63,22 +64,7 @@ class ListAdapterTest : public ::testing::Test {
6364 enqueue_component, component_at_indexes));
6465 list_container =
6566 std::make_unique<ListContainerImpl>(list_element_ref.get ());
66- default_list_adapter = std::make_unique<DefaultListAdapter>(
67- list_container.get (), list_element_ref.get ());
68- list_children_helper = std::make_unique<ListChildrenHelper>();
69- }
70-
71- public:
72- fml::RefPtr<Element> CreateListItemElement () {
73- static int32_t base_css_id = 0 ;
74- base::String component_id (std::to_string (++base_css_id));
75- base::String entry_name (" __ListItem__" );
76- base::String component_name (" __ListItem__" );
77- base::String path (" /index/components/ListItem" );
78- auto list_item_ref = manager->CreateFiberComponent (
79- component_id, base_css_id, entry_name, component_name, path);
80- list_element_ref->AddChildAt (list_item_ref, -1 );
81- return list_item_ref;
67+ list_children_helper = list_container->list_children_helper ();
8268 }
8369}; // ListAdapterTest
8470
@@ -94,37 +80,46 @@ TEST_F(ListAdapterTest, DiffCase) {
9480 .sticky_bottoms = {7 , 8 },
9581 .full_spans = {0 , 1 , 7 , 8 },
9682 };
97- default_list_adapter ->UpdateDataSource (
83+ list_container-> list_adapter_ ->UpdateDataSource (
9884 lepus_value (diff_result.GenerateDiffResult ()));
99- EXPECT_EQ (default_list_adapter->list_adapter_helper ()->item_keys ().size (),
85+ EXPECT_EQ (
86+ list_container->list_adapter_ ->list_adapter_helper ()->item_keys ().size (),
87+ diff_result.GetItemCount ());
88+ EXPECT_EQ (list_container->list_adapter_ ->list_adapter_helper ()
89+ ->item_key_map ()
90+ .size (),
10091 diff_result.GetItemCount ());
101- EXPECT_EQ (default_list_adapter-> list_adapter_helper ()-> item_key_map (). size (),
92+ EXPECT_EQ (list_container-> list_adapter_ -> GetDataCount (),
10293 diff_result.GetItemCount ());
103- EXPECT_EQ (default_list_adapter->GetDataCount (), diff_result.GetItemCount ());
104- EXPECT_EQ (default_list_adapter->list_adapter_helper ()
94+ EXPECT_EQ (list_container->list_adapter_ ->list_adapter_helper ()
10595 ->estimated_heights_px ()
10696 .size (),
10797 diff_result.GetItemCount ());
98+ EXPECT_EQ (list_container->list_adapter_ ->list_adapter_helper ()
99+ ->estimated_sizes_px ()
100+ .size (),
101+ diff_result.GetItemCount ());
108102 EXPECT_EQ (
109- default_list_adapter-> list_adapter_helper ()->estimated_sizes_px ().size (),
110- diff_result.GetItemCount ());
111- EXPECT_EQ (default_list_adapter-> list_adapter_helper ()-> full_spans (). size (),
112- diff_result. full_spans . size ());
113- EXPECT_EQ (default_list_adapter-> list_adapter_helper ()-> sticky_tops () .size (),
103+ list_container-> list_adapter_ -> list_adapter_helper ()->full_spans ().size (),
104+ diff_result.full_spans . size ());
105+ EXPECT_EQ (list_container-> list_adapter_ -> list_adapter_helper ()
106+ -> sticky_tops ()
107+ .size (),
114108 diff_result.sticky_tops .size ());
115- EXPECT_EQ (default_list_adapter ->GetStickyTops ().size (),
109+ EXPECT_EQ (list_container-> list_adapter_ ->GetStickyTops ().size (),
116110 diff_result.sticky_tops .size ());
117- EXPECT_EQ (
118- default_list_adapter->list_adapter_helper ()->sticky_bottoms ().size (),
119- diff_result.sticky_bottoms .size ());
120- EXPECT_EQ (default_list_adapter->GetStickyBottoms ().size (),
111+ EXPECT_EQ (list_container->list_adapter_ ->list_adapter_helper ()
112+ ->sticky_bottoms ()
113+ .size (),
114+ diff_result.sticky_bottoms .size ());
115+ EXPECT_EQ (list_container->list_adapter_ ->GetStickyBottoms ().size (),
121116 diff_result.sticky_bottoms .size ());
122- EXPECT_TRUE (default_list_adapter ->HasFullSpanItems ());
123- default_list_adapter-> UpdateItemHolderToLatest (list_children_helper. get () );
117+ EXPECT_TRUE (list_container-> list_adapter_ ->HasFullSpanItems ());
118+ list_container-> list_adapter_ -> UpdateItemHolderToLatest (list_children_helper);
124119 for (int index = 0 ; index < static_cast <int >(diff_result.GetItemCount ());
125120 ++index) {
126121 ItemHolder* item_holder =
127- default_list_adapter ->GetItemHolderForIndex (index);
122+ list_container-> list_adapter_ ->GetItemHolderForIndex (index);
128123 EXPECT_NE (item_holder, nullptr );
129124 if (index == 0 || index == 1 ) {
130125 EXPECT_TRUE (item_holder->sticky_top ());
@@ -134,6 +129,121 @@ TEST_F(ListAdapterTest, DiffCase) {
134129 }
135130}
136131
132+ TEST_F (ListAdapterTest, UpdateAnchorRefItemTest) {
133+ list_container->search_ref_anchor_strategy_ =
134+ list::SearchRefAnchorStrategy::kToStart ;
135+ list::InsertAction insert_action;
136+ list::RemoveAction remove_action;
137+ list::UpdateAction update_action;
138+ insert_action = {.insert_ops_ = {
139+ {.position_ = 0 , " A_0" , 100 , false , false , false , false },
140+ {.position_ = 1 , " B_1" , 100 , false , false , false , false },
141+ {.position_ = 2 , " C_2" , 100 , false , false , false , false },
142+ {.position_ = 3 , " D_3" , 100 , false , false , false , false },
143+ {.position_ = 4 , " E_4" , 100 , false , false , false , false },
144+ {.position_ = 5 , " F_5" , 100 , false , false , false , false },
145+ {.position_ = 6 , " G_6" , 100 , false , false , false , false },
146+ {.position_ = 7 , " H_7" , 100 , false , false , false , false },
147+ {.position_ = 8 , " I_8" , 100 , false , false , false , false },
148+ {.position_ = 9 , " J_9" , 100 , false , false , false , false },
149+ }};
150+ list::FiberDiffResult fiber_diff_result_0{
151+ .insert_action_ = insert_action,
152+ };
153+ list_container->list_adapter_ ->UpdateFiberDataSource (
154+ lepus::Value (fiber_diff_result_0.Resolve ()));
155+ list_container->list_adapter_ ->UpdateItemHolderToLatest (list_children_helper);
156+
157+ // init on screen children: E_4, F_5, G_6, H_7
158+ list_children_helper->on_screen_children_ .insert (
159+ list_container->GetItemHolderForIndex (4 ));
160+ list_children_helper->on_screen_children_ .insert (
161+ list_container->GetItemHolderForIndex (5 ));
162+ list_children_helper->on_screen_children_ .insert (
163+ list_container->GetItemHolderForIndex (6 ));
164+ list_children_helper->on_screen_children_ .insert (
165+ list_container->GetItemHolderForIndex (7 ));
166+
167+ // remove C_2, E_4, F_5, H_7
168+ // insert New_A_0, New_B_1, New_C_2, New_D_3
169+ insert_action = {
170+ .insert_ops_ = {
171+ {.position_ = 2 , " New_A_0" , 100 , false , false , false , false },
172+ {.position_ = 3 , " New_B_1" , 100 , false , false , false , false },
173+ {.position_ = 4 , " New_C_2" , 100 , false , false , false , false },
174+ {.position_ = 5 , " New_D_3" , 100 , false , false , false , false },
175+ }};
176+ remove_action = {
177+ .remove_ops_ = {2 , 4 , 5 , 7 },
178+ };
179+ list::FiberDiffResult fiber_diff_result_1{
180+ .insert_action_ = insert_action,
181+ .remove_action_ = remove_action,
182+ };
183+ list_container->list_adapter_ ->UpdateFiberDataSource (
184+ lepus::Value (fiber_diff_result_1.Resolve ()));
185+ list_container->list_adapter_ ->UpdateItemHolderToLatest (list_children_helper);
186+
187+ ItemHolder* holder_C2 =
188+ list_container->list_adapter_ ->item_holder_map_ ->at (" C_2" ).get ();
189+ ItemHolder* holder_E4 =
190+ list_container->list_adapter_ ->item_holder_map_ ->at (" E_4" ).get ();
191+ ItemHolder* holder_F5 =
192+ list_container->list_adapter_ ->item_holder_map_ ->at (" F_5" ).get ();
193+ ItemHolder* holder_G6 =
194+ list_container->list_adapter_ ->item_holder_map_ ->at (" G_6" ).get ();
195+ ItemHolder* holder_H7 =
196+ list_container->list_adapter_ ->item_holder_map_ ->at (" H_7" ).get ();
197+ // C_2 is not on screen children set, so it has no anchor ref item.
198+ EXPECT_EQ (holder_C2->weak_anchor_ref ().has_value (), false );
199+ // E_4 and F_5 are on screen children set and they are removed in this diff,
200+ // so they have anchor ref item with D_3.
201+ EXPECT_EQ (holder_E4->weak_anchor_ref ().has_value (), true );
202+ EXPECT_TRUE (holder_E4->weak_anchor_ref ().value ()->item_key () == " D_3" );
203+ EXPECT_EQ (holder_F5->weak_anchor_ref ().has_value (), true );
204+ EXPECT_TRUE (holder_F5->weak_anchor_ref ().value ().get ()->item_key () == " D_3" );
205+ // G_6 is not removed in this diff, so it has no anchor ref item.
206+ EXPECT_EQ (holder_G6->weak_anchor_ref ().has_value (), false );
207+ // H_7 is on screen children set and removed in this diff, so it has anchor
208+ // ref item with G_6.
209+ EXPECT_EQ (holder_H7->weak_anchor_ref ().has_value (), true );
210+ EXPECT_TRUE (holder_H7->weak_anchor_ref ().value ().get ()->item_key () == " G_6" );
211+
212+ // remove D_3
213+ remove_action = {
214+ .remove_ops_ = {6 },
215+ };
216+ list::FiberDiffResult fiber_diff_result_2{
217+ .remove_action_ = remove_action,
218+ };
219+ list_container->list_adapter_ ->UpdateFiberDataSource (
220+ lepus::Value (fiber_diff_result_2.Resolve ()));
221+ list_container->list_adapter_ ->UpdateItemHolderToLatest (list_children_helper);
222+ // D_3 is removed in this diff, so E_4 and F_5 should update anchor ref item
223+ // to New_D_3.
224+ EXPECT_EQ (holder_E4->weak_anchor_ref ().has_value (), true );
225+ EXPECT_TRUE (holder_E4->weak_anchor_ref ().value ()->item_key () == " New_D_3" );
226+ EXPECT_EQ (holder_F5->weak_anchor_ref ().has_value (), true );
227+ EXPECT_TRUE (holder_F5->weak_anchor_ref ().value ()->item_key () == " New_D_3" );
228+
229+ // remove G_6
230+ remove_action = {
231+ .remove_ops_ = {6 },
232+ };
233+ list::FiberDiffResult fiber_diff_result_3{
234+ .remove_action_ = remove_action,
235+ };
236+ list_container->list_adapter_ ->UpdateFiberDataSource (
237+ lepus::Value (fiber_diff_result_3.Resolve ()));
238+ list_container->list_adapter_ ->UpdateItemHolderToLatest (list_children_helper);
239+ // G_6 is removed in this diff, so G_6 and H_7 should update anchor ref item
240+ // to New_G_6.
241+ EXPECT_EQ (holder_G6->weak_anchor_ref ().has_value (), true );
242+ EXPECT_TRUE (holder_G6->weak_anchor_ref ().value ()->item_key () == " New_D_3" );
243+ EXPECT_EQ (holder_H7->weak_anchor_ref ().has_value (), true );
244+ EXPECT_TRUE (holder_H7->weak_anchor_ref ().value ()->item_key () == " New_D_3" );
245+ }
246+
137247} // namespace testing
138248} // namespace tasm
139249} // namespace lynx
0 commit comments