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