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 "mock_navigation_stack.h"
17
18 namespace OHOS::Ace::NG {
19
20 namespace {
CheckIndexValid(int32_t index,size_t maxSize)21 bool CheckIndexValid(int32_t index, size_t maxSize)
22 {
23 return index >= 0 && index < static_cast<int32_t>(maxSize);
24 }
25 } // namespace
26
FindInPopArray(const std::string & name)27 std::pair<int32_t, std::string> MockNavigationStack::FindInPopArray(const std::string& name)
28 {
29 for (int32_t index = int(mockPopArray_.size()) - 1; index >= 0; --index) {
30 auto info = mockPopArray_[index];
31 if (info->GetName() == name) {
32 auto ret = std::make_pair(info->index, info->GetNavDestinationId());
33 auto iter = mockPopArray_.begin();
34 std::advance(iter, index);
35 mockPopArray_.erase(iter);
36 return ret;
37 }
38 }
39 return std::make_pair(-1, UNDEFINED_ID);
40 }
41
FireNavigationInterception(bool isBefore,const RefPtr<NavDestinationContext> & from,const RefPtr<NavDestinationContext> & to,NavigationOperation operation,bool isAnimated)42 void MockNavigationStack::FireNavigationInterception(bool isBefore, const RefPtr<NavDestinationContext>& from,
43 const RefPtr<NavDestinationContext>& to, NavigationOperation operation, bool isAnimated)
44 {
45 if (isBefore) {
46 if (beforeCallback_) {
47 beforeCallback_(from, to, operation, isAnimated);
48 }
49 } else {
50 if (afterCallback_) {
51 afterCallback_(from, to, operation, isAnimated);
52 }
53 }
54 }
55
CreateNodeByIndex(int32_t index,const OHOS::Ace::WeakPtr<OHOS::Ace::NG::UINode> & customNode,OHOS::Ace::RefPtr<OHOS::Ace::NG::UINode> & node)56 bool MockNavigationStack::CreateNodeByIndex(int32_t index, const OHOS::Ace::WeakPtr<OHOS::Ace::NG::UINode>& customNode,
57 OHOS::Ace::RefPtr<OHOS::Ace::NG::UINode>& node)
58 {
59 auto* stack = ViewStackProcessor::GetInstance();
60 // navDestination node
61 int32_t nodeId = stack->ClaimNodeId();
62 auto frameNode = NavDestinationGroupNode::GetOrCreateGroupNode(
63 V2::NAVDESTINATION_VIEW_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<NavDestinationPattern>(); });
64 EXPECT_NE(frameNode, nullptr);
65 auto name = mockPathArray_[index]->GetName();
66 auto container = MockContainer::Current();
67 auto navigationRoute = container->GetNavigationRoute();
68 if (!navigationRoute) {
69 return false;
70 }
71 if (!navigationRoute->HasLoaded(name)) {
72 int32_t res = navigationRoute->LoadPage(name);
73 if (res != 0) {
74 node = frameNode;
75 return true;
76 }
77 }
78 node = frameNode;
79 auto pattern = AceType::DynamicCast<NavDestinationPattern>(frameNode->GetPattern());
80 EXPECT_NE(pattern, nullptr);
81 pattern->SetName(name);
82 auto navDestinationId = std::to_string(pattern->GetNavDestinationId());
83 mockPathArray_[index]->SetNavDestinationId(navDestinationId);
84 return true;
85 }
86
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)87 void MockNavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo)
88 {
89 MockPushPath(AceType::MakeRefPtr<MockNavPathInfo>(name));
90 }
91
Push(const std::string & name,int32_t index)92 void MockNavigationStack::Push(const std::string& name, int32_t index)
93 {
94 MockPushPath(AceType::MakeRefPtr<MockNavPathInfo>(name));
95 }
96
GetAllPathName()97 std::vector<std::string> MockNavigationStack::GetAllPathName()
98 {
99 std::vector<std::string> pathNames;
100 for (int32_t i = 0; i < static_cast<int32_t>(mockPathArray_.size()); i++) {
101 pathNames.emplace_back(mockPathArray_[i]->GetName());
102 }
103 return pathNames;
104 }
105
GetAllPathIndex()106 std::vector<int32_t> MockNavigationStack::GetAllPathIndex()
107 {
108 if (mockPathArray_.empty()) {
109 return {};
110 }
111 std::vector<int32_t> pathIndex;
112 for (int32_t i = 0; i < static_cast<int32_t>(mockPathArray_.size()); i++) {
113 pathIndex.emplace_back(i);
114 }
115 return pathIndex;
116 }
117
Clear()118 void MockNavigationStack::Clear()
119 {
120 NavigationStack::Clear();
121 mockPathArray_.clear();
122 }
123
Pop()124 void MockNavigationStack::Pop()
125 {
126 mockPopArray_.emplace_back(mockPathArray_.back());
127 auto info = mockPopArray_.back();
128 mockPathArray_.pop_back();
129 if (info->GetOnPop()) {
130 info->GetOnPop();
131 }
132 }
133
PopToIndex(int32_t index)134 void MockNavigationStack::PopToIndex(int32_t index)
135 {
136 auto iter = mockPathArray_.begin();
137 std::advance(iter, index + 1);
138 mockPathArray_.erase(iter, mockPathArray_.end());
139 }
140
InitNavPathIndex(const std::vector<std::string> & pathNames)141 void MockNavigationStack::InitNavPathIndex(const std::vector<std::string>& pathNames)
142 {
143 mockPopArray_.clear();
144 for (size_t index = 0; index < mockPathArray_.size() && index < pathNames.size(); index++) {
145 if (pathNames[index] == mockPathArray_[index]->GetName() && GetReplaceValue() != 1) {
146 mockPathArray_[index]->index = index;
147 }
148 }
149 }
150
SetDestinationIdToJsStack(int32_t index,const std::string & navDestinationId)151 void MockNavigationStack::SetDestinationIdToJsStack(int32_t index, const std::string& navDestinationId)
152 {
153 if (index < 0 || index >= static_cast<int32_t>(mockPathArray_.size())) {
154 return;
155 }
156 mockPathArray_[index]->SetNavDestinationId(navDestinationId);
157 }
158
MockPushPath(const RefPtr<MockNavPathInfo> & info,bool animated,LaunchMode launchmode)159 void MockNavigationStack::MockPushPath(const RefPtr<MockNavPathInfo>& info, bool animated, LaunchMode launchmode)
160 {
161 if (launchmode == LaunchMode::NEW_INSTANCE) {
162 info->needBuildNewInstance = true;
163 }
164 auto indexAndId = FindInPopArray(info->GetName());
165 if (indexAndId.first != -1 && indexAndId.second != UNDEFINED_ID) {
166 info->index = indexAndId.first;
167 info->SetNavDestinationId(indexAndId.second);
168 }
169 animated_ = animated;
170 mockPathArray_.push_back(info);
171 }
172
NeedBuildNewInstance(int32_t index)173 bool MockNavigationStack::NeedBuildNewInstance(int32_t index)
174 {
175 if (!CheckIndexValid(index, mockPathArray_.size())) {
176 return false;
177 }
178 return mockPathArray_[index]->needBuildNewInstance;
179 }
180
SetNeedBuildNewInstance(int32_t index,bool need)181 void MockNavigationStack::SetNeedBuildNewInstance(int32_t index, bool need)
182 {
183 if (!CheckIndexValid(index, mockPathArray_.size())) {
184 return;
185 }
186 mockPathArray_[index]->needBuildNewInstance = need;
187 }
188
SetPathArray(const std::vector<NavdestinationRecoveryInfo> & navdestinationsInfo)189 void MockNavigationStack::SetPathArray(const std::vector<NavdestinationRecoveryInfo>& navdestinationsInfo)
190 {
191 std::vector<RefPtr<MockNavPathInfo>> newPathArray;
192 for (auto recoveryInfo : navdestinationsInfo) {
193 auto navPathInfo = AceType::MakeRefPtr<MockNavPathInfo>(recoveryInfo.name);
194 navPathInfo->mode = recoveryInfo.mode;
195 navPathInfo->fromRecovery = true;
196 newPathArray.push_back(navPathInfo);
197 }
198 mockPathArray_ = newPathArray;
199 }
200
SetFromRecovery(int32_t index,bool fromRecovery)201 void MockNavigationStack::SetFromRecovery(int32_t index, bool fromRecovery)
202 {
203 if (!CheckIndexValid(index, mockPathArray_.size())) {
204 return;
205 }
206 mockPathArray_[index]->fromRecovery = fromRecovery;
207 }
208
IsFromRecovery(int32_t index)209 bool MockNavigationStack::IsFromRecovery(int32_t index)
210 {
211 if (!CheckIndexValid(index, mockPathArray_.size())) {
212 return false;
213 }
214 return mockPathArray_[index]->fromRecovery;
215 }
216
MockRemoveByNavDestinationId(const std::string & navDestinationId)217 bool MockNavigationStack::MockRemoveByNavDestinationId(const std::string& navDestinationId)
218 {
219 for (auto it = mockPathArray_.begin(); it != mockPathArray_.end(); ++ it) {
220 auto info = *it;
221 if (info->GetNavDestinationId() == navDestinationId) {
222 mockPathArray_.erase(it);
223 return true;
224 }
225 }
226 return false;
227 }
228
MockRemoveByInexes(std::vector<int32_t> indexes)229 int32_t MockNavigationStack::MockRemoveByInexes(std::vector<int32_t> indexes)
230 {
231 int32_t deleteCount = 0;
232 for (auto it = mockPathArray_.begin(); it != mockPathArray_.end();) {
233 auto info = *it;
234 if (std::find(indexes.begin(), indexes.end(), info->index) != indexes.end()) {
235 mockPathArray_.erase(it);
236 deleteCount++;
237 continue;
238 }
239 it++;
240 }
241 return deleteCount;
242 }
243
MockRemoveByName(const std::string & name)244 int32_t MockNavigationStack::MockRemoveByName(const std::string& name)
245 {
246 int32_t deleteCount = 0;
247 for (auto it = mockPathArray_.begin(); it != mockPathArray_.end();) {
248 auto info = *it;
249 if (info->GetName() == name) {
250 mockPathArray_.erase(it);
251 deleteCount++;
252 continue;
253 }
254 it++;
255 }
256 return deleteCount;
257 }
258
GetNavDestinationIdByIndex(int32_t index)259 std::string MockNavigationStack::GetNavDestinationIdByIndex(int32_t index)
260 {
261 if (!CheckIndexValid(index, mockPathArray_.size())) {
262 return "";
263 }
264 return mockPathArray_[index]->GetNavDestinationId();
265 }
266
MockPopToName(const std::string & name)267 int32_t MockNavigationStack::MockPopToName(const std::string& name)
268 {
269 int32_t candidateIndex = -1;
270 for (int32_t index = 0; index < static_cast<int32_t>(mockPathArray_.size()); ++index) {
271 if (mockPathArray_[index]->GetName() == name) {
272 candidateIndex = index;
273 break;
274 }
275 }
276 if (candidateIndex != -1) {
277 auto preStackSize = Size();
278 for (int32_t index = candidateIndex + 1; index < preStackSize; ++index) {
279 mockPathArray_.pop_back();
280 }
281 }
282 return candidateIndex;
283 }
284
MockPopToIndex(int32_t index)285 void MockNavigationStack::MockPopToIndex(int32_t index)
286 {
287 if (!CheckIndexValid(index, mockPathArray_.size())) {
288 return;
289 }
290 auto preStackSize = Size();
291 for (int32_t removeCount = index + 1; removeCount < preStackSize; ++removeCount) {
292 mockPathArray_.pop_back();
293 }
294 }
295
MockMoveToTop(const std::string & name)296 int32_t MockNavigationStack::MockMoveToTop(const std::string& name)
297 {
298 int32_t candidateIndex = -1;
299 for (int32_t index = 0; index < static_cast<int32_t>(mockPathArray_.size()); ++index) {
300 if (mockPathArray_[index]->GetName() == name) {
301 candidateIndex = index;
302 break;
303 }
304 }
305 if (candidateIndex != -1) {
306 auto movedInfo = mockPathArray_[candidateIndex];
307 auto it = mockPathArray_.begin();
308 std::advance(it, candidateIndex);
309 mockPathArray_.erase(it);
310 mockPathArray_.push_back(movedInfo);
311 }
312 return candidateIndex;
313 }
314
SetIsEntryByIndex(int32_t index,bool isEntry)315 void MockNavigationStack::SetIsEntryByIndex(int32_t index, bool isEntry)
316 {
317 mockIsEntryMap_[index] = isEntry;
318 }
319
MockGetPathStack()320 std::vector<RefPtr<MockNavPathInfo>> MockNavigationStack::MockGetPathStack()
321 {
322 std::vector<RefPtr<MockNavPathInfo>> pathArray;
323 for (int32_t index = 0; index < static_cast<int32_t>(mockPathArray_.size()); ++index) {
324 pathArray.push_back(mockPathArray_[index]);
325 }
326 return pathArray;
327 }
328
MockSetPathStack(std::vector<RefPtr<MockNavPathInfo>> & setPathArray,bool animated)329 void MockNavigationStack::MockSetPathStack(std::vector<RefPtr<MockNavPathInfo>>& setPathArray, bool animated)
330 {
331 Clear();
332 for (int32_t index = 0; index < static_cast<int32_t>(setPathArray.size()); ++index) {
333 mockPathArray_.push_back(setPathArray[index]);
334 }
335 animated_ = animated;
336 }
337
GetRecoveredDestinationMode(int32_t index)338 int32_t MockNavigationStack::GetRecoveredDestinationMode(int32_t index)
339 {
340 if (!CheckIndexValid(index, mockPathArray_.size())) {
341 return 0;
342 }
343
344 return mockPathArray_[index]->mode;
345 }
346
GetNavDestinationIdInt(int32_t index)347 uint64_t MockNavigationStack::GetNavDestinationIdInt(int32_t index)
348 {
349 if (!CheckIndexValid(index, mockPathArray_.size())) {
350 return -1;
351 }
352
353 return std::atol(mockPathArray_[index]->GetNavDestinationId().c_str());
354 }
355
GetIsForceSet(int32_t index)356 bool MockNavigationStack::GetIsForceSet(int32_t index)
357 {
358 if (!CheckIndexValid(index, mockPathArray_.size())) {
359 return false;
360 }
361
362 return mockPathArray_[index]->isForceSet;
363 }
364
ResetIsForceSetFlag(int32_t index)365 void MockNavigationStack::ResetIsForceSetFlag(int32_t index)
366 {
367 if (!CheckIndexValid(index, mockPathArray_.size())) {
368 return;
369 }
370
371 mockPathArray_[index]->isForceSet = false;
372 }
373
CheckIsReplacedDestination(int32_t index,std::string & replacedName,int32_t & replacedIndex)374 bool MockNavigationStack::CheckIsReplacedDestination(int32_t index, std::string& replacedName, int32_t& replacedIndex)
375 {
376 if (!CheckIndexValid(index, mockPathArray_.size())) {
377 return false;
378 }
379
380 return mockPathArray_[index]->isReplaced;
381 }
382
SetRecoveryFromReplaceDestination(int32_t index,bool value)383 void MockNavigationStack::SetRecoveryFromReplaceDestination(int32_t index, bool value)
384 {
385 if (!CheckIndexValid(index, mockPathArray_.size())) {
386 return;
387 }
388
389 mockPathArray_[index]->isReplaced = value;
390 }
391 } // namespace OHOS::Ace::NG