XCUIElementFBFindTests.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  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 "FBIntegrationTestCase.h"
  11. #import "FBElementUtils.h"
  12. #import "FBExceptions.h"
  13. #import "FBTestMacros.h"
  14. #import "XCUIElement.h"
  15. #import "XCUIElement+FBFind.h"
  16. #import "FBXCElementSnapshotWrapper+Helpers.h"
  17. #import "XCUIElement+FBIsVisible.h"
  18. #import "XCUIElement+FBClassChain.h"
  19. #import "XCUIElement+FBResolve.h"
  20. #import "FBXPath.h"
  21. #import "FBXCodeCompatibility.h"
  22. @interface XCUIElementFBFindTests : FBIntegrationTestCase
  23. @property (nonatomic, strong) XCUIElement *testedView;
  24. @end
  25. @implementation XCUIElementFBFindTests
  26. - (void)setUp
  27. {
  28. [super setUp];
  29. static dispatch_once_t onceToken;
  30. dispatch_once(&onceToken, ^{
  31. [self launchApplication];
  32. });
  33. self.testedView = self.testedApplication.otherElements[@"MainView"];
  34. FBAssertWaitTillBecomesTrue(self.testedView.exists);
  35. }
  36. - (void)testDescendantsWithClassName
  37. {
  38. NSSet<NSString *> *expectedLabels = [NSSet setWithArray:@[
  39. @"Alerts",
  40. @"Attributes",
  41. @"Scrolling",
  42. @"Deadlock app",
  43. @"Touch",
  44. ]];
  45. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassName:@"XCUIElementTypeButton"
  46. shouldReturnAfterFirstMatch:NO];
  47. XCTAssertEqual(matchingSnapshots.count, expectedLabels.count);
  48. NSArray<NSString *> *labels = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.label"];
  49. XCTAssertEqualObjects([NSSet setWithArray:labels], expectedLabels);
  50. NSArray<NSNumber *> *types = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.elementType"];
  51. XCTAssertEqual(types.count, 1, @"matchingSnapshots should contain only one type");
  52. XCTAssertEqualObjects(types.lastObject, @(XCUIElementTypeButton), @"matchingSnapshots should contain only one type");
  53. }
  54. - (void)testSingleDescendantWithClassName
  55. {
  56. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassName:@"XCUIElementTypeButton"
  57. shouldReturnAfterFirstMatch:YES];
  58. XCTAssertEqual(matchingSnapshots.count, 1);
  59. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  60. }
  61. - (void)testDescendantsWithIdentifier
  62. {
  63. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
  64. shouldReturnAfterFirstMatch:NO];
  65. int snapshotsCount = 1;
  66. if (@available(iOS 13.0, *)) {
  67. snapshotsCount = 2;
  68. }
  69. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  70. XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
  71. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  72. NSArray<XCUIElement *> *selfElementsById = [matchingSnapshots.lastObject fb_descendantsMatchingIdentifier:@"Alerts" shouldReturnAfterFirstMatch:NO];
  73. XCTAssertEqual(selfElementsById.count, 1);
  74. }
  75. - (void)testSingleDescendantWithIdentifier
  76. {
  77. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
  78. shouldReturnAfterFirstMatch:YES];
  79. XCTAssertEqual(matchingSnapshots.count, 1);
  80. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  81. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  82. }
  83. - (void)testStableInstance
  84. {
  85. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
  86. shouldReturnAfterFirstMatch:YES];
  87. XCTAssertEqual(matchingSnapshots.count, 1);
  88. for (XCUIElement *el in @[matchingSnapshots.lastObject, matchingSnapshots.lastObject.fb_stableInstance]) {
  89. XCTAssertEqual(el.elementType, XCUIElementTypeButton);
  90. XCTAssertEqualObjects(el.label, @"Alerts");
  91. }
  92. }
  93. - (void)testSingleDescendantWithMissingIdentifier
  94. {
  95. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"blabla" shouldReturnAfterFirstMatch:YES];
  96. XCTAssertEqual(matchingSnapshots.count, 0);
  97. }
  98. - (void)testDescendantsWithXPathQuery
  99. {
  100. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Alerts']"
  101. shouldReturnAfterFirstMatch:NO];
  102. XCTAssertEqual(matchingSnapshots.count, 1);
  103. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  104. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  105. }
  106. - (void)testSelfWithXPathQuery
  107. {
  108. NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeApplication"
  109. shouldReturnAfterFirstMatch:NO];
  110. XCTAssertEqual(matchingSnapshots.count, 1);
  111. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeApplication);
  112. }
  113. - (void)testSingleDescendantWithXPathQuery
  114. {
  115. NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@hittable='true']"
  116. shouldReturnAfterFirstMatch:YES];
  117. XCTAssertEqual(matchingSnapshots.count, 1);
  118. XCUIElement *matchingSnapshot = [matchingSnapshots firstObject];
  119. XCTAssertNotNil(matchingSnapshot);
  120. XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
  121. XCTAssertEqualObjects(matchingSnapshot.label, @"Alerts");
  122. }
  123. - (void)testSingleDescendantWithXPathQueryNoMatches
  124. {
  125. XCUIElement *matchingSnapshot = [[self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButtonnn"
  126. shouldReturnAfterFirstMatch:YES] firstObject];
  127. XCTAssertNil(matchingSnapshot);
  128. }
  129. - (void)testSingleLastDescendantWithXPathQuery
  130. {
  131. XCUIElement *matchingSnapshot = [[self.testedView fb_descendantsMatchingXPathQuery:@"(//XCUIElementTypeButton)[last()]"
  132. shouldReturnAfterFirstMatch:YES] firstObject];
  133. XCTAssertNotNil(matchingSnapshot);
  134. XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
  135. }
  136. - (void)testDescendantsWithXPathQueryNoMatches
  137. {
  138. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Alerts1']"
  139. shouldReturnAfterFirstMatch:NO];
  140. XCTAssertEqual(matchingSnapshots.count, 0);
  141. }
  142. - (void)testDescendantsWithComplexXPathQuery
  143. {
  144. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//*[@label='Scrolling']/preceding::*[boolean(string(@label))]"
  145. shouldReturnAfterFirstMatch:NO];
  146. int snapshotsCount = 3;
  147. if (@available(iOS 13.0, *)) {
  148. snapshotsCount = 6;
  149. }
  150. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  151. }
  152. - (void)testDescendantsWithWrongXPathQuery
  153. {
  154. XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingXPathQuery:@"//*[blabla(@label, Scrolling')]"
  155. shouldReturnAfterFirstMatch:NO],
  156. NSException, FBInvalidXPathException);
  157. }
  158. - (void)testFirstDescendantWithWrongXPathQuery
  159. {
  160. XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingXPathQuery:@"//*[blabla(@label, Scrolling')]"
  161. shouldReturnAfterFirstMatch:YES],
  162. NSException, FBInvalidXPathException);
  163. }
  164. - (void)testVisibleDescendantWithXPathQuery
  165. {
  166. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@name='Alerts' and @enabled='true' and @visible='true']" shouldReturnAfterFirstMatch:NO];
  167. XCTAssertEqual(matchingSnapshots.count, 1);
  168. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  169. XCTAssertTrue(matchingSnapshots.lastObject.isEnabled);
  170. XCTAssertTrue(matchingSnapshots.lastObject.fb_isVisible);
  171. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  172. }
  173. - (void)testDescendantsWithPredicateString
  174. {
  175. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label = 'Alerts'"];
  176. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate
  177. shouldReturnAfterFirstMatch:NO];
  178. int snapshotsCount = 1;
  179. if (@available(iOS 13.0, *)) {
  180. snapshotsCount = 2;
  181. }
  182. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  183. XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
  184. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  185. NSPredicate *selfPredicate = [NSPredicate predicateWithFormat:@"label == 'Alerts'"];
  186. NSArray<XCUIElement *> *selfElementsByPredicate = [matchingSnapshots.lastObject fb_descendantsMatchingPredicate:selfPredicate
  187. shouldReturnAfterFirstMatch:NO];
  188. XCTAssertEqual(selfElementsByPredicate.count, 1);
  189. }
  190. - (void)testSelfWithPredicateString
  191. {
  192. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == 'XCUIElementTypeApplication'"];
  193. NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingPredicate:predicate
  194. shouldReturnAfterFirstMatch:NO];
  195. XCTAssertEqual(matchingSnapshots.count, 1);
  196. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeApplication);
  197. }
  198. - (void)testSingleDescendantWithPredicateString
  199. {
  200. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type = 'XCUIElementTypeButton'"];
  201. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:YES];
  202. XCTAssertEqual(matchingSnapshots.count, 1);
  203. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  204. }
  205. - (void)testSingleDescendantWithPredicateStringByIndex
  206. {
  207. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == 'XCUIElementTypeButton' AND index == 2"];
  208. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:NO];
  209. XCTAssertEqual(matchingSnapshots.count, 1);
  210. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  211. }
  212. - (void)testDescendantsWithPropertyStrict
  213. {
  214. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label"
  215. value:@"Alert"
  216. partialSearch:NO];
  217. XCTAssertEqual(matchingSnapshots.count, 0);
  218. matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO];
  219. int snapshotsCount = 1;
  220. if (@available(iOS 13.0, *)) {
  221. snapshotsCount = 2;
  222. }
  223. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  224. XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
  225. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  226. }
  227. - (void)testGlobalWithPropertyStrict
  228. {
  229. NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingProperty:@"label"
  230. value:@"Alert"
  231. partialSearch:NO];
  232. XCTAssertEqual(matchingSnapshots.count, 0);
  233. matchingSnapshots = [self.testedApplication fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO];
  234. int snapshotsCount = 1;
  235. if (@available(iOS 13.0, *)) {
  236. snapshotsCount = 2;
  237. }
  238. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  239. XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
  240. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  241. }
  242. - (void)testDescendantsWithPropertyPartial
  243. {
  244. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label"
  245. value:@"Alerts"
  246. partialSearch:NO];
  247. int snapshotsCount = 1;
  248. if (@available(iOS 13.0, *)) {
  249. snapshotsCount = 2;
  250. }
  251. XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
  252. XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
  253. XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
  254. }
  255. - (void)testDescendantsWithClassChain
  256. {
  257. NSArray<XCUIElement *> *matchingSnapshots;
  258. NSString *queryString =@"XCUIElementTypeWindow/XCUIElementTypeOther/**/XCUIElementTypeButton";
  259. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  260. shouldReturnAfterFirstMatch:NO];
  261. XCTAssertEqual(matchingSnapshots.count, 5); // /XCUIElementTypeButton
  262. for (XCUIElement *matchingSnapshot in matchingSnapshots) {
  263. XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
  264. }
  265. }
  266. - (void)testDescendantsWithClassChainWithIndex
  267. {
  268. NSArray<XCUIElement *> *matchingSnapshots;
  269. NSString *queryString = @"XCUIElementTypeWindow/*/*[2]/*/*/XCUIElementTypeButton";
  270. if (@available(iOS 13.0, *)) {
  271. // iPhone
  272. queryString = @"XCUIElementTypeWindow/*/*/*/*[2]/*/*/XCUIElementTypeButton";
  273. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  274. shouldReturnAfterFirstMatch:NO];
  275. if (matchingSnapshots.count == 0) {
  276. // iPad
  277. queryString = @"XCUIElementTypeWindow/*/*/*/*/*[2]/*/*/XCUIElementTypeButton";
  278. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  279. shouldReturnAfterFirstMatch:NO];
  280. }
  281. } else {
  282. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  283. shouldReturnAfterFirstMatch:NO];
  284. }
  285. XCTAssertEqual(matchingSnapshots.count, 5); // /XCUIElementTypeButton
  286. for (XCUIElement *matchingSnapshot in matchingSnapshots) {
  287. XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
  288. }
  289. }
  290. - (void)testDescendantsWithClassChainAndPredicates
  291. {
  292. NSArray<XCUIElement *> *matchingSnapshots;
  293. NSString *queryString = @"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]";
  294. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  295. shouldReturnAfterFirstMatch:NO];
  296. XCTAssertEqual(matchingSnapshots.count, 2);
  297. XCTAssertEqualObjects([matchingSnapshots firstObject].label, @"Alerts");
  298. XCTAssertEqualObjects([matchingSnapshots lastObject].label, @"Attributes");
  299. }
  300. - (void)testDescendantsWithIndirectClassChainAndPredicates
  301. {
  302. NSString *queryString = @"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]";
  303. NSArray<XCUIElement *> *simpleQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  304. shouldReturnAfterFirstMatch:NO];
  305. NSArray<XCUIElement *> *deepQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]"
  306. shouldReturnAfterFirstMatch:NO];
  307. XCTAssertEqual(simpleQueryMatches.count, deepQueryMatches.count);
  308. XCTAssertEqualObjects([simpleQueryMatches firstObject].label, [deepQueryMatches firstObject].label);
  309. XCTAssertEqualObjects([simpleQueryMatches lastObject].label, [deepQueryMatches lastObject].label);
  310. }
  311. - (void)testClassChainWithDescendantPredicate
  312. {
  313. NSArray<XCUIElement *> *simpleQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/*/*[1]"
  314. shouldReturnAfterFirstMatch:NO];
  315. NSArray<XCUIElement *> *predicateQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/*/*[$type == 'XCUIElementTypeButton' AND label BEGINSWITH 'A'$]"
  316. shouldReturnAfterFirstMatch:NO];
  317. XCTAssertEqual(simpleQueryMatches.count, predicateQueryMatches.count);
  318. XCTAssertEqual([simpleQueryMatches firstObject].elementType, [predicateQueryMatches firstObject].elementType);
  319. XCTAssertEqual([simpleQueryMatches lastObject].elementType, [predicateQueryMatches lastObject].elementType);
  320. }
  321. - (void)testSingleDescendantWithComplexIndirectClassChain
  322. {
  323. NSArray<XCUIElement *> *queryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"**/*/XCUIElementTypeButton[2]"
  324. shouldReturnAfterFirstMatch:NO];
  325. XCTAssertEqual(queryMatches.count, 1);
  326. XCTAssertEqual(queryMatches.lastObject.elementType, XCUIElementTypeButton);
  327. XCTAssertEqualObjects(queryMatches.lastObject.label, @"Deadlock app");
  328. }
  329. - (void)testSingleDescendantWithComplexIndirectClassChainAndZeroMatches
  330. {
  331. NSArray<XCUIElement *> *queryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"**/*/XCUIElementTypeWindow"
  332. shouldReturnAfterFirstMatch:NO];
  333. XCTAssertEqual(queryMatches.count, 0);
  334. }
  335. - (void)testDescendantsWithClassChainAndPredicatesAndIndexes
  336. {
  337. NSArray<XCUIElement *> *matchingSnapshots;
  338. NSString *queryString = @"XCUIElementTypeWindow[`name != 'bla'`]/**/XCUIElementTypeButton[`label BEGINSWITH \"A\"`][1]";
  339. matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
  340. shouldReturnAfterFirstMatch:NO];
  341. XCTAssertEqual(matchingSnapshots.count, 1);
  342. XCTAssertEqualObjects([matchingSnapshots firstObject].label, @"Alerts");
  343. }
  344. - (void)testSingleDescendantWithClassChain
  345. {
  346. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton"
  347. shouldReturnAfterFirstMatch:YES];
  348. XCTAssertEqual(matchingSnapshots.count, 1);
  349. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  350. XCTAssertTrue([matchingSnapshots.lastObject.label isEqualToString:@"Alerts"]);
  351. }
  352. - (void)testSingleDescendantWithClassChainAndNegativeIndex
  353. {
  354. NSArray<XCUIElement *> *matchingSnapshots;
  355. matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton[-1]"
  356. shouldReturnAfterFirstMatch:YES];
  357. XCTAssertEqual(matchingSnapshots.count, 1);
  358. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
  359. XCTAssertTrue([matchingSnapshots.lastObject.label isEqualToString:@"Touch"]);
  360. matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton[-10]"
  361. shouldReturnAfterFirstMatch:YES];
  362. XCTAssertEqual(matchingSnapshots.count, 0);
  363. }
  364. - (void)testInvalidQueryWithClassChain
  365. {
  366. XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingClassChain:@"NoXCUIElementTypePrefix"
  367. shouldReturnAfterFirstMatch:YES],
  368. NSException, FBClassChainQueryParseException);
  369. }
  370. - (void)testHandleInvalidQueryWithClassChainAsNoElementWithoutError
  371. {
  372. NSArray<XCUIElement *> *matchingSnapshots = [self.testedView
  373. fb_descendantsMatchingClassChain:@"XCUIElementTypeBlabla"
  374. shouldReturnAfterFirstMatch:YES];
  375. XCTAssertEqual(matchingSnapshots.count, 0);
  376. }
  377. - (void)testClassChainWithInvalidPredicate
  378. {
  379. XCTAssertThrowsSpecificNamed([self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow[`bla != 'bla'`]"
  380. shouldReturnAfterFirstMatch:NO],
  381. NSException, FBUnknownAttributeException);;
  382. }
  383. @end
  384. @interface XCUIElementFBFindTests_AttributesPage : FBIntegrationTestCase
  385. @end
  386. @implementation XCUIElementFBFindTests_AttributesPage
  387. - (void)setUp
  388. {
  389. [super setUp];
  390. static dispatch_once_t onceToken;
  391. dispatch_once(&onceToken, ^{
  392. [self launchApplication];
  393. [self goToAttributesPage];
  394. });
  395. }
  396. - (void)testNestedQueryWithClassChain
  397. {
  398. NSString *queryString = @"XCUIElementTypeOther";
  399. if (@available(iOS 13.0, *)) {
  400. queryString = @"XCUIElementTypePicker";
  401. }
  402. FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"Button"].fb_isVisible);
  403. XCUIElement *datePicker = [self.testedApplication
  404. descendantsMatchingType:XCUIElementTypeDatePicker].allElementsBoundByIndex.firstObject;
  405. NSArray<XCUIElement *> *matches = [datePicker fb_descendantsMatchingClassChain:queryString
  406. shouldReturnAfterFirstMatch:NO];
  407. XCTAssertEqual(matches.count, 1);
  408. XCUIElementType expectedType = XCUIElementTypeOther;
  409. if (@available(iOS 13.0, *)) {
  410. expectedType = XCUIElementTypePicker;
  411. }
  412. XCTAssertEqual([matches firstObject].elementType, expectedType);
  413. }
  414. @end
  415. @interface XCUIElementFBFindTests_ScrollPage : FBIntegrationTestCase
  416. @end
  417. @implementation XCUIElementFBFindTests_ScrollPage
  418. - (void)setUp
  419. {
  420. [super setUp];
  421. static dispatch_once_t onceToken;
  422. dispatch_once(&onceToken, ^{
  423. [self launchApplication];
  424. [self goToScrollPageWithCells:YES];
  425. });
  426. }
  427. - (void)testInvisibleDescendantWithXPathQuery
  428. {
  429. NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeStaticText[@visible='false']"
  430. shouldReturnAfterFirstMatch:NO];
  431. XCTAssertGreaterThan(matchingSnapshots.count, 1);
  432. XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeStaticText);
  433. XCTAssertFalse(matchingSnapshots.lastObject.fb_isVisible);
  434. }
  435. @end