1 /*
2 * Copyright (c) 2022-2025 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 "tabs_test_ng.h"
17
18 #include "test/mock/base/mock_task_executor.h"
19 #include "test/mock/core/common/mock_theme_manager.h"
20 #include "test/mock/core/pipeline/mock_pipeline_context.h"
21 #include "test/mock/core/render/mock_render_context.h"
22 #include "test/mock/core/rosen/mock_canvas.h"
23
24 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
25 #include "core/components/dialog/dialog_theme.h"
26 #include "core/components/tab_bar/tab_theme.h"
27 #include "core/components_ng/pattern/linear_layout/column_model_ng.h"
28
29 namespace OHOS::Ace::NG {
30 namespace {
GetTheme(ThemeType type)31 RefPtr<Theme> GetTheme(ThemeType type)
32 {
33 if (type == AgingAdapationDialogTheme::TypeId()) {
34 auto agingAdapationDialogTheme = AceType::MakeRefPtr<AgingAdapationDialogTheme>();
35 agingAdapationDialogTheme->bigFontSizeScale_ = BIG_FONT_SIZE_SCALE;
36 agingAdapationDialogTheme->largeFontSizeScale_ = LARGE_FONT_SIZE_SCALE;
37 agingAdapationDialogTheme->maxFontSizeScale_ = MAX_FONT_SIZE_SCALE;
38 agingAdapationDialogTheme->bigDialogWidth_ = BIG_DIALOG_WIDTH;
39 agingAdapationDialogTheme->maxDialogWidth_ = MAX_DIALOG_WIDTH;
40 return agingAdapationDialogTheme;
41 } else if (type == TabTheme::TypeId()) {
42 auto themeConstants = TestNG::CreateThemeConstants(THEME_PATTERN_TAB);
43 auto tabTheme = TabTheme::Builder().Build(themeConstants);
44 tabTheme->defaultTabBarName_ = "tabBarItemName";
45 tabTheme->tabBarDefaultWidth_ = Dimension(TAB_BAR_SIZE);
46 tabTheme->tabBarDefaultHeight_ = Dimension(TAB_BAR_SIZE);
47 tabTheme->subTabBarHoverColor_ = Color::RED;
48 tabTheme->subTabBarPressedColor_ = Color::GREEN;
49 tabTheme->bottomTabSymbolOn_ = Color::BLUE;
50 tabTheme->bottomTabIconOff_ = Color::BLACK;
51 tabTheme->tabBarFocusedColor_ = Color::GRAY;
52 return tabTheme;
53 } else {
54 return AceType::MakeRefPtr<DialogTheme>();
55 }
56 }
57 } // namespace
58
SetUpTestSuite()59 void TabsTestNg::SetUpTestSuite()
60 {
61 TestNG::SetUpTestSuite();
62 MockPipelineContext::GetCurrent()->SetUseFlushUITasks(true);
63 auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
64 EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly([](ThemeType type) -> RefPtr<Theme> {
65 return GetTheme(type);
66 });
67 EXPECT_CALL(*themeManager, GetTheme(_, _))
68 .WillRepeatedly([](ThemeType type, int32_t themeScopeId) -> RefPtr<Theme> { return GetTheme(type); });
69 MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
70 }
71
TearDownTestSuite()72 void TabsTestNg::TearDownTestSuite()
73 {
74 TestNG::TearDownTestSuite();
75 }
76
SetUp()77 void TabsTestNg::SetUp() {}
78
TearDown()79 void TabsTestNg::TearDown()
80 {
81 RemoveFromStageNode();
82 frameNode_ = nullptr;
83 pattern_ = nullptr;
84 layoutProperty_ = nullptr;
85
86 swiperNode_ = nullptr;
87 swiperPattern_ = nullptr;
88 swiperLayoutProperty_ = nullptr;
89 swiperPaintProperty_ = nullptr;
90 swiperController_ = nullptr;
91
92 tabBarNode_ = nullptr;
93 tabBarPattern_ = nullptr;
94 tabBarLayoutProperty_ = nullptr;
95 tabBarPaintProperty_ = nullptr;
96 tabBarAccessibilityProperty_ = nullptr;
97
98 dividerNode_ = nullptr;
99 dividerRenderProperty_ = nullptr;
100 ClearOldNodes(); // Each testCase will create new list at begin
101 AceApplicationInfo::GetInstance().isRightToLeft_ = false;
102 }
103
GetTabs()104 void TabsTestNg::GetTabs()
105 {
106 // tabs
107 RefPtr<UINode> element = ViewStackProcessor::GetInstance()->GetMainElementNode();
108 frameNode_ = AceType::DynamicCast<TabsNode>(element);
109 pattern_ = frameNode_->GetPattern<TabsPattern>();
110 layoutProperty_ = frameNode_->GetLayoutProperty<TabsLayoutProperty>();
111 // swiper>tabContent
112 swiperNode_ = AceType::DynamicCast<FrameNode>(frameNode_->GetTabs());
113 swiperPattern_ = swiperNode_->GetPattern<SwiperPattern>();
114 swiperLayoutProperty_ = swiperNode_->GetLayoutProperty<SwiperLayoutProperty>();
115 swiperPaintProperty_ = swiperNode_->GetPaintProperty<SwiperPaintProperty>();
116 swiperController_ = swiperPattern_->GetSwiperController();
117 // tabBar
118 tabBarNode_ = AceType::DynamicCast<FrameNode>(frameNode_->GetTabBar());
119 tabBarPattern_ = tabBarNode_->GetPattern<TabBarPattern>();
120 tabBarLayoutProperty_ = tabBarNode_->GetLayoutProperty<TabBarLayoutProperty>();
121 tabBarPaintProperty_ = tabBarNode_->GetPaintProperty<TabBarPaintProperty>();
122 tabBarAccessibilityProperty_ = tabBarNode_->GetAccessibilityProperty<TabBarAccessibilityProperty>();
123 // divider
124 dividerNode_ = AceType::DynamicCast<FrameNode>(frameNode_->GetDivider());
125 dividerRenderProperty_ = dividerNode_->GetPaintProperty<DividerRenderProperty>();
126 }
127
CreateTabs(BarPosition barPosition,int32_t index)128 TabsModelNG TabsTestNg::CreateTabs(BarPosition barPosition, int32_t index)
129 {
130 ResetElmtId();
131 ViewStackProcessor::GetInstance()->StartGetAccessRecordingFor(GetElmtId());
132 TabsModelNG model;
133 model.Create(barPosition, index, nullptr, nullptr);
134 ViewAbstract::SetWidth(CalcLength(TABS_WIDTH));
135 ViewAbstract::SetHeight(CalcLength(TABS_HEIGHT));
136 auto tabNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
137 auto tabBarNode = AceType::DynamicCast<FrameNode>(tabNode->GetTabBar());
138 tabBarNode->GetOrCreateFocusHub();
139 GetTabs();
140 return model;
141 }
142
CreateTabContent()143 TabContentModelNG TabsTestNg::CreateTabContent()
144 {
145 return CreateTabContentWithDeepRender(nullptr);
146 }
147
CreateTabContentWithDeepRender(std::function<void ()> && deepRenderFunc)148 TabContentModelNG TabsTestNg::CreateTabContentWithDeepRender(std::function<void()>&& deepRenderFunc)
149 {
150 int32_t elmtId = GetElmtId();
151 ViewStackProcessor::GetInstance()->StartGetAccessRecordingFor(elmtId);
152 auto tabFrameNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
153 auto weakTab = AceType::WeakClaim(AceType::RawPtr(tabFrameNode));
154 TabContentModelNG tabContentModel;
155 tabContentModel.Create(std::move(deepRenderFunc));
156 ViewAbstract::SetWidth(CalcLength(FILL_LENGTH));
157 ViewAbstract::SetHeight(CalcLength(FILL_LENGTH));
158 auto tabContentFrameNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
159 auto tabContentNode = AceType::DynamicCast<TabContentNode>(tabContentFrameNode);
160 tabContentNode->UpdateRecycleElmtId(elmtId); // for AddChildToGroup
161 tabContentNode->GetTabBarItemId(); // for AddTabBarItem
162 tabContentNode->SetParent(weakTab); // for AddTabBarItem
163 return tabContentModel;
164 }
165
CreateTabsDone(TabsModelNG model)166 void TabsTestNg::CreateTabsDone(TabsModelNG model)
167 {
168 model.Pop();
169 CreateDone();
170 auto pipeline = frameNode_->GetContext();
171 pipeline->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
172 }
173
CreateTabContents(int32_t itemNumber)174 void TabsTestNg::CreateTabContents(int32_t itemNumber)
175 {
176 for (int32_t index = 0; index < itemNumber; index++) {
177 TabContentModelNG tabContentModel = CreateTabContent();
178 ViewStackProcessor::GetInstance()->Pop();
179 ViewStackProcessor::GetInstance()->StopGetAccessRecording();
180 }
181 }
182
CreateTabContentsWithBuilder(int32_t itemNumber)183 void TabsTestNg::CreateTabContentsWithBuilder(int32_t itemNumber)
184 {
185 for (int32_t index = 0; index < itemNumber; index++) {
186 TabContentModelNG tabContentModel = CreateTabContent();
187 auto tabBarItemFunc = TabBarItemBuilder();
188 tabContentModel.SetTabBar("", "", std::nullopt, std::move(tabBarItemFunc), true);
189 ViewStackProcessor::GetInstance()->Pop();
190 ViewStackProcessor::GetInstance()->StopGetAccessRecording();
191 }
192 }
193
TabBarItemBuilder()194 TabBarBuilderFunc TabsTestNg::TabBarItemBuilder()
195 {
196 return []() {
197 ColumnModelNG colModel;
198 colModel.Create(Dimension(0), nullptr, "");
199 ViewAbstract::SetWidth(CalcLength(BAR_ITEM_SIZE));
200 ViewAbstract::SetHeight(CalcLength(BAR_ITEM_SIZE));
201 };
202 }
203
CreateTabContentTabBarStyle(TabBarStyle tabBarStyle)204 void TabsTestNg::CreateTabContentTabBarStyle(TabBarStyle tabBarStyle)
205 {
206 TabContentModelNG tabContentModel = CreateTabContent();
207 tabContentModel.SetTabBarStyle(tabBarStyle);
208 tabContentModel.SetTabBar("text", IMAGE_SRC_URL, std::nullopt, nullptr, true);
209 ViewStackProcessor::GetInstance()->Pop();
210 ViewStackProcessor::GetInstance()->StopGetAccessRecording();
211 }
212
CreateTabContentTabBarStyleWithBuilder(TabBarStyle tabBarStyle)213 void TabsTestNg::CreateTabContentTabBarStyleWithBuilder(TabBarStyle tabBarStyle)
214 {
215 TabContentModelNG tabContentModel = CreateTabContent();
216 tabContentModel.SetTabBarStyle(tabBarStyle);
217 auto tabBarItemFunc = TabBarItemBuilder();
218 tabContentModel.SetTabBar("", "", std::nullopt, std::move(tabBarItemFunc), true);
219 ViewStackProcessor::GetInstance()->Pop();
220 ViewStackProcessor::GetInstance()->StopGetAccessRecording();
221 }
222
ChangeIndex(int32_t index)223 void TabsTestNg::ChangeIndex(int32_t index)
224 {
225 swiperController_->SwipeTo(index);
226 frameNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); // for update swiper
227 FlushUITasks();
228 }
229
HandleClick(int32_t index)230 void TabsTestNg::HandleClick(int32_t index)
231 {
232 tabBarPattern_->HandleClick(SourceType::NONE, index);
233 frameNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); // for update swiper
234 FlushUITasks();
235 }
236
HandleMouseEvent(MouseAction action,Offset location)237 void TabsTestNg::HandleMouseEvent(MouseAction action, Offset location)
238 {
239 MouseInfo mouseInfo;
240 mouseInfo.SetAction(action);
241 mouseInfo.SetLocalLocation(location);
242 tabBarPattern_->HandleMouseEvent(mouseInfo);
243 }
244
HandleHoverEvent(bool isHover)245 void TabsTestNg::HandleHoverEvent(bool isHover)
246 {
247 tabBarPattern_->HandleHoverEvent(isHover);
248 }
249
CreateDragInfo(bool moveDirection)250 GestureEvent TabsTestNg::CreateDragInfo(bool moveDirection)
251 {
252 GestureEvent info;
253 info.SetInputEventType(InputEventType::AXIS);
254 info.SetSourceTool(SourceTool::TOUCHPAD);
255 info.SetGlobalLocation(Offset(100.f, 100.f));
256 info.SetMainDelta(moveDirection ? -DRAG_DELTA : DRAG_DELTA);
257 info.SetMainVelocity(moveDirection ? -2000.f : 2000.f);
258 return info;
259 }
260
CurrentIndex(int32_t expectIndex)261 AssertionResult TabsTestNg::CurrentIndex(int32_t expectIndex)
262 {
263 if (swiperPattern_->GetCurrentIndex() != expectIndex) {
264 return IsEqual(swiperPattern_->GetCurrentIndex(), expectIndex);
265 }
266 if (tabBarLayoutProperty_->GetIndicatorValue() != expectIndex) {
267 return IsEqual(tabBarLayoutProperty_->GetIndicatorValue(), expectIndex);
268 }
269 if (!GetChildFrameNode(swiperNode_, expectIndex)) {
270 return AssertionFailure() << "There is no item at expectIndex: " << expectIndex;
271 }
272 if (!GetChildFrameNode(swiperNode_, expectIndex)->IsActive()) {
273 return AssertionFailure() << "The expectIndex item is not active";
274 }
275 if (GetChildFrameNode(swiperNode_, expectIndex)->GetLayoutProperty()->GetVisibility() != VisibleType::GONE) {
276 if (NearZero(GetChildWidth(swiperNode_, expectIndex))) {
277 return AssertionFailure() << "The expectIndex item width is 0";
278 }
279 if (NearZero(GetChildHeight(swiperNode_, expectIndex))) {
280 return AssertionFailure() << "The expectIndex item height is 0";
281 }
282 }
283 return AssertionSuccess();
284 }
285
OnDraw()286 RefPtr<TabBarModifier> TabsTestNg::OnDraw()
287 {
288 RefPtr<NodePaintMethod> paint = tabBarPattern_->CreateNodePaintMethod();
289 RefPtr<TabBarPaintMethod> tabBarPaint = AceType::DynamicCast<TabBarPaintMethod>(paint);
290 auto tabBarPaintWrapper = tabBarNode_->CreatePaintWrapper();
291 tabBarPaint->UpdateContentModifier(AceType::RawPtr(tabBarPaintWrapper));
292
293 auto modifier = tabBarPaint->GetContentModifier(nullptr);
294 auto tabBarModifier = AceType::DynamicCast<TabBarModifier>(modifier);
295 Testing::MockCanvas canvas;
296 DrawingContext drawingContext = { canvas, TABS_WIDTH, TABS_HEIGHT };
297 tabBarModifier->onDraw(drawingContext);
298 return tabBarModifier;
299 }
300
VerifyBackgroundColor(int32_t itemIndex,Color expectColor)301 AssertionResult TabsTestNg::VerifyBackgroundColor(int32_t itemIndex, Color expectColor)
302 {
303 Color actualColor = GetChildFrameNode(tabBarNode_, itemIndex)->GetRenderContext()->GetBackgroundColor().value();
304 return IsEqual(actualColor, expectColor);
305 }
306
MockPaintRect(const RefPtr<FrameNode> & frameNode)307 void TabsTestNg::MockPaintRect(const RefPtr<FrameNode>& frameNode)
308 {
309 auto mockRenderContext = AceType::DynamicCast<MockRenderContext>(frameNode->renderContext_);
310 mockRenderContext->paintRect_ = RectF(0.f, 0.f, TABS_WIDTH, TABS_HEIGHT);
311 }
312
313 /**
314 * @tc.name: InitSurfaceChangedCallback001
315 * @tc.desc: test InitSurfaceChangedCallback
316 * @tc.type: FUNC
317 */
318 HWTEST_F(TabsTestNg, InitSurfaceChangedCallback001, TestSize.Level1)
319 {
320 TabsModelNG model = CreateTabs();
321 CreateTabContents(TABCONTENT_NUMBER);
322 CreateTabsDone(model);
323
324 /**
325 * @tc.steps: case1. WindowSizeChangeReason::UNDEFINED
326 */
327 auto callbackId = tabBarPattern_->surfaceChangedCallbackId_.value();
328 auto func = MockPipelineContext::GetCurrent()->surfaceChangedCallbackMap_[callbackId];
329 func(100.f, 100.f, TABS_WIDTH, TABS_HEIGHT, WindowSizeChangeReason::UNDEFINED);
330 EXPECT_EQ(tabBarPattern_->windowSizeChangeReason_, WindowSizeChangeReason::UNDEFINED);
331
332 /**
333 * @tc.steps: case2. WindowSizeChangeReason::ROTATION
334 * @tc.expected: StopTranslateAnimation
335 */
336 func(100.f, 100.f, TABS_WIDTH, TABS_HEIGHT, WindowSizeChangeReason::ROTATION);
337 EXPECT_EQ(tabBarPattern_->windowSizeChangeReason_, WindowSizeChangeReason::ROTATION);
338 EXPECT_FALSE(tabBarPattern_->indicatorAnimationIsRunning_);
339 EXPECT_FALSE(tabBarPattern_->translateAnimationIsRunning_);
340
341 /**
342 * @tc.steps: case3. Other WindowSizeChangeReason
343 * @tc.expected: Nothing happend
344 */
345 func(100.f, 100.f, TABS_WIDTH, TABS_HEIGHT, WindowSizeChangeReason::TRANSFORM);
346 EXPECT_EQ(tabBarPattern_->windowSizeChangeReason_, WindowSizeChangeReason::TRANSFORM);
347 }
348
349 /**
350 * @tc.name: TabsPatternGetScopeFocusAlgorithm001
351 * @tc.desc: test GetScopeFocusAlgorithm
352 * @tc.type: FUNC
353 */
354 HWTEST_F(TabsTestNg, TabsPatternGetScopeFocusAlgorithm001, TestSize.Level1)
355 {
356 TabsModelNG model = CreateTabs(BarPosition::END);
357 CreateTabContentTabBarStyle(TabBarStyle::SUBTABBATSTYLE);
358 CreateTabContentTabBarStyle(TabBarStyle::SUBTABBATSTYLE);
359 CreateTabsDone(model);
360
361 /**
362 * @tc.steps: steps2. GetScopeFocusAlgorithm
363 * @tc.expected: steps2. Check the result of GetScopeFocusAlgorithm
364 */
365 auto tabsLayoutProperty = layoutProperty_;
366 auto tabsPattern = frameNode_->GetPattern<TabsPattern>();
367 tabsLayoutProperty->UpdateAxis(Axis::HORIZONTAL);
368 tabsPattern->GetScopeFocusAlgorithm();
369 EXPECT_EQ(tabsLayoutProperty->GetAxis().value(), Axis::HORIZONTAL);
370 tabsLayoutProperty->UpdateAxis(Axis::VERTICAL);
371 tabsPattern->GetScopeFocusAlgorithm();
372 EXPECT_EQ(tabsLayoutProperty->GetAxis().value(), Axis::VERTICAL);
373 }
374
375 /**
376 * @tc.name: ConvertToString001
377 * @tc.desc: Test the ConvertLayoutModeToString function in the TabContentNodel class.
378 * @tc.type: FUNC
379 */
380 HWTEST_F(TabsTestNg, ConvertToString001, TestSize.Level1)
381 {
382 TabsModelNG model = CreateTabs();
383 CreateTabContents(1);
384 CreateTabsDone(model);
385 auto tabContentFrameNode = AceType::DynamicCast<TabContentNode>(GetChildFrameNode(swiperNode_, 0));
386 EXPECT_EQ(tabContentFrameNode->ConvertFlexAlignToString(FlexAlign::FLEX_START), "VerticalAlign.Top");
387 EXPECT_EQ(tabContentFrameNode->ConvertFlexAlignToString(FlexAlign::FLEX_END), "VerticalAlign.Bottom");
388 EXPECT_EQ(tabContentFrameNode->ConvertLayoutModeToString(LayoutMode::VERTICAL), "LayoutMode.VERTICAL");
389 EXPECT_EQ(tabContentFrameNode->ConvertLayoutModeToString(LayoutMode::HORIZONTAL), "LayoutMode.HORIZONTAL");
390 EXPECT_EQ(tabContentFrameNode->ConvertLayoutModeToString(LayoutMode::AUTO), "LayoutMode.AUTO");
391 }
392
393 /**
394 * @tc.name: TabsNodeToJsonValue001
395 * @tc.desc: Test the ToJsonValue function in the TabsNode class.
396 * @tc.type: FUNC
397 */
398 HWTEST_F(TabsTestNg, TabsNodeToJsonValue001, TestSize.Level2)
399 {
400 TabsModelNG model = CreateTabs();
401 CreateTabContents(1);
402 CreateTabsDone(model);
403
404 auto json = JsonUtil::Create(true);
405 InspectorFilter filter;
406 frameNode_->ToJsonValue(json, filter);
407 EXPECT_EQ(json->GetString("index"), "0");
408 EXPECT_EQ(json->GetString("animationDuration"), "");
409 EXPECT_EQ(json->GetString("barMode"), "BarMode.Fixed");
410 EXPECT_EQ(json->GetString("barWidth"), "720.000000");
411 EXPECT_EQ(json->GetString("barHeight"), "56.000000");
412 EXPECT_EQ(json->GetString("fadingEdge"), "true");
413 EXPECT_EQ(json->GetString("barBackgroundColor"), "#00000000");
414 EXPECT_EQ(json->GetString("barBackgroundBlurStyle"), "BlurStyle.NONE");
415 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.CONTENT_FIRST");
416 EXPECT_EQ(json->GetString("edgeEffect"), "EdgeEffect::SPRING");
417 EXPECT_EQ(json->GetString("barGridAlign"), "");
418
419 pattern_->SetAnimateMode(TabAnimateMode::ACTION_FIRST);
420 tabBarLayoutProperty_->UpdateTabBarMode(TabBarMode::SCROLLABLE);
421 swiperPaintProperty_->UpdateEdgeEffect(EdgeEffect::FADE);
422 json = JsonUtil::Create(true);
423 frameNode_->ToJsonValue(json, filter);
424 EXPECT_EQ(json->GetString("barMode"),
425 "BarMode.Scrollable,{\"margin\":\"0.00vp\",\"nonScrollableLayoutStyle\":\"LayoutStyle.ALWAYS_CENTER\"}");
426 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.ACTION_FIRST");
427 EXPECT_EQ(json->GetString("edgeEffect"), "EdgeEffect::FADE");
428
429 ScrollableBarModeOptions options;
430 options.nonScrollableLayoutStyle = LayoutStyle::ALWAYS_AVERAGE_SPLIT;
431 tabBarLayoutProperty_->UpdateScrollableBarModeOptions(options);
432 pattern_->SetAnimateMode(TabAnimateMode::NO_ANIMATION);
433 swiperPaintProperty_->UpdateEdgeEffect(EdgeEffect::NONE);
434 json = JsonUtil::Create(true);
435 frameNode_->ToJsonValue(json, filter);
436 EXPECT_EQ(json->GetString("barMode"),
437 "BarMode.Scrollable,{\"margin\":\"0.00vp\",\"nonScrollableLayoutStyle\":\"LayoutStyle.ALWAYS_AVERAGE_SPLIT\"}");
438 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.NO_ANIMATION");
439 EXPECT_EQ(json->GetString("edgeEffect"), "EdgeEffect::NONE");
440
441 options.nonScrollableLayoutStyle = LayoutStyle::SPACE_BETWEEN_OR_CENTER;
442 tabBarLayoutProperty_->UpdateScrollableBarModeOptions(options);
443 pattern_->SetAnimateMode(TabAnimateMode::MAX_VALUE);
444 json = JsonUtil::Create(true);
445 frameNode_->ToJsonValue(json, filter);
446 EXPECT_EQ(json->GetString("barMode"), "BarMode.Scrollable,{\"margin\":\"0.00vp\",\"nonScrollableLayoutStyle\":"
447 "\"LayoutStyle.SPACE_BETWEEN_OR_CENTER\"}");
448 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.CONTENT_FIRST");
449 }
450
451 /**
452 * @tc.name: TabsNodeToJsonValue002
453 * @tc.desc: Test the ToJsonValue function in the TabsNode class.
454 * @tc.type: FUNC
455 */
456 HWTEST_F(TabsTestNg, TabsNodeToJsonValue002, TestSize.Level2)
457 {
458 TabsModelNG model = CreateTabs();
459 CreateTabContents(1);
460 CreateTabsDone(model);
461
462 frameNode_->swiperId_ = std::nullopt;
463 frameNode_->tabBarId_ = std::nullopt;
464 auto json = JsonUtil::Create(true);
465 InspectorFilter filter;
466 frameNode_->ToJsonValue(json, filter);
467 EXPECT_EQ(json->GetString("index"), "0");
468 EXPECT_EQ(json->GetString("animationDuration"), "");
469 EXPECT_EQ(json->GetString("barMode"), "BarMode.Fixed");
470 EXPECT_EQ(json->GetString("barWidth"), "0.000000");
471 EXPECT_EQ(json->GetString("barHeight"), "0.000000");
472 EXPECT_EQ(json->GetString("fadingEdge"), "true");
473 EXPECT_EQ(json->GetString("barBackgroundColor"), "#00000000");
474 EXPECT_EQ(json->GetString("barBackgroundBlurStyle"), "BlurStyle.NONE");
475 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.CONTENT_FIRST");
476 EXPECT_EQ(json->GetString("edgeEffect"), "EdgeEffect::SPRING");
477 EXPECT_EQ(json->GetString("barGridAlign"), "");
478
479 std::string attr = "id";
480 filter.AddFilterAttr(attr);
481 json = JsonUtil::Create(true);
482 frameNode_->ToJsonValue(json, filter);
483 EXPECT_TRUE(filter.IsFastFilter());
484 EXPECT_EQ(json->ToString(), "{\"id\":\"\"}");
485 }
486
487 /**
488 * @tc.name: TabsNodeToJsonValue003
489 * @tc.desc: Test the ToJsonValue function in the TabsNode class.
490 * @tc.type: FUNC
491 */
492 HWTEST_F(TabsTestNg, TabsNodeToJsonValue003, TestSize.Level2)
493 {
494 TabsModelNG model = CreateTabs();
495 CreateTabContents(1);
496 CreateTabsDone(model);
497 ASSERT_NE(frameNode_, nullptr);
498 ASSERT_NE(pattern_, nullptr);
499
500 InspectorFilter filter;
501 auto json = JsonUtil::Create(true);
502 ASSERT_NE(json, nullptr);
503 frameNode_->ToJsonValue(json, filter);
504 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.CONTENT_FIRST");
505
506 pattern_->SetAnimateMode(TabAnimateMode::CONTENT_FIRST_WITH_JUMP);
507 json = JsonUtil::Create(true);
508 ASSERT_NE(json, nullptr);
509 frameNode_->ToJsonValue(json, filter);
510 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.CONTENT_FIRST_WITH_JUMP");
511
512 pattern_->SetAnimateMode(TabAnimateMode::ACTION_FIRST_WITH_JUMP);
513 json = JsonUtil::Create(true);
514 ASSERT_NE(json, nullptr);
515 frameNode_->ToJsonValue(json, filter);
516 EXPECT_EQ(json->GetString("animationMode"), "AnimationMode.ACTION_FIRST_WITH_JUMP");
517 }
518
519 /**
520 * @tc.name: TabsNodeGetScrollableBarModeOptions001
521 * @tc.desc: Test the GetScrollableBarModeOptions function in the TabsNode class.
522 * @tc.type: FUNC
523 */
524 HWTEST_F(TabsTestNg, TabsNodeGetScrollableBarModeOptions001, TestSize.Level2)
525 {
526 TabsModelNG model = CreateTabs();
527 CreateTabContents(TABCONTENT_NUMBER);
528 CreateTabsDone(model);
529 tabBarPattern_->tabBarStyle_ = TabBarStyle::SUBTABBATSTYLE;
530
531 /**
532 * @tc.steps: steps2. GetScrollableBarModeOptions.
533 * @tc.expected: steps2. Check the result of GetScrollableBarModeOptions.
534 */
535 frameNode_->GetScrollableBarModeOptions();
536 frameNode_->tabBarId_ = frameNode_->GetTabBarId();
537 ScrollableBarModeOptions option = frameNode_->GetScrollableBarModeOptions();
538 EXPECT_EQ(option.margin.Value(), 0.0f);
539 EXPECT_EQ(option.nonScrollableLayoutStyle, std::nullopt);
540 frameNode_->tabBarId_ = {};
541 option = frameNode_->GetScrollableBarModeOptions();
542 EXPECT_EQ(option.margin.Value(), 0.0f);
543 EXPECT_EQ(option.nonScrollableLayoutStyle, std::nullopt);
544 }
545
546 /**
547 * @tc.name: ProvideRestoreInfo001
548 * @tc.desc: test AddTabBarItem
549 * @tc.type: FUNC
550 */
551 HWTEST_F(TabsTestNg, ProvideRestoreInfo001, TestSize.Level1)
552 {
553 TabsModelNG model = CreateTabs();
554 CreateTabContents(TABCONTENT_NUMBER);
555 CreateTabsDone(model);
556 EXPECT_EQ(tabBarPattern_->ProvideRestoreInfo(), "{\"Index\":0}");
557 ChangeIndex(1);
558 EXPECT_EQ(tabBarPattern_->ProvideRestoreInfo(), "{\"Index\":1}");
559 }
560
561 /**
562 * @tc.name: Create003
563 * @tc.desc: test SetEdgeEffect
564 * @tc.type: FUNC
565 */
566 HWTEST_F(TabsTestNg, Create003, TestSize.Level1)
567 {
568 /**
569 * @tc.steps: step1. Construct TabContentModelNG object
570 */
571 int32_t testIndex = 0;
572 TabsModelNG model = CreateTabs(BarPosition::END, testIndex);
573 CreateTabContents(TABCONTENT_NUMBER);
574 CreateTabsDone(model);
575
576 /**
577 * @tc.steps: step2. Test function Create.
578 * @tc.expected: TestIndex greater than or equal to 0
579 */
580 swiperPaintProperty_->UpdateEdgeEffect(EdgeEffect::SPRING);
581 EXPECT_TRUE(testIndex >= 0);
582 }
583
584 /**
585 * @tc.name: TabsPatternParseJsonString002
586 * @tc.desc: test ParseJsonString
587 * @tc.type: FUNC
588 */
589 HWTEST_F(TabsTestNg, TabsPatternOnRestoreInfo002, TestSize.Level1)
590 {
591 /**
592 * @tc.steps: step1. Function OnRestoreInfo is called.
593 * @tc.expected: Passing invalid & valid JSON format.
594 */
595 TabsModelNG model = CreateTabs(BarPosition::END);
596 CreateTabContents(TABCONTENT_NUMBER);
597 CreateTabsDone(model);
598 pattern_->OnRestoreInfo("");
599 auto info = JsonUtil::ParseJsonString("");
600 EXPECT_FALSE(info->IsObject());
601 }
602
603 /**
604 * @tc.name: TabsPatternSetOnAnimationEnd002
605 * @tc.desc: test Measure
606 * @tc.type: FUNC
607 */
608 HWTEST_F(TabsTestNg, TabsPatternSetOnAnimationEnd002, TestSize.Level1)
609 {
__anon130c75710502(int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) 610 auto onAnimationStart = [](int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) {};
__anon130c75710602(int32_t index, const AnimationCallbackInfo& info) 611 auto onAnimationEnd = [](int32_t index, const AnimationCallbackInfo& info) {};
612 TabsModelNG model = CreateTabs();
613 model.SetOnAnimationStart(std::move(onAnimationStart));
614 model.SetOnAnimationEnd(std::move(onAnimationEnd));
615 CreateTabContents(TABCONTENT_NUMBER);
616 CreateTabsDone(model);
617
618 /**
619 * @tc.steps: step2.2. Test SetOnAnimationEnd function.
620 * @tc.expected:pattern_->animationEndEvent_ not null.
621 */
622 tabBarPattern_->InitTurnPageRateEvent();
623 int32_t testswipingIndex = 1;
624 float testturnPageRate = 1.0f;
625 swiperController_->GetTurnPageRateCallback()(testswipingIndex, testturnPageRate);
626
627 /**
628 * @tc.steps: step1. Convert lvalue to rvalue reference using std:: move()
629 */
630 EXPECT_NE(pattern_->animationEndEvent_, nullptr);
631 pattern_->SetAnimationEndEvent(std::move(*tabBarPattern_->animationEndEvent_));
632 EXPECT_NE(pattern_->animationEndEvent_, nullptr);
633 }
634
635 /**
636 * @tc.name: TabsPatternGetAxis003
637 * @tc.desc: test GetAxis
638 * @tc.type: FUNC
639 */
640 HWTEST_F(TabsTestNg, TabsPatternGetAxis003, TestSize.Level1)
641 {
642 TabsModelNG model = CreateTabs();
643 CreateTabContents(TABCONTENT_NUMBER);
644 CreateTabsDone(model);
645
646 /**
647 * @tc.steps: steps2. GetScopeFocusAlgorithm
648 * @tc.expected: steps2. Check the result of GetScopeFocusAlgorithm
649 */
650 layoutProperty_->UpdateAxis(Axis::HORIZONTAL);
651 pattern_->GetScopeFocusAlgorithm();
652 EXPECT_EQ(layoutProperty_->GetAxis().value(), Axis::HORIZONTAL);
653
654 layoutProperty_->UpdateAxis(Axis::VERTICAL);
655 pattern_->GetScopeFocusAlgorithm();
656 EXPECT_EQ(layoutProperty_->GetAxis().value(), Axis::VERTICAL);
657
658 layoutProperty_->UpdateAxis(Axis::FREE);
659 pattern_->GetScopeFocusAlgorithm();
660 EXPECT_EQ(layoutProperty_->GetAxis().value(), Axis::FREE);
661
662 layoutProperty_->UpdateAxis(Axis::NONE);
663 pattern_->GetScopeFocusAlgorithm();
664 EXPECT_EQ(layoutProperty_->GetAxis().value(), Axis::NONE);
665 }
666
667 /**
668 * @tc.name: TabsPatternGetScopeFocusAlgorithm004
669 * @tc.desc: test GetScopeFocusAlgorithm
670 * @tc.type: FUNC
671 */
672 HWTEST_F(TabsTestNg, TabsPatternGetScopeFocusAlgorithm004, TestSize.Level1)
673 {
674 /**
675 * @tc.steps: steps2. GetScopeFocusAlgorithm
676 * @tc.expected: steps2. Check the result of GetScopeFocusAlgorithm
677 */
678 TabsModelNG model = CreateTabs();
679 CreateTabContents(TABCONTENT_NUMBER);
680 CreateTabsDone(model);
681 layoutProperty_->Reset();
682 pattern_->GetScopeFocusAlgorithm();
683 EXPECT_FALSE(layoutProperty_->GetAxis().has_value());
684 }
685
686 /**
687 * @tc.name: CustomAnimationTest001
688 * @tc.desc: test custom animation disable swipe
689 * @tc.type: FUNC
690 */
691 HWTEST_F(TabsTestNg, CustomAnimationTest001, TestSize.Level1)
692 {
693 TabsModelNG model = CreateTabs(BarPosition::START, 1);
694 model.SetIsCustomAnimation(true);
__anon130c75710702(int32_t from, int32_t to) 695 model.SetOnCustomAnimation([](int32_t from, int32_t to) -> TabContentAnimatedTransition {
696 TabContentAnimatedTransition transitionInfo;
697 transitionInfo.transition = [](const RefPtr<TabContentTransitionProxy>& proxy) {};
698 return transitionInfo;
699 });
700 CreateTabContentsWithBuilder(TABCONTENT_NUMBER);
701 CreateTabsDone(model);
702
703 tabBarLayoutProperty_->UpdateAxis(Axis::VERTICAL);
704 EXPECT_EQ(tabBarLayoutProperty_->GetAxisValue(), Axis::VERTICAL);
705 tabBarPattern_->tabBarStyle_ = TabBarStyle::SUBTABBATSTYLE;
706 tabBarPattern_->visibleItemPosition_[0] = { 0.0f, 10.0f };
707 swiperLayoutProperty_->UpdateIndex(1);
708 GestureEvent info;
709 Offset offset(1, 1);
710 info.SetLocalLocation(offset);
711 tabBarLayoutProperty_->UpdateAxis(Axis::HORIZONTAL);
712 tabBarPattern_->HandleClick(info.GetSourceDevice(), 0);
713 EXPECT_TRUE(swiperPattern_->IsDisableSwipe());
714 EXPECT_TRUE(swiperPattern_->customAnimationToIndex_.has_value());
715
716 swiperPattern_->OnCustomAnimationFinish(1, 0, false);
717 EXPECT_FALSE(swiperPattern_->customAnimationToIndex_.has_value());
718
719 swiperPattern_->SwipeTo(1);
720 EXPECT_TRUE(swiperPattern_->customAnimationToIndex_.has_value());
721 }
722
723 /**
724 * @tc.name: CustomAnimationTest002
725 * @tc.desc: test custom animation set undefined
726 * @tc.type: FUNC
727 */
728 HWTEST_F(TabsTestNg, CustomAnimationTest002, TestSize.Level1)
729 {
730 TabsModelNG model = CreateTabs();
731 model.SetIsCustomAnimation(false);
732 CreateTabContents(TABCONTENT_NUMBER);
733 CreateTabsDone(model);
734 EXPECT_FALSE(swiperPattern_->IsDisableSwipe());
735 }
736
737 /**
738 * @tc.name: DragSwiper001
739 * @tc.desc: Could drag swiper, change tabBar index
740 * @tc.type: FUNC
741 */
742 HWTEST_F(TabsTestNg, DragSwiper001, TestSize.Level1)
743 {
744 MockAnimationManager::Enable(true);
745 MockAnimationManager::GetInstance().SetTicks(1);
746 TabsModelNG model = CreateTabs();
747 CreateTabContents(TABCONTENT_NUMBER);
748 CreateTabsDone(model);
749 EXPECT_TRUE(swiperPattern_->panEvent_);
750
751 GestureEvent info = CreateDragInfo(true);
752 swiperPattern_->HandleDragStart(info);
753 swiperPattern_->HandleDragUpdate(info);
754 FlushUITasks();
755 swiperPattern_->HandleDragEnd(info.GetMainVelocity());
756 FlushUITasks();
757 MockAnimationManager::GetInstance().Tick();
758 FlushUITasks();
759 EXPECT_TRUE(CurrentIndex(1));
760 MockAnimationManager::Enable(false);
761 }
762
763 /**
764 * @tc.name: DragSwiper002
765 * @tc.desc: Set BOTTOMTABBATSTYLE, Test drag swiper, would change tabBar index
766 * @tc.type: FUNC
767 */
768 HWTEST_F(TabsTestNg, DragSwiper002, TestSize.Level1)
769 {
770 MockAnimationManager::Enable(true);
771 MockAnimationManager::GetInstance().SetTicks(1);
772 TabsModelNG model = CreateTabs();
773 // set BOTTOMTABBATSTYLE
774 CreateTabContentTabBarStyle(TabBarStyle::BOTTOMTABBATSTYLE);
775 CreateTabContentTabBarStyle(TabBarStyle::BOTTOMTABBATSTYLE);
776 CreateTabsDone(model);
777
778 GestureEvent info = CreateDragInfo(true);
779 swiperPattern_->HandleDragStart(info);
780 swiperPattern_->HandleDragUpdate(info);
781 FlushUITasks();
782 swiperPattern_->HandleDragEnd(info.GetMainVelocity());
783 FlushUITasks();
784 MockAnimationManager::GetInstance().Tick();
785 FlushUITasks();
786 EXPECT_TRUE(CurrentIndex(1));
787 MockAnimationManager::Enable(false);
788 }
789
790 /**
791 * @tc.name: DragSwiper003
792 * @tc.desc: SetScrollable to false, could not drag to change page
793 * @tc.type: FUNC
794 */
795 HWTEST_F(TabsTestNg, DragSwiper003, TestSize.Level1)
796 {
797 TabsModelNG model = CreateTabs();
798 // SetScrollable to false, could not drag to change page
799 model.SetScrollable(false);
800 CreateTabContents(TABCONTENT_NUMBER);
801 CreateTabsDone(model);
802 EXPECT_FALSE(swiperPattern_->panEvent_);
803 }
804 } // namespace OHOS::Ace::NG
805