FBClassChainTests.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. */
  9. #import <XCTest/XCTest.h>
  10. #import "XCUIElementDouble.h"
  11. #import "FBClassChainQueryParser.h"
  12. @interface FBClassChainTests : XCTestCase
  13. @end
  14. @implementation FBClassChainTests
  15. - (void)testValidChain
  16. {
  17. NSError *error;
  18. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton" error:&error];
  19. XCTAssertNotNil(result);
  20. XCTAssertEqual(result.elements.count, 2);
  21. FBClassChainItem *firstElement = [result.elements firstObject];
  22. XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
  23. XCTAssertNil(firstElement.position);
  24. XCTAssertFalse(firstElement.isDescendant);
  25. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  26. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  27. XCTAssertNil(secondElement.position);
  28. XCTAssertFalse(secondElement.isDescendant);
  29. }
  30. - (void)testValidChainWithStar
  31. {
  32. NSError *error;
  33. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[3]/*[4]/*[5]/XCUIElementTypeAlert" error:&error];
  34. XCTAssertNotNil(result);
  35. XCTAssertEqual(result.elements.count, 5);
  36. FBClassChainItem *firstElement = [result.elements firstObject];
  37. XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
  38. XCTAssertNil(firstElement.position);
  39. XCTAssertFalse(firstElement.isDescendant);
  40. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  41. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  42. XCTAssertEqual(secondElement.position.integerValue, 3);
  43. XCTAssertFalse(secondElement.isDescendant);
  44. FBClassChainItem *thirdElement = [result.elements objectAtIndex:2];
  45. XCTAssertEqual(thirdElement.type, XCUIElementTypeAny);
  46. XCTAssertEqual(thirdElement.position.integerValue, 4);
  47. XCTAssertFalse(thirdElement.isDescendant);
  48. FBClassChainItem *fourthElement = [result.elements objectAtIndex:3];
  49. XCTAssertEqual(fourthElement.type, XCUIElementTypeAny);
  50. XCTAssertEqual(fourthElement.position.integerValue, 5);
  51. XCTAssertFalse(fourthElement.isDescendant);
  52. FBClassChainItem *fifthsElement = [result.elements objectAtIndex:4];
  53. XCTAssertEqual(fifthsElement.type, XCUIElementTypeAlert);
  54. XCTAssertNil(fifthsElement.position);
  55. XCTAssertFalse(fifthsElement.isDescendant);
  56. }
  57. - (void)testValidSingleStarChain
  58. {
  59. NSError *error;
  60. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*" error:&error];
  61. XCTAssertNotNil(result);
  62. XCTAssertEqual(result.elements.count, 1);
  63. FBClassChainItem *firstElement = [result.elements firstObject];
  64. XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
  65. XCTAssertNil(firstElement.position);
  66. XCTAssertFalse(firstElement.isDescendant);
  67. }
  68. - (void)testValidSingleStarIndirectChain
  69. {
  70. NSError *error;
  71. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/*/*/XCUIElementTypeButton" error:&error];
  72. XCTAssertNotNil(result);
  73. XCTAssertEqual(result.elements.count, 3);
  74. FBClassChainItem *firstElement = [result.elements firstObject];
  75. XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
  76. XCTAssertNil(firstElement.position);
  77. XCTAssertTrue(firstElement.isDescendant);
  78. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  79. XCTAssertEqual(secondElement.type, XCUIElementTypeAny);
  80. XCTAssertNil(secondElement.position);
  81. XCTAssertFalse(secondElement.isDescendant);
  82. FBClassChainItem *thirdElement = [result.elements objectAtIndex:2];
  83. XCTAssertEqual(thirdElement.type, XCUIElementTypeButton);
  84. XCTAssertNil(thirdElement.position);
  85. XCTAssertFalse(thirdElement.isDescendant);
  86. }
  87. - (void)testValidDoubleIndirectChainAndStar
  88. {
  89. NSError *error;
  90. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/*" error:&error];
  91. XCTAssertNotNil(result);
  92. XCTAssertEqual(result.elements.count, 2);
  93. FBClassChainItem *firstElement = [result.elements firstObject];
  94. XCTAssertEqual(firstElement.type, XCUIElementTypeButton);
  95. XCTAssertNil(firstElement.position);
  96. XCTAssertTrue(firstElement.isDescendant);
  97. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  98. XCTAssertEqual(secondElement.type, XCUIElementTypeAny);
  99. XCTAssertNil(secondElement.position);
  100. XCTAssertTrue(secondElement.isDescendant);
  101. }
  102. - (void)testValidDoubleIndirectChainAndClassName
  103. {
  104. NSError *error;
  105. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/XCUIElementTypeImage" error:&error];
  106. XCTAssertNotNil(result);
  107. XCTAssertEqual(result.elements.count, 2);
  108. FBClassChainItem *firstElement = [result.elements firstObject];
  109. XCTAssertEqual(firstElement.type, XCUIElementTypeButton);
  110. XCTAssertNil(firstElement.position);
  111. XCTAssertTrue(firstElement.isDescendant);
  112. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  113. XCTAssertEqual(secondElement.type, XCUIElementTypeImage);
  114. XCTAssertNil(secondElement.position);
  115. XCTAssertTrue(secondElement.isDescendant);
  116. }
  117. - (void)testValidChainWithNegativeIndex
  118. {
  119. NSError *error;
  120. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[-1]" error:&error];
  121. XCTAssertNotNil(result);
  122. XCTAssertEqual(result.elements.count, 2);
  123. FBClassChainItem *firstElement = [result.elements firstObject];
  124. XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
  125. XCTAssertNil(firstElement.position);
  126. XCTAssertEqual(firstElement.predicates.count, 0);
  127. XCTAssertFalse(firstElement.isDescendant);
  128. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  129. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  130. XCTAssertEqual(secondElement.position.integerValue, -1);
  131. XCTAssertEqual(secondElement.predicates.count, 0);
  132. XCTAssertFalse(secondElement.isDescendant);
  133. }
  134. - (void)testValidChainWithSinglePredicate
  135. {
  136. NSError *error;
  137. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton" error:&error];
  138. XCTAssertNotNil(result);
  139. XCTAssertEqual(result.elements.count, 2);
  140. FBClassChainItem *firstElement = [result.elements firstObject];
  141. XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
  142. XCTAssertNil(firstElement.position);
  143. XCTAssertEqual(firstElement.predicates.count, 1);
  144. XCTAssertFalse(firstElement.isDescendant);
  145. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  146. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  147. XCTAssertNil(secondElement.position);
  148. XCTAssertEqual(secondElement.predicates.count, 0);
  149. XCTAssertFalse(secondElement.isDescendant);
  150. }
  151. - (void)testValidChainWithMultiplePredicates
  152. {
  153. NSError *error;
  154. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton[`value == 'blabla'`]" error:&error];
  155. XCTAssertNotNil(result);
  156. XCTAssertEqual(result.elements.count, 2);
  157. FBClassChainItem *firstElement = [result.elements firstObject];
  158. XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
  159. XCTAssertNil(firstElement.position);
  160. XCTAssertEqual(firstElement.predicates.count, 1);
  161. XCTAssertFalse(firstElement.isDescendant);
  162. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  163. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  164. XCTAssertNil(secondElement.position);
  165. XCTAssertEqual(secondElement.predicates.count, 1);
  166. XCTAssertFalse(secondElement.isDescendant);
  167. }
  168. - (void)testValidChainWithIndirectSearchAndPredicates
  169. {
  170. NSError *error;
  171. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[`name == 'blabla'`][10]/**/XCUIElementTypeButton[`value == 'blabla'`]" error:&error];
  172. XCTAssertNotNil(result);
  173. XCTAssertEqual(result.elements.count, 2);
  174. FBClassChainItem *firstElement = [result.elements firstObject];
  175. XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
  176. XCTAssertEqual(firstElement.position.integerValue, 10);
  177. XCTAssertEqual(firstElement.predicates.count, 1);
  178. XCTAssertTrue(firstElement.isDescendant);
  179. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  180. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  181. XCTAssertNil(secondElement.position);
  182. XCTAssertEqual(secondElement.predicates.count, 1);
  183. XCTAssertTrue(secondElement.isDescendant);
  184. }
  185. - (void)testValidChainWithMultiplePredicatesAndPositions
  186. {
  187. NSError *error;
  188. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*[`name == \"к``ири````'лиця\"`][3]/XCUIElementTypeButton[`value == \"blabla\"`][-1]" error:&error];
  189. XCTAssertNotNil(result);
  190. XCTAssertEqual(result.elements.count, 2);
  191. FBClassChainItem *firstElement = [result.elements firstObject];
  192. XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
  193. XCTAssertEqual(firstElement.position.integerValue, 3);
  194. XCTAssertEqual(firstElement.predicates.count, 1);
  195. XCTAssertFalse(firstElement.isDescendant);
  196. FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
  197. XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
  198. XCTAssertEqual(secondElement.position.integerValue, -1);
  199. XCTAssertEqual(secondElement.predicates.count, 1);
  200. XCTAssertFalse(secondElement.isDescendant);
  201. }
  202. - (void)testValidChainWithDescendantPredicate
  203. {
  204. NSError *error;
  205. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`name == 'blabla'`][10]" error:&error];
  206. XCTAssertNotNil(result);
  207. XCTAssertEqual(result.elements.count, 1);
  208. FBClassChainItem *firstElement = [result.elements firstObject];
  209. XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
  210. XCTAssertEqual(firstElement.position.integerValue, 10);
  211. XCTAssertEqual(firstElement.predicates.count, 2);
  212. XCTAssertTrue(firstElement.isDescendant);
  213. }
  214. - (void)testValidChainWithMultipleDescendantPredicates
  215. {
  216. NSError *error;
  217. FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`value == 'peace'`][$value == 'yolo'$][`name == 'blabla'`][10]" error:&error];
  218. XCTAssertNotNil(result);
  219. XCTAssertEqual(result.elements.count, 1);
  220. FBClassChainItem *firstElement = [result.elements firstObject];
  221. XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
  222. XCTAssertEqual(firstElement.position.integerValue, 10);
  223. XCTAssertEqual(firstElement.predicates.count, 4);
  224. XCTAssertTrue(firstElement.isDescendant);
  225. }
  226. - (void)testInvalidChains
  227. {
  228. NSArray *invalidQueries = @[
  229. @"/XCUIElementTypeWindow"
  230. ,@"XCUIElementTypeWindow/"
  231. ,@"XCUIElementTypeWindow//*"
  232. ,@"XCUIElementTypeWindow*/*"
  233. ,@"**"
  234. ,@"***"
  235. ,@"**/*/**"
  236. ,@"/**"
  237. ,@"XCUIElementTypeWindow/**"
  238. ,@"**[1]/XCUIElementTypeWindow"
  239. ,@"**[`name == '1'`]/XCUIElementTypeWindow"
  240. ,@"XCUIElementTypeWindow[0]"
  241. ,@"XCUIElementTypeWindow[1][1]"
  242. ,@"blabla"
  243. ,@"XCUIElementTypeWindow/blabla"
  244. ,@" XCUIElementTypeWindow"
  245. ,@"XCUIElementTypeWindow[ 2 ]"
  246. ,@"XCUIElementTypeWindow[[2]"
  247. ,@"XCUIElementTypeWindow[2]]"
  248. ,@"XCUIElementType[Window[2]]"
  249. ,@"XCUIElementTypeWindow[visible = 1]"
  250. ,@"XCUIElementTypeWindow[1][`visible = 1`]"
  251. ,@"XCUIElementTypeWindow[1] [`visible = 1`]"
  252. ,@"XCUIElementTypeWindow[ `visible = 1`]"
  253. ,@"XCUIElementTypeWindow[`visible = 1][`name = \"bla\"`]"
  254. ,@"XCUIElementTypeWindow[`visible = 1]"
  255. ,@"XCUIElementTypeWindow[$visible = 1]"
  256. ,@"XCUIElementTypeWindow[``]"
  257. ,@"XCUIElementTypeWindow[$$]"
  258. ,@"XCUIElementTypeWindow[`name = \"bla```bla\"`]"
  259. ,@"XCUIElementTypeWindow[$name = \"bla$$$bla\"$]"
  260. ];
  261. for (NSString *invalidQuery in invalidQueries) {
  262. NSError *error;
  263. FBClassChain *result = [FBClassChainQueryParser parseQuery:invalidQuery error:&error];
  264. XCTAssertNil(result);
  265. XCTAssertNotNil(error);
  266. }
  267. }
  268. @end