• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "gtest/gtest.h"
16 #include "ui_driver.h"
17 #include "ui_model.h"
18 
19 using namespace OHOS::uitest;
20 using namespace std;
21 
22 static constexpr auto ATTR_TEXT = "text";
23 // record the triggered touch events.
24 static vector<TouchEvent> touch_event_records;
25 
26 class MockController : public UiController {
27 public:
MockController()28     explicit MockController() : UiController("mock_controller") {}
29 
30     ~MockController() = default;
31 
SetDomFrame(string_view domFrame)32     void SetDomFrame(string_view domFrame)
33     {
34         mockDomFrame_ = domFrame;
35     }
36 
GetUiHierarchy(vector<pair<Window,nlohmann::json>> & out)37     void GetUiHierarchy(vector<pair<Window, nlohmann::json>>& out) override
38     {
39         auto winInfo = Window(0);
40         auto  dom = nlohmann::json::parse(mockDomFrame_);
41         out.push_back(make_pair(move(winInfo), move(dom)));
42     }
43 
IsWorkable() const44     bool IsWorkable() const override
45     {
46         return true;
47     }
48 
49 private:
50     string mockDomFrame_;
51 };
52 
53 // test fixture
54 class UiDriverTest : public testing::Test {
55 protected:
SetUp()56     void SetUp() override
57     {
58         touch_event_records.clear();
59         auto mockController = make_unique<MockController>();
60         controller_ = mockController.get();
61         UiController::RegisterController(move(mockController), Priority::MEDIUM);
62         driver_ = make_unique<UiDriver>();
63     }
64 
TearDown()65     void TearDown() override
66     {
67         controller_ = nullptr;
68         UiController::RemoveAllControllers();
69     }
70 
71     MockController *controller_ = nullptr;
72     unique_ptr<UiDriver> driver_ = nullptr;
73     UiOpArgs opt_;
74 
75     ~UiDriverTest() override = default;
76 };
77 
TEST_F(UiDriverTest,internalError)78 TEST_F(UiDriverTest, internalError)
79 {
80     // give no UiController, should cause internal error
81     UiController::RemoveAllControllers();
82     auto error = ApiCallErr(NO_ERROR);
83     auto key = Back();
84     driver_->TriggerKey(key, opt_, error);
85     ASSERT_EQ(ERR_INTERNAL, error.code_);
86 }
87 
TEST_F(UiDriverTest,normalInteraction)88 TEST_F(UiDriverTest, normalInteraction)
89 {
90     constexpr auto mockDom0 = R"({
91 "attributes": {
92 "index": "0",
93 "resource-id": "id1",
94 "bounds": "[0,0][100,100]",
95 "text": ""
96 },
97 "children": [
98 {
99 "attributes": {
100 "index": "0",
101 "resource-id": "id4",
102 "bounds": "[0,0][50,50]",
103 "text": "USB",
104 "type": "Text"
105 },
106 "children": []
107 }
108 ]
109 }
110 )";
111     controller_->SetDomFrame(mockDom0);
112 
113     auto error = ApiCallErr(NO_ERROR);
114     auto selector = WidgetSelector();
115     auto matcher = WidgetAttrMatcher(ATTR_TEXT, "USB", EQ);
116     selector.AddMatcher(matcher);
117     vector<unique_ptr<Widget>> widgets;
118     driver_->FindWidgets(selector, widgets, error);
119 
120     ASSERT_EQ(1, widgets.size());
121     ASSERT_EQ("NONE", widgets.at(0)->GetHostTreeId()); // should return dettached widget
122     // perform interactions
123     auto key = Back();
124     driver_->TriggerKey(key, opt_, error);
125     ASSERT_EQ(NO_ERROR, error.code_);
126 }
127 
TEST_F(UiDriverTest,retrieveWidgetFailure)128 TEST_F(UiDriverTest, retrieveWidgetFailure)
129 {
130     constexpr auto mockDom0 = R"({
131 "attributes": {
132 "text": "",
133 "bounds": "[0,0][100,100]"
134 },
135 "children": [
136 {
137 "attributes": {
138 "text": "USB",
139 "bounds": "[0,0][50,50]"
140 },
141 "children": []
142 }
143 ]
144 }
145 )";
146     constexpr auto mockDom1 = R"({
147 "attributes": {
148 "text": "",
149 "bounds": "[0,0][100,100]"
150 },
151 "children": [
152 {
153 "attributes": {
154 "text": "WYZ",
155 "bounds": "[0,0][50,50]"
156 },
157 "children": []
158 }
159 ]
160 }
161 )";
162     controller_->SetDomFrame(mockDom0);
163 
164     auto error = ApiCallErr(NO_ERROR);
165     auto selector = WidgetSelector();
166     auto matcher = WidgetAttrMatcher(ATTR_TEXT, "USB", EQ);
167     selector.AddMatcher(matcher);
168     vector<unique_ptr<Widget>> widgets;
169     driver_->FindWidgets(selector, widgets, error);
170 
171     ASSERT_EQ(1, widgets.size());
172 
173     // mock another dom on which the target widget is missing, and perform click
174     controller_->SetDomFrame(mockDom1);
175     error = ApiCallErr(NO_ERROR);
176     driver_->RetrieveWidget(*widgets.at(0), error, true);
177 
178     // retrieve widget failed should be marked as exception
179     ASSERT_EQ(ERR_COMPONENT_LOST, error.code_);
180     ASSERT_TRUE(error.message_.find(selector.Describe()) != string::npos)
181                                 << "Error message should contains the widget selection description";
182 }
183 
TEST_F(UiDriverTest,retrieveWidget)184 TEST_F(UiDriverTest, retrieveWidget)
185 {
186     constexpr auto mockDom0 = R"({
187 "attributes": {"bounds": "[0,0][100,100]", "text": ""},
188 "children": [
189 {
190 "attributes": {
191 "bounds": "[0,0][50,50]",
192 "hashcode": "12345",
193 "text": "USB","type": "Text"},
194 "children": []}]})";
195     controller_->SetDomFrame(mockDom0);
196 
197     auto error = ApiCallErr(NO_ERROR);
198     auto selector = WidgetSelector();
199     auto matcher = WidgetAttrMatcher(ATTR_NAMES[UiAttr::HASHCODE], "12345", EQ);
200     selector.AddMatcher(matcher);
201     vector<unique_ptr<Widget>> widgets;
202     driver_->FindWidgets(selector, widgets, error);
203     ASSERT_EQ(1, widgets.size());
204     ASSERT_EQ("USB", widgets.at(0)->GetAttr(ATTR_TEXT, ""));
205 
206     // mock new UI
207     constexpr auto mockDom1 = R"({
208 "attributes": {"bounds": "[0,0][100,100]", "text": ""},
209 "children": [
210 {
211 "attributes": {
212 "bounds": "[0,0][50,50]",
213 "hashcode": "12345",
214 "text": "WYZ","type": "Text"},
215 "children": []}]})";
216     controller_->SetDomFrame(mockDom1);
217     // we should be able to refresh WidgetImage on the new UI
218     auto snapshot = driver_->RetrieveWidget(*widgets.at(0), error);
219     ASSERT_EQ(NO_ERROR, error.code_);
220     ASSERT_NE(nullptr, snapshot);
221     ASSERT_EQ("WYZ", snapshot->GetAttr(ATTR_TEXT, "")); // attribute should be updated to new value
222     // mock new UI
223     constexpr auto mockDom2 = R"({
224 "attributes": {"bounds": "[0,0][100,100]", "text": ""},
225 "children": [
226 {
227 "attributes": {
228 "bounds": "[0,0][50,50]",
229 "hashcode": "23456",
230 "text": "ZL", "type":"Button"},
231 "children": []}]})";
232     controller_->SetDomFrame(mockDom2);
233     // we should not be able to refresh WidgetImage on the new UI since its gone (hashcode and attributes changed)
234     snapshot = driver_->RetrieveWidget(*widgets.at(0), error);
235     ASSERT_EQ(ERR_COMPONENT_LOST, error.code_);
236     ASSERT_EQ(nullptr, snapshot);
237 }