/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #import #import "FBIntegrationTestCase.h" #import "FBMacros.h" #import "FBTestMacros.h" #import "FBXPath.h" #import "FBXCAccessibilityElement.h" #import "FBXCodeCompatibility.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBXMLGenerationOptions.h" #import "XCUIApplication.h" #import "XCUIElement.h" #import "XCUIElement+FBFind.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" @interface FBXPathIntegrationTests : FBIntegrationTestCase @property (nonatomic, strong) XCUIElement *testedView; @end @implementation FBXPathIntegrationTests - (void)setUp { [super setUp]; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self launchApplication]; }); self.testedView = self.testedApplication.otherElements[@"MainView"]; XCTAssertTrue(self.testedView.exists); FBAssertWaitTillBecomesTrue(self.testedView.buttons.count > 0); } - (id)destinationSnapshot { XCUIElement *matchingElement = self.testedView.buttons.allElementsBoundByIndex.firstObject; id snapshot = [matchingElement fb_customSnapshot]; // Over iOS13, snapshot returns a child. // The purpose of here is return a single element to replace children with an empty array for testing. snapshot.children = @[]; return snapshot; } - (void)testApplicationNodeXMLRepresentation { id snapshot = [self.testedApplication fb_customSnapshot]; snapshot.children = @[]; FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:nil]; int pid = [snapshot.accessibilityElement processIdentifier]; XCTAssertNotNil(xmlStr); NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\" processId=\"%d\" bundleId=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, wrappedSnapshot.wdTraits, pid, [self.testedApplication bundleID]]; XCTAssertEqualObjects(xmlStr, expectedXml); } - (void)testSingleDescendantXMLRepresentation { id snapshot = self.destinationSnapshot; FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:nil]; XCTAssertNotNil(xmlStr); NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, wrappedSnapshot.wdTraits]; XCTAssertEqualObjects(xmlStr, expectedXml); } - (void)testSingleDescendantXMLRepresentationWithScope { id snapshot = self.destinationSnapshot; NSString *scope = @"AppiumAUT"; FBXMLGenerationOptions *options = [[FBXMLGenerationOptions new] withScope:scope]; FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:options]; XCTAssertNotNil(xmlStr); NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\"/>\n\n", scope, wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, wrappedSnapshot.wdTraits, scope]; XCTAssertEqualObjects(xmlStr, expectedXml); } - (void)testSingleDescendantXMLRepresentationWithoutAttributes { id snapshot = self.destinationSnapshot; FBXMLGenerationOptions *options = [[FBXMLGenerationOptions new] withExcludedAttributes:@[@"visible", @"enabled", @"index", @"blabla"]]; FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:options]; XCTAssertNotNil(xmlStr); NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" traits=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdTraits]; XCTAssertEqualObjects(xmlStr, expectedXml); } - (void)testFindMatchesInElement { NSArray> *matchingSnapshots = [FBXPath matchesWithRootElement:self.testedApplication forQuery:@"//XCUIElementTypeButton"]; XCTAssertEqual([matchingSnapshots count], 5); for (id element in matchingSnapshots) { XCTAssertTrue([[FBXCElementSnapshotWrapper ensureWrapped:element].wdType isEqualToString:@"XCUIElementTypeButton"]); } } - (void)testFindMatchesWithoutContextScopeLimit { XCUIElement *button = self.testedApplication.buttons.firstMatch; BOOL previousValue = FBConfiguration.limitXpathContextScope; FBConfiguration.limitXpathContextScope = NO; @try { NSArray *parentSnapshots = [FBXPath matchesWithRootElement:button forQuery:@".."]; XCTAssertEqual(parentSnapshots.count, 1); XCTAssertEqualObjects( [FBXCElementSnapshotWrapper ensureWrapped:[parentSnapshots objectAtIndex:0]].wdLabel, @"MainView" ); NSArray *elements = [button.application fb_filterDescendantsWithSnapshots:parentSnapshots onlyChildren:NO]; XCTAssertEqual(elements.count, 1); XCTAssertEqualObjects( [[elements objectAtIndex:0] wdLabel], @"MainView" ); NSArray *currentSnapshots = [FBXPath matchesWithRootElement:button forQuery:@"."]; XCTAssertEqual(currentSnapshots.count, 1); XCTAssertEqualObjects( [FBXCElementSnapshotWrapper ensureWrapped:[currentSnapshots objectAtIndex:0]].wdType, @"XCUIElementTypeButton" ); NSArray *currentElements = [button.application fb_filterDescendantsWithSnapshots:currentSnapshots onlyChildren:NO]; XCTAssertEqual(currentElements.count, 1); XCTAssertEqualObjects( [[currentElements objectAtIndex:0] wdType], @"XCUIElementTypeButton" ); } @finally { FBConfiguration.limitXpathContextScope = previousValue; } } - (void)testFindMatchesInElementWithDotNotation { NSArray> *matchingSnapshots = [FBXPath matchesWithRootElement:self.testedApplication forQuery:@".//XCUIElementTypeButton"]; XCTAssertEqual([matchingSnapshots count], 5); for (id element in matchingSnapshots) { XCTAssertTrue([[FBXCElementSnapshotWrapper ensureWrapped:element].wdType isEqualToString:@"XCUIElementTypeButton"]); } } @end