1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "list_test_ng.h"
17 #include "test/mock/core/pipeline/mock_pipeline_context.h"
18 #include "test/mock/core/rosen/mock_canvas.h"
19 
20 #include "core/components_ng/pattern/list/list_item_group_paint_method.h"
21 #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
22 
23 namespace OHOS::Ace::NG {
24 
25 namespace {} // namespace
26 
27 class ListLayoutTestNg : public ListTestNg {
28 public:
29     void UpdateContentModifier();
30     RefPtr<ListPaintMethod> UpdateOverlayModifier(RefPtr<PaintWrapper> paintWrapper);
31     void UpdateDividerMap();
32     void PaintDivider(RefPtr<PaintWrapper> paintWrapper, int32_t expectLineNumber, bool isClip = false);
33     void GroupPaintDivider(RefPtr<PaintWrapper> paintWrapper, int32_t expectLineNumber);
34 };
35 
UpdateContentModifier()36 void ListLayoutTestNg::UpdateContentModifier()
37 {
38     RefPtr<NodePaintMethod> paint = pattern_->CreateNodePaintMethod();
39     RefPtr<ListPaintMethod> listPaint = AceType::DynamicCast<ListPaintMethod>(paint);
40     auto paintWrapper = frameNode_->CreatePaintWrapper();
41     listPaint->UpdateContentModifier(AceType::RawPtr(paintWrapper));
42 }
43 
UpdateOverlayModifier(RefPtr<PaintWrapper> paintWrapper)44 RefPtr<ListPaintMethod> ListLayoutTestNg::UpdateOverlayModifier(RefPtr<PaintWrapper> paintWrapper)
45 {
46     auto paintMethod = AceType::DynamicCast<ListPaintMethod>(paintWrapper->nodePaintImpl_);
47     paintMethod->UpdateOverlayModifier(AceType::RawPtr(paintWrapper));
48     return paintMethod;
49 }
50 
UpdateDividerMap()51 void ListLayoutTestNg::UpdateDividerMap()
52 {
53     int cur = 0;
54     for (auto& child : pattern_->itemPosition_) {
55         child.second.id += cur;
56         cur++;
57     }
58     UpdateContentModifier();
59 }
60 
PaintDivider(RefPtr<PaintWrapper> paintWrapper,int32_t expectLineNumber,bool isClip)61 void ListLayoutTestNg::PaintDivider(RefPtr<PaintWrapper> paintWrapper, int32_t expectLineNumber, bool isClip)
62 {
63     auto paintMethod = AceType::DynamicCast<ListPaintMethod>(paintWrapper->nodePaintImpl_);
64     auto modifier = paintMethod->GetContentModifier(nullptr);
65     auto listContentModifier = AceType::DynamicCast<ListContentModifier>(modifier);
66     Testing::MockCanvas canvas;
67     EXPECT_CALL(canvas, ClipRect(_, _, _)).Times(isClip ? 1 : 0);
68     EXPECT_CALL(canvas, AttachBrush(_)).WillRepeatedly(ReturnRef(canvas));
69     EXPECT_CALL(canvas, AttachPen(_)).WillRepeatedly(ReturnRef(canvas));
70     EXPECT_CALL(canvas, DetachBrush()).WillRepeatedly(ReturnRef(canvas));
71     EXPECT_CALL(canvas, DetachPen()).WillRepeatedly(ReturnRef(canvas));
72     EXPECT_CALL(canvas, DrawLine(_, _)).Times(expectLineNumber); // DrawLine
73     DrawingContext drawingContext = { canvas, LIST_WIDTH, LIST_HEIGHT };
74     paintMethod->UpdateContentModifier(AceType::RawPtr(paintWrapper));
75     listContentModifier->onDraw(drawingContext);
76 }
77 
GroupPaintDivider(RefPtr<PaintWrapper> paintWrapper,int32_t expectLineNumber)78 void ListLayoutTestNg::GroupPaintDivider(RefPtr<PaintWrapper> paintWrapper, int32_t expectLineNumber)
79 {
80     auto paintMethod = AceType::DynamicCast<ListItemGroupPaintMethod>(paintWrapper->nodePaintImpl_);
81     Testing::MockCanvas canvas;
82     EXPECT_CALL(canvas, AttachBrush(_)).WillRepeatedly(ReturnRef(canvas));
83     EXPECT_CALL(canvas, AttachPen(_)).WillRepeatedly(ReturnRef(canvas));
84     EXPECT_CALL(canvas, DetachBrush()).WillRepeatedly(ReturnRef(canvas));
85     EXPECT_CALL(canvas, DetachPen()).WillRepeatedly(ReturnRef(canvas));
86     EXPECT_CALL(canvas, DrawLine(_, _)).Times(expectLineNumber); // DrawLine
87     paintMethod->PaintDivider(AceType::RawPtr(paintWrapper), canvas);
88 }
89 
90 /**
91  * @tc.name: GetOverScrollOffset001
92  * @tc.desc: Test GetOverScrollOffset
93  * @tc.type: FUNC
94  */
95 HWTEST_F(ListLayoutTestNg, GetOverScrollOffset001, TestSize.Level1)
96 {
97     /**
98      * @tc.steps: step1. !IsScrollSnapAlignCenter
99      */
100     CreateList();
101     CreateListItemGroups(2);
102     CreateDone(frameNode_);
103     OverScrollOffset offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
104     OverScrollOffset expectOffset = { ITEM_HEIGHT, 0 };
105     EXPECT_TRUE(IsEqual(offset, expectOffset));
106     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT);
107     expectOffset = { 0, -ITEM_HEIGHT };
108     EXPECT_TRUE(IsEqual(offset, expectOffset));
109 
110     ScrollTo(ITEM_HEIGHT);
111     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
112     expectOffset = { ITEM_HEIGHT, 0 };
113     EXPECT_TRUE(IsEqual(offset, expectOffset));
114     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT);
115     expectOffset = { 0, -ITEM_HEIGHT };
116     EXPECT_TRUE(IsEqual(offset, expectOffset));
117 
118     /**
119      * @tc.steps: step2. !IsScrollSnapAlignCenter
120      */
121     ClearOldNodes();
122     CreateList();
123     CreateListItemGroups(1);
124     CreateDone(frameNode_);
125     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT * 5);
126     expectOffset = { 500, 0 };
127     EXPECT_TRUE(IsEqual(offset, expectOffset));
128     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT);
129     expectOffset = { 0, -ITEM_HEIGHT };
130     EXPECT_TRUE(IsEqual(offset, expectOffset));
131 
132     ScrollTo(ITEM_HEIGHT);
133     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
134     expectOffset = { ITEM_HEIGHT, 0 };
135     EXPECT_TRUE(IsEqual(offset, expectOffset));
136     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT);
137     expectOffset = { 0, -ITEM_HEIGHT };
138     EXPECT_TRUE(IsEqual(offset, expectOffset));
139 
140     /**
141      * @tc.steps: step3. IsScrollSnapAlignCenter
142      */
143     ClearOldNodes();
144     ListModelNG model = CreateList();
145     model.SetScrollSnapAlign(V2::ScrollSnapAlign::CENTER);
146     CreateListItemGroups(2);
147     CreateDone(frameNode_);
148     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
149     expectOffset = { ITEM_HEIGHT, 0 };
150     EXPECT_TRUE(IsEqual(offset, expectOffset));
151     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT);
152     expectOffset = { 0, 0 };
153     EXPECT_TRUE(IsEqual(offset, expectOffset));
154 
155     UpdateCurrentOffset(-ITEM_HEIGHT);
156     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
157     expectOffset = { 0, 0 };
158     EXPECT_TRUE(IsEqual(offset, expectOffset));
159     offset = pattern_->GetOverScrollOffset(-ITEM_HEIGHT * 4);
160     expectOffset = { 0, -ITEM_HEIGHT * 3 };
161     EXPECT_TRUE(IsEqual(offset, expectOffset));
162 
163     /**
164      * @tc.steps: step4. has no group, groupAtStart and groupAtEnd are false
165      */
166     ClearOldNodes();
167     CreateList();
168     CreateListItems(TOTAL_ITEM_NUMBER);
169     CreateDone(frameNode_);
170     offset = pattern_->GetOverScrollOffset(ITEM_HEIGHT);
171     expectOffset = { ITEM_HEIGHT, 0 };
172     EXPECT_TRUE(IsEqual(offset, expectOffset));
173 }
174 
175 /**
176  * @tc.name: ContentEndOffset001
177  * @tc.desc: Test ContentEndOffset should change behavior of IsAtBottom
178  * @tc.type: FUNC
179  */
180 HWTEST_F(ListLayoutTestNg, ContentEndOffset001, TestSize.Level1)
181 {
182     /**
183      * @tc.steps: step1. create List
184      */
185     ListModelNG model = CreateList();
186     model.SetScrollBar(DisplayMode::ON);
187     model.SetEdgeEffect(EdgeEffect::FADE, false);
188     model.SetContentEndOffset(100);
189     // total height = 1600
190     CreateListItems(16);
191     CreateDone(frameNode_);
192     std::vector<int32_t> scrollFromVector = { SCROLL_FROM_NONE, SCROLL_FROM_UPDATE, SCROLL_FROM_ANIMATION,
193         SCROLL_FROM_JUMP, SCROLL_FROM_ANIMATION_SPRING, SCROLL_FROM_BAR, SCROLL_FROM_ANIMATION_CONTROLLER,
194         SCROLL_FROM_BAR_FLING };
195 
196     // ~ -1200 to reach bottom if no contentEndOffset
197     EXPECT_TRUE(pattern_->UpdateCurrentOffset(-1195, SCROLL_FROM_UPDATE));
198     FlushLayoutTask(frameNode_);
199     EXPECT_FALSE(pattern_->IsAtBottom());
200 
201     // contentEndOffset_ takes 100 extra offset to reach bottom
202     EXPECT_TRUE(pattern_->UpdateCurrentOffset(-50, SCROLL_FROM_UPDATE));
203     FlushLayoutTask(frameNode_);
204     EXPECT_FALSE(pattern_->IsAtBottom());
205 
206     EXPECT_TRUE(pattern_->UpdateCurrentOffset(-100, SCROLL_FROM_UPDATE));
207     FlushLayoutTask(frameNode_);
208     EXPECT_TRUE(pattern_->IsAtBottom());
209 }
210 
211 /**
212  * @tc.name: ContentOffset001
213  * @tc.desc: Test top content offset and bottom end offset
214  * @tc.type: FUNC
215  */
216 HWTEST_F(ListLayoutTestNg, ContentOffset001, TestSize.Level1)
217 {
218     /**
219      * @tc.steps: step1. create List
220      * @tc.expected: Total Offset is negative contentStartOffset.
221      */
222     const int32_t itemNumber = 10;
223     const float contentStartOffset = 100;
224     const float contentEndOffset = 50;
225     ListModelNG model = CreateList();
226     model.SetContentStartOffset(contentStartOffset);
227     model.SetContentEndOffset(contentEndOffset);
228     CreateListItems(itemNumber);
229     CreateDone(frameNode_);
230     for (int32_t index = 0; index < 3; index++) {
231         EXPECT_EQ(GetChildRect(frameNode_, index).GetY(), contentStartOffset + index * ITEM_HEIGHT);
232     }
233 
234     float offset = pattern_->GetTotalOffset();
235     EXPECT_FLOAT_EQ(offset, -contentStartOffset);
236 
237     /**
238      * @tc.steps: step2. scroll to bottom
239      * @tc.expected: Bottom content offset equal to contentEndOffset.
240      */
241     ScrollToEdge(ScrollEdgeType::SCROLL_BOTTOM);
242     offset = pattern_->GetTotalOffset();
243     EXPECT_FLOAT_EQ(offset, itemNumber * ITEM_HEIGHT - LIST_HEIGHT + contentEndOffset);
244 
245     /**
246      * @tc.steps: step3. scroll to top
247      * @tc.expected: Bottom content offset equal to contentEndOffset.
248      */
249     ScrollToEdge(ScrollEdgeType::SCROLL_TOP);
250     offset = pattern_->GetTotalOffset();
251     EXPECT_FLOAT_EQ(offset, -contentStartOffset);
252 }
253 
254 /**
255  * @tc.name: ContentOffset002
256  * @tc.desc: Test scroll to Index with content offset
257  * @tc.type: FUNC
258  */
259 HWTEST_F(ListLayoutTestNg, ContentOffset002, TestSize.Level1)
260 {
261     /**
262      * @tc.steps: step1. create List
263      */
264     const int32_t itemNumber = 20;
265     const float contentStartOffset = 100;
266     const float contentEndOffset = 50;
267     ListModelNG model = CreateList();
268     model.SetContentStartOffset(contentStartOffset);
269     model.SetContentEndOffset(contentEndOffset);
270     CreateListItems(itemNumber);
271     CreateDone(frameNode_);
272 
273     /**
274      * @tc.steps: step2. scroll to target item align start.
275      * @tc.expected: check whether the offset is correct.
276      */
277     EXPECT_TRUE(ScrollToIndex(0, false, ScrollAlign::START, -contentStartOffset));
278     EXPECT_TRUE(ScrollToIndex(1, false, ScrollAlign::START, ITEM_HEIGHT - contentStartOffset));
279     EXPECT_TRUE(ScrollToIndex(2, false, ScrollAlign::START, ITEM_HEIGHT * 2 - contentStartOffset));
280     ScrollToIndex(0, true, ScrollAlign::START);
281     EXPECT_EQ(pattern_->GetTotalOffset(), -contentStartOffset);
282     ScrollToIndex(1, true, ScrollAlign::START);
283     EXPECT_EQ(pattern_->GetTotalOffset(), ITEM_HEIGHT - contentStartOffset);
284     ScrollToIndex(2, true, ScrollAlign::START);
285     EXPECT_EQ(pattern_->GetTotalOffset(), ITEM_HEIGHT * 2 - contentStartOffset);
286 
287     /**
288      * @tc.steps: step3. scroll to target item align end.
289      * @tc.expected: check whether the offset is correct.
290      */
291     const float MAX_OFFSET = itemNumber * ITEM_HEIGHT - LIST_HEIGHT + contentEndOffset;
292     EXPECT_TRUE(ScrollToIndex(itemNumber - 1, false, ScrollAlign::END, MAX_OFFSET));
293     EXPECT_TRUE(ScrollToIndex(itemNumber - 2, false, ScrollAlign::END, MAX_OFFSET - ITEM_HEIGHT));
294     EXPECT_TRUE(ScrollToIndex(itemNumber - 3, false, ScrollAlign::END, MAX_OFFSET - ITEM_HEIGHT * 2));
295     ScrollToIndex(itemNumber - 1, true, ScrollAlign::END);
296     EXPECT_EQ(pattern_->GetTotalOffset(), MAX_OFFSET);
297     ScrollToIndex(itemNumber - 2, true, ScrollAlign::END);
298     EXPECT_EQ(pattern_->GetTotalOffset(), MAX_OFFSET - ITEM_HEIGHT);
299     ScrollToIndex(itemNumber - 3, true, ScrollAlign::END);
300     EXPECT_EQ(pattern_->GetTotalOffset(), MAX_OFFSET - ITEM_HEIGHT * 2);
301 }
302 
303 /**
304  * @tc.name: ContentOffset003
305  * @tc.desc: Test scroll to ListItemGroup with content offset
306  * @tc.type: FUNC
307  */
308 HWTEST_F(ListLayoutTestNg, ContentOffset003, TestSize.Level1)
309 {
310     /**
311      * @tc.steps: step1. create List
312      */
313     const int32_t GroupNumber = 5;
314     const float contentStartOffset = 100;
315     const float contentEndOffset = 50;
316     ListModelNG model = CreateList();
317     model.SetContentStartOffset(contentStartOffset);
318     model.SetContentEndOffset(contentEndOffset);
319     CreateListItemGroups(GroupNumber);
320     CreateDone(frameNode_);
321 
322     /**
323      * @tc.steps: step2. scroll to target group align start.
324      * @tc.expected: check whether the offset is correct.
325      */
326     for (int32_t i = 0; i < 3; i++) {
327         ScrollToIndex(i, false, ScrollAlign::START);
328         EXPECT_EQ(GetChildRect(frameNode_, i).GetY(), contentStartOffset);
329     }
330     for (int32_t i = 0; i < 3; i++) {
331         ScrollToIndex(i, true, ScrollAlign::START);
332         EXPECT_EQ(GetChildRect(frameNode_, i).GetY(), contentStartOffset);
333     }
334 
335     /**
336      * @tc.steps: step3. scroll to target group align end.
337      * @tc.expected: check whether the offset is correct.
338      */
339     for (int32_t i = 0; i < 3; i++) {
340         int32_t index = GroupNumber - i - 1;
341         ScrollToIndex(index, false, ScrollAlign::END);
342         auto rect = GetChildRect(frameNode_, index);
343         EXPECT_EQ(rect.Bottom(), LIST_HEIGHT - contentEndOffset);
344     }
345     for (int32_t i = 0; i < 3; i++) {
346         int32_t index = GroupNumber - i - 1;
347         ScrollToIndex(index, true, ScrollAlign::END);
348         auto rect = GetChildRect(frameNode_, index);
349         EXPECT_EQ(rect.Bottom(), LIST_HEIGHT - contentEndOffset);
350     }
351 }
352 
353 /**
354  * @tc.name: ContentOffset004
355  * @tc.desc: Test ListItemGroup Sticky postion
356  * @tc.type: FUNC
357  */
358 HWTEST_F(ListLayoutTestNg, ContentOffset004, TestSize.Level1)
359 {
360     /**
361      * @tc.steps: step1. create List
362      */
363     const int32_t groupNumber = 5;
364     const float contentStartOffset = 100;
365     const float contentEndOffset = 50;
366     ListModelNG model = CreateList();
367     model.SetContentStartOffset(contentStartOffset);
368     model.SetContentEndOffset(contentEndOffset);
369     CreateGroupWithSetting(groupNumber, V2::ListItemGroupStyle::NONE);
370     CreateDone(frameNode_);
371 
372     /**
373      * @tc.steps: step2. Scroll To ListItem in group.
374      * @tc.expected: ListItem position is correct.
375      */
376     ScrollToItemInGroup(1, 0, false, ScrollAlign::START);
377     auto group1 = GetChildFrameNode(frameNode_, 1);
378     auto groupRect = group1->GetGeometryNode()->GetFrameRect();
379     float groupPos = groupRect.Top();
380     auto item1Rect = GetChildRect(group1, 2);
381     EXPECT_EQ(item1Rect.Top(), contentStartOffset - groupPos);
382 
383     ScrollToItemInGroup(2, 1, false, ScrollAlign::END);
384     auto group2 = GetChildFrameNode(frameNode_, 2);
385     groupPos = group2->GetGeometryNode()->GetFrameRect().Top();
386     auto item2Rect = GetChildRect(group1, 3);
387     EXPECT_EQ(item2Rect.Bottom(), LIST_HEIGHT - contentEndOffset - groupPos);
388 
389     ScrollToItemInGroup(1, 0, true, ScrollAlign::START);
390     group1 = GetChildFrameNode(frameNode_, 1);
391     groupRect = group1->GetGeometryNode()->GetFrameRect();
392     groupPos = groupRect.Top();
393     item1Rect = GetChildRect(group1, 2);
394     EXPECT_EQ(item1Rect.Top(), contentStartOffset - groupPos);
395 
396     ScrollToItemInGroup(2, 1, true, ScrollAlign::END);
397     group2 = GetChildFrameNode(frameNode_, 2);
398     groupPos = group2->GetGeometryNode()->GetFrameRect().Top();
399     item2Rect = GetChildRect(group1, 3);
400     EXPECT_EQ(item2Rect.Bottom(), LIST_HEIGHT - contentEndOffset - groupPos);
401 }
402 
403 /**
404  * @tc.name: ContentOffset005
405  * @tc.desc: Test ListItemGroup Sticky postion
406  * @tc.type: FUNC
407  */
408 HWTEST_F(ListLayoutTestNg, ContentOffset005, TestSize.Level1)
409 {
410     /**
411      * @tc.steps: step1. create List
412      */
413     const int32_t groupNumber = 5;
414     const float contentStartOffset = 100;
415     const float contentEndOffset = 50;
416     ListModelNG model = CreateList();
417     model.SetContentStartOffset(contentStartOffset);
418     model.SetContentEndOffset(contentEndOffset);
419     model.SetSticky(V2::StickyStyle::BOTH);
420     CreateGroupWithSetting(groupNumber, V2::ListItemGroupStyle::NONE);
421     CreateDone(frameNode_);
422 
423     /**
424      * @tc.steps: step2. scroll by 100.
425      * @tc.expected: header stick postion and footer sticky postion is correct.
426      */
427     pattern_->UpdateCurrentOffset(-100, SCROLL_FROM_UPDATE);
428     FlushLayoutTask(frameNode_);
429     auto group0 = GetChildFrameNode(frameNode_, 0);
430     auto groupPos = group0->GetGeometryNode()->GetFrameRect().Top();
431     auto header0Rect = GetChildRect(group0, 0);
432     EXPECT_EQ(header0Rect.Top(), contentStartOffset - groupPos);
433 
434     auto group1 = GetChildFrameNode(frameNode_, 1);
435     groupPos = group1->GetGeometryNode()->GetFrameRect().Top();
436     auto footer1Rect = GetChildRect(group1, 1);
437     EXPECT_EQ(footer1Rect.Bottom(), 100.f);
438 
439     /**
440      * @tc.steps: step3. Scroll To ListItem in group.
441      * @tc.expected: ListItem position is correct.
442      */
443     ScrollToItemInGroup(1, 0, false, ScrollAlign::START);
444     group1 = GetChildFrameNode(frameNode_, 1);
445     groupPos = group1->GetGeometryNode()->GetFrameRect().Top();
446     auto item1Rect = GetChildRect(group1, 2);
447     EXPECT_EQ(item1Rect.Top(), contentStartOffset + GROUP_HEADER_LEN - groupPos);
448 
449     ScrollToItemInGroup(2, 1, false, ScrollAlign::END);
450     auto group2 = GetChildFrameNode(frameNode_, 2);
451     groupPos = group2->GetGeometryNode()->GetFrameRect().Top();
452     auto item2Rect = GetChildRect(group2, 3);
453     EXPECT_EQ(item2Rect.Bottom(), LIST_HEIGHT - contentEndOffset - GROUP_HEADER_LEN - groupPos);
454 
455     ScrollToItemInGroup(1, 0, true, ScrollAlign::START);
456     group1 = GetChildFrameNode(frameNode_, 1);
457     groupPos = group1->GetGeometryNode()->GetFrameRect().Top();
458     item1Rect = GetChildRect(group1, 2);
459     EXPECT_EQ(item1Rect.Top(), contentStartOffset + GROUP_HEADER_LEN - groupPos);
460 
461     ScrollToItemInGroup(2, 1, true, ScrollAlign::END);
462     group2 = GetChildFrameNode(frameNode_, 2);
463     groupPos = group2->GetGeometryNode()->GetFrameRect().Top();
464     item2Rect = GetChildRect(group2, 3);
465     EXPECT_EQ(item2Rect.Bottom(), LIST_HEIGHT - contentEndOffset - GROUP_HEADER_LEN - groupPos);
466 }
467 
468 /**
469  * @tc.name: ContentOffset006
470  * @tc.desc: Test top content offset and bottom end offset
471  * @tc.type: FUNC
472  */
473 HWTEST_F(ListLayoutTestNg, ContentOffset006, TestSize.Level1)
474 {
475     /**
476      * @tc.steps: step1. create List with ScrollSnapAlign START
477      * @tc.expected:
478      */
479     const int32_t itemNumber = 20;
480     const float contentStartOffset = 100;
481     const float contentEndOffset = 50;
482     ListModelNG model = CreateList();
483     model.SetContentStartOffset(contentStartOffset);
484     model.SetContentEndOffset(contentEndOffset);
485     model.SetScrollSnapAlign(V2::ScrollSnapAlign::START);
486     CreateListItems(itemNumber);
487     CreateDone(frameNode_);
488 
489     /**
490      * @tc.steps: step2. scroll snap
491      * @tc.expected: item top snap to contentEndOffset.
492      */
493     ScrollSnap(-120, 0);
494     EXPECT_FLOAT_EQ(pattern_->GetTotalOffset(), ITEM_HEIGHT - contentStartOffset);
495     ScrollSnap(-80, 0);
496     EXPECT_FLOAT_EQ(pattern_->GetTotalOffset(), ITEM_HEIGHT * 2 - contentStartOffset);
497 
498     /**
499      * @tc.steps: step3. change scroll snap to END
500      * @tc.expected: item bottom snap to contentEndOffset.
501      */
502     ClearOldNodes();
503     model = CreateList();
504     model.SetContentStartOffset(contentStartOffset);
505     model.SetContentEndOffset(contentEndOffset);
506     model.SetScrollSnapAlign(V2::ScrollSnapAlign::END);
507     CreateListItems(itemNumber);
508     CreateDone(frameNode_);
509     ScrollSnap(-40, 0);
510     EXPECT_FLOAT_EQ(pattern_->GetTotalOffset(), -100);
511     ScrollSnap(-110, 0);
512     EXPECT_FLOAT_EQ(pattern_->GetTotalOffset(), 50);
513 }
514 
515 /**
516  * @tc.name: ContentOffset007
517  * @tc.desc: Test List edge check
518  * @tc.type: FUNC
519  */
520 HWTEST_F(ListLayoutTestNg, ContentOffset007, TestSize.Level1)
521 {
522     /**
523      * @tc.steps: step1. create List with ScrollSnapAlign START
524      * @tc.expected: not OutOfBoundary
525      */
526     const float contentStartOffset = 50;
527     const float contentEndOffset = 50;
528     ListModelNG model = CreateList();
529     model.SetContentStartOffset(contentStartOffset);
530     model.SetContentEndOffset(contentEndOffset);
531     model.SetScrollSnapAlign(V2::ScrollSnapAlign::START);
532     CreateDone(frameNode_);
533 
534     EXPECT_FALSE(pattern_->IsOutOfBoundary());
535 }
536 
537 /**
538  * @tc.name: PaintMethod001
539  * @tc.desc: Test paint method when has no ListItem in List and in ListItemGroup
540  * @tc.type: FUNC
541  */
542 HWTEST_F(ListLayoutTestNg, PaintMethod001, TestSize.Level1)
543 {
544     /**
545      * @tc.steps: step1. Has no ListItem
546      * @tc.expected: UnScrollable, not need paint scrollBar, not DrawLine
547      */
548     ListModelNG model = CreateList();
549     model.SetScrollBar(DisplayMode::ON);
550     CreateListItemGroup(V2::ListItemGroupStyle::NONE); // no ListItem in ListItemGroup
551     auto paintWrapper = CreateDone(frameNode_);
552 
553     /**
554      * @tc.steps: step2. UnScrollable List
555      * @tc.expected: Not need paint scrollBar
556      */
557     auto paintMethod = UpdateOverlayModifier(paintWrapper);
558     auto scrollBarOverlayModifier = paintMethod->scrollBarOverlayModifier_.Upgrade();
559     auto scrollBar = paintMethod->scrollBar_.Upgrade();
560     EXPECT_NE(scrollBar, nullptr);
561     EXPECT_FALSE(scrollBar->NeedPaint());
562     PaintDivider(paintWrapper, 0);
563 
564     /**
565      * @tc.steps: step3. No ListItem in ListItemGroup
566      * @tc.expected: Not DrawLine
567      */
568     auto groupFrameNode = GetChildFrameNode(frameNode_, 0);
569     auto groupPaintWrapper = FlushLayoutTask(groupFrameNode);
570     GroupPaintDivider(groupPaintWrapper, 0);
571 }
572 
573 /**
574  * @tc.name: PaintMethod002
575  * @tc.desc: Test List paint method about UpdateOverlayModifier(scroll bar)
576  * @tc.type: FUNC
577  */
578 HWTEST_F(ListLayoutTestNg, PaintMethod002, TestSize.Level1)
579 {
580     /**
581      * @tc.steps: step1. Set DisplayMode ON
582      * @tc.expected: Has scrollbar and on the right
583      */
584     ListModelNG model = CreateList();
585     model.SetScrollBar(DisplayMode::ON);
586     CreateListItems(TOTAL_ITEM_NUMBER);
587     auto paintWrapper = CreateDone(frameNode_);
588     RefPtr<ListPaintMethod> paintMethod = UpdateOverlayModifier(paintWrapper);
589     auto scrollBarOverlayModifier = paintMethod->scrollBarOverlayModifier_.Upgrade();
590     auto scrollBar = paintMethod->scrollBar_.Upgrade();
591     EXPECT_EQ(scrollBarOverlayModifier->positionMode_, PositionMode::RIGHT);
592     EXPECT_TRUE(scrollBar->NeedPaint());
593 
594     /**
595      * @tc.steps: step2. Change axis to HORIZONTAL
596      * @tc.expected: The scrollbar and on the bottom
597      */
598     model = CreateList();
599     model.SetScrollBar(DisplayMode::ON);
600     model.SetListDirection(Axis::HORIZONTAL);
601     CreateListItems(TOTAL_ITEM_NUMBER);
602     paintWrapper = CreateDone(frameNode_);
603     paintMethod = UpdateOverlayModifier(paintWrapper);
604     scrollBarOverlayModifier = paintMethod->scrollBarOverlayModifier_.Upgrade();
605     scrollBar = paintMethod->scrollBar_.Upgrade();
606     EXPECT_TRUE(scrollBar->NeedPaint());
607     EXPECT_EQ(scrollBarOverlayModifier->positionMode_, PositionMode::BOTTOM);
608 
609     /**
610      * @tc.steps: step3. Set DisplayMode::OFF
611      * @tc.expected: Has no scrollbar
612      */
613     model = CreateList();
614     model.SetScrollBar(DisplayMode::OFF);
615     CreateListItems(TOTAL_ITEM_NUMBER);
616     paintWrapper = CreateDone(frameNode_);
617     paintMethod = UpdateOverlayModifier(paintWrapper);
618     scrollBar = paintMethod->scrollBar_.Upgrade();
619     EXPECT_EQ(scrollBar, nullptr);
620 }
621 
622 /**
623  * @tc.name: PaintMethod003
624  * @tc.desc: Test List paint method about PaintDivider in diff Layout
625  * @tc.type: FUNC
626  */
627 HWTEST_F(ListLayoutTestNg, PaintMethod003, TestSize.Level1)
628 {
629     /**
630      * @tc.steps: step1. Not set divider
631      * @tc.expected: Not DrawLine
632      */
633     ListModelNG model = CreateList();
634     // Group
635     ListItemGroupModelNG groupModel = CreateListItemGroup(V2::ListItemGroupStyle::NONE);
636     CreateListItems(2);
637     ViewStackProcessor::GetInstance()->Pop();
638     ViewStackProcessor::GetInstance()->StopGetAccessRecording();
639     // ListItems
640     CreateListItems(2);
641     auto paintWrapper = CreateDone(frameNode_);
642     auto groupFrameNode = GetChildFrameNode(frameNode_, 0);
643     auto groupPaintWrapper = FlushLayoutTask(groupFrameNode);
644     PaintDivider(paintWrapper, 0);
645     GroupPaintDivider(groupPaintWrapper, 0);
646 
647     /**
648      * @tc.steps: step2. Set divider
649      * @tc.expected: DrawLine, call times depends on the divider number in view
650      */
651     model.SetDivider(AceType::RawPtr(frameNode_), ITEM_DIVIDER);
652     groupModel.SetDivider(AceType::RawPtr(groupFrameNode), ITEM_DIVIDER);
653     paintWrapper = FlushLayoutTask(frameNode_);
654     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
655     PaintDivider(paintWrapper, 2);
656     GroupPaintDivider(groupPaintWrapper, 1);
657 
658     /**
659      * @tc.steps: step3. Set lanes>1
660      * @tc.expected: DrawLine, call times depends on the divider number in view
661      */
662     model.SetLanes(AceType::RawPtr(frameNode_), 2);
663     paintWrapper = FlushLayoutTask(frameNode_);
664     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
665     PaintDivider(paintWrapper, 2);
666     GroupPaintDivider(groupPaintWrapper, 0);
667 
668     /**
669      * @tc.steps: step4. Set padding
670      * @tc.expected: Trigger ClipRect
671      */
672     ViewAbstract::SetPadding(AceType::RawPtr(frameNode_), CalcLength(10.f));
673     paintWrapper = FlushLayoutTask(frameNode_);
674     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
675     PaintDivider(paintWrapper, 2, true);
676     GroupPaintDivider(groupPaintWrapper, 0);
677 }
678 
679 /**
680  * @tc.name: PaintMethod004
681  * @tc.desc: Test ListItemGroup paint method about PaintDivider with diff args
682  * @tc.type: FUNC
683  */
684 HWTEST_F(ListLayoutTestNg, PaintMethod004, TestSize.Level1)
685 {
686     auto itemDivider = ITEM_DIVIDER;
687     ListModelNG model = CreateList();
688     model.SetDivider(itemDivider);
689     // Group
690     ListItemGroupModelNG groupModel = CreateListItemGroup(V2::ListItemGroupStyle::NONE);
691     groupModel.SetDivider(itemDivider);
692     CreateListItems(2);
693     ViewStackProcessor::GetInstance()->Pop();
694     ViewStackProcessor::GetInstance()->StopGetAccessRecording();
695     // ListItems
696     CreateListItems(2);
697     auto paintWrapper = CreateDone(frameNode_);
698     auto groupFrameNode = GetChildFrameNode(frameNode_, 0);
699     auto groupPaintWrapper = FlushLayoutTask(groupFrameNode);
700     auto groupPaint = AceType::DynamicCast<ListItemGroupPaintMethod>(groupPaintWrapper->nodePaintImpl_);
701 
702     /**
703      * @tc.steps: step1. strokeWidth > 0
704      * @tc.expected: DrawLine, call times depends on the divider number in view
705      */
706     PaintDivider(paintWrapper, 2);
707     GroupPaintDivider(groupPaintWrapper, 1);
708 
709     /**
710      * @tc.steps: step2. strokeWidth > 0, but PERCENT
711      * @tc.expected: Not DrawLine
712      */
713     itemDivider.strokeWidth = Dimension(STROKE_WIDTH, DimensionUnit::PERCENT);
714     model.SetDivider(AceType::RawPtr(frameNode_), itemDivider);
715     groupModel.SetDivider(AceType::RawPtr(groupFrameNode), itemDivider);
716     paintWrapper = FlushLayoutTask(frameNode_);
717     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
718     PaintDivider(paintWrapper, 0);
719     GroupPaintDivider(groupPaintWrapper, 0);
720 
721     /**
722      * @tc.steps: step3. strokeWidth < 0
723      * @tc.expected: Not DrawLine
724      */
725     itemDivider.strokeWidth = Dimension(-1);
726     model.SetDivider(AceType::RawPtr(frameNode_), itemDivider);
727     groupModel.SetDivider(AceType::RawPtr(groupFrameNode), itemDivider);
728     paintWrapper = FlushLayoutTask(frameNode_);
729     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
730     PaintDivider(paintWrapper, 0);
731     GroupPaintDivider(groupPaintWrapper, 0);
732 
733     /**
734      * @tc.steps: step4. startMargin + endMargin == LIST_WIDTH
735      * @tc.expected: Not DrawLine
736      */
737     itemDivider = ITEM_DIVIDER;
738     itemDivider.startMargin = Dimension(LIST_WIDTH / 2);
739     itemDivider.endMargin = Dimension(LIST_WIDTH / 2);
740     model.SetDivider(AceType::RawPtr(frameNode_), itemDivider);
741     groupModel.SetDivider(AceType::RawPtr(groupFrameNode), itemDivider);
742     paintWrapper = FlushLayoutTask(frameNode_);
743     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
744     PaintDivider(paintWrapper, 0);
745     GroupPaintDivider(groupPaintWrapper, 0);
746 
747     /**
748      * @tc.steps: step5. startMargin + endMargin > LIST_WIDTH
749      * @tc.expected: Rest margin and DrawLine
750      */
751     itemDivider = ITEM_DIVIDER;
752     itemDivider.startMargin = Dimension(LIST_WIDTH / 2);
753     itemDivider.endMargin = Dimension(LIST_WIDTH / 2 + 1);
754     model.SetDivider(AceType::RawPtr(frameNode_), itemDivider);
755     groupModel.SetDivider(AceType::RawPtr(groupFrameNode), itemDivider);
756     paintWrapper = FlushLayoutTask(frameNode_);
757     groupPaintWrapper = FlushLayoutTask(groupFrameNode);
758     PaintDivider(paintWrapper, 2);
759     GroupPaintDivider(groupPaintWrapper, 1);
760 }
761 
762 /**
763  * @tc.name: PaintMethod005
764  * @tc.desc: Test List paint method about UpdateContentModifier
765  * @tc.type: FUNC
766  */
767 HWTEST_F(ListLayoutTestNg, PaintMethod005, TestSize.Level1)
768 {
769     /**
770      * @tc.steps: step1. Set divider startMargin and endMargin normal value
771      * @tc.expected: offset.GetX() == startMargin and length = LIST_WIDTH - startMargin - endMargin
772      */
773     auto itemDivider = ITEM_DIVIDER;
774     ListModelNG model = CreateList();
775     model.SetDivider(itemDivider);
776     CreateListItems(TOTAL_ITEM_NUMBER);
777     CreateDone(frameNode_);
778     auto renderContext = frameNode_->GetRenderContext();
779     renderContext->UpdatePaintRect(frameNode_->GetGeometryNode()->GetFrameRect());
780     UpdateDividerMap();
781     auto dividerList = pattern_->listContentModifier_->dividerList_->Get();
782     auto dividerMap = AceType::DynamicCast<ListDividerArithmetic>(dividerList)->GetDividerMap();
783     EXPECT_EQ(dividerMap.size(), 4);
784     auto length = LIST_WIDTH - (ITEM_DIVIDER.startMargin + ITEM_DIVIDER.endMargin).ConvertToPx();
785     EXPECT_EQ(pattern_->listContentModifier_->width_, ITEM_DIVIDER.strokeWidth.ConvertToPx());
786     for (auto child : dividerMap) {
787         EXPECT_EQ(child.second.offset.GetX(), ITEM_DIVIDER.startMargin.ConvertToPx());
788         EXPECT_EQ(child.second.length, length);
789     }
790 
791     /**
792      * @tc.steps: step2. Set divider startMargin and endMargin abnormal value
793      * @tc.expected: startMargin == 0 and endMargin == 0
794      */
795     std::vector<V2::ItemDivider> dividerArray = { { Dimension(10), Dimension(-10), Dimension(-10) },
796         { Dimension(10), Dimension(LIST_WIDTH), Dimension(LIST_WIDTH) },
797         { Dimension(10), Dimension(10, DimensionUnit::PERCENT), Dimension(10, DimensionUnit::PERCENT) } };
798     for (auto itemDivider : dividerArray) {
799         layoutProperty_->UpdateDivider(itemDivider);
800         FlushLayoutTask(frameNode_);
801         auto renderContext = frameNode_->GetRenderContext();
802         renderContext->UpdatePaintRect(frameNode_->GetGeometryNode()->GetFrameRect());
803         UpdateDividerMap();
804         dividerList = pattern_->listContentModifier_->dividerList_->Get();
805         dividerMap = AceType::DynamicCast<ListDividerArithmetic>(dividerList)->GetDividerMap();
806         EXPECT_EQ(dividerMap.size(), 4);
807         EXPECT_EQ(pattern_->listContentModifier_->width_, itemDivider.strokeWidth.ConvertToPx());
808         for (auto child : dividerMap) {
809             EXPECT_EQ(child.second.offset.GetX(), 0.f);
810             EXPECT_EQ(child.second.length, LIST_WIDTH);
811         }
812     }
813 }
814 
815 /**
816  * @tc.name: OnModifyDone001
817  * @tc.desc: Test list_pattern OnModifyDone
818  * @tc.type: FUNC
819  */
820 HWTEST_F(ListLayoutTestNg, OnModifyDone001, TestSize.Level1)
821 {
822     /**
823      * @tc.steps: step1. Set multiSelectable_ to true
824      * @tc.expected: InitMouseEvent() triggered by OnModifyDone()
825      */
826     ListModelNG model = CreateList();
827     model.SetScrollBar(DisplayMode::ON);
828     model.SetMultiSelectable(true);
829     CreateListItems(TOTAL_ITEM_NUMBER);
830     ViewStackProcessor::GetInstance()->Finish();
831     ViewStackProcessor::GetInstance()->StopGetAccessRecording();
832     EXPECT_NE(pattern_->GetScrollableEvent(), nullptr);
833     ASSERT_NE(pattern_->GetScrollBar(), nullptr);
834     EXPECT_EQ(pattern_->GetScrollBar()->GetDisplayMode(), DisplayMode::ON);
835     EXPECT_TRUE(pattern_->isMouseEventInit_);
836 
837     /**
838      * @tc.steps: step2. Call OnDirtyLayoutWrapperSwap()
839      * @tc.expected: isInitialized_ would be true
840      */
841     EXPECT_FALSE(pattern_->isInitialized_);
842     FlushLayoutTask(frameNode_);
843     EXPECT_TRUE(pattern_->isInitialized_);
844 
845     /**
846      * @tc.steps: step3. When isMouseEventInit_ is true, Call OnModifyDone()
847      * @tc.expected: UninitMouseEvent() would not be triggered, isMouseEventInit_ is still be true
848      */
849     pattern_->OnModifyDone();
850     EXPECT_TRUE(pattern_->isMouseEventInit_);
851 
852     /**
853      * @tc.steps: step4. Change multiSelectable_ to false, call OnModifyDone()
854      * @tc.expected: UninitMouseEvent() triggered
855      */
856     pattern_->SetMultiSelectable(false);
857     EXPECT_FALSE(pattern_->multiSelectable_);
858     pattern_->OnModifyDone();
859     EXPECT_FALSE(pattern_->isMouseEventInit_);
860 }
861 
862 /**
863  * @tc.name: Pattern003
864  * @tc.desc: Test OutBoundaryCallback
865  * @tc.type: FUNC
866  */
867 HWTEST_F(ListLayoutTestNg, Pattern003, TestSize.Level1)
868 {
869     CreateList();
870     CreateListItems(TOTAL_ITEM_NUMBER);
871     CreateDone(frameNode_);
872     EXPECT_NE(pattern_->scrollableEvent_, nullptr);
873     auto scrollable = pattern_->scrollableEvent_->GetScrollable();
874     EXPECT_NE(scrollable, nullptr);
875     scrollable->isTouching_ = true;
876     EXPECT_FALSE(pattern_->OutBoundaryCallback());
877     UpdateCurrentOffset(ITEM_HEIGHT);
878     EXPECT_TRUE(pattern_->OutBoundaryCallback());
879     ScrollTo(ITEM_HEIGHT * 2);
880     EXPECT_FALSE(pattern_->OutBoundaryCallback());
881     UpdateCurrentOffset(-ITEM_HEIGHT * 2);
882     EXPECT_TRUE(pattern_->OutBoundaryCallback());
883 
884     ClearOldNodes();
885     ListModelNG model = CreateList();
886     model.SetChainAnimation(true);
887     model.SetChainAnimationOptions({ Dimension(0), Dimension(10), 0, 0, 0, DEFAULT_STIFFNESS, DEFAULT_DAMPING });
888     CreateListItems(TOTAL_ITEM_NUMBER);
889     CreateDone(frameNode_);
890     EXPECT_NE(pattern_->scrollableEvent_, nullptr);
891     scrollable = pattern_->scrollableEvent_->GetScrollable();
892     EXPECT_NE(scrollable, nullptr);
893     scrollable->isTouching_ = true;
894     EXPECT_NE(pattern_->springProperty_, nullptr);
895     EXPECT_NE(pattern_->chainAnimation_, nullptr);
896     UpdateCurrentOffset(ITEM_HEIGHT);
897     EXPECT_TRUE(pattern_->OutBoundaryCallback());
898 }
899 
900 /**
901  * @tc.name: Pattern006
902  * @tc.desc: Test GetItemIndexByPosition
903  * @tc.type: FUNC
904  */
905 HWTEST_F(ListLayoutTestNg, Pattern006, TestSize.Level1)
906 {
907     int32_t lanes = 2;
908     ListModelNG model = CreateList();
909     model.SetLanes(lanes);
910     CreateListItems(VIEW_ITEM_NUMBER * lanes);
911     CreateDone(frameNode_);
912 
913     /**
914      * @tc.steps: step1. When lanes > 1, call GetItemIndexByPosition
915      * @tc.expected: Would return correct itemIndex
916      */
917     const Point point = Point(150.f, 250.f);
918     int32_t itemIndex = pattern_->GetItemIndexByPosition(point.GetX(), point.GetY());
919     EXPECT_EQ(itemIndex, 5);
920 }
921 
922 /**
923  * @tc.name: Pattern007
924  * @tc.desc: Test GetItemIndexByPosition
925  * @tc.type: FUNC
926  */
927 HWTEST_F(ListLayoutTestNg, Pattern007, TestSize.Level1)
928 {
929     /**
930      * @tc.steps: step1. When has ListItem, position not at any ListItem
931      * @tc.expected: Would return the last itemIndex
932      */
933     CreateList();
934     CreateListItems(VIEW_ITEM_NUMBER);
935     CreateDone(frameNode_);
936     const Point point = Point(0, 1000.f);
937     int32_t itemIndex = pattern_->GetItemIndexByPosition(point.GetX(), point.GetY());
938     EXPECT_EQ(itemIndex, VIEW_ITEM_NUMBER);
939 }
940 
941 /**
942  * @tc.name: Pattern008
943  * @tc.desc: Test GetItemIndexByPosition
944  * @tc.type: FUNC
945  */
946 HWTEST_F(ListLayoutTestNg, Pattern008, TestSize.Level1)
947 {
948     /**
949      * @tc.steps: step1. When has no ListItem, call GetItemIndexByPosition
950      * @tc.expected: Would return 0
951      */
952     CreateList();
953     CreateDone(frameNode_);
954     const Point point = Point(0, 1000.f);
955     int32_t itemIndex = pattern_->GetItemIndexByPosition(point.GetX(), point.GetY());
956     EXPECT_EQ(itemIndex, 0);
957 }
958 
959 /**
960  * @tc.name: ListSize001
961  * @tc.desc: Test List size in diff condition
962  * @tc.type: FUNC
963  */
964 HWTEST_F(ListLayoutTestNg, ListSize001, TestSize.Level1)
965 {
966     /**
967      * @tc.steps: step1. Not set size to List, but no ListItems
968      * @tc.expected: List with is rootWidth
969      */
970     const float rootWidth = MockPipelineContext::GetCurrent()->rootWidth_;
971     ListModelNG model;
972     model.Create();
973     GetList();
974     CreateDone(frameNode_);
975     EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), rootWidth);
976 
977     /**
978      * @tc.steps: step2. Not set size to List and has ListItems
979      * @tc.expected: List with is rootWidth
980      */
981     model.Create();
982     CreateListItems(TOTAL_ITEM_NUMBER);
983     GetList();
984     CreateDone(frameNode_);
985     EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), rootWidth);
986 
987     /**
988      * @tc.steps: step3. Set List width to Infinity
989      * @tc.expected: List with is Infinity
990      */
991     CreateList();
992     ViewAbstract::SetWidth(CalcLength(Infinity<float>()));
993     CreateListItems(TOTAL_ITEM_NUMBER);
994     CreateDone(frameNode_);
995     EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), Infinity<float>());
996 
997     /**
998      * @tc.steps: step4. Set List width to Infinity, but no ListItems
999      * @tc.expected: List with is 0
1000      */
1001     ClearOldNodes();
1002     CreateList();
1003     ViewAbstract::SetWidth(CalcLength(Infinity<float>()));
1004     CreateDone(frameNode_);
1005     EXPECT_EQ(frameNode_->GetGeometryNode()->GetFrameSize().Width(), 0.f);
1006 }
1007 
1008 /**
1009  * @tc.name: Pattern011
1010  * @tc.desc: Test ContentStartOffset and ContentEndOffset
1011  * @tc.type: FUNC
1012  */
1013 HWTEST_F(ListLayoutTestNg, Pattern011, TestSize.Level1)
1014 {
1015     /**
1016      * @tc.cases: contentStartOffset_ + contentEndOffset_ < contentMainSize
1017      * @tc.expected: contentStartOffset_ = 10.f and contentEndOffset_ = 10.f
1018      */
1019     ListModelNG model = CreateList();
1020     model.SetContentStartOffset(10.f);
1021     model.SetContentEndOffset(10.f);
1022     CreateListItems(20);
1023     CreateDone(frameNode_);
1024     EXPECT_EQ(layoutProperty_->GetContentStartOffsetValue(), 10.f);
1025     EXPECT_EQ(layoutProperty_->GetContentEndOffsetValue(), 10.f);
1026     EXPECT_EQ(pattern_->contentStartOffset_, 10.f);
1027     EXPECT_EQ(pattern_->contentEndOffset_, 10.f);
1028     EXPECT_EQ(pattern_->GetOffsetWithLimit(5.f), 0.f);
1029     EXPECT_EQ(pattern_->GetOffsetWithLimit(0.f), 0.f);
1030     EXPECT_EQ(pattern_->GetOffsetWithLimit(-5.f), -5.f);
1031 
1032     /**
1033      * @tc.cases: contentStartOffset_ + contentEndOffset_ >= contentMainSize
1034      * @tc.expected: contentStartOffset_ = 0.f and contentEndOffset_ = 0.f
1035      */
1036     model = CreateList();
1037     model.SetContentStartOffset(0.5f * LIST_HEIGHT);
1038     model.SetContentEndOffset(0.5f * LIST_HEIGHT);
1039     CreateListItems(20);
1040     CreateDone(frameNode_);
1041     EXPECT_EQ(layoutProperty_->GetContentStartOffsetValue(), 0.5f * LIST_HEIGHT);
1042     EXPECT_EQ(layoutProperty_->GetContentEndOffsetValue(), 0.5f * LIST_HEIGHT);
1043     EXPECT_EQ(pattern_->contentStartOffset_, 0.f);
1044     EXPECT_EQ(pattern_->contentEndOffset_, 0.f);
1045 }
1046 
1047 /**
1048  * @tc.name: ListItemGroupCreateForCardModeTest001
1049  * @tc.desc: Test the initialization of listItem in card mode.
1050  * @tc.type: FUNC
1051  */
1052 HWTEST_F(ListLayoutTestNg, ListItemGroupCreateForCardModeTest001, TestSize.Level1)
1053 {
1054     /**
1055      * @tc.steps: step2. create ListItemGroup.
1056      * @tc.expected: step2. create a card style ListItemGroup success.
1057      */
1058     ListItemGroupModelNG groupModel;
1059     groupModel.Create(V2::ListItemGroupStyle::CARD);
1060     auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
1061     auto pattern = frameNode->GetPattern<ListItemGroupPattern>();
1062     RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
1063     EXPECT_EQ(pattern->GetListItemGroupStyle(), V2::ListItemGroupStyle::CARD);
1064 
1065     /**
1066      * @tc.steps: step3. compare the obtained value with the set value.
1067      * @tc.expected: step3. the obtained value is equal to the set value.
1068      */
1069     auto renderContext = frameNode->GetRenderContext();
1070     EXPECT_EQ(renderContext->GetBackgroundColorValue(), Color::WHITE);
1071     EXPECT_EQ(layoutProperty->GetMarginProperty()->left.value(), CalcLength(GROUP_MARGIN));
1072     EXPECT_EQ(layoutProperty->GetMarginProperty()->right.value(), CalcLength(GROUP_MARGIN));
1073 }
1074 
1075 /**
1076  * @tc.name: ListItemCreateForCardModeTest001
1077  * @tc.desc: Test the initialization of listItem in card mode.
1078  * @tc.type: FUNC
1079  */
1080 HWTEST_F(ListLayoutTestNg, ListItemCreateForCardModeTest001, TestSize.Level1)
1081 {
1082     /**
1083      * @tc.steps: step2. create ListItem in card mode.
1084      * @tc.expected: step2. create a card style ListItem success.
1085      */
1086     ListItemModelNG itemModel;
__anonc56bfe6a0202(int32_t) 1087     itemModel.Create([](int32_t) {}, V2::ListItemStyle::CARD);
1088     auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
1089     auto pattern = frameNode->GetPattern<ListItemPattern>();
1090     RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
1091     EXPECT_EQ(pattern->GetListItemStyle(), V2::ListItemStyle::CARD);
1092 
1093     /**
1094      * @tc.steps: step3. compare the obtained value with the set value.
1095      * @tc.expected: step3. the obtained value is equal to the set value.
1096      */
1097     auto renderContext = frameNode->GetRenderContext();
1098     EXPECT_EQ(renderContext->GetBackgroundColorValue(), Color::WHITE);
1099 }
1100 
1101 /**
1102  * @tc.name: ListItemHoverEventForCardModeTest001
1103  * @tc.desc: Test the hover event when the hover status of card mode listItem is true.
1104  * @tc.type: FUNC
1105  */
1106 HWTEST_F(ListLayoutTestNg, ListItemHoverEventForCardModeTest001, TestSize.Level1)
1107 {
1108     /**
1109      * @tc.steps: step2. create ListItem in card mode.
1110      * @tc.expected: step2. create a card style ListItem success.
1111      */
1112     ListItemModelNG itemModel;
__anonc56bfe6a0302(int32_t) 1113     itemModel.Create([](int32_t) {}, V2::ListItemStyle::CARD);
1114     auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
1115     ASSERT_NE(frameNode, nullptr);
1116     auto pattern = frameNode->GetPattern<ListItemPattern>();
1117     ASSERT_NE(pattern, nullptr);
1118 
1119     /**
1120      * @tc.steps: step3. call function HandleHoverEvent and Set hover status to true.
1121      * @tc.expected: step3. the hover status is true.
1122      */
1123     pattern->HandleHoverEvent(true, frameNode);
1124     EXPECT_TRUE(pattern->isHover_);
1125 
1126     /**
1127      * @tc.steps: step3. call function HandleHoverEvent and Set hover status to false.
1128      * @tc.expected: step3. the hover status is false.
1129      */
1130     pattern->HandleHoverEvent(false, frameNode);
1131     EXPECT_FALSE(pattern->isHover_);
1132 }
1133 
1134 /**
1135  * @tc.name: ListItemPressEventForCardModeTest001
1136  * @tc.desc: Test the press event when the TouchType is DOWN.
1137  * @tc.type: FUNC
1138  */
1139 HWTEST_F(ListLayoutTestNg, ListItemPressEventForCardModeTest001, TestSize.Level1)
1140 {
1141     CreateList();
1142     CreateListItem(V2::ListItemStyle::CARD);
1143     CreateDone(frameNode_);
1144     auto itemPattern = GetChildPattern<ListItemPattern>(frameNode_, 0);
1145     auto handleHoverEvent = itemPattern->hoverEvent_->GetOnHoverEventFunc();
1146     auto itemNode = GetChildFrameNode(frameNode_, 0);
1147     auto gesture = itemNode->GetOrCreateGestureEventHub();
1148     auto handlePressEvent = gesture->touchEventActuator_->touchEvents_.back()->GetTouchEventCallback();
1149 
1150     /**
1151      * @tc.steps: step1. Hover and Touch Down/Move/Up
1152      */
1153     handleHoverEvent(true);
1154     EXPECT_TRUE(itemPattern->isHover_);
1155     EXPECT_EQ(itemPattern->GetBlendGgColor(), HOVER_COLOR);
1156 
1157     TouchEventInfo info = CreateTouchEventInfo(TouchType::DOWN, Offset());
1158     handlePressEvent(info);
1159     EXPECT_TRUE(itemPattern->isPressed_);
1160     EXPECT_EQ(itemPattern->GetBlendGgColor(), PRESS_COLOR);
1161 
1162     info = CreateTouchEventInfo(TouchType::MOVE, Offset());
1163     handlePressEvent(info);
1164     EXPECT_TRUE(itemPattern->isPressed_);
1165     EXPECT_EQ(itemPattern->GetBlendGgColor(), PRESS_COLOR);
1166 
1167     info = CreateTouchEventInfo(TouchType::UP, Offset());
1168     handlePressEvent(info);
1169     EXPECT_FALSE(itemPattern->isPressed_);
1170     EXPECT_EQ(itemPattern->GetBlendGgColor(), HOVER_COLOR);
1171 
1172     handleHoverEvent(false);
1173     EXPECT_FALSE(itemPattern->isHover_);
1174     EXPECT_EQ(itemPattern->GetBlendGgColor(), Color::TRANSPARENT);
1175 
1176     /**
1177      * @tc.steps: step2. Touch Down/Cancel
1178      */
1179     info = CreateTouchEventInfo(TouchType::DOWN, Offset());
1180     handlePressEvent(info);
1181     EXPECT_TRUE(itemPattern->isPressed_);
1182 
1183     info = CreateTouchEventInfo(TouchType::CANCEL, Offset());
1184     handlePressEvent(info);
1185     EXPECT_FALSE(itemPattern->isPressed_);
1186 }
1187 
1188 /**
1189  * @tc.name: ListItemDisableEventForCardModeTest001
1190  * @tc.desc: Test InitDisableEvent
1191  * @tc.type: FUNC
1192  */
1193 HWTEST_F(ListLayoutTestNg, ListItemDisableEventForCardModeTest001, TestSize.Level1)
1194 {
1195     /**
1196      * @tc.steps: step1. create ListItem in card mode.
1197      * @tc.expected: create a card style ListItem success and set enable status to false.
1198      */
1199     CreateList();
1200     CreateListItem(V2::ListItemStyle::CARD);
1201     CreateDone(frameNode_);
1202     auto itemNode = GetChildFrameNode(frameNode_, 0);
1203     auto itemPattern = GetChildPattern<ListItemPattern>(frameNode_, 0);
1204     auto itemEventHub = GetChildEventHub<ListItemEventHub>(frameNode_, 0);
1205     auto itemRenderContext = itemNode->GetRenderContext();
1206     EXPECT_TRUE(itemEventHub->IsEnabled());
1207     EXPECT_TRUE(itemEventHub->IsDeveloperEnabled());
1208     EXPECT_EQ(itemRenderContext->GetOpacity(), 1.0);
1209 
1210     itemEventHub->SetEnabled(false);
1211     itemPattern->OnModifyDone(); // Test InitDisableEvent
1212     EXPECT_FALSE(itemPattern->Selectable());
1213     EXPECT_FALSE(itemEventHub->IsEnabled());
1214     EXPECT_FALSE(itemEventHub->IsDeveloperEnabled());
1215     EXPECT_EQ(itemRenderContext->GetOpacity(), 0.4);
1216 
1217     itemPattern->OnModifyDone();
1218     EXPECT_FALSE(itemPattern->Selectable());
1219 
1220     itemEventHub->SetEnabled(true);
1221     itemPattern->OnModifyDone();
1222     EXPECT_FALSE(itemPattern->Selectable());
1223     EXPECT_EQ(itemRenderContext->GetOpacity(), 0.4);
1224 }
1225 
1226 /**
1227  * @tc.name: ListPattern_GetItemRect001
1228  * @tc.desc: Test the GetItemRect function of List.
1229  * @tc.type: FUNC
1230  */
1231 HWTEST_F(ListLayoutTestNg, ListPattern_GetItemRect001, TestSize.Level1)
1232 {
1233     /**
1234      * @tc.steps: step1. Init List then slide List by Scroller.
1235      */
1236     ListModelNG model = CreateList();
1237     model.SetInitialIndex(1);
1238     CreateListItems(TOTAL_ITEM_NUMBER * 2);
1239     CreateDone(frameNode_);
1240     pattern_->ScrollBy(ITEM_HEIGHT / 2.0f);
1241     FlushLayoutTask(frameNode_);
1242 
1243     /**
1244      * @tc.steps: step2. Get invalid ListItem Rect.
1245      * @tc.expected: Return 0 when input invalid index.
1246      */
1247     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(-1), Rect()));
1248     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(0), Rect()));
1249     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(TOTAL_ITEM_NUMBER * 2 - 1), Rect()));
1250     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(TOTAL_ITEM_NUMBER * 2), Rect()));
1251 
1252     /**
1253      * @tc.steps: step3. Get ListItem Rect by GetItemRectInGroup.
1254      * @tc.expected: Return 0 when get ListItem Rect by GetItemRectInGroup.
1255      */
1256     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(1, 0), Rect()));
1257 
1258     /**
1259      * @tc.steps: step4. Get valid ListItem Rect.
1260      * @tc.expected: Return actual Rect when input valid index.
1261      */
1262     EXPECT_TRUE(
1263         IsEqual(pattern_->GetItemRect(1), Rect(0, -ITEM_HEIGHT / 2.0f, FILL_LENGTH.Value() * LIST_WIDTH, ITEM_HEIGHT)));
1264     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(3),
1265         Rect(0, -ITEM_HEIGHT / 2.0f + ITEM_HEIGHT * 2, FILL_LENGTH.Value() * LIST_WIDTH, ITEM_HEIGHT)));
1266 
1267     /**
1268      * @tc.steps: step5. Slide List by Scroller.
1269      */
1270     pattern_->ScrollToIndex(8);
1271     FlushLayoutTask(frameNode_);
1272     /**
1273      * @tc.steps: step6. Get invalid ListItem Rect.
1274      * @tc.expected: Return 0 when input invalid index.
1275      */
1276     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(7), Rect()));
1277 
1278     /**
1279      * @tc.steps: step7. Get valid ListItem Rect.
1280      * @tc.expected: Return actual Rect when input valid index.
1281      */
1282     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(pattern_->GetEndIndex()),
1283         Rect(0, LIST_HEIGHT - ITEM_HEIGHT, FILL_LENGTH.Value() * LIST_WIDTH, ITEM_HEIGHT)));
1284 }
1285 
1286 /**
1287  * @tc.name: ListPattern_GetItemRectInGroup001
1288  * @tc.desc: Test the GetItemRectInGroup function of List.
1289  * @tc.type: FUNC
1290  */
1291 HWTEST_F(ListLayoutTestNg, ListPattern_GetItemRectInGroup001, TestSize.Level1)
1292 {
1293     /**
1294      * @tc.steps: step1. Init List then slide List by Scroller.
1295      */
1296     ListModelNG model = CreateList();
1297     CreateListItemGroup(V2::ListItemGroupStyle::NONE);
1298     CreateListItems(TOTAL_ITEM_NUMBER);
1299     CreateDone(frameNode_);
1300     pattern_->ScrollTo(ITEM_HEIGHT * 2);
1301     FlushLayoutTask(frameNode_);
1302 
1303     /**
1304      * @tc.steps: step2. Get invalid group item Rect.
1305      * @tc.expected: Return 0 when input invalid group index.
1306      */
1307     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(-1, 0), Rect()));
1308     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(2, -1), Rect()));
1309     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(0, 0), Rect()));
1310     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(1, 0), Rect()));
1311     EXPECT_TRUE(IsEqual(pattern_->GetItemRectInGroup(0, TOTAL_ITEM_NUMBER), Rect()));
1312 
1313     /**
1314      * @tc.steps: step3. Get valid group item Rect.
1315      * @tc.expected: Return actual Rect when input valid group index.
1316      */
1317     EXPECT_TRUE(IsEqual(
1318         pattern_->GetItemRectInGroup(0, 2), Rect(0, 0, FILL_LENGTH.Value() * LIST_WIDTH, ITEM_HEIGHT)));
1319 
1320     /**
1321      * @tc.steps: step4. Get valid ListItemGroup Rect.
1322      * @tc.expected: Return actual Rect when input valid index.
1323      */
1324     EXPECT_TRUE(IsEqual(pattern_->GetItemRect(0),
1325         Rect(0, -ITEM_HEIGHT * 2, LIST_WIDTH, ITEM_HEIGHT * TOTAL_ITEM_NUMBER)));
1326 }
1327 
1328 /**
1329  * @tc.name: ListLayout_SafeArea001
1330  * @tc.desc: Test list layout with expandSafeArea.
1331  * @tc.type: FUNC
1332  */
1333 HWTEST_F(ListLayoutTestNg, ListLayout_SafeArea001, TestSize.Level1)
1334 {
1335     /**
1336      * @tc.steps: step1. Init List.
1337      */
1338     ListModelNG model = CreateList();
1339     model.SetInitialIndex(1);
1340     CreateListItems(TOTAL_ITEM_NUMBER * 2);
1341     CreateDone(frameNode_);
1342     EXPECT_CALL(*MockPipelineContext::pipeline_, GetSafeArea)
1343         .Times(1)
1344         .WillOnce(Return(SafeAreaInsets { {}, {}, {}, { .start = 0, .end = 100 } }));
1345     layoutProperty_->UpdateSafeAreaExpandOpts({ .type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_ALL });
1346     FlushLayoutTask(frameNode_);
1347     EXPECT_EQ(pattern_->contentEndOffset_, 100);
1348     EXPECT_TRUE(IsEqual(frameNode_->geometryNode_->GetFrameSize(), SizeF(LIST_WIDTH, LIST_HEIGHT)));
1349 }
1350 
1351 /**
1352  * @tc.name: ListLayout_SafeArea002
1353  * @tc.desc: Test list layout with expandSafeArea.
1354  * @tc.type: FUNC
1355  */
1356 HWTEST_F(ListLayoutTestNg, ListLayout_SafeArea002, TestSize.Level1)
1357 {
1358     /**
1359      * @tc.steps: step1. Init List.
1360      */
1361     ListModelNG model = CreateList();
1362     model.SetInitialIndex(1);
1363     CreateListItems(TOTAL_ITEM_NUMBER * 2);
1364     CreateDone(frameNode_);
1365     EXPECT_CALL(*MockPipelineContext::pipeline_, GetSafeArea).Times(0);
1366     layoutProperty_->UpdateSafeAreaExpandOpts({ .type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_TOP });
1367     FlushLayoutTask(frameNode_);
1368     EXPECT_EQ(pattern_->contentEndOffset_, 0);
1369     EXPECT_TRUE(IsEqual(frameNode_->geometryNode_->GetFrameSize(), SizeF(LIST_WIDTH, LIST_HEIGHT)));
1370 }
1371 
1372 /**
1373  * @tc.name: PostListItemPressStyleTask001
1374  * @tc.desc: Test list layout with PostListItemPressStyleTask.
1375  * @tc.type: FUNC
1376  */
1377 HWTEST_F(ListLayoutTestNg, PostListItemPressStyleTask001, TestSize.Level1)
1378 {
1379     /**
1380      * @tc.steps: step1. Init List.
1381      */
1382     ListModelNG model = CreateList();
1383     model.SetDivider(ITEM_DIVIDER);
1384     CreateListItems(TOTAL_ITEM_NUMBER);
1385     CreateDone(frameNode_);
1386     int cur = 0;
1387     for (auto& child : pattern_->itemPosition_) {
1388         child.second.id += cur;
1389         cur++;
1390     }
1391     auto renderContext = frameNode_->GetRenderContext();
1392     renderContext->UpdatePaintRect(frameNode_->GetGeometryNode()->GetFrameRect());
1393     UpdateContentModifier();
1394     auto dividerList_ = pattern_->listContentModifier_->dividerList_->Get();
1395     auto lda = AceType::DynamicCast<ListDividerArithmetic>(dividerList_);
1396     auto dividerMap = lda->GetDividerMap();
1397     EXPECT_EQ(dividerMap.size(), 4);
1398 
1399     auto listItemNode = GetChildFrameNode(frameNode_, 0);
1400     auto listItemNodeId = listItemNode->GetId();
1401     auto stateStyleMgr = AceType::MakeRefPtr<StateStyleManager>(listItemNode);
1402     stateStyleMgr->PostListItemPressStyleTask(UI_STATE_PRESSED);
1403     RefPtr<NodePaintMethod> paint = pattern_->CreateNodePaintMethod();
1404     RefPtr<ListPaintMethod> listPaint = AceType::DynamicCast<ListPaintMethod>(paint);
1405     for (auto child : listPaint->itemPosition_) {
1406         if (child.second.id == listItemNodeId) {
1407             EXPECT_TRUE(child.second.isPressed);
1408         }
1409     }
1410 
1411     UpdateContentModifier();
1412     dividerList_ = pattern_->listContentModifier_->dividerList_->Get();
1413     lda = AceType::DynamicCast<ListDividerArithmetic>(dividerList_);
1414     dividerMap = lda->GetDividerMap();
1415     EXPECT_EQ(dividerMap.size(), 3);
1416 }
1417 
1418 /**
1419  * @tc.name: PostListItemPressStyleTask002
1420  * @tc.desc: Test listItemGroup layout with PostListItemPressStyleTask.
1421  * @tc.type: FUNC
1422  */
1423 HWTEST_F(ListLayoutTestNg, PostListItemPressStyleTask002, TestSize.Level1)
1424 {
1425     /**
1426      * @tc.steps: step1. Init List.
1427      */
1428     ListModelNG model = CreateList();
1429     model.SetDivider(ITEM_DIVIDER);
1430     CreateListItemGroups(TOTAL_ITEM_NUMBER);
1431     CreateDone(frameNode_);
1432     auto groupFrameNode = GetChildFrameNode(frameNode_, 0);
1433     auto groupPattern = groupFrameNode->GetPattern<ListItemGroupPattern>();
1434     int cur = 0;
1435     for (auto& child : groupPattern->itemPosition_) {
1436         child.second.id += cur;
1437         cur++;
1438     }
1439 
1440     auto listItemNode = GetChildFrameNode(groupFrameNode, 0);
1441     auto listItemNodeId = listItemNode->GetId();
1442     auto stateStyleMgr = AceType::MakeRefPtr<StateStyleManager>(listItemNode);
1443     stateStyleMgr->PostListItemPressStyleTask(UI_STATE_PRESSED);
1444     RefPtr<NodePaintMethod> paint = groupPattern->CreateNodePaintMethod();
1445     RefPtr<ListItemGroupPaintMethod> groupPaint = AceType::DynamicCast<ListItemGroupPaintMethod>(paint);
1446     for (auto child : groupPaint->itemPosition_) {
1447         if (child.second.id == listItemNodeId) {
1448             EXPECT_TRUE(child.second.isPressed);
1449         }
1450     }
1451 }
1452 
1453 /**
1454  * @tc.name: ChildrenMainSize005
1455  * @tc.desc: Test childrenMainSize layout
1456  * @tc.type: FUNC
1457  */
1458 HWTEST_F(ListLayoutTestNg, ChildrenMainSize005, TestSize.Level1)
1459 {
1460     /**
1461      * @tc.steps: step1. Create list
1462      * @tc.expected: Default Size is 0
1463      */
1464     ListModelNG model = CreateList();
1465     auto childrenSize = model.GetOrCreateListChildrenMainSize();
1466     childrenSize->UpdateDefaultSize(0);
1467     childrenSize->ChangeData(0, 2, { 100.f, 100.f });
1468     childrenSize->ChangeData(4, 1, { 200.f });
1469     childrenSize->ChangeData(5, 8, { 100.f, 100.f, 100.f, 100.f, 100.f, 100.f, 100.f, 100.f });
1470     CreateListItems(2);
1471     CreateItemWithSize(2, SizeT<Dimension>(FILL_LENGTH, Dimension(0.f)));
1472     CreateItemWithSize(1, SizeT<Dimension>(FILL_LENGTH, Dimension(200.f)));
1473     CreateListItems(8);
1474     CreateDone(frameNode_);
1475     EXPECT_TRUE(ScrollToIndex(1, false, ScrollAlign::START, 100.f));
1476     EXPECT_TRUE(ScrollToIndex(2, false, ScrollAlign::START, 200.f));
1477     EXPECT_TRUE(ScrollToIndex(3, false, ScrollAlign::START, 200.f));
1478     EXPECT_TRUE(ScrollToIndex(4, false, ScrollAlign::START, 200.f));
1479 }
1480 
1481 /**
1482  * @tc.name: ChildrenMainSize006
1483  * @tc.desc: Test childrenMainSize layout
1484  * @tc.type: FUNC
1485  */
1486 HWTEST_F(ListLayoutTestNg, ChildrenMainSize006, TestSize.Level1)
1487 {
1488     /**
1489      * @tc.steps: step1. Create list
1490      * @tc.expected: Default Size is 100
1491      */
1492     ListModelNG model = CreateList();
1493     auto childrenSize = model.GetOrCreateListChildrenMainSize();
1494     childrenSize->UpdateDefaultSize(ITEM_HEIGHT);
1495     childrenSize->ChangeData(2, 2, { -100.f, 200.f });
1496     CreateListItems(2);
1497     CreateItemWithSize(1, SizeT<Dimension>(FILL_LENGTH, Dimension(-100.f)));
1498     CreateItemWithSize(1, SizeT<Dimension>(FILL_LENGTH, Dimension(200.f)));
1499     CreateListItems(8);
1500     CreateDone(frameNode_);
1501     EXPECT_TRUE(ScrollToIndex(3, false, ScrollAlign::START, ITEM_HEIGHT));
1502     EXPECT_TRUE(ScrollToIndex(4, false, ScrollAlign::START, 300.f));
1503 
1504     /**
1505      * @tc.steps: step2. insert data
1506      * @tc.expected: childrenSize_.size() == 10
1507      */
1508     ClearOldNodes();
1509     model = CreateList();
1510     childrenSize = model.GetOrCreateListChildrenMainSize();
1511     childrenSize->UpdateDefaultSize(ITEM_HEIGHT);
1512     childrenSize->ChangeData(8, 0, { 50.f, 200.f });
1513     CreateListItems(8);
1514     CreateItemWithSize(1, SizeT<Dimension>(FILL_LENGTH, Dimension(50.f)));
1515     CreateItemWithSize(1, SizeT<Dimension>(FILL_LENGTH, Dimension(200.f)));
1516     CreateDone(frameNode_);
1517     EXPECT_EQ(pattern_->childrenSize_->childrenSize_.size(), 10);
1518     EXPECT_TRUE(ScrollToIndex(8, false, ScrollAlign::END, 450.f));
1519     EXPECT_TRUE(ScrollToIndex(9, false, ScrollAlign::END, 650.f));
1520 }
1521 
1522 /**
1523  * @tc.name: ListRepeatCacheCount001
1524  * @tc.desc: List cacheCount
1525  * @tc.type: FUNC
1526  */
1527 HWTEST_F(ListLayoutTestNg, ListRepeatCacheCount001, TestSize.Level1)
1528 {
1529     ListModelNG model = CreateList();
1530     ViewStackProcessor::GetInstance()->StartGetAccessRecordingFor(GetElmtId());
__anonc56bfe6a0402(int32_t idx) 1531     CreateRepeatVirtualScrollNode(10, [this](int32_t idx) {
1532         CreateListItem();
1533         ViewStackProcessor::GetInstance()->Pop();
1534         ViewStackProcessor::GetInstance()->StopGetAccessRecording();
1535     });
1536     CreateDone(frameNode_);
1537 
1538     /**
1539      * @tc.steps: step1. Check Repeat frameCount
1540      */
1541     auto repeat = AceType::DynamicCast<RepeatVirtualScrollNode>(frameNode_->GetChildAtIndex(0));
1542     EXPECT_NE(repeat, nullptr);
1543     int32_t frameCount = repeat->FrameCount();
1544     EXPECT_EQ(frameCount, 10);
1545 
1546     /**
1547      * @tc.steps: step2. Flush Idle Task
1548      * @tc.expected: ListItem 4 is cached
1549      */
1550     auto listPattern = frameNode_->GetPattern<ListPattern>();
1551     FlushIdleTask(listPattern);
1552     int32_t childrenCount = repeat->GetChildren().size();
1553     EXPECT_EQ(childrenCount, 5);
1554     auto cachedItem = frameNode_->GetChildByIndex(4)->GetHostNode();
1555     EXPECT_EQ(cachedItem->IsActive(), false);
1556     EXPECT_EQ(GetChildY(frameNode_, 4), LIST_HEIGHT);
1557 
1558     /**
1559      * @tc.steps: step2. Flush Idle Task
1560      * @tc.expected: ListItem 1 and 7 is cached, ListItem 2,3,4,5,6 is active.
1561      */
1562     UpdateCurrentOffset(-250);
1563     FlushIdleTask(listPattern);
1564     childrenCount = repeat->GetChildren().size();
1565     EXPECT_EQ(childrenCount, 7);
1566     cachedItem = frameNode_->GetChildByIndex(1)->GetHostNode();
1567     EXPECT_EQ(cachedItem->IsActive(), false);
1568     cachedItem = frameNode_->GetChildByIndex(7)->GetHostNode();
1569     EXPECT_EQ(cachedItem->IsActive(), false);
1570     EXPECT_EQ(GetChildY(frameNode_, 1), -150.0f);
1571     EXPECT_EQ(GetChildY(frameNode_, 7), 450.0f);
1572 }
1573 
1574 /**
1575  * @tc.name: ListRepeatCacheCount002
1576  * @tc.desc: List lanes cacheCount
1577  * @tc.type: FUNC
1578  */
1579 HWTEST_F(ListLayoutTestNg, ListRepeatCacheCount002, TestSize.Level1)
1580 {
1581     ListModelNG model = CreateList();
1582     model.SetLanes(2);
1583     ViewStackProcessor::GetInstance()->StartGetAccessRecordingFor(GetElmtId());
__anonc56bfe6a0502(int32_t idx) 1584     CreateRepeatVirtualScrollNode(20, [this](int32_t idx) {
1585         CreateListItem();
1586         ViewStackProcessor::GetInstance()->Pop();
1587         ViewStackProcessor::GetInstance()->StopGetAccessRecording();
1588     });
1589     CreateDone(frameNode_);
1590 
1591     /**
1592      * @tc.steps: step1. Check Repeat frameCount
1593      */
1594     auto repeat = AceType::DynamicCast<RepeatVirtualScrollNode>(frameNode_->GetChildAtIndex(0));
1595     EXPECT_NE(repeat, nullptr);
1596     int32_t frameCount = repeat->FrameCount();
1597     EXPECT_EQ(frameCount, 20);
1598 
1599     /**
1600      * @tc.steps: step2. Flush Idle Task
1601      * @tc.expected: ListItem 8,9 is cached
1602      */
1603     auto listPattern = frameNode_->GetPattern<ListPattern>();
1604     FlushIdleTask(listPattern);
1605     int32_t childrenCount = repeat->GetChildren().size();
1606     EXPECT_EQ(childrenCount, 10);
1607     auto item8 = frameNode_->GetChildByIndex(8)->GetHostNode();
1608     EXPECT_EQ(item8->IsActive(), false);
1609     EXPECT_EQ(GetChildX(frameNode_, 8), 0.0f);
1610     EXPECT_EQ(GetChildY(frameNode_, 8), LIST_HEIGHT);
1611     auto item9 = frameNode_->GetChildByIndex(9)->GetHostNode();
1612     EXPECT_EQ(item9->IsActive(), false);
1613     EXPECT_EQ(GetChildX(frameNode_, 9), LIST_WIDTH / 2);
1614     EXPECT_EQ(GetChildY(frameNode_, 9), LIST_HEIGHT);
1615 
1616     /**
1617      * @tc.steps: step2. Flush Idle Task
1618      * @tc.expected: ListItem 2,3,14,15 is cached, ListItem 4-13 active.
1619      */
1620     UpdateCurrentOffset(-250);
1621     FlushIdleTask(listPattern);
1622     childrenCount = repeat->GetChildren().size();
1623     EXPECT_EQ(childrenCount, 14);
1624     auto item2 = frameNode_->GetChildByIndex(2)->GetHostNode();
1625     EXPECT_EQ(item2->IsActive(), false);
1626     EXPECT_EQ(GetChildX(frameNode_, 2), 0.0f);
1627     EXPECT_EQ(GetChildY(frameNode_, 2), -150.0f);
1628     auto item3 = frameNode_->GetChildByIndex(3)->GetHostNode();
1629     EXPECT_EQ(item3->IsActive(), false);
1630     EXPECT_EQ(GetChildX(frameNode_, 3), LIST_WIDTH / 2);
1631     EXPECT_EQ(GetChildY(frameNode_, 3), -150.0f);
1632     auto item14 = frameNode_->GetChildByIndex(14)->GetHostNode();
1633     EXPECT_EQ(item14->IsActive(), false);
1634     EXPECT_EQ(GetChildX(frameNode_, 14), 0.0f);
1635     EXPECT_EQ(GetChildY(frameNode_, 14), 450.0f);
1636     auto item15 = frameNode_->GetChildByIndex(15)->GetHostNode();
1637     EXPECT_EQ(item15->IsActive(), false);
1638     EXPECT_EQ(GetChildX(frameNode_, 15), LIST_WIDTH / 2);
1639     EXPECT_EQ(GetChildY(frameNode_, 15), 450.0f);
1640 }
1641 
1642 /**
1643  * @tc.name: SetHeaderFooterComponent01
1644  * @tc.desc: Test HeaderComponent/FooterComponent of ListItemGroup
1645  * @tc.type: FUNC
1646  */
1647 HWTEST_F(ListLayoutTestNg, SetHeaderFooterComponent01, TestSize.Level1)
1648 {
1649     /**
1650      * @tc.steps: step1. create List group with ComponentContent
1651      */
1652     const int32_t groupNumber = 5;
1653     const float contentStartOffset = 100;
1654     const float contentEndOffset = 50;
1655     ListModelNG model = CreateList();
1656     model.SetContentStartOffset(contentStartOffset);
1657     model.SetContentEndOffset(contentEndOffset);
1658     model.SetSticky(V2::StickyStyle::BOTH);
1659     CreateGroupWithSettingWithComponentContent(groupNumber, V2::ListItemGroupStyle::NONE);
1660     CreateDone(frameNode_);
1661 
1662     /**
1663      * @tc.steps: step2. Get the count of group
1664      * @tc.expected: header and footer can be added successfully.
1665      */
1666     auto group0 = GetChildFrameNode(frameNode_, 0);
1667     auto group1 = GetChildFrameNode(frameNode_, 1);
1668     auto group0Children = group0->GetChildren();
1669     auto group1Children = group1->GetChildren();
1670     auto group0Pattern = group0->GetPattern<ListItemGroupPattern>();
1671     EXPECT_EQ(group0Children.size(), 4);
1672     EXPECT_EQ(group1Children.size(), 4);
1673 
1674     /**
1675      * @tc.steps: step3. Update header and footer
1676      * @tc.expected: new header and footer can be set.
1677      */
1678     bool headerResult = false;
1679     bool footerResult = false;
1680     group0Pattern->AddHeader(CreateCustomNode("NewHeader"));
1681     group0Pattern->AddFooter(CreateCustomNode("NewFooter"));
1682     const char newFooter[] = "NewFooter";
1683     const char newHeader[] = "NewHeader";
1684     auto children = group0->GetChildren();
1685     for (auto child : children) {
1686         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
1687         if (childFrameNode->GetTag() == newHeader) {
1688             headerResult = true;
1689         }
1690         if (childFrameNode->GetTag() == newFooter) {
1691             footerResult = true;
1692         }
1693     }
1694     EXPECT_TRUE(headerResult);
1695     EXPECT_TRUE(footerResult);
1696 
1697     /**
1698      * @tc.steps: step4. Remove group0 header and footer
1699      * @tc.expected: header and footer can be removed successfully.
1700      */
1701     group0Pattern->RemoveHeader();
1702     group0Pattern->RemoveFooter();
1703     group0Children = group0->GetChildren();
1704     EXPECT_EQ(group0Children.size(), 2);
1705 }
1706 } // namespace OHOS::Ace::NG
1707