/** * 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 "XCUIElementDouble.h" #import "FBClassChainQueryParser.h" @interface FBClassChainTests : XCTestCase @end @implementation FBClassChainTests - (void)testValidChain { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeWindow); XCTAssertNil(firstElement.position); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertNil(secondElement.position); XCTAssertFalse(secondElement.isDescendant); } - (void)testValidChainWithStar { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[3]/*[4]/*[5]/XCUIElementTypeAlert" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 5); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeWindow); XCTAssertNil(firstElement.position); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertEqual(secondElement.position.integerValue, 3); XCTAssertFalse(secondElement.isDescendant); FBClassChainItem *thirdElement = [result.elements objectAtIndex:2]; XCTAssertEqual(thirdElement.type, XCUIElementTypeAny); XCTAssertEqual(thirdElement.position.integerValue, 4); XCTAssertFalse(thirdElement.isDescendant); FBClassChainItem *fourthElement = [result.elements objectAtIndex:3]; XCTAssertEqual(fourthElement.type, XCUIElementTypeAny); XCTAssertEqual(fourthElement.position.integerValue, 5); XCTAssertFalse(fourthElement.isDescendant); FBClassChainItem *fifthsElement = [result.elements objectAtIndex:4]; XCTAssertEqual(fifthsElement.type, XCUIElementTypeAlert); XCTAssertNil(fifthsElement.position); XCTAssertFalse(fifthsElement.isDescendant); } - (void)testValidSingleStarChain { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 1); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeAny); XCTAssertNil(firstElement.position); XCTAssertFalse(firstElement.isDescendant); } - (void)testValidSingleStarIndirectChain { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/*/*/XCUIElementTypeButton" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 3); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeAny); XCTAssertNil(firstElement.position); XCTAssertTrue(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeAny); XCTAssertNil(secondElement.position); XCTAssertFalse(secondElement.isDescendant); FBClassChainItem *thirdElement = [result.elements objectAtIndex:2]; XCTAssertEqual(thirdElement.type, XCUIElementTypeButton); XCTAssertNil(thirdElement.position); XCTAssertFalse(thirdElement.isDescendant); } - (void)testValidDoubleIndirectChainAndStar { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/*" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeButton); XCTAssertNil(firstElement.position); XCTAssertTrue(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeAny); XCTAssertNil(secondElement.position); XCTAssertTrue(secondElement.isDescendant); } - (void)testValidDoubleIndirectChainAndClassName { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/XCUIElementTypeImage" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeButton); XCTAssertNil(firstElement.position); XCTAssertTrue(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeImage); XCTAssertNil(secondElement.position); XCTAssertTrue(secondElement.isDescendant); } - (void)testValidChainWithNegativeIndex { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[-1]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeWindow); XCTAssertNil(firstElement.position); XCTAssertEqual(firstElement.predicates.count, 0); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertEqual(secondElement.position.integerValue, -1); XCTAssertEqual(secondElement.predicates.count, 0); XCTAssertFalse(secondElement.isDescendant); } - (void)testValidChainWithSinglePredicate { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeWindow); XCTAssertNil(firstElement.position); XCTAssertEqual(firstElement.predicates.count, 1); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertNil(secondElement.position); XCTAssertEqual(secondElement.predicates.count, 0); XCTAssertFalse(secondElement.isDescendant); } - (void)testValidChainWithMultiplePredicates { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton[`value == 'blabla'`]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeWindow); XCTAssertNil(firstElement.position); XCTAssertEqual(firstElement.predicates.count, 1); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertNil(secondElement.position); XCTAssertEqual(secondElement.predicates.count, 1); XCTAssertFalse(secondElement.isDescendant); } - (void)testValidChainWithIndirectSearchAndPredicates { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[`name == 'blabla'`][10]/**/XCUIElementTypeButton[`value == 'blabla'`]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeTable); XCTAssertEqual(firstElement.position.integerValue, 10); XCTAssertEqual(firstElement.predicates.count, 1); XCTAssertTrue(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertNil(secondElement.position); XCTAssertEqual(secondElement.predicates.count, 1); XCTAssertTrue(secondElement.isDescendant); } - (void)testValidChainWithMultiplePredicatesAndPositions { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*[`name == \"к``ири````'лиця\"`][3]/XCUIElementTypeButton[`value == \"blabla\"`][-1]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 2); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeAny); XCTAssertEqual(firstElement.position.integerValue, 3); XCTAssertEqual(firstElement.predicates.count, 1); XCTAssertFalse(firstElement.isDescendant); FBClassChainItem *secondElement = [result.elements objectAtIndex:1]; XCTAssertEqual(secondElement.type, XCUIElementTypeButton); XCTAssertEqual(secondElement.position.integerValue, -1); XCTAssertEqual(secondElement.predicates.count, 1); XCTAssertFalse(secondElement.isDescendant); } - (void)testValidChainWithDescendantPredicate { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`name == 'blabla'`][10]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 1); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeTable); XCTAssertEqual(firstElement.position.integerValue, 10); XCTAssertEqual(firstElement.predicates.count, 2); XCTAssertTrue(firstElement.isDescendant); } - (void)testValidChainWithMultipleDescendantPredicates { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`value == 'peace'`][$value == 'yolo'$][`name == 'blabla'`][10]" error:&error]; XCTAssertNotNil(result); XCTAssertEqual(result.elements.count, 1); FBClassChainItem *firstElement = [result.elements firstObject]; XCTAssertEqual(firstElement.type, XCUIElementTypeTable); XCTAssertEqual(firstElement.position.integerValue, 10); XCTAssertEqual(firstElement.predicates.count, 4); XCTAssertTrue(firstElement.isDescendant); } - (void)testInvalidChains { NSArray *invalidQueries = @[ @"/XCUIElementTypeWindow" ,@"XCUIElementTypeWindow/" ,@"XCUIElementTypeWindow//*" ,@"XCUIElementTypeWindow*/*" ,@"**" ,@"***" ,@"**/*/**" ,@"/**" ,@"XCUIElementTypeWindow/**" ,@"**[1]/XCUIElementTypeWindow" ,@"**[`name == '1'`]/XCUIElementTypeWindow" ,@"XCUIElementTypeWindow[0]" ,@"XCUIElementTypeWindow[1][1]" ,@"blabla" ,@"XCUIElementTypeWindow/blabla" ,@" XCUIElementTypeWindow" ,@"XCUIElementTypeWindow[ 2 ]" ,@"XCUIElementTypeWindow[[2]" ,@"XCUIElementTypeWindow[2]]" ,@"XCUIElementType[Window[2]]" ,@"XCUIElementTypeWindow[visible = 1]" ,@"XCUIElementTypeWindow[1][`visible = 1`]" ,@"XCUIElementTypeWindow[1] [`visible = 1`]" ,@"XCUIElementTypeWindow[ `visible = 1`]" ,@"XCUIElementTypeWindow[`visible = 1][`name = \"bla\"`]" ,@"XCUIElementTypeWindow[`visible = 1]" ,@"XCUIElementTypeWindow[$visible = 1]" ,@"XCUIElementTypeWindow[``]" ,@"XCUIElementTypeWindow[$$]" ,@"XCUIElementTypeWindow[`name = \"bla```bla\"`]" ,@"XCUIElementTypeWindow[$name = \"bla$$$bla\"$]" ]; for (NSString *invalidQuery in invalidQueries) { NSError *error; FBClassChain *result = [FBClassChainQueryParser parseQuery:invalidQuery error:&error]; XCTAssertNil(result); XCTAssertNotNil(error); } } @end