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 <cstddef>
17
18 #include "gtest/gtest.h"
19
20 #include "core/interfaces/native/node/node_content_modifier.h"
21 #define private public
22 #include "interfaces/native/native_node.h"
23 #include "test/mock/core/pipeline/mock_pipeline_context.h"
24
25 #include "base/memory/ace_type.h"
26 #include "core/components_ng/base/ui_node.h"
27 #include "core/components_ng/base/view_stack_processor.h"
28 #include "core/components_ng/syntax/content_slot_model_ng.h"
29 #include "core/components_ng/syntax/content_slot_node.h"
30 #include "core/components_ng/syntax/node_content.h"
31
32 using namespace testing;
33 using namespace testing::ext;
34
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr int32_t NODE_CONTENT_INIT_STATUS = 1000;
38 constexpr int32_t NODE_CONTENT_ATTACH_TO_TREE = 1001;
39 constexpr int32_t NODE_CONTENT_DETACH_FROM_TREE = 1002;
40 constexpr uint32_t NUM_1 = 1;
41 constexpr uint32_t NUM_2 = 2;
42 const std::string NODE_TAG = "node";
43 } // namespace
44
45 class ContentSlotSyntaxTestNg : public testing::Test {
46 public:
47 static void SetUpTestSuite();
48 static void TearDownTestSuite();
49 void SetUp() override;
50 void TearDown() override;
51 RefPtr<NodeContent> nodeContentPtr_ = nullptr;
52 };
53
SetUpTestSuite()54 void ContentSlotSyntaxTestNg::SetUpTestSuite()
55 {
56 GTEST_LOG_(INFO) << "ContentSlotSyntaxTestNg SetUpTestCase";
57 }
58
TearDownTestSuite()59 void ContentSlotSyntaxTestNg::TearDownTestSuite()
60 {
61 GTEST_LOG_(INFO) << "ContentSlotSyntaxTestNg TearDownTestCase";
62 }
63
SetUp()64 void ContentSlotSyntaxTestNg::SetUp()
65 {
66 nodeContentPtr_ = AceType::MakeRefPtr<NodeContent>();
67 MockPipelineContext::SetUp();
68 }
69
TearDown()70 void ContentSlotSyntaxTestNg::TearDown()
71 {
72 nodeContentPtr_ = nullptr;
73 MockPipelineContext::TearDown();
74 }
75
76 /**
77 * @tc.name: ContentSlotSyntaxTest001
78 * @tc.desc: ContentSlot For CAPI 1
79 * @tc.type: FUNC
80 */
81 HWTEST_F(ContentSlotSyntaxTestNg, ContentSlotSyntaxTest001, TestSize.Level1)
82 {
83 /**
84 * @tc.steps: step1. Create contentSlotNode
85 * @tc.expected: contentSlotNode create successfully
86 */
87 NodeContent* nodeContent = AceType::RawPtr(nodeContentPtr_);
88 ASSERT_NE(nodeContent, nullptr);
89 ContentSlotModel::Create(nodeContent);
90 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
91 EXPECT_TRUE(contentSlotNode != nullptr && contentSlotNode->GetTag() == V2::JS_NODE_SLOT_ETS_TAG);
92
93 /**
94 * @tc.steps: step2. add/insert/remove child
95 * @tc.expected: add/insert/remove child successfully
96 */
97 const auto* contentModifier = NodeModifier::GetNodeContentModifier();
98 auto childFrameNode1 = FrameNode::CreateFrameNode("frameNode1", -1, AceType::MakeRefPtr<Pattern>());
99 contentModifier->addChild(reinterpret_cast<ArkUINodeContentHandle>(nodeContent),
100 reinterpret_cast<ArkUINodeHandle>(Referenced::RawPtr(childFrameNode1)));
101 auto children = contentSlotNode->GetChildren();
102 EXPECT_TRUE(children.size() == NUM_1 && children.front()->GetTag() == "frameNode1");
103
104 auto childFrameNode2 = FrameNode::CreateFrameNode("frameNode2", -1, AceType::MakeRefPtr<Pattern>());
105 contentModifier->insertChild(reinterpret_cast<ArkUINodeContentHandle>(nodeContent),
106 reinterpret_cast<ArkUINodeHandle>(Referenced::RawPtr(childFrameNode2)), 0);
107 children = contentSlotNode->GetChildren();
108 EXPECT_TRUE(children.size() == NUM_2 && children.front()->GetTag() == "frameNode2");
109
110 contentModifier->removeChild(reinterpret_cast<ArkUINodeContentHandle>(nodeContent),
111 reinterpret_cast<ArkUINodeHandle>(Referenced::RawPtr(childFrameNode1)));
112 contentModifier->removeChild(reinterpret_cast<ArkUINodeContentHandle>(nodeContent),
113 reinterpret_cast<ArkUINodeHandle>(Referenced::RawPtr(childFrameNode2)));
114 children = contentSlotNode->GetChildren();
115 EXPECT_TRUE(children.size() == 0);
116 }
117
118 /**
119 * @tc.name: ContentSlotSyntaxTest002
120 * @tc.desc: ContentSlot For CAPI 2
121 * @tc.type: FUNC
122 */
123 HWTEST_F(ContentSlotSyntaxTestNg, ContentSlotSyntaxTest002, TestSize.Level1)
124 {
125 /**
126 * @tc.steps: step1. Create contentSlotNode
127 * @tc.expected: contentSlotNode create successfully
128 */
129 NodeContent* nodeContent = AceType::RawPtr(nodeContentPtr_);
130 ASSERT_NE(nodeContent, nullptr);
131 ContentSlotModel::Create(nodeContent);
132 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
133 EXPECT_TRUE(contentSlotNode != nullptr && contentSlotNode->GetTag() == V2::JS_NODE_SLOT_ETS_TAG);
134
135 /**
136 * @tc.steps: step2. releated to event
137 * @tc.expected: registerEvent, set/getUserData, getNodeContent successfully
138 */
139 const auto* contentModifier = NodeModifier::GetNodeContentModifier();
140 auto* userData = new int32_t(NODE_CONTENT_INIT_STATUS);
141 contentModifier->setUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent), userData);
__anon5b34169b0202(ArkUINodeContentEvent* event) 142 auto callback = [](ArkUINodeContentEvent* event) {
143 auto* nodeContent = event->nodeContent;
144 const auto* contentModifier = NodeModifier::GetNodeContentModifier();
145 if (event->type == 0) {
146 int32_t* userData = reinterpret_cast<int32_t*>(
147 contentModifier->getUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent)));
148 EXPECT_EQ(*userData, NODE_CONTENT_INIT_STATUS);
149 delete userData;
150 userData = new int32_t(NODE_CONTENT_ATTACH_TO_TREE);
151 contentModifier->setUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent), userData);
152 } else if (event->type == 1) {
153 int32_t* userData = reinterpret_cast<int32_t*>(
154 contentModifier->getUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent)));
155 EXPECT_EQ(*userData, NODE_CONTENT_ATTACH_TO_TREE);
156 delete userData;
157 userData = new int32_t(NODE_CONTENT_DETACH_FROM_TREE);
158 contentModifier->setUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent), userData);
159 }
160 };
161 contentModifier->registerEvent(reinterpret_cast<ArkUINodeContentHandle>(nodeContent), nullptr, std::move(callback));
162 nodeContent->OnAttachToMainTree();
163 EXPECT_TRUE(nodeContent->onMainTree_);
164 nodeContent->OnDetachFromMainTree();
165 EXPECT_FALSE(nodeContent->onMainTree_);
166 userData =
167 reinterpret_cast<int32_t*>(contentModifier->getUserData(reinterpret_cast<ArkUINodeContentHandle>(nodeContent)));
168 EXPECT_EQ(*userData, NODE_CONTENT_DETACH_FROM_TREE);
169 delete userData;
170 }
171
172 /**
173 * @tc.name: ContentSlotSyntaxTest003
174 * @tc.desc: ContentSlot For Create
175 * @tc.type: FUNC
176 */
177 HWTEST_F(ContentSlotSyntaxTestNg, ContentSlotSyntaxTest003, TestSize.Level1)
178 {
179 /**
180 * @tc.steps: step1. Create contentSlotNode
181 * @tc.expected: contentSlotNode create failed
182 */
183 NodeContent* nodeContent = nullptr;
184 ContentSlotModel::Create(nodeContent);
185
186 /**
187 * @tc.steps: step2. Create contentSlotNode
188 * @tc.expected: contentSlotNode create success
189 */
190 nodeContent = AceType::RawPtr(nodeContentPtr_);
191 ASSERT_NE(nodeContent, nullptr);
192 ContentSlotModel::Create(nodeContent);
193 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
194 ASSERT_NE(contentSlotNode, nullptr);
195 EXPECT_EQ(contentSlotNode->GetTag(), V2::JS_NODE_SLOT_ETS_TAG);
196
197 /**
198 * @tc.steps: step3. GetOrCreateContentSlot by nodeId
199 * @tc.expected: GetOrCreateContentSlot create success
200 */
201 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
202 auto node = contentSlotNode->GetOrCreateContentSlot(nodeId);
203 ASSERT_NE(contentSlotNode, nullptr);
204 EXPECT_EQ(node->GetId(), nodeId);
205
206 node = contentSlotNode->GetOrCreateContentSlot(nodeId);
207 ASSERT_NE(node, nullptr);
208 EXPECT_EQ(node->GetId(), nodeId);
209 }
210
211 /**
212 * @tc.name: AttachToNode001
213 * @tc.desc: ContentSlot for AttachToNode
214 * @tc.type: FUNC
215 */
216 HWTEST_F(ContentSlotSyntaxTestNg, AttachToNode001, TestSize.Level1)
217 {
218 /**
219 * @tc.steps: step1. Create contentSlotNode
220 * @tc.expected: contentSlotNode create success
221 */
222 auto nodeContent = AceType::RawPtr(nodeContentPtr_);
223 ASSERT_NE(nodeContent, nullptr);
224 ContentSlotModel::Create(nodeContent);
225 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
226 ASSERT_NE(contentSlotNode, nullptr);
227 EXPECT_EQ(contentSlotNode->GetTag(), V2::JS_NODE_SLOT_ETS_TAG);
228
229 /**
230 * @tc.steps: step2. Create childNode
231 * @tc.expected: childNode create success
232 */
233 auto childNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
234 ASSERT_NE(childNode, nullptr);
235 nodeContent->children_.push_back(childNode);
236 EXPECT_GT(nodeContent->children_.size(), 0);
237 auto node = AceType::MakeRefPtr<FrameNode>(NODE_TAG, -1, AceType::MakeRefPtr<Pattern>());
238 nodeContent->nodeSlot_ = childNode;
239 UINode* uiNode = Referenced::RawPtr(childNode);
240 ASSERT_NE(uiNode, nullptr);
241 uiNode->onMainTree_ = true;
242
243 /**
244 * @tc.steps: step3. AttachToNode uiNode
245 * @tc.expected: the size of children more than 0
246 */
247 nodeContent->AttachToNode(uiNode);
248 EXPECT_GT(nodeContent->children_.size(), 0);
249 nodeContent->DetachFromNode();
250 }
251
252 /**
253 * @tc.name: AttachToNode002
254 * @tc.desc: ContentSlot for AttachToNode
255 * @tc.type: FUNC
256 */
257 HWTEST_F(ContentSlotSyntaxTestNg, AttachToNode002, TestSize.Level1)
258 {
259 /**
260 * @tc.steps: step1. Create contentSlotNode
261 * @tc.expected: contentSlotNode create success
262 */
263 auto nodeContent = AceType::RawPtr(nodeContentPtr_);
264 ASSERT_NE(nodeContent, nullptr);
265 ContentSlotModel::Create(nodeContent);
266 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
267 ASSERT_NE(contentSlotNode, nullptr);
268 EXPECT_EQ(contentSlotNode->GetTag(), V2::JS_NODE_SLOT_ETS_TAG);
269
270 /**
271 * @tc.steps: step3. AttachToNode uiNode
272 * @tc.expected: the size of children is 0
273 */
274 auto node = AceType::MakeRefPtr<FrameNode>(NODE_TAG, -1, AceType::MakeRefPtr<Pattern>());
275 nodeContent->nodeSlot_ = node;
276 auto uiNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
277 ASSERT_NE(uiNode, nullptr);
278 nodeContent->AttachToNode(AceType::RawPtr(uiNode));
279 EXPECT_EQ(nodeContent->children_.size(), 0);
280 nodeContent->DetachFromNode();
281 }
282
283 /**
284 * @tc.name: AddNode001
285 * @tc.desc: Test for AddNode
286 * @tc.type: FUNC
287 */
288 HWTEST_F(ContentSlotSyntaxTestNg, AddNode001, TestSize.Level1)
289 {
290 /**
291 * @tc.steps: step1. Create contentSlotNode
292 * @tc.expected: contentSlotNode create success
293 */
294 auto nodeContent = AceType::RawPtr(nodeContentPtr_);
295 ASSERT_NE(nodeContent, nullptr);
296 ContentSlotModel::Create(nodeContent);
297 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
298 ASSERT_NE(contentSlotNode, nullptr);
299 EXPECT_EQ(contentSlotNode->GetTag(), V2::JS_NODE_SLOT_ETS_TAG);
300
301 /**
302 * @tc.steps: step2. Create childNode
303 * @tc.expected: childNode create success
304 */
305 auto childNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
306 ASSERT_NE(childNode, nullptr);
307 nodeContent->nodeSlot_ = childNode;
308 UINode* uiNode = Referenced::RawPtr(childNode);
309 ASSERT_NE(uiNode, nullptr);
310
311 /**
312 * @tc.steps: step3. AddNode uiNode
313 * @tc.expected: the size of children more than 0
314 */
315 nodeContent->AddNode(uiNode, 0);
316 auto size = nodeContent->children_.size();
317 nodeContent->AddNode(uiNode, 0);
318 EXPECT_EQ(size, nodeContent->children_.size());
319 nodeContent->RemoveNode(uiNode);
320 EXPECT_EQ(nodeContent->children_.size(), size - 1);
321 }
322
323 /**
324 * @tc.name: RemoveNode001
325 * @tc.desc: Test for RemoveNode
326 * @tc.type: FUNC
327 */
328 HWTEST_F(ContentSlotSyntaxTestNg, RemoveNode001, TestSize.Level1)
329 {
330 /**
331 * @tc.steps: step1. Create contentSlotNode
332 * @tc.expected: contentSlotNode create success
333 */
334 auto nodeContent = AceType::RawPtr(nodeContentPtr_);
335 ASSERT_NE(nodeContent, nullptr);
336 ContentSlotModel::Create(nodeContent);
337 auto contentSlotNode = AceType::DynamicCast<ContentSlotNode>(ViewStackProcessor::GetInstance()->Finish());
338 ASSERT_NE(contentSlotNode, nullptr);
339 EXPECT_EQ(contentSlotNode->GetTag(), V2::JS_NODE_SLOT_ETS_TAG);
340
341 /**
342 * @tc.steps: step2. Create childNode
343 * @tc.expected: childNode create success
344 */
345 auto childNode = ViewStackProcessor::GetInstance()->GetMainElementNode();
346 ASSERT_NE(childNode, nullptr);
347 nodeContent->nodeSlot_ = childNode;
348 UINode* uiNode = Referenced::RawPtr(childNode);
349 ASSERT_NE(uiNode, nullptr);
350
351 /**
352 * @tc.steps: step3. AddNode uiNode
353 * @tc.expected: the size of children more than 0
354 */
355 nodeContent->AddNode(uiNode, 0);
356 auto size = nodeContent->children_.size();
357 EXPECT_GT(size, 0);
358
359 /**
360 * @tc.steps: step3. remove other uiNode
361 * @tc.expected: the size of children is no change
362 */
363 auto node = AceType::MakeRefPtr<FrameNode>(NODE_TAG, -1, AceType::MakeRefPtr<Pattern>());
364 UINode* uiNodeOhter = Referenced::RawPtr(node);
365 nodeContent->RemoveNode(uiNodeOhter);
366 EXPECT_EQ(size, nodeContent->children_.size());
367 }
368
369 /**
370 * @tc.name: OnAttachToMainTree001
371 * @tc.desc: Test for RemoveNode
372 * @tc.type: FUNC
373 */
374 HWTEST_F(ContentSlotSyntaxTestNg, OnAttachToMainTree001, TestSize.Level1)
375 {
376 /**
377 * @tc.steps: step1. Call OnAttachToMainTree and SetAttachToMainTreeCallback
378 * @tc.expected: onMainTree_ is true
379 */
380 auto nodeContent = AceType::RawPtr(nodeContentPtr_);
381 ASSERT_NE(nodeContent, nullptr);
382 ContentSlotModel::Create(nodeContent);
383 bool attachcallbackRet = false;
__anon5b34169b0302() 384 std::function<void()> attachcallback = [&attachcallbackRet]() { attachcallbackRet = true; };
385 nodeContent->SetAttachToMainTreeCallback(move(attachcallback));
386 nodeContent->OnAttachToMainTree();
387 EXPECT_TRUE(attachcallbackRet);
388 EXPECT_TRUE(nodeContent->onMainTree_);
389
390 /**
391 * @tc.steps: step2. Call OnDetachFromMainTree and SetDetachFromMainTreeCallback
392 * @tc.expected: onMainTree_ is false
393 */
394 bool detachcallbackRet = false;
__anon5b34169b0402() 395 std::function<void()> detachcallback = [&detachcallbackRet]() { detachcallbackRet = true; };
396 nodeContent->SetDetachFromMainTreeCallback(move(detachcallback));
397 nodeContent->OnDetachFromMainTree();
398 EXPECT_TRUE(detachcallbackRet);
399 EXPECT_FALSE(nodeContent->onMainTree_);
400 }
401 } // namespace OHOS::Ace::NG