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 16 #include "widget_matcher.h" 17 18 namespace OHOS::uitest { 19 using namespace std; 20 using namespace nlohmann; 21 GetRuleName(ValueMatchRule rule)22 string GetRuleName(ValueMatchRule rule) 23 { 24 switch (rule) { 25 case EQ: 26 return "="; 27 case CONTAINS: 28 return "contains"; 29 case STARTS_WITH: 30 return "startsWith"; 31 case ENDS_WITH: 32 return "endsWith"; 33 } 34 } 35 Matches(string_view testedValue) const36 bool ValueMatcher::Matches(string_view testedValue) const 37 { 38 switch (rule_) { 39 case EQ: 40 return testedValue == testValue_; 41 case CONTAINS: 42 return testedValue.find(testValue_) != string::npos; 43 case STARTS_WITH: 44 return testedValue.find(testValue_) == 0; 45 case ENDS_WITH: 46 return (testedValue.find(testValue_) == (testedValue.length() - testValue_.length())); 47 } 48 } 49 Describe() const50 string ValueMatcher::Describe() const 51 { 52 stringstream ss; 53 ss << GetRuleName(rule_); 54 ss << " '" << testValue_ << "'"; 55 return ss.str(); 56 } 57 WidgetAttrMatcher(string_view attr,string_view testValue,ValueMatchRule rule)58 WidgetAttrMatcher::WidgetAttrMatcher(string_view attr, string_view testValue, ValueMatchRule rule) 59 : attrName_(attr), testVal_(testValue), matchRule_(rule) {} 60 Matches(const Widget & widget) const61 bool WidgetAttrMatcher::Matches(const Widget &widget) const 62 { 63 if (!widget.HasAttr(attrName_)) { 64 return false; 65 } 66 auto attrValue = widget.GetAttr(attrName_, ""); 67 auto valueMatcher = ValueMatcher(testVal_, matchRule_); 68 return valueMatcher.Matches(attrValue); 69 }; 70 Describe() const71 string WidgetAttrMatcher::Describe() const 72 { 73 auto valueMatcher = ValueMatcher(testVal_, matchRule_); 74 return "$" + string(attrName_) + " " + valueMatcher.Describe(); 75 } 76 WriteIntoParcel(json & data) const77 void WidgetAttrMatcher::WriteIntoParcel(json &data) const 78 { 79 data["attr_name"] = attrName_; 80 data["test_value"] = testVal_; 81 data["match_rule"] = matchRule_; 82 } 83 ReadFromParcel(const json & data)84 void WidgetAttrMatcher::ReadFromParcel(const json &data) 85 { 86 attrName_ = data["attr_name"]; 87 testVal_ = data["test_value"]; 88 uint8_t intVal = data["match_rule"]; 89 matchRule_ = static_cast<ValueMatchRule>(intVal); 90 } 91 All(const WidgetAttrMatcher & ma,const WidgetAttrMatcher & mb)92 All::All(const WidgetAttrMatcher &ma, const WidgetAttrMatcher &mb) 93 { 94 matchers_.emplace_back(ma); 95 matchers_.emplace_back(mb); 96 } 97 All(const vector<WidgetAttrMatcher> & matchers)98 All::All(const vector<WidgetAttrMatcher> &matchers) 99 { 100 for (auto &ref:matchers) { 101 this->matchers_.emplace_back(ref); 102 } 103 } 104 Matches(const Widget & testedValue) const105 bool All::Matches(const Widget &testedValue) const 106 { 107 bool match = true; 108 for (auto &matcher:matchers_) { 109 match = match && matcher.Matches(testedValue); 110 if (!match) { 111 break; 112 } 113 } 114 return match; 115 } 116 Describe() const117 string All::Describe() const 118 { 119 stringstream desc; 120 uint32_t index = 0; 121 for (auto &matcher:matchers_) { 122 if (index > 0) { 123 desc << " AND "; 124 } 125 desc << "(" << matcher.Describe() << ")"; 126 index++; 127 } 128 return desc.str(); 129 } 130 Matches(const Widget & widget) const131 bool RootMatcher::Matches(const Widget &widget) const 132 { 133 return WidgetTree::IsRootWidgetHierarchy(widget.GetHierarchy()); 134 } 135 Describe() const136 string RootMatcher::Describe() const 137 { 138 return "the root widget on the tree"; 139 } 140 Visit(const Widget & widget)141 void MatchedWidgetCollector::Visit(const Widget &widget) 142 { 143 if (matcher_.Matches(widget)) { 144 receiver_.emplace_back(widget); 145 } 146 } 147 Any(const WidgetAttrMatcher & ma,const WidgetAttrMatcher & mb)148 Any::Any(const WidgetAttrMatcher &ma, const WidgetAttrMatcher &mb) 149 { 150 matchers_.emplace_back(ma); 151 matchers_.emplace_back(mb); 152 } 153 Any(const vector<WidgetAttrMatcher> & matchers)154 Any::Any(const vector<WidgetAttrMatcher> &matchers) 155 { 156 for (auto &ref:matchers) { 157 this->matchers_.emplace_back(ref); 158 } 159 } 160 Matches(const Widget & testedValue) const161 bool Any::Matches(const Widget &testedValue) const 162 { 163 bool match = false; 164 for (auto &matcher:matchers_) { 165 match = match || matcher.Matches(testedValue); 166 if (match) break; 167 } 168 return match; 169 } 170 Describe() const171 string Any::Describe() const 172 { 173 stringstream desc; 174 uint32_t index = 0; 175 for (auto &matcher:matchers_) { 176 if (index > 0) { 177 desc << " OR "; 178 } 179 desc << "(" << matcher.Describe() << ")"; 180 index++; 181 } 182 return desc.str(); 183 } 184 } // namespace uitest