• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "frameworks/bridge/test/unittest/jsfrontend/dom_node_factory.h"
17 
18 #include <map>
19 
20 #include "gtest/gtest.h"
21 
22 #include "base/json/json_util.h"
23 #include "base/log/log.h"
24 #include "base/utils/utils.h"
25 #include "core/components/declaration/common/declaration.h"
26 #include "core/components/theme/theme_manager_impl.h"
27 #include "frameworks/bridge/common/dom/dom_document.h"
28 #include "frameworks/bridge/test/unittest/jsfrontend/dom_mock.h"
29 #include "frameworks/bridge/test/unittest/jsfrontend/dom_test_constants.h"
30 
31 namespace OHOS::Ace::Framework {
32 namespace {
33 
34 const std::map<std::string, const std::vector<std::string>&> DOMSTYLELIST = {
35     { DOM_NODE_TAG_DIV, DIV_STYLE_LIST },
36     { DOM_NODE_TAG_TEXT, TEXT_STYLE_LIST },
37     { DOM_NODE_TAG_PROGRESS, PROGRESS_STYLE_LIST },
38     { DOM_NODE_TAG_SLIDER, SLIDER_STYLE_LIST },
39     { DOM_NODE_TAG_SWIPER, SWIPER_STYLE_LIST },
40     { DOM_NODE_TAG_REFRESH, REFRESH_STYLE_LIST },
41     { DOM_NODE_TAG_IMAGE, IMAGE_STYLE_LIST },
42     { DOM_NODE_TAG_SPAN, SPAN_STYLE_LIST },
43     { DOM_NODE_TAG_VIDEO, VIDEO_STYLE_LIST },
44     { DOM_NODE_TAG_RATING, RATING_STYLE_LIST },
45     { DOM_NODE_TAG_MARQUEE, MARQUEE_STYLE_LIST },
46     { DOM_NODE_TAG_TEXTAREA, TEXTAREA_STYLE_LIST },
47     { DOM_NODE_TAG_POPUP, POPUP_STYLE_LIST },
48     { DOM_NODE_TAG_LIST, LIST_STYLE_LIST },
49     { DOM_NODE_TAG_INPUT, INPUT_STYLE_LIST },
50     { DOM_NODE_TAG_LABEL, TEXT_STYLE_LIST },
51     { DOM_NODE_TAG_DIVIDER, DIVIDER_STYLE_LIST },
52     { DOM_NODE_TAG_SWITCH, SWITCH_STYLE_LIST },
53     { DOM_NODE_TAG_BUTTON, BUTTON_STYLE_LIST },
54     { DOM_NODE_TAG_SEARCH, SEARCH_STYLE_LIST },
55 };
56 
57 const std::map<std::string, std::vector<std::string>> DOMATTRLIST = {
58     { DOM_NODE_TAG_PROGRESS, PROGRESS_ATTR_LIST },
59     { DOM_NODE_TAG_SLIDER, SLIDER_ATTR_LIST },
60     { DOM_NODE_TAG_SWIPER, SWIPER_ATTR_LIST },
61     { DOM_NODE_TAG_SWITCH, SWITCH_ATTR_LIST },
62     { DOM_NODE_TAG_TEXT, TEXT_ATTR_LIST },
63     { DOM_NODE_TAG_SVG_TEXT, SVG_TEXT_ATTR_LIST },
64     { DOM_NODE_TAG_TEXT_PATH, SVG_TEXT_PATH_ATTR_LIST },
65     { DOM_NODE_TAG_TSPAN, SVG_TSPAN_ATTR_LIST },
66     { DOM_NODE_TAG_IMAGE, IMAGE_ATTR_LIST },
67     { DOM_NODE_TAG_SPAN, SPAN_ATTR_LIST },
68     { DOM_NODE_TAG_TABS, TABS_ATTR_LIST },
69     { DOM_NODE_TAG_TAB_BAR, TABBAR_ATTR_LIST },
70     { DOM_NODE_TAG_TAB_CONTENT, TABCONTENT_ATTR_LIST },
71     { DOM_NODE_TAG_REFRESH, REFRESH_ATTR_LIST },
72     { DOM_NODE_TAG_VIDEO, VIDEO_ATTR_LIST },
73     { DOM_NODE_TAG_RATING, RATING_ATTR_LIST },
74     { DOM_NODE_TAG_MARQUEE, MARQUEE_ATTR_LIST },
75     { DOM_NODE_TAG_TEXTAREA, TEXTAREA_ATTR_LIST },
76     { DOM_NODE_TAG_POPUP, POPUP_ATTR_LIST },
77     { DOM_NODE_TAG_LIST, LIST_ATTR_LIST },
78     { DOM_NODE_TAG_INPUT, INPUT_ATTR_LIST },
79     { DOM_NODE_TAG_LABEL, LABEL_ATTR_LIST },
80     { DOM_NODE_TAG_BUTTON, BUTTON_ATTR_LIST },
81     { DOM_NODE_TAG_DIVIDER, DIVIDER_ATTR_LIST },
82     { DOM_NODE_TAG_SEARCH, SEARCH_ATTR_LIST },
83     { DOM_NODE_TAG_IMAGE_ANIMATOR, IMAGE_ANIMATOR_ATTR_LIST },
84     { DOM_NODE_TAG_PIECE, PIECE_ATTR_LIST },
85     { DOM_NODE_TAG_DIV, DIV_ATTR_LIST },
86     { DOM_NODE_TAG_SVG, SVG_ATTR_LIST },
87     { DOM_NODE_TAG_RECT, SVG_RECT_ATTR_LIST },
88     { DOM_NODE_TAG_CIRCLE, SVG_CIRCLE_ATTR_LIST },
89     { DOM_NODE_TAG_ELLIPSE, SVG_ELLIPSE_ATTR_LIST },
90     { DOM_NODE_TAG_PATH, SVG_PATH_ATTR_LIST },
91     { DOM_NODE_TAG_LINE, SVG_LINE_ATTR_LIST },
92     { DOM_NODE_TAG_POLYLINE, SVG_POLYLINE_ATTR_LIST },
93     { DOM_NODE_TAG_POLYGON, SVG_POLYGON_ATTR_LIST },
94     { DOM_NODE_TAG_ANIMATE, SVG_ANIMATE_ATTR_LIST },
95     { DOM_NODE_TAG_ANIMATE_MOTION, SVG_ANIMATE_MOTION_ATTR_LIST },
96 };
97 const std::map<std::string, std::vector<std::string>> DOMEVENTLIST = {
98     { DOM_NODE_TAG_SWIPER, SWIPER_EVENT_LIST },
99     { DOM_NODE_TAG_SLIDER, SLIDER_EVENT_LIST },
100     { DOM_NODE_TAG_SWITCH, SWITCH_EVENT_LIST },
101     { DOM_NODE_TAG_IMAGE, IMAGE_EVENT_LIST },
102     { DOM_NODE_TAG_VIDEO, VIDEO_EVENT_LIST },
103     { DOM_NODE_TAG_REFRESH, REFRESH_EVENT_LIST },
104     { DOM_NODE_TAG_RATING, RATING_EVENT_LIST },
105     { DOM_NODE_TAG_MARQUEE, MARQUEE_EVENT_LIST },
106     { DOM_NODE_TAG_TEXTAREA, TEXTAREA_EVENT_LIST },
107     { DOM_NODE_TAG_POPUP, POPUP_EVENT_LIST },
108     { DOM_NODE_TAG_INPUT, INPUT_EVENT_LIST },
109     { DOM_NODE_TAG_SEARCH, SEARCH_EVENT_LIST },
110     { DOM_NODE_TAG_PIECE, PIECE_EVENT_LIST },
111 };
112 
ParseJsonString(const std::string & jsonValue)113 std::unique_ptr<JsonValue> ParseJsonString(const std::string& jsonValue)
114 {
115     return JsonUtil::ParseJsonString(jsonValue);
116 }
117 
CreateDomNode(const JsonValue & componentValue,int32_t nodeId)118 RefPtr<DOMNode> CreateDomNode(const JsonValue& componentValue, int32_t nodeId)
119 {
120     if (!componentValue.Contains(DOM_TAG)) {
121         LOGE("not have tag field.");
122         return nullptr;
123     }
124 
125     auto typeValue = componentValue.GetValue(DOM_TAG);
126     std::string type = typeValue->GetString();
127     return DOMNodeFactory::GetInstance().GetDocument()->CreateNodeWithId(type, nodeId);
128 }
129 
AppendChildNode(const JsonValue & jsonValue,const RefPtr<DOMNode> & parentNode)130 void AppendChildNode(const JsonValue& jsonValue, const RefPtr<DOMNode>& parentNode)
131 {
132     NodeId nodeId = parentNode->GetNodeId() + 1;
133     if (!jsonValue.IsArray()) {
134         auto child = CreateDomNode(jsonValue, nodeId);
135         parentNode->AddNode(child);
136         return;
137     }
138 
139     int32_t arraySize = jsonValue.GetArraySize();
140     for (int32_t index = 0; index < arraySize; ++index, nodeId++) {
141         auto item = jsonValue.GetArrayItem(index);
142         auto child = CreateDomNode(*item, nodeId);
143         parentNode->AddNode(child);
144         if (jsonValue.Contains(CHILD_TAG)) {
145             const auto childValue = jsonValue.GetValue(CHILD_TAG);
146             if (childValue != nullptr) {
147                 AppendChildNode(*childValue, child);
148             }
149         }
150     }
151 }
152 
SetStyleFromJson(const std::string & jsonStr,const RefPtr<DOMNode> & domNode,const RefPtr<Declaration> & declaration)153 void SetStyleFromJson(
154     const std::string& jsonStr, const RefPtr<DOMNode>& domNode, const RefPtr<Declaration>& declaration)
155 {
156     if (!declaration || !domNode) {
157         return;
158     }
159     auto domJson = ParseJsonString(jsonStr);
160     std::vector<std::pair<std::string, std::string>> styles;
161     if (domJson->Contains(COMMON_STYLE)) {
162         const auto commonStyleValue = domJson->GetValue(COMMON_STYLE);
163         int32_t size = commonStyleValue->GetArraySize();
164         for (int32_t index = 0; index < size; index++) {
165             auto item = commonStyleValue->GetArrayItem(index);
166             for (const auto& commonStyle : COMMON_STYLE_LIST) {
167                 if (item->Contains(commonStyle)) {
168                     styles.emplace_back(commonStyle, item->GetValue(commonStyle)->GetString());
169                     break;
170                 }
171             }
172         }
173     }
174     std::string type = domJson->GetValue(DOM_TAG)->GetString();
175     if (DOMSTYLELIST.find(type) == DOMSTYLELIST.end()) {
176         LOGD("json file not define style for %s", type.c_str());
177     } else {
178         const std::vector<std::string> styleList = DOMSTYLELIST.find(type)->second;
179         if (domJson->Contains(DOM_STYLE)) {
180             const auto styleValue = domJson->GetValue(DOM_STYLE);
181             int32_t size = styleValue->GetArraySize();
182             for (int32_t index = 0; index < size; index++) {
183                 auto item = styleValue->GetArrayItem(index);
184                 for (const auto& style : styleList) {
185                     if (item->Contains(style)) {
186                         styles.emplace_back(style, item->GetValue(style)->GetString());
187                         break;
188                     }
189                 }
190             }
191         }
192     }
193     declaration->SetStyle(styles);
194     domNode->SetStyle(styles);
195 }
196 
SetAttrFromJson(const std::string & jsonStr,const RefPtr<DOMNode> & domNode,const RefPtr<Declaration> & declaration)197 void SetAttrFromJson(const std::string& jsonStr, const RefPtr<DOMNode>& domNode, const RefPtr<Declaration>& declaration)
198 {
199     if (!declaration || !domNode) {
200         return;
201     }
202     auto domJson = ParseJsonString(jsonStr);
203     std::string type = domJson->GetValue(DOM_TAG)->GetString();
204     if (DOMATTRLIST.find(type) == DOMATTRLIST.end()) {
205         LOGD("json file not define attribute for %s", type.c_str());
206         return;
207     }
208     const std::vector<std::string> attrList = DOMATTRLIST.find(type)->second;
209     std::vector<std::pair<std::string, std::string>> attrs;
210     if (domJson->Contains(DOM_ATTR)) {
211         const auto attrValue = domJson->GetValue(DOM_ATTR);
212         int32_t size = attrValue->GetArraySize();
213         for (int32_t index = 0; index < size; index++) {
214             auto item = attrValue->GetArrayItem(index);
215             for (const auto& attr : attrList) {
216                 if (item->Contains(attr)) {
217                     attrs.emplace_back(attr, item->GetValue(attr)->GetString());
218                     break;
219                 }
220             }
221         }
222     }
223     declaration->SetAttr(attrs);
224     domNode->SetAttr(attrs);
225 }
226 
SetEventFromJson(const std::string & jsonStr,const RefPtr<DOMNode> & domNode,const RefPtr<Declaration> & declaration)227 void SetEventFromJson(
228     const std::string& jsonStr, const RefPtr<DOMNode>& domNode, const RefPtr<Declaration>& declaration)
229 {
230     if (!declaration || !domNode) {
231         return;
232     }
233     auto domJson = ParseJsonString(jsonStr);
234     std::vector<std::string> events;
235     if (domJson->Contains(COMMON_EVENT)) {
236         const auto commonEventValue = domJson->GetValue(COMMON_EVENT);
237         int32_t size = commonEventValue->GetArraySize();
238         for (int32_t index = 0; index < size; index++) {
239             auto itemStr = commonEventValue->GetArrayItem(index)->GetString();
240             auto eventIter = std::find_if(std::begin(COMMON_EVENT_LIST), std::end(COMMON_EVENT_LIST),
241                 [itemStr](const std::string& commonEvent) { return itemStr == commonEvent; });
242             if (eventIter != std::end(COMMON_EVENT_LIST)) {
243                 events.emplace_back(*eventIter);
244             }
245         }
246     }
247     std::string type = domJson->GetValue(DOM_TAG)->GetString();
248     if (DOMEVENTLIST.find(type) == DOMEVENTLIST.end()) {
249         LOGD("json file not define event for %s", type.c_str());
250     } else {
251         const std::vector<std::string> eventList = DOMEVENTLIST.find(type)->second;
252         if (domJson->Contains(DOM_EVENT)) {
253             const auto eventValue = domJson->GetValue(DOM_EVENT);
254             int32_t size = eventValue->GetArraySize();
255             for (int32_t index = 0; index < size; index++) {
256                 auto item = eventValue->GetArrayItem(index);
257                 if (!item->IsString()) {
258                     continue;
259                 }
260 
261                 auto itemStr = item->GetString();
262                 auto eventIter = std::find_if(std::begin(eventList), std::end(eventList),
263                     [itemStr](const std::string& event) { return itemStr == event; });
264                 if (eventIter != std::end(COMMON_EVENT_LIST)) {
265                     events.emplace_back(*eventIter);
266                 }
267             }
268         }
269     }
270     declaration->AddEvent(PAGE_ID, domNode->GetNodeIdForEvent(), events);
271     domNode->AddEvent(PAGE_ID, events);
272 }
273 
274 } // namespace
275 
276 DOMNodeFactory::DOMNodeFactory() = default;
277 DOMNodeFactory::~DOMNodeFactory() = default;
278 
CreateDOMNodeFromDsl(const std::string & jsonStr)279 RefPtr<DOMNode> DOMNodeFactory::CreateDOMNodeFromDsl(const std::string& jsonStr)
280 {
281     auto domJson = ParseJsonString(jsonStr);
282     auto typeValue = domJson->GetValue(DOM_TAG);
283     std::string type = typeValue->GetString();
284     document_ = AceType::MakeRefPtr<DOMDocument>(DOM_ROOT_NODE_ID_BASE);
285     RefPtr<DOMNode> domNodeRoot = document_->CreateNodeWithId(type, DOM_ROOT_NODE_ID_BASE);
286 
287     if (!context_) {
288         auto frontend = AceType::MakeRefPtr<MockFrontend>();
289         auto platformWindow = std::make_unique<MockPlatformWindow>();
290         auto window = std::make_unique<Window>(std::move(platformWindow));
291         context_ = AceType::MakeRefPtr<PipelineContext>(std::move(window), nullptr, nullptr, nullptr, frontend, 0);
292         context_->SetThemeManager(AceType::MakeRefPtr<ThemeManagerImpl>());
293     }
294 
295     domNodeRoot->SetPipelineContext(context_);
296     domNodeRoot->InitializeStyle();
297     auto declaration = domNodeRoot->GetDeclaration();
298     if (declaration) {
299         declaration->BindPipelineContext(context_);
300         declaration->InitializeStyle();
301     }
302     SetAttrFromJson(jsonStr, domNodeRoot, declaration);
303     SetStyleFromJson(jsonStr, domNodeRoot, declaration);
304     SetEventFromJson(jsonStr, domNodeRoot, declaration);
305     domNodeRoot->GenerateComponentNode();
306 
307     if (domJson->Contains(CHILD_TAG)) {
308         const auto childValue = domJson->GetValue(CHILD_TAG);
309         if (childValue != nullptr) {
310             AppendChildNode(*childValue, domNodeRoot);
311         }
312     }
313     return domNodeRoot;
314 }
315 
GetBoxChildComponent(const RefPtr<DOMNode> & domNode)316 RefPtr<BoxComponent> DOMNodeFactory::GetBoxChildComponent(const RefPtr<DOMNode>& domNode)
317 {
318     RefPtr<BoxComponent> boxComponent = domNode->GetBoxComponent();
319     return boxComponent;
320 }
321 
322 } // namespace OHOS::Ace::Framework
323