初始化提交

This commit is contained in:
2026-02-03 16:52:44 +08:00
commit d2f9806384
512 changed files with 65167 additions and 0 deletions

View File

@@ -0,0 +1,188 @@
/**
* 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 <XCTest/XCTest.h>
#import <WebDriverAgentLib/FBAlert.h>
#import "FBConfiguration.h"
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "FBMacros.h"
@interface FBAlertTests : FBIntegrationTestCase
@end
@implementation FBAlertTests
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAlertsPage];
[FBConfiguration disableApplicationUIInterruptionsHandling];
});
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
[super tearDown];
}
- (void)showApplicationAlert
{
[self.testedApplication.buttons[FBShowAlertButtonName] tap];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count != 0);
}
- (void)showApplicationSheet
{
[self.testedApplication.buttons[FBShowSheetAlertButtonName] tap];
FBAssertWaitTillBecomesTrue(self.testedApplication.sheets.count != 0);
}
- (void)testAlertPresence
{
FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertFalse(alert.isPresent);
[self showApplicationAlert];
XCTAssertTrue(alert.isPresent);
}
- (void)testAlertText
{
FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertNil(alert.text);
[self showApplicationAlert];
XCTAssertTrue([alert.text containsString:@"Magic"]);
XCTAssertTrue([alert.text containsString:@"Should read"]);
}
- (void)testAlertLabels
{
FBAlert* alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertNil(alert.buttonLabels);
[self showApplicationAlert];
XCTAssertNotNil(alert.buttonLabels);
XCTAssertEqual(1, alert.buttonLabels.count);
XCTAssertEqualObjects(@"Will do", alert.buttonLabels[0]);
}
- (void)testClickAlertButton
{
FBAlert* alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertFalse([alert clickAlertButton:@"Invalid" error:nil]);
[self showApplicationAlert];
XCTAssertFalse([alert clickAlertButton:@"Invalid" error:nil]);
FBAssertWaitTillBecomesTrue(alert.isPresent);
XCTAssertTrue([alert clickAlertButton:@"Will do" error:nil]);
FBAssertWaitTillBecomesTrue(!alert.isPresent);
}
- (void)testAcceptingAlert
{
NSError *error;
[self showApplicationAlert];
XCTAssertTrue([[FBAlert alertWithApplication:self.testedApplication] acceptWithError:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
XCTAssertNil(error);
}
- (void)testAcceptingAlertWithCustomLocator
{
NSError *error;
[self showApplicationAlert];
[FBConfiguration setAcceptAlertButtonSelector:@"**/XCUIElementTypeButton[-1]"];
@try {
XCTAssertTrue([[FBAlert alertWithApplication:self.testedApplication] acceptWithError:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
XCTAssertNil(error);
} @finally {
[FBConfiguration setAcceptAlertButtonSelector:@""];
}
}
- (void)testDismissingAlert
{
NSError *error;
[self showApplicationAlert];
XCTAssertTrue([[FBAlert alertWithApplication:self.testedApplication] dismissWithError:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
XCTAssertNil(error);
}
- (void)testDismissingAlertWithCustomLocator
{
NSError *error;
[self showApplicationAlert];
[FBConfiguration setDismissAlertButtonSelector:@"**/XCUIElementTypeButton[-1]"];
@try {
XCTAssertTrue([[FBAlert alertWithApplication:self.testedApplication] dismissWithError:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
XCTAssertNil(error);
} @finally {
[FBConfiguration setDismissAlertButtonSelector:@""];
}
}
- (void)testAlertElement
{
[self showApplicationAlert];
XCUIElement *alertElement = [FBAlert alertWithApplication:self.testedApplication].alertElement;
XCTAssertTrue(alertElement.exists);
XCTAssertTrue(alertElement.elementType == XCUIElementTypeAlert);
}
- (void)testNotificationAlert
{
FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertNil(alert.text);
[self.testedApplication.buttons[@"Create Notification Alert"] tap];
FBAssertWaitTillBecomesTrue(alert.isPresent);
XCTAssertTrue([alert.text containsString:@"Would Like to Send You Notifications"]);
XCTAssertTrue([alert.text containsString:@"Notifications may include"]);
}
// This test case depends on the local app permission state.
- (void)testCameraRollAlert
{
FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertNil(alert.text);
[self.testedApplication.buttons[@"Create Camera Roll Alert"] tap];
FBAssertWaitTillBecomesTrue(alert.isPresent);
// "Would Like to Access Your Photos" or "Would Like to Access Your Photo Library" displayes on the alert button.
XCTAssertTrue([alert.text containsString:@"Would Like to Access Your Photo"]);
// iOS 15 has different UI flow
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
[[FBAlert alertWithApplication:self.testedApplication] dismissWithError:nil];
// CI env could take longer time to show up the button, thus it needs to wait a bit.
XCTAssertTrue([self.testedApplication.buttons[@"Cancel"] waitForExistenceWithTimeout:30.0]);
[self.testedApplication.buttons[@"Cancel"] tap];
}
}
- (void)testGPSAccessAlert
{
FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication];
XCTAssertNil(alert.text);
[self.testedApplication.buttons[@"Create GPS access Alert"] tap];
FBAssertWaitTillBecomesTrue(alert.isPresent);
XCTAssertTrue([alert.text containsString:@"location"]);
XCTAssertTrue([alert.text containsString:@"Yo Yo"]);
}
@end

View File

@@ -0,0 +1,73 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBMacros.h"
#import "FBSession.h"
#import "FBXCodeCompatibility.h"
#import "FBTestMacros.h"
#import "XCUIElement+FBUtilities.h"
@interface FBAutoAlertsHandlerTests : FBIntegrationTestCase
@property (nonatomic) FBSession *session;
@end
@implementation FBAutoAlertsHandlerTests
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAlertsPage];
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
if (self.session) {
[self.session kill];
}
[super tearDown];
}
// The test is flaky on slow Travis CI
- (void)disabled_testAutoAcceptingOfAlerts
{
self.session = [FBSession
initWithApplication:XCUIApplication.fb_activeApplication
defaultAlertAction:@"accept"];
for (int i = 0; i < 2; i++) {
[self.testedApplication.buttons[FBShowAlertButtonName] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
}
}
// The test is flaky on slow Travis CI
- (void)disabled_testAutoDismissingOfAlerts
{
self.session = [FBSession
initWithApplication:XCUIApplication.fb_activeApplication
defaultAlertAction:@"dismiss"];
for (int i = 0; i < 2; i++) {
[self.testedApplication.buttons[FBShowAlertButtonName] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
}
}
@end

View File

@@ -0,0 +1,38 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBConfiguration.h"
#import "FBRuntimeUtils.h"
@interface FBConfigurationTests : FBIntegrationTestCase
@end
@implementation FBConfigurationTests
- (void)setUp
{
[super setUp];
[self launchApplication];
}
- (void)testReduceMotion
{
BOOL defaultReduceMotionEnabled = [FBConfiguration reduceMotionEnabled];
[FBConfiguration setReduceMotionEnabled:YES];
XCTAssertTrue([FBConfiguration reduceMotionEnabled]);
[FBConfiguration setReduceMotionEnabled:defaultReduceMotionEnabled];
XCTAssertEqual([FBConfiguration reduceMotionEnabled], defaultReduceMotionEnabled);
}
@end

View File

@@ -0,0 +1,250 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBFindElementCommands.h"
#import "FBTestMacros.h"
#import "FBXCodeCompatibility.h"
#import "XCUIElement+FBAccessibility.h"
#import "XCUIElement+FBIsVisible.h"
#import "XCUIElement+FBWebDriverAttributes.h"
@interface FBElementAttributeTests : FBIntegrationTestCase
@end
@implementation FBElementAttributeTests
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAttributesPage];
});
}
- (void)testElementAccessibilityAttributes
{
// "Button" is accessibility element, and therefore isn't accessibility container
XCUIElement *buttonElement = self.testedApplication.buttons[@"Button"];
XCTAssertTrue(buttonElement.exists);
XCTAssertTrue(buttonElement.fb_isAccessibilityElement);
XCTAssertFalse(buttonElement.isWDAccessibilityContainer);
}
- (void)testContainerAccessibilityAttributes
{
// "not_accessible" isn't accessibility element, but contains accessibility elements, so it is accessibility container
XCUIElement *inaccessibleButtonElement = self.testedApplication.buttons[@"not_accessible"];
XCTAssertTrue(inaccessibleButtonElement.exists);
XCTAssertFalse(inaccessibleButtonElement.fb_isAccessibilityElement);
// FIXME: Xcode 11 environment returns false even if iOS 12
// We must fix here to XCTAssertTrue if Xcode version will return the value properly
XCTAssertFalse(inaccessibleButtonElement.isWDAccessibilityContainer);
}
- (void)testIgnoredAccessibilityAttributes
{
// Images are neither accessibility elements nor contain them, so both checks should fail
XCUIElement *imageElement = self.testedApplication.images.allElementsBoundByIndex.firstObject;
XCTAssertTrue(imageElement.exists);
XCTAssertFalse(imageElement.fb_isAccessibilityElement);
XCTAssertFalse(imageElement.isWDAccessibilityContainer);
}
- (void)testButtonAttributes
{
XCUIElement *element = self.testedApplication.buttons[@"Button"];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeButton");
XCTAssertEqualObjects(element.wdName, @"Button");
XCTAssertEqualObjects(element.wdLabel, @"Button");
XCTAssertNil(element.wdValue);
XCTAssertFalse(element.wdSelected);
XCTAssertTrue(element.fb_isVisible);
[element tap];
XCTAssertTrue(element.wdValue.boolValue);
XCTAssertTrue(element.wdSelected);
}
- (void)testLabelAttributes
{
XCUIElement *element = self.testedApplication.staticTexts[@"Label"];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeStaticText");
XCTAssertEqualObjects(element.wdName, @"Label");
XCTAssertEqualObjects(element.wdLabel, @"Label");
XCTAssertEqualObjects(element.wdValue, @"Label");
}
- (void)testIndexAttributes
{
XCUIElement *element = self.testedApplication.buttons[@"Button"];
XCTAssertTrue(element.exists);
XCTAssertEqual(element.wdIndex, 2);
XCUIElement *element2 = self.testedApplication;
XCTAssertTrue(element2.exists);
XCTAssertEqual(element2.wdIndex, 0);
}
- (void)testAccessibilityTraits
{
XCUIElement *button = self.testedApplication.buttons.firstMatch;
XCTAssertTrue(button.exists);
NSArray *buttonTraits = [button.wdTraits componentsSeparatedByString:@", "];
NSArray *expectedButtonTraits = @[@"Button"];
XCTAssertEqual(buttonTraits.count, expectedButtonTraits.count, @"Button should have exactly 1 trait");
XCTAssertEqualObjects(buttonTraits, expectedButtonTraits);
XCTAssertEqualObjects(button.wdType, @"XCUIElementTypeButton");
XCUIElement *toggle = self.testedApplication.switches.firstMatch;
XCTAssertTrue(toggle.exists);
// iOS 17.0 specific traits if available
NSArray *toggleTraits = [toggle.wdTraits componentsSeparatedByString:@", "];
NSArray *expectedToggleTraits;
#if __clang_major__ >= 16
if (@available(iOS 17.0, *)) {
expectedToggleTraits = @[@"ToggleButton", @"Button"];
XCTAssertEqual(toggleTraits.count, 2, @"Toggle should have exactly 2 traits on iOS 17+");
}
#else
expectedToggleTraits = @[@"Button"];
XCTAssertEqual(toggleTraits.count, 1, @"Toggle should have exactly 1 trait on iOS < 17");
#endif
XCTAssertEqualObjects(toggleTraits, expectedToggleTraits);
XCTAssertEqualObjects(toggle.wdType, @"XCUIElementTypeSwitch");
XCUIElement *slider = self.testedApplication.sliders.firstMatch;
XCTAssertTrue(slider.exists);
NSArray *sliderTraits = [slider.wdTraits componentsSeparatedByString:@", "];
NSArray *expectedSliderTraits = @[@"Adjustable"];
XCTAssertEqual(sliderTraits.count, expectedSliderTraits.count, @"Slider should have exactly 1 trait");
XCTAssertEqualObjects(sliderTraits, expectedSliderTraits);
XCTAssertEqualObjects(slider.wdType, @"XCUIElementTypeSlider");
XCUIElement *picker = self.testedApplication.pickerWheels.firstMatch;
XCTAssertTrue(picker.exists);
NSArray *pickerTraits = [picker.wdTraits componentsSeparatedByString:@", "];
NSArray *expectedPickerTraits = @[@"Adjustable"];
XCTAssertEqual(pickerTraits.count, expectedPickerTraits.count, @"Picker should have exactly 1 trait");
XCTAssertEqualObjects(pickerTraits, expectedPickerTraits);
XCTAssertEqualObjects(picker.wdType, @"XCUIElementTypePickerWheel");
}
- (void)testTextFieldAttributes
{
XCUIElement *element = self.testedApplication.textFields[@"Value"];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeTextField");
XCTAssertNil(element.wdName);
XCTAssertEqualObjects(element.wdLabel, @"");
XCTAssertEqualObjects(element.wdValue, @"Value");
}
- (void)testTextFieldWithAccessibilityIdentifiersAttributes
{
XCUIElement *element = self.testedApplication.textFields[@"aIdentifier"];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeTextField");
XCTAssertEqualObjects(element.wdName, @"aIdentifier");
XCTAssertEqualObjects(element.wdLabel, @"aLabel");
XCTAssertEqualObjects(element.wdValue, @"Value2");
}
- (void)testSegmentedControlAttributes
{
XCUIElement *element = self.testedApplication.segmentedControls.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSegmentedControl");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertNil(element.wdValue);
}
- (void)testSliderAttributes
{
XCUIElement *element = self.testedApplication.sliders.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSlider");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertTrue([element.wdValue containsString:@"50"]);
NSNumber *minValue = element.wdMinValue;
NSNumber *maxValue = element.wdMaxValue;
XCTAssertNotNil(minValue, @"Slider minValue should not be nil");
XCTAssertNotNil(maxValue, @"Slider maxValue should not be nil");
XCTAssertEqualObjects(minValue, @0);
XCTAssertEqualObjects(maxValue, @1);
}
- (void)testActivityIndicatorAttributes
{
XCUIElement *element = self.testedApplication.activityIndicators.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeActivityIndicator");
XCTAssertEqualObjects(element.wdName, @"Progress halted");
XCTAssertEqualObjects(element.wdLabel, @"Progress halted");
XCTAssertEqualObjects(element.wdValue, @"0");
}
- (void)testSwitchAttributes
{
XCUIElement *element = self.testedApplication.switches.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSwitch");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertNil(element.wdPlaceholderValue);
XCTAssertEqualObjects(element.wdValue, @"1");
XCTAssertFalse(element.wdSelected);
XCTAssertEqual(element.wdHittable, element.hittable);
[element tap];
XCTAssertEqualObjects(element.wdValue, @"0");
XCTAssertFalse(element.wdSelected);
}
- (void)testPickerWheelAttributes
{
XCUIElement *element = self.testedApplication.pickerWheels[@"Today"];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypePickerWheel");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertEqualObjects(element.wdValue, @"Today");
}
- (void)testPageIndicatorAttributes
{
XCUIElement *element = self.testedApplication.pageIndicators.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypePageIndicator");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertEqualObjects(element.wdValue, @"page 1 of 3");
}
- (void)testTextViewAttributes
{
XCUIElement *element = self.testedApplication.textViews.element;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeTextView");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
XCTAssertEqualObjects(element.wdValue, @"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901");
}
@end

View File

@@ -0,0 +1,127 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "FBXCodeCompatibility.h"
#import "XCUIElement+FBSwiping.h"
@interface FBElementSwipingTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *scrollView;
- (void)openScrollView;
@end
@implementation FBElementSwipingTests
- (void)openScrollView
{
[self launchApplication];
[self goToScrollPageWithCells:YES];
self.scrollView = [[self.testedApplication.query descendantsMatchingType:XCUIElementTypeAny] matchingIdentifier:@"scrollView"].element;
}
- (void)setUp
{
[super setUp];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
[self openScrollView];
} else {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self openScrollView];
});
}
}
- (void)tearDown
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
// Move to top page once to reset the scroll place
// since iOS 15 seems cannot handle cell visibility well when the view keps the view
[self.testedApplication terminate];
}
}
- (void)testSwipeUp
{
[self.scrollView fb_swipeWithDirection:@"up" velocity:nil];
FBAssertInvisibleCell(@"0");
}
- (void)testSwipeDown
{
[self.scrollView fb_swipeWithDirection:@"up" velocity:nil];
FBAssertInvisibleCell(@"0");
[self.scrollView fb_swipeWithDirection:@"down" velocity:nil];
FBAssertVisibleCell(@"0");
}
- (void)testSwipeDownWithVelocity
{
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
}
[self.scrollView fb_swipeWithDirection:@"up" velocity:@2500];
FBAssertInvisibleCell(@"0");
[self.scrollView fb_swipeWithDirection:@"down" velocity:@3000];
FBAssertVisibleCell(@"0");
}
@end
@interface FBElementSwipingApplicationTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *scrollView;
- (void)openScrollView;
@end
@implementation FBElementSwipingApplicationTests
- (void)openScrollView
{
[self launchApplication];
[self goToScrollPageWithCells:YES];
}
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self openScrollView];
});
}
- (void)testSwipeUp
{
[self.testedApplication fb_swipeWithDirection:@"up" velocity:nil];
FBAssertInvisibleCell(@"0");
}
- (void)testSwipeDown
{
[self.testedApplication fb_swipeWithDirection:@"up" velocity:nil];
FBAssertInvisibleCell(@"0");
[self.testedApplication fb_swipeWithDirection:@"down" velocity:nil];
FBAssertVisibleCell(@"0");
}
- (void)testSwipeDownWithVelocity
{
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
}
[self.testedApplication fb_swipeWithDirection:@"up" velocity:@2500];
FBAssertInvisibleCell(@"0");
[self.testedApplication fb_swipeWithDirection:@"down" velocity:@2500];
FBAssertVisibleCell(@"0");
}
@end

View File

@@ -0,0 +1,73 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBMacros.h"
#import "FBTestMacros.h"
#import "FBXCodeCompatibility.h"
#import "XCUIElement+FBIsVisible.h"
@interface FBElementVisibilityTests : FBIntegrationTestCase
@end
@implementation FBElementVisibilityTests
- (void)testSpringBoardIcons
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
return;
}
[self launchApplication];
[self goToSpringBoardFirstPage];
// Check Icons on first screen
// Note: Calender app exits 2 (an app icon + a widget) exist on the home screen
// on iOS 15+. The firstMatch is for it.
XCTAssertTrue(self.springboard.icons[@"Calendar"].firstMatch.fb_isVisible);
XCTAssertTrue(self.springboard.icons[@"Reminders"].fb_isVisible);
// Check Icons on second screen screen
XCTAssertFalse(self.springboard.icons[@"IntegrationApp"].firstMatch.fb_isVisible);
}
- (void)testSpringBoardSubfolder
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad
|| SYSTEM_VERSION_GREATER_THAN(@"12.0")) {
return;
}
[self launchApplication];
[self goToSpringBoardExtras];
XCTAssertFalse(self.springboard.icons[@"Extras"].otherElements[@"Contacts"].fb_isVisible);
}
- (void)disabled_testIconsFromSearchDashboard
{
// This test causes:
// Failure fetching attributes for element <XCAccessibilityElement: 0x60800044dd10> Device element: Error Domain=XCTDaemonErrorDomain Code=13 "Value for attribute 5017 is an error." UserInfo={NSLocalizedDescription=Value for attribute 5017 is an error.}
[self launchApplication];
[self goToSpringBoardDashboard];
XCTAssertFalse(self.springboard.icons[@"Reminders"].fb_isVisible);
XCTAssertFalse([[[self.springboard descendantsMatchingType:XCUIElementTypeIcon]
matchingIdentifier:@"IntegrationApp"]
firstMatch].fb_isVisible);
}
- (void)testTableViewCells
{
[self launchApplication];
[self goToScrollPageWithCells:YES];
for (int i = 0 ; i < 10 ; i++) {
FBAssertWaitTillBecomesTrue(self.testedApplication.cells.allElementsBoundByIndex[i].fb_isVisible);
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts.allElementsBoundByIndex[i].fb_isVisible);
}
}
@end

View File

@@ -0,0 +1,41 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBFailureProofTestCase.h"
#import "FBExceptionHandler.h"
@interface FBFailureProofTestCaseTests : FBFailureProofTestCase
@end
@implementation FBFailureProofTestCaseTests
- (void)setUp
{
[super setUp];
[[XCUIApplication new] launch];
}
- (void)testPreventElementSearchFailure
{
[[XCUIApplication new].buttons[@"kaboom"] tap];
}
- (void)testInactiveAppSearch
{
[[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
[[XCUIApplication new].buttons[@"kaboom"] tap];
}
- (void)testPreventAssertFailure
{
XCTAssertNotNil(nil);
}
@end

View File

@@ -0,0 +1,85 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBMacros.h"
#import "FBElementCache.h"
#import "FBTestMacros.h"
#import "XCUIDevice.h"
#import "XCUIDevice+FBRotation.h"
#import "XCUIElement+FBForceTouch.h"
#import "XCUIElement+FBIsVisible.h"
@interface FBForceTouchTests : FBIntegrationTestCase
@end
// It is recommnded to verify these tests with different iOS versions
@implementation FBForceTouchTests
- (void)verifyForceTapWithOrientation:(UIDeviceOrientation)orientation
{
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
NSError *error;
XCTAssertTrue(self.testedApplication.alerts.count == 0);
[self.testedApplication.buttons[FBShowAlertForceTouchButtonName] fb_forceTouchCoordinate:nil
pressure:nil
duration:nil
error:&error];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0);
}
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAlertsPage];
});
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
[self resetOrientation];
[super tearDown];
}
- (void)testForceTap
{
if (![XCUIDevice sharedDevice].supportsPressureInteraction) {
return;
}
[self verifyForceTapWithOrientation:UIDeviceOrientationPortrait];
}
- (void)testForceTapInLandscapeLeft
{
if (![XCUIDevice sharedDevice].supportsPressureInteraction) {
return;
}
[self verifyForceTapWithOrientation:UIDeviceOrientationLandscapeLeft];
}
- (void)testForceTapInLandscapeRight
{
if (![XCUIDevice sharedDevice].supportsPressureInteraction) {
return;
}
[self verifyForceTapWithOrientation:UIDeviceOrientationLandscapeRight];
}
@end

View File

@@ -0,0 +1,82 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBImageProcessor.h"
#import "FBIntegrationTestCase.h"
@interface FBImageProcessorTests : FBIntegrationTestCase
@property (nonatomic) NSData *originalImage;
@property (nonatomic) CGSize originalSize;
@end
@implementation FBImageProcessorTests
- (void)setUp {
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
XCUIScreenshot *screenshot = app.screenshot;
self.originalImage = UIImageJPEGRepresentation(screenshot.image, 1.0);
self.originalSize = [FBImageProcessorTests scaledSizeFromImage:screenshot.image];
}
- (void)testScaling {
CGFloat halfScale = 0.5;
CGSize expectedHalfScaleSize = [FBImageProcessorTests sizeFromSize:self.originalSize scalingFactor:0.5];
[self scaleImageWithFactor:halfScale
expectedSize:expectedHalfScaleSize];
// 0 is the smalles scaling factor we accept
CGFloat minScale = 0.0;
CGSize expectedMinScaleSize = [FBImageProcessorTests sizeFromSize:self.originalSize scalingFactor:0.01];
[self scaleImageWithFactor:minScale
expectedSize:expectedMinScaleSize];
// For scaling factors above 100 we don't perform any scaling and just return the unmodified image
[self scaleImageWithFactor:1.0
expectedSize:self.originalSize];
[self scaleImageWithFactor:2.0
expectedSize:self.originalSize];
}
- (void)scaleImageWithFactor:(CGFloat)scalingFactor expectedSize:(CGSize)excpectedSize {
FBImageProcessor *scaler = [[FBImageProcessor alloc] init];
id expScaled = [self expectationWithDescription:@"Receive scaled image"];
[scaler submitImageData:self.originalImage
scalingFactor:scalingFactor
completionHandler:^(NSData *scaled) {
UIImage *scaledImage = [UIImage imageWithData:scaled];
CGSize scaledSize = [FBImageProcessorTests scaledSizeFromImage:scaledImage];
XCTAssertEqualWithAccuracy(scaledSize.width, excpectedSize.width, 1.0);
XCTAssertEqualWithAccuracy(scaledSize.height, excpectedSize.height, 1.0);
[expScaled fulfill];
}];
[self waitForExpectations:@[expScaled]
timeout:0.5];
}
+ (CGSize)scaledSizeFromImage:(UIImage *)image {
return CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);
}
+ (CGSize)sizeFromSize:(CGSize)size scalingFactor:(CGFloat)scalingFactor {
return CGSizeMake(round(size.width * scalingFactor), round(size.height * scalingFactor));
}
@end

View File

@@ -0,0 +1,76 @@
/**
* 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 <XCTest/XCTest.h>
extern NSString *const FBShowAlertButtonName;
extern NSString *const FBShowSheetAlertButtonName;
extern NSString *const FBShowAlertForceTouchButtonName;
extern NSString *const FBTouchesCountLabelIdentifier;
extern NSString *const FBTapsCountLabelIdentifier;
/**
XCTestCase helper class used for integration tests
*/
@interface FBIntegrationTestCase : XCTestCase
@property (nonatomic, strong, readonly) XCUIApplication *testedApplication;
@property (nonatomic, strong, readonly) XCUIApplication *springboard;
/**
Launches application and resets side effects of testing like orientation etc.
*/
- (void)launchApplication;
/**
Navigates integration app to attributes page
*/
- (void)goToAttributesPage;
/**
Navigates integration app to alerts page
*/
- (void)goToAlertsPage;
/**
Navigates integration app to touch page
*/
- (void)goToTouchPage;
/**
Navigates to SpringBoard first page
*/
- (void)goToSpringBoardFirstPage;
/**
Navigates to SpringBoard path with Extras folder
*/
- (void)goToSpringBoardExtras;
/**
Navigates to SpringBoard's dashboard
*/
- (void)goToSpringBoardDashboard;
/**
Navigates integration app to scrolling page
@param showCells whether should navigate to view with cell or plain scrollview
*/
- (void)goToScrollPageWithCells:(BOOL)showCells;
/**
Verifies no alerts are present on the page.
If an alert exists then it is going to be dismissed.
*/
- (void)clearAlert;
/**
Resets device orientation to portrait mode
*/
- (void)resetOrientation;
@end

View File

@@ -0,0 +1,140 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBAlert.h"
#import "FBTestMacros.h"
#import "FBIntegrationTestCase.h"
#import "FBConfiguration.h"
#import "FBMacros.h"
#import "FBRunLoopSpinner.h"
#import "XCUIApplication+FBHelpers.h"
#import "XCUIDevice+FBRotation.h"
#import "XCUIElement.h"
#import "XCUIElement+FBIsVisible.h"
#import "XCUIElement+FBUtilities.h"
#import "XCTestConfiguration.h"
NSString *const FBShowAlertButtonName = @"Create App Alert";
NSString *const FBShowSheetAlertButtonName = @"Create Sheet Alert";
NSString *const FBShowAlertForceTouchButtonName = @"Create Alert (Force Touch)";
NSString *const FBTouchesCountLabelIdentifier = @"numberOfTouchesLabel";
NSString *const FBTapsCountLabelIdentifier = @"numberOfTapsLabel";
@interface FBIntegrationTestCase ()
@property (nonatomic, strong) XCUIApplication *testedApplication;
@property (nonatomic, strong) XCUIApplication *springboard;
@end
@implementation FBIntegrationTestCase
- (void)setUp
{
// Enable it to get extended XCTest logs printed into the console
// [FBConfiguration enableXcTestDebugLogs];
[super setUp];
[FBConfiguration disableRemoteQueryEvaluation];
[FBConfiguration disableAttributeKeyPathAnalysis];
[FBConfiguration configureDefaultKeyboardPreferences];
[FBConfiguration disableApplicationUIInterruptionsHandling];
[FBConfiguration disableScreenshots];
self.continueAfterFailure = NO;
self.springboard = XCUIApplication.fb_systemApplication;
self.testedApplication = [XCUIApplication new];
}
- (void)resetOrientation
{
if ([XCUIDevice sharedDevice].orientation != UIDeviceOrientationPortrait) {
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationPortrait];
}
}
- (void)launchApplication
{
[self.testedApplication launch];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"Alerts"].fb_isVisible);
}
- (void)goToAttributesPage
{
[self.testedApplication.buttons[@"Attributes"] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"Button"].fb_isVisible);
}
- (void)goToAlertsPage
{
[self.testedApplication.buttons[@"Alerts"] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[FBShowAlertButtonName].fb_isVisible);
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[FBShowSheetAlertButtonName].fb_isVisible);
}
- (void)goToTouchPage
{
[self.testedApplication.buttons[@"Touch"] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[FBTouchesCountLabelIdentifier].fb_isVisible);
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[FBTapsCountLabelIdentifier].fb_isVisible);
}
- (void)goToSpringBoardFirstPage
{
[[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(XCUIApplication.fb_systemApplication.icons[@"Safari"].exists);
[[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(XCUIApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.fb_isVisible);
}
- (void)goToSpringBoardExtras
{
[self goToSpringBoardFirstPage];
[self.springboard swipeLeft];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.springboard.icons[@"Extras"].fb_isVisible);
}
- (void)goToSpringBoardDashboard
{
[self goToSpringBoardFirstPage];
[self.springboard swipeRight];
[self.testedApplication fb_waitUntilStable];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
@"%K IN %@",
FBStringify(XCUIElement, identifier),
@[@"SBSearchEtceteraIsolatedView", @"SpotlightSearchField"]
];
FBAssertWaitTillBecomesTrue([[self.springboard descendantsMatchingType:XCUIElementTypeAny] elementMatchingPredicate:predicate].fb_isVisible);
FBAssertWaitTillBecomesTrue(!self.springboard.icons[@"Calendar"].fb_isVisible);
}
- (void)goToScrollPageWithCells:(BOOL)showCells
{
[self.testedApplication.buttons[@"Scrolling"] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"TableView"].fb_isVisible);
[self.testedApplication.buttons[showCells ? @"TableView": @"ScrollView"] tap];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[@"3"].fb_isVisible);
}
- (void)clearAlert
{
[self.testedApplication fb_waitUntilStable];
[[FBAlert alertWithApplication:self.testedApplication] dismissWithError:nil];
[self.testedApplication fb_waitUntilStable];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
}
@end

View File

@@ -0,0 +1,61 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBMacros.h"
#import "FBIntegrationTestCase.h"
#import "FBKeyboard.h"
#import "FBRunLoopSpinner.h"
#import "XCUIApplication+FBHelpers.h"
@interface FBKeyboardTests : FBIntegrationTestCase
@end
@implementation FBKeyboardTests
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAttributesPage];
}
- (void)testKeyboardDismissal
{
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
// A workaround until find out to clear tutorial on iOS 15
XCUIElement *textField = self.testedApplication.staticTexts[@"Continue"];
if (textField.hittable) {
[textField tap];
}
}
NSError *error;
XCTAssertTrue([FBKeyboard waitUntilVisibleForApplication:self.testedApplication timeout:1 error:&error]);
XCTAssertNil(error);
if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
XCTAssertTrue([self.testedApplication fb_dismissKeyboardWithKeyNames:nil error:&error]);
XCTAssertNil(error);
} else {
XCTAssertFalse([self.testedApplication fb_dismissKeyboardWithKeyNames:@[@"return"] error:&error]);
XCTAssertNotNil(error);
}
}
- (void)testKeyboardPresenceVerification
{
NSError *error;
XCTAssertFalse([FBKeyboard waitUntilVisibleForApplication:self.testedApplication timeout:1 error:&error]);
XCTAssertNotNil(error);
}
@end

View File

@@ -0,0 +1,91 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement+FBTyping.h"
#import "FBPasteboard.h"
#import "FBTestMacros.h"
#import "FBXCodeCompatibility.h"
@interface FBPasteboardTests : FBIntegrationTestCase
@end
@implementation FBPasteboardTests
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAttributesPage];
}
- (void)testSetPasteboard
{
NSString *text = @"Happy pasting";
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
NSError *error;
BOOL result = [FBPasteboard setData:(NSData *)[text dataUsingEncoding:NSUTF8StringEncoding]
forType:@"plaintext"
error:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
[textField tap];
XCTAssertTrue([textField fb_clearTextWithError:&error]);
[textField pressForDuration:2.0];
XCUIElementQuery *pastItemsQuery = [[self.testedApplication descendantsMatchingType:XCUIElementTypeAny] matchingIdentifier:@"Paste"];
if (![pastItemsQuery.firstMatch waitForExistenceWithTimeout:2.0]) {
XCTFail(@"No matched element named 'Paste'");
}
XCUIElement *pasteItem = pastItemsQuery.firstMatch;
XCTAssertNotNil(pasteItem);
[pasteItem tap];
FBAssertWaitTillBecomesTrue([textField.value isEqualToString:text]);
}
- (void)testGetPasteboard
{
NSString *text = @"Happy copying";
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
NSError *error;
XCTAssertTrue([textField fb_typeText:text shouldClear:NO error:&error]);
[textField pressForDuration:2.0];
XCUIElement *selectAllItem = [[self.testedApplication descendantsMatchingType:XCUIElementTypeAny]
matchingIdentifier:@"Select All"].firstMatch;
XCTAssertTrue([selectAllItem waitForExistenceWithTimeout:5]);
[selectAllItem tap];
if (SYSTEM_VERSION_LESS_THAN(@"16.0")) {
[textField pressForDuration:2.0];
}
XCUIElement *copyItem = [[self.testedApplication descendantsMatchingType:XCUIElementTypeAny]
matchingIdentifier:@"Copy"].firstMatch;
XCTAssertTrue([copyItem waitForExistenceWithTimeout:5]);
[copyItem tap];
FBWaitExact(1.0);
NSData *result = [FBPasteboard dataForType:@"plaintext" error:&error];
XCTAssertNil(error);
XCTAssertEqualObjects(textField.value, [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]);
}
- (void)testUrlCopyPaste
{
NSString *urlString = @"http://appium.io?some=value";
NSError *error;
XCTAssertTrue([FBPasteboard setData:(NSData *)[urlString dataUsingEncoding:NSUTF8StringEncoding]
forType:@"url"
error:&error]);
XCTAssertNil(error);
NSData *result = [FBPasteboard dataForType:@"url" error:&error];
XCTAssertNil(error);
XCTAssertEqualObjects(urlString, [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]);
}
@end

View File

@@ -0,0 +1,55 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement+FBPickerWheel.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "FBXCodeCompatibility.h"
@interface FBPickerWheelSelectTests : FBIntegrationTestCase
@end
@implementation FBPickerWheelSelectTests
static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAttributesPage];
});
}
- (void)testSelectNextPickerValue
{
XCUIElement *element = self.testedApplication.pickerWheels.allElementsBoundByIndex.firstObject;
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypePickerWheel");
NSError *error;
NSString *previousValue = element.wdValue;
XCTAssertTrue([element fb_selectNextOptionWithOffset:DEFAULT_OFFSET error:&error]);
XCTAssertNotEqualObjects(previousValue, element.wdValue);
}
- (void)testSelectPreviousPickerValue
{
XCUIElement *element = [self.testedApplication.pickerWheels elementBoundByIndex:1];
XCTAssertTrue(element.exists);
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypePickerWheel");
NSError *error;
NSString *previousValue = element.wdValue;
XCTAssertTrue([element fb_selectPreviousOptionWithOffset:DEFAULT_OFFSET error:&error]);
XCTAssertNotEqualObjects(previousValue, element.wdValue);
}
@end

View File

@@ -0,0 +1,73 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "FBMacros.h"
#import "FBSession.h"
#import "FBXCodeCompatibility.h"
#import "XCUIElement+FBTyping.h"
#import "FBAlert.h"
#import "XCUIApplication+FBAlert.h"
@interface FBSafariAlertIntegrationTests : FBIntegrationTestCase
@property (nonatomic) FBSession *session;
@property (nonatomic) XCUIApplication *safariApp;
@end
@implementation FBSafariAlertIntegrationTests
- (void)setUp
{
[super setUp];
self.session = [FBSession initWithApplication:XCUIApplication.fb_activeApplication];
[self.session launchApplicationWithBundleId:FB_SAFARI_BUNDLE_ID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
self.safariApp = self.session.activeApplication;
}
- (void)tearDown
{
[self.session terminateApplicationWithBundleId:FB_SAFARI_BUNDLE_ID];
}
- (void)disabled_testCanHandleSafariInputPrompt
{
XCUIElement *urlInput = [[self.safariApp
descendantsMatchingType:XCUIElementTypeTextField]
matchingPredicate:[
NSPredicate predicateWithFormat:@"label == 'Address' or label == 'URL'"
]].firstMatch;
if (!urlInput.exists) {
[[[self.safariApp descendantsMatchingType:XCUIElementTypeButton] matchingPredicate:[
NSPredicate predicateWithFormat:@"label == 'Address' or label == 'URL'"]].firstMatch tap];
}
XCTAssertTrue([urlInput fb_typeText:@"https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert"
shouldClear:YES
error:nil]);
[[[self.safariApp descendantsMatchingType:XCUIElementTypeButton] matchingIdentifier:@"Go"].firstMatch tap];
XCUIElement *clickMeButton = [[self.safariApp descendantsMatchingType:XCUIElementTypeButton]
matchingPredicate:[NSPredicate predicateWithFormat:@"label == 'Try it'"]].firstMatch;
XCTAssertTrue([clickMeButton waitForExistenceWithTimeout:15.0]);
[clickMeButton tap];
FBAlert *alert = [FBAlert alertWithApplication:self.safariApp];
FBAssertWaitTillBecomesTrue([alert.text isEqualToString:@"I am an alert box!"]);
NSArray *buttonLabels = alert.buttonLabels;
XCTAssertEqualObjects(buttonLabels.firstObject, @"Close");
XCTAssertNotNil([self.safariApp fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Close']"
shouldReturnAfterFirstMatch:YES].firstObject);
XCTAssertTrue([alert acceptWithError:nil]);
}
@end

View File

@@ -0,0 +1,31 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBScreen.h"
@interface FBScreenTests : FBIntegrationTestCase
@end
@implementation FBScreenTests
- (void)setUp
{
[super setUp];
[self launchApplication];
}
- (void)testScreenScale
{
XCTAssertTrue([FBScreen scale] >= 2);
}
@end

View File

@@ -0,0 +1,126 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "FBMacros.h"
#import "XCUIElement+FBIsVisible.h"
#import "XCUIElement+FBScrolling.h"
#import "XCUIElement+FBClassChain.h"
#import "FBXCodeCompatibility.h"
@interface FBScrollingTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *scrollView;
@end
@implementation FBScrollingTests
+ (BOOL)shouldShowCells
{
return YES;
}
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToScrollPageWithCells:YES];
self.scrollView = [[self.testedApplication.query descendantsMatchingType:XCUIElementTypeAny] matchingIdentifier:@"scrollView"].element;
}
- (void)testCellVisibility
{
FBAssertVisibleCell(@"0");
FBAssertVisibleCell(@"10");
XCUIElement *cell10 = FBCellElementWithLabel(@"10");
XCTAssertEqual([cell10 isWDHittable], [cell10 isHittable]);
FBAssertInvisibleCell(@"30");
FBAssertInvisibleCell(@"50");
XCUIElement *cell50 = FBCellElementWithLabel(@"50");
XCTAssertEqual([cell50 isWDHittable], [cell50 isHittable]);
}
- (void)testSimpleScroll
{
if (SYSTEM_VERSION_LESS_THAN(@"16.0")) {
// This test is unstable in CI env
return;
}
FBAssertVisibleCell(@"0");
FBAssertVisibleCell(@"10");
[self.scrollView fb_scrollDownByNormalizedDistance:1.0];
FBAssertInvisibleCell(@"0");
FBAssertInvisibleCell(@"10");
XCTAssertTrue(self.testedApplication.staticTexts.count > 0);
[self.scrollView fb_scrollUpByNormalizedDistance:1.0];
FBAssertVisibleCell(@"0");
FBAssertVisibleCell(@"10");
}
- (void)testScrollToVisible
{
NSString *cellName = @"30";
FBAssertInvisibleCell(cellName);
NSError *error;
XCTAssertTrue([FBCellElementWithLabel(cellName) fb_scrollToVisibleWithError:&error]);
XCTAssertNil(error);
FBAssertVisibleCell(cellName);
}
- (void)testFarScrollToVisible
{
NSString *cellName = @"80";
NSError *error;
FBAssertInvisibleCell(cellName);
XCTAssertTrue([FBCellElementWithLabel(cellName) fb_scrollToVisibleWithError:&error]);
XCTAssertNil(error);
FBAssertVisibleCell(cellName);
}
- (void)testNativeFarScrollToVisible
{
if (SYSTEM_VERSION_LESS_THAN(@"16.0")) {
// This test is unstable in CI env
return;
}
NSString *cellName = @"80";
NSError *error;
FBAssertInvisibleCell(cellName);
XCTAssertTrue([FBCellElementWithLabel(cellName) fb_nativeScrollToVisibleWithError:&error]);
XCTAssertNil(error);
FBAssertVisibleCell(cellName);
}
- (void)testAttributeWithNullScrollToVisible
{
NSError *error;
NSArray<XCUIElement *> *queryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"**/XCUIElementTypeTable/XCUIElementTypeCell[60]" shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(queryMatches.count, 1);
XCUIElement *element = queryMatches.firstObject;
XCTAssertFalse(element.fb_isVisible);
[element fb_scrollToVisibleWithError:&error];
XCTAssertNil(error);
XCTAssertTrue(element.fb_isVisible);
if (SYSTEM_VERSION_LESS_THAN(@"16.0")) {
// This test is unstable in CI env
return;
}
[element tap];
XCTAssertTrue(element.wdSelected);
}
@end

View File

@@ -0,0 +1,133 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBExceptions.h"
#import "FBMacros.h"
#import "FBSession.h"
#import "FBXCodeCompatibility.h"
#import "FBTestMacros.h"
#import "FBUnattachedAppLauncher.h"
#import "XCUIApplication+FBHelpers.h"
#import "XCUIApplication.h"
@interface FBSession (Tests)
@end
@interface FBSessionIntegrationTests : FBIntegrationTestCase
@property (nonatomic) FBSession *session;
@end
static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.Preferences";
@implementation FBSessionIntegrationTests
- (void)setUp
{
[super setUp];
[self launchApplication];
XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID];
self.session = [FBSession initWithApplication:app];
}
- (void)tearDown
{
[self.session kill];
[super tearDown];
}
- (void)testSettingsAppCanBeOpenedInScopeOfTheCurrentSession
{
XCUIApplication *testedApp = XCUIApplication.fb_activeApplication;
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
XCTAssertEqual([self.session applicationStateWithBundleId:SETTINGS_BUNDLE_ID], 4);
[self.session activateApplicationWithBundleId:testedApp.bundleID];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString: testedApp.bundleID]);
XCTAssertEqual([self.session applicationStateWithBundleId:testedApp.bundleID], 4);
}
- (void)testSettingsAppCanBeReopenedInScopeOfTheCurrentSession
{
XCUIApplication *systemApp = self.springboard;
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
XCTAssertTrue([self.session terminateApplicationWithBundleId:SETTINGS_BUNDLE_ID]);
FBAssertWaitTillBecomesTrue([systemApp.bundleID isEqualToString:self.session.activeApplication.bundleID]);
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
}
- (void)testMainAppCanBeReactivatedInScopeOfTheCurrentSession
{
XCUIApplication *testedApp = XCUIApplication.fb_activeApplication;
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
[self.session activateApplicationWithBundleId:testedApp.bundleID];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
}
- (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession
{
XCUIApplication *systemApp = self.springboard;
XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID];
[self.session terminateApplicationWithBundleId:testedApp.bundleID];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:systemApp.bundleID]);
[self.session launchApplicationWithBundleId:testedApp.bundleID
shouldWaitForQuiescence:nil
arguments:nil
environment:nil];
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
}
- (void)testLaunchUnattachedApp
{
[FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID];
[self.session kill];
XCTAssertEqualObjects(SETTINGS_BUNDLE_ID, XCUIApplication.fb_activeApplication.bundleID);
}
- (void)testAppWithInvalidBundleIDCannotBeStarted
{
XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"yolo"];
@try {
[testedApp launch];
XCTFail(@"An exception is expected to be thrown");
} @catch (NSException *exception) {
XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
}
}
- (void)testAppWithInvalidBundleIDCannotBeActivated
{
XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"yolo"];
@try {
[testedApp activate];
XCTFail(@"An exception is expected to be thrown");
} @catch (NSException *exception) {
XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
}
}
@end

View File

@@ -0,0 +1,103 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBElementCache.h"
#import "FBTestMacros.h"
#import "XCUIDevice+FBRotation.h"
#import "XCUIElement+FBIsVisible.h"
@interface FBTapTest : FBIntegrationTestCase
@end
// It is recommnded to verify these tests with different iOS versions
@implementation FBTapTest
- (void)verifyTapWithOrientation:(UIDeviceOrientation)orientation
{
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
[self.testedApplication.buttons[FBShowAlertButtonName] tap];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0);
}
- (void)setUp
{
// Launch the app everytime to ensure the orientation for each test.
[super setUp];
[self launchApplication];
[self goToAlertsPage];
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
[self resetOrientation];
[super tearDown];
}
- (void)testTap
{
[self verifyTapWithOrientation:UIDeviceOrientationPortrait];
}
- (void)testTapInLandscapeLeft
{
[self verifyTapWithOrientation:UIDeviceOrientationLandscapeLeft];
}
- (void)testTapInLandscapeRight
{
[self verifyTapWithOrientation:UIDeviceOrientationLandscapeRight];
}
- (void)testTapInPortraitUpsideDown
{
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
}
[self verifyTapWithOrientation:UIDeviceOrientationPortraitUpsideDown];
}
- (void)verifyTapByCoordinatesWithOrientation:(UIDeviceOrientation)orientation
{
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
XCUIElement *dstButton = self.testedApplication.buttons[FBShowAlertButtonName];
[[dstButton coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] tap];
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0);
}
- (void)testTapCoordinates
{
[self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationPortrait];
}
- (void)testTapCoordinatesInLandscapeLeft
{
[self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationLandscapeLeft];
}
- (void)testTapCoordinatesInLandscapeRight
{
[self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationLandscapeRight];
}
- (void)testTapCoordinatesInPortraitUpsideDown
{
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
}
[self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationPortraitUpsideDown];
}
@end

View File

@@ -0,0 +1,33 @@
/**
* 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 <WebDriverAgentLib/FBRunLoopSpinner.h>
/**
Macro used to wait till certain condition is true.
If condition will not become true within default timeout (1m) it will fail running test
*/
#define FBAssertWaitTillBecomesTrue(condition) \
({ \
NSError *__error; \
XCTAssertTrue([[[FBRunLoopSpinner new] \
interval:1.0] \
spinUntilTrue:^BOOL{ \
return (condition); \
}]); \
XCTAssertNil(__error); \
})
#define FBWaitExact(timeoutSeconds) \
({ \
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:(timeoutSeconds)]]; \
})
#define FBCellElementWithLabel(label) ([self.testedApplication descendantsMatchingType:XCUIElementTypeAny][label])
#define FBAssertVisibleCell(label) FBAssertWaitTillBecomesTrue(FBCellElementWithLabel(label).fb_isVisible)
#define FBAssertInvisibleCell(label) FBAssertWaitTillBecomesTrue(!FBCellElementWithLabel(label).fb_isVisible)

View File

@@ -0,0 +1,68 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement.h"
#import "XCUIElement+FBTyping.h"
@interface FBTypingTest : FBIntegrationTestCase
@end
@implementation FBTypingTest
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAttributesPage];
}
- (void)testTextTyping
{
NSString *text = @"Happy typing";
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
NSError *error;
XCTAssertTrue([textField fb_typeText:text shouldClear:NO error:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(textField.value, text);
}
- (void)testTextTypingOnFocusedElement
{
NSString *text = @"Happy typing";
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
XCTAssertTrue(textField.hasKeyboardFocus);
NSError *error;
XCTAssertTrue([textField fb_typeText:text shouldClear:NO error:&error]);
XCTAssertNil(error);
XCTAssertTrue([textField fb_typeText:text shouldClear:NO error:&error]);
XCTAssertNil(error);
NSString *expectedText = [NSString stringWithFormat:@"%@%@", text, text];
XCTAssertEqualObjects(textField.value, expectedText);
}
- (void)testTextClearing
{
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
[textField typeText:@"Happy typing"];
XCTAssertTrue([textField.value length] > 0);
NSError *error;
XCTAssertTrue([textField fb_clearTextWithError:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(textField.value, @"");
XCTAssertTrue([textField fb_typeText:@"Happy typing" shouldClear:YES error:&error]);
XCTAssertTrue([textField fb_typeText:@"Happy typing 2" shouldClear:YES error:&error]);
XCTAssertEqualObjects(textField.value, @"Happy typing 2");
XCTAssertNil(error);
}
@end

View File

@@ -0,0 +1,64 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBConfiguration.h"
#import "FBMacros.h"
#import "FBScreenRecordingPromise.h"
#import "FBScreenRecordingRequest.h"
#import "FBScreenRecordingContainer.h"
#import "FBXCTestDaemonsProxy.h"
@interface FBVideoRecordingTests : FBIntegrationTestCase
@end
@implementation FBVideoRecordingTests
- (void)setUp
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableDiagnosticScreenRecordings"];
[super setUp];
}
- (void)testStartingAndStoppingVideoRecording
{
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
// Video recording is only available since iOS 17
if (SYSTEM_VERSION_LESS_THAN(@"17.0")) {
return;
}
FBScreenRecordingRequest *recordingRequest = [[FBScreenRecordingRequest alloc] initWithFps:24
codec:0];
NSError *error;
FBScreenRecordingPromise *promise = [FBXCTestDaemonsProxy startScreenRecordingWithRequest:recordingRequest
error:&error];
XCTAssertNotNil(promise);
XCTAssertNotNil(promise.identifier);
XCTAssertNil(error);
[FBScreenRecordingContainer.sharedInstance storeScreenRecordingPromise:promise
fps:24
codec:0];
XCTAssertEqual(FBScreenRecordingContainer.sharedInstance.screenRecordingPromise, promise);
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.]];
BOOL isSuccessfull = [FBXCTestDaemonsProxy stopScreenRecordingWithUUID:promise.identifier error:&error];
XCTAssertTrue(isSuccessfull);
XCTAssertNil(error);
[FBScreenRecordingContainer.sharedInstance reset];
XCTAssertNil(FBScreenRecordingContainer.sharedInstance.screenRecordingPromise);
}
@end

View File

@@ -0,0 +1,124 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement.h"
#import "XCUIApplication+FBTouchAction.h"
#import "FBTestMacros.h"
#import "XCUIDevice+FBRotation.h"
#import "FBRunLoopSpinner.h"
@interface FBW3CMultiTouchActionsIntegrationTests : FBIntegrationTestCase
@end
@implementation FBW3CMultiTouchActionsIntegrationTests
- (void)verifyGesture:(NSArray<NSDictionary<NSString *, id> *> *)gesture orientation:(UIDeviceOrientation)orientation
{
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:gesture elementCache:nil error:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0);
}
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAlertsPage];
});
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
[self resetOrientation];
[super tearDown];
}
- (void)testErroneousGestures
{
NSArray<NSArray<NSDictionary<NSString *, id> *> *> *invalidGestures =
@[
// One of the chains has duplicated id
@[
@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
];
for (NSArray<NSDictionary<NSString *, id> *> *invalidGesture in invalidGestures) {
NSError *error;
XCTAssertFalse([self.testedApplication fb_performW3CActions:invalidGesture elementCache:nil error:&error]);
XCTAssertNotNil(error);
}
}
- (void)testSymmetricTwoFingersTap
{
XCUIElement *element = self.testedApplication.buttons[FBShowAlertButtonName];
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[
@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": element, @"x": @0, @"y": @0},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
@{
@"type": @"pointer",
@"id": @"finger2",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": element, @"x": @0, @"y": @0},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
}
@end

View File

@@ -0,0 +1,491 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement.h"
#import "XCUIDevice.h"
#import "XCUIApplication+FBTouchAction.h"
#import "FBTestMacros.h"
#import "XCUIDevice+FBRotation.h"
#import "FBRunLoopSpinner.h"
#import "FBXCodeCompatibility.h"
@interface FBW3CTouchActionsIntegrationTestsPart1 : FBIntegrationTestCase
@end
@interface FBW3CTouchActionsIntegrationTestsPart2 : FBIntegrationTestCase
@property (nonatomic) XCUIElement *pickerWheel;
@end
@implementation FBW3CTouchActionsIntegrationTestsPart1
- (void)verifyGesture:(NSArray<NSDictionary<NSString *, id> *> *)gesture orientation:(UIDeviceOrientation)orientation
{
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:gesture elementCache:nil error:&error]);
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0);
}
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAlertsPage];
});
[self clearAlert];
}
- (void)tearDown
{
[self clearAlert];
[self resetOrientation];
[super tearDown];
}
- (void)testErroneousGestures
{
NSArray<NSArray<NSDictionary<NSString *, id> *> *> *invalidGestures =
@[
// Empty chain
@[],
// Chain element without 'actions' key
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
},
],
// Chain element without type
@[@{
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element without id
@[@{
@"type": @"pointer",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element with empty id
@[@{
@"type": @"pointer",
@"id": @"",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element with unsupported type
@[@{
@"type": @"key",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element with unsupported pointerType (default)
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element with unsupported pointerType (non-default)
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"pen"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @100, @"y": @100},
],
},
],
// Chain element without action item type
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element with singe up action
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerUp"},
],
},
],
// Chain element containing action item without y coordinate
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element containing action item with an unknown type
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMoved", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element where action items start with an incorrect item
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element where pointerMove action item does not contain coordinates
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element where pointerMove action item cannot use coordinates of the previous item
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": @"pointer"},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element where action items contains negative duration
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @-100},
@{@"type": @"pointerUp"},
],
},
],
// Chain element where action items start with an incorrect one, because the correct one is canceled
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
@{@"type": @"pointerCancel"},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @-100},
@{@"type": @"pointerUp"},
],
},
],
];
for (NSArray<NSDictionary<NSString *, id> *> *invalidGesture in invalidGestures) {
NSError *error;
XCTAssertFalse([self.testedApplication fb_performW3CActions:invalidGesture elementCache:nil error:&error]);
XCTAssertNotNil(error);
}
}
- (void)testNothingDoesWithoutError
{
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[],
},
];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:gesture elementCache:nil error:&error]);
XCTAssertNil(error);
}
- (void)testTap
{
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": self.testedApplication.buttons[FBShowAlertButtonName], @"x": @0, @"y": @0},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
}
- (void)testDoubleTap
{
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": self.testedApplication.buttons[FBShowAlertButtonName]},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @50},
@{@"type": @"pointerUp"},
@{@"type": @"pause", @"duration": @200},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @50},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
}
- (void)testLongPressWithCombinedPause
{
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": self.testedApplication.buttons[FBShowAlertButtonName], @"x": @5, @"y": @5},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @200},
@{@"type": @"pause", @"duration": @200},
@{@"type": @"pause", @"duration": @100},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeRight];
}
- (void)testLongPress
{
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
XCTSkip(@"Failed on Azure Pipeline. Local run succeeded.");
}
UIDeviceOrientation orientation = UIDeviceOrientationLandscapeLeft;
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation];
CGRect elementFrame = self.testedApplication.buttons[FBShowAlertButtonName].frame;
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @(elementFrame.origin.x + 1), @"y": @(elementFrame.origin.y + 1)},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @500},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:orientation];
}
- (void)testForceTap
{
if (![XCUIDevice.sharedDevice supportsPressureInteraction]) {
return;
}
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": self.testedApplication.buttons[FBShowAlertButtonName]},
@{@"type": @"pointerDown"},
@{@"type": @"pause", @"duration": @500},
@{@"type": @"pointerDown", @"pressure": @1.0, @"width":@10, @"height":@10},
@{@"type": @"pause", @"duration": @50},
@{@"type": @"pointerDown", @"pressure": @1.0, @"width":@10, @"height":@10},
@{@"type": @"pause", @"duration": @50},
@{@"type": @"pointerUp"},
],
},
];
[self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
}
@end
@implementation FBW3CTouchActionsIntegrationTestsPart2
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAttributesPage];
});
self.pickerWheel = self.testedApplication.pickerWheels.allElementsBoundByIndex.firstObject;
}
- (void)tearDown
{
[self resetOrientation];
[super tearDown];
}
- (void)verifyPickerWheelPositionChangeWithGesture:(NSArray<NSDictionary<NSString *, id> *> *)gesture
{
NSString *previousValue = self.pickerWheel.value;
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:gesture elementCache:nil error:&error]);
XCTAssertNil(error);
XCTAssertTrue([[[[FBRunLoopSpinner new]
timeout:2.0]
timeoutErrorMessage:@"Picker wheel value has not been changed after 2 seconds timeout"]
spinUntilTrue:^BOOL{
return ![[self.pickerWheel fb_standardSnapshot].value isEqualToString:previousValue];
}
error:&error]);
XCTAssertNil(error);
}
- (void)testSwipePickerWheelWithElementCoordinates
{
CGRect pickerFrame = self.pickerWheel.frame;
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"origin": self.pickerWheel, @"x": @0, @"y":@0},
@{@"type": @"pointerDown"},
@{@"type": @"pointerMove", @"duration": @100,@"width":@10, @"height":@10, @"pressure":@0.5, @"origin": self.pickerWheel, @"x": @0, @"y": @(pickerFrame.size.height / 2)},
@{@"type": @"pointerUp"},
],
},
];
[self verifyPickerWheelPositionChangeWithGesture:gesture];
}
- (void)testSwipePickerWheelWithRelativeCoordinates
{
CGRect pickerFrame = self.pickerWheel.frame;
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @100, @"origin": self.pickerWheel, @"x": @0, @"y": @0},
@{@"type": @"pointerDown"},
@{@"type": @"pointerMove", @"duration": @100, @"width":@10, @"height":@10, @"pressure":@0.5, @"origin": @"pointer", @"x": @0, @"y": @(-pickerFrame.size.height / 2)},
@{@"type": @"pointerUp"},
],
},
];
[self verifyPickerWheelPositionChangeWithGesture:gesture];
}
- (void)testSwipePickerWheelWithAbsoluteCoordinates
{
CGRect pickerFrame = self.pickerWheel.frame;
NSArray<NSDictionary<NSString *, id> *> *gesture =
@[@{
@"type": @"pointer",
@"id": @"finger1",
@"parameters": @{@"pointerType": @"touch"},
@"actions": @[
@{@"type": @"pointerMove", @"duration": @0, @"x": @(pickerFrame.origin.x + pickerFrame.size.width / 2), @"y": @(pickerFrame.origin.y + pickerFrame.size.height / 2)},
@{@"type": @"pointerDown"},
@{@"type": @"pointerMove", @"duration": @100,@"width":@10, @"height":@10, @"pressure":@0.5, @"origin": @"pointer", @"x": @0, @"y": @(pickerFrame.size.height / 2)},
@{@"type": @"pointerUp"},
],
},
];
[self verifyPickerWheelPositionChangeWithGesture:gesture];
}
@end

View File

@@ -0,0 +1,184 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIElement.h"
#import "XCUIElement+FBTyping.h"
#import "XCUIApplication+FBTouchAction.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "FBRuntimeUtils.h"
#import "FBXCodeCompatibility.h"
@interface FBW3CTypeActionsTests : FBIntegrationTestCase
@end
@implementation FBW3CTypeActionsTests
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAttributesPage];
}
- (void)testErroneousGestures
{
if (![XCPointerEvent.class fb_areKeyEventsSupported]) {
return;
}
NSArray<NSArray<NSDictionary<NSString *, id> *> *> *invalidGestures =
@[
// missing balance 1
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"keyDown", @"value": @"h"},
@{@"type": @"keyUp", @"value": @"k"},
],
},
],
// missing balance 2
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"keyDown", @"value": @"h"},
],
},
],
// missing balance 3
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"keyUp", @"value": @"h"},
],
},
],
// missing key value
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"keyUp"},
],
},
],
// wrong key value
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"keyUp", @"value": @500},
],
},
],
// missing duration value
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"pause"},
],
},
],
// wrong duration value
@[@{
@"type": @"key",
@"id": @"keyboard",
@"actions": @[
@{@"type": @"duration", @"duration": @"bla"},
],
},
],
];
for (NSArray<NSDictionary<NSString *, id> *> *invalidGesture in invalidGestures) {
NSError *error;
XCTAssertFalse([self.testedApplication fb_performW3CActions:invalidGesture elementCache:nil error:&error]);
XCTAssertNotNil(error);
}
}
- (void)testTextTyping
{
if (![XCPointerEvent.class fb_areKeyEventsSupported]) {
return;
}
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
NSArray<NSDictionary<NSString *, id> *> *typeAction =
@[
@{
@"type": @"key",
@"id": @"keyboard2",
@"actions": @[
@{@"type": @"pause", @"duration": @500},
@{@"type": @"keyDown", @"value": @"🏀"},
@{@"type": @"keyUp", @"value": @"🏀"},
@{@"type": @"keyDown", @"value": @"N"},
@{@"type": @"keyUp", @"value": @"N"},
@{@"type": @"keyDown", @"value": @"B"},
@{@"type": @"keyUp", @"value": @"B"},
@{@"type": @"keyDown", @"value": @"A"},
@{@"type": @"keyUp", @"value": @"A"},
@{@"type": @"keyDown", @"value": @"a"},
@{@"type": @"keyUp", @"value": @"a"},
@{@"type": @"keyDown", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
@{@"type": @"keyUp", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
@{@"type": @"pause", @"duration": @500},
],
},
];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction
elementCache:nil
error:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(textField.wdValue, @"🏀NBA");
}
- (void)testTextTypingWithEmptyActions
{
if (![XCPointerEvent.class fb_areKeyEventsSupported]) {
return;
}
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
NSArray<NSDictionary<NSString *, id> *> *typeAction =
@[
@{
@"type": @"pointer",
@"id": @"touch",
@"actions": @[],
},
];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction
elementCache:nil
error:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(textField.value, @"");
}
@end

View File

@@ -0,0 +1,157 @@
/**
* 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 <XCTest/XCTest.h>
#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<FBXCElementSnapshot>)destinationSnapshot
{
XCUIElement *matchingElement = self.testedView.buttons.allElementsBoundByIndex.firstObject;
id<FBXCElementSnapshot> 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<FBXCElementSnapshot> 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:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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<FBXCElementSnapshot> snapshot = self.destinationSnapshot;
FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
options:nil];
XCTAssertNotNil(xmlStr);
NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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<FBXCElementSnapshot> 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:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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<FBXCElementSnapshot> 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:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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<id<FBXCElementSnapshot>> *matchingSnapshots = [FBXPath matchesWithRootElement:self.testedApplication forQuery:@"//XCUIElementTypeButton"];
XCTAssertEqual([matchingSnapshots count], 5);
for (id<FBXCElementSnapshot> 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<id<FBXCElementSnapshot>> *matchingSnapshots = [FBXPath matchesWithRootElement:self.testedApplication forQuery:@".//XCUIElementTypeButton"];
XCTAssertEqual([matchingSnapshots count], 5);
for (id<FBXCElementSnapshot> element in matchingSnapshots) {
XCTAssertTrue([[FBXCElementSnapshotWrapper ensureWrapped:element].wdType isEqualToString:@"XCUIElementTypeButton"]);
}
}
@end

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.facebook.wda.integrationTests</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -0,0 +1,209 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "XCUIElement.h"
#import "XCUIElement+FBIsVisible.h"
#import "XCUIElement+FBUtilities.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "FBXCElementSnapshotWrapper+Helpers.h"
#import "FBXCodeCompatibility.h"
@interface XCElementSnapshotHelperTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *testedView;
@end
@implementation XCElementSnapshotHelperTests
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
});
self.testedView = self.testedApplication.otherElements[@"MainView"];
XCTAssertTrue(self.testedView.exists);
}
- (void)testDescendantsMatchingType
{
NSSet<NSString *> *expectedLabels = [NSSet setWithArray:@[
@"Alerts",
@"Attributes",
@"Scrolling",
@"Deadlock app",
@"Touch",
]];
NSArray<id<FBXCElementSnapshot>> *matchingSnapshots = [[FBXCElementSnapshotWrapper ensureWrapped:
[self.testedView fb_customSnapshot]]
fb_descendantsMatchingType:XCUIElementTypeButton];
XCTAssertEqual(matchingSnapshots.count, expectedLabels.count);
NSArray<NSString *> *labels = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.label"];
XCTAssertEqualObjects([NSSet setWithArray:labels], expectedLabels);
NSArray<NSNumber *> *types = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.elementType"];
XCTAssertEqual(types.count, 1, @"matchingSnapshots should contain only one type");
XCTAssertEqualObjects(types.lastObject, @(XCUIElementTypeButton), @"matchingSnapshots should contain only one type");
}
- (void)testParentMatchingType
{
XCUIElement *button = self.testedApplication.buttons[@"Alerts"];
FBAssertWaitTillBecomesTrue(button.exists);
id<FBXCElementSnapshot> windowSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped:
[self.testedView fb_customSnapshot]]
fb_parentMatchingType:XCUIElementTypeWindow];
XCTAssertNotNil(windowSnapshot);
XCTAssertEqual(windowSnapshot.elementType, XCUIElementTypeWindow);
}
@end
@interface XCElementSnapshotHelperTests_AttributePage : FBIntegrationTestCase
@end
@implementation XCElementSnapshotHelperTests_AttributePage
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAttributesPage];
});
}
- (void)testParentMatchingOneOfTypes
{
XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"];
FBAssertWaitTillBecomesTrue(todayPickerWheel.exists);
id<FBXCElementSnapshot> datePicker = [[FBXCElementSnapshotWrapper ensureWrapped:
[todayPickerWheel fb_customSnapshot]]
fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeDatePicker), @(XCUIElementTypeWindow)]];
XCTAssertNotNil(datePicker);
XCTAssertEqual(datePicker.elementType, XCUIElementTypeDatePicker);
}
- (void)testParentMatchingOneOfTypesWithXCUIElementTypeAny
{
XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"];
FBAssertWaitTillBecomesTrue(todayPickerWheel.exists);
id<FBXCElementSnapshot> otherSnapshot =[[FBXCElementSnapshotWrapper ensureWrapped:
[todayPickerWheel fb_customSnapshot]]
fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeAny)]];
XCTAssertNotNil(otherSnapshot);
}
- (void)testParentMatchingOneOfTypesWithAbsentParents
{
XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"];
FBAssertWaitTillBecomesTrue(todayPickerWheel.exists);
id<FBXCElementSnapshot> otherSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped:
[todayPickerWheel fb_customSnapshot]]
fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeTab), @(XCUIElementTypeLink)]];
XCTAssertNil(otherSnapshot);
}
@end
@interface XCElementSnapshotHelperTests_ScrollView : FBIntegrationTestCase
@end
@implementation XCElementSnapshotHelperTests_ScrollView
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToScrollPageWithCells:false];
});
}
- (void)testParentMatchingOneOfTypesWithFilter
{
XCUIElement *threeStaticText = self.testedApplication.staticTexts[@"3"];
FBAssertWaitTillBecomesTrue(threeStaticText.exists);
NSArray *acceptedParents = @[
@(XCUIElementTypeScrollView),
@(XCUIElementTypeCollectionView),
@(XCUIElementTypeTable),
];
id<FBXCElementSnapshot> scrollView = [[FBXCElementSnapshotWrapper ensureWrapped:
[threeStaticText fb_customSnapshot]]
fb_parentMatchingOneOfTypes:acceptedParents
filter:^BOOL(id<FBXCElementSnapshot> snapshot) {
return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] isWDVisible];
}];
XCTAssertEqualObjects(scrollView.identifier, @"scrollView");
}
- (void)testParentMatchingOneOfTypesWithFilterRetruningNo
{
XCUIElement *threeStaticText = self.testedApplication.staticTexts[@"3"];
FBAssertWaitTillBecomesTrue(threeStaticText.exists);
NSArray *acceptedParents = @[
@(XCUIElementTypeScrollView),
@(XCUIElementTypeCollectionView),
@(XCUIElementTypeTable),
];
id<FBXCElementSnapshot> scrollView = [[FBXCElementSnapshotWrapper ensureWrapped:
[threeStaticText fb_customSnapshot]]
fb_parentMatchingOneOfTypes:acceptedParents
filter:^BOOL(id<FBXCElementSnapshot> snapshot) {
return NO;
}];
XCTAssertNil(scrollView);
}
- (void)testDescendantsCellSnapshots
{
XCUIElement *scrollView = self.testedApplication.scrollViews[@"scrollView"];
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[@"3"].fb_isVisible);
NSArray *cells = [[FBXCElementSnapshotWrapper ensureWrapped:
[scrollView fb_customSnapshot]]
fb_descendantsCellSnapshots];
XCTAssertGreaterThanOrEqual(cells.count, 10);
id<FBXCElementSnapshot> element = cells.firstObject;
XCTAssertEqualObjects(element.label, @"0");
}
@end
@interface XCElementSnapshotHelperTests_ScrollViewCells : FBIntegrationTestCase
@end
@implementation XCElementSnapshotHelperTests_ScrollViewCells
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToScrollPageWithCells:true];
});
}
- (void)testParentCellSnapshot
{
FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[@"3"].fb_isVisible);
XCUIElement *threeStaticText = self.testedApplication.staticTexts[@"3"];
id<FBXCElementSnapshot> xcuiElementCell = [[FBXCElementSnapshotWrapper ensureWrapped:
[threeStaticText fb_customSnapshot]]
fb_parentCellSnapshot];
XCTAssertEqual(xcuiElementCell.elementType, 75);
}
@end

View File

@@ -0,0 +1,30 @@
/**
* 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 "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "FBXCElementSnapshotWrapper+Helpers.h"
#import "XCUIElement.h"
#import "XCUIElement+FBUtilities.h"
@interface XCElementSnapshotHitPoint : FBIntegrationTestCase
@end
@implementation XCElementSnapshotHitPoint
- (void)testAccessibilityActivationPoint
{
[self launchApplication];
[self goToAttributesPage];
XCUIElement *dstBtn = self.testedApplication.buttons[@"not_accessible"];
CGPoint hitPoint = [FBXCElementSnapshotWrapper
ensureWrapped:[dstBtn fb_standardSnapshot]].fb_hitPoint.CGPointValue;
XCTAssertTrue(hitPoint.x > 0 && hitPoint.y > 0);
}
@end

View File

@@ -0,0 +1,163 @@
/**
* 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 <XCTest/XCTest.h>
#import <mach/mach_time.h>
#import "FBIntegrationTestCase.h"
#import "FBElement.h"
#import "FBMacros.h"
#import "FBTestMacros.h"
#import "XCUIApplication.h"
#import "XCUIApplication+FBHelpers.h"
#import "XCUIElement+FBIsVisible.h"
#import "FBXCodeCompatibility.h"
void calculateMaxTreeDepth(NSDictionary *tree, NSNumber *currentDepth, NSNumber** maxDepth) {
if (nil == maxDepth) {
return;
}
NSArray *children = tree[@"children"];
if (nil == children || 0 == children.count) {
return;
}
for (NSDictionary *child in children) {
if (currentDepth.integerValue > [*maxDepth integerValue]) {
*maxDepth = currentDepth;
}
calculateMaxTreeDepth(child, @(currentDepth.integerValue + 1), maxDepth);
}
}
@interface XCUIApplicationHelperTests : FBIntegrationTestCase
@end
@implementation XCUIApplicationHelperTests
- (void)setUp
{
[super setUp];
[self launchApplication];
}
- (void)testQueringSpringboard
{
[self goToSpringBoardFirstPage];
XCTAssertTrue(XCUIApplication.fb_systemApplication.icons[@"Safari"].exists);
XCTAssertTrue(XCUIApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.exists);
}
- (void)testApplicationTree
{
NSDictionary *tree = self.testedApplication.fb_tree;
XCTAssertNotNil(tree);
NSNumber *maxDepth;
calculateMaxTreeDepth(tree, @0, &maxDepth);
XCTAssertGreaterThan(maxDepth.integerValue, 3);
XCTAssertNotNil(self.testedApplication.fb_accessibilityTree);
}
- (void)testApplicationTreeAttributesFiltering
{
NSDictionary *applicationTree = [self.testedApplication fb_tree:[NSSet setWithArray:@[@"visible"]]];
XCTAssertNotNil(applicationTree);
XCTAssertNil([applicationTree objectForKey:@"isVisible"], @"'isVisible' key should not be present in the application tree");
}
- (void)testDeactivateApplication
{
NSError *error;
uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW);
NSTimeInterval backgroundDuration = 5.0;
XCTAssertTrue([self.testedApplication fb_deactivateWithDuration:backgroundDuration error:&error]);
NSTimeInterval timeElapsed = (clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - timeStarted) / NSEC_PER_SEC;
XCTAssertNil(error);
XCTAssertEqualWithAccuracy(timeElapsed, backgroundDuration, 3.0);
XCTAssertTrue(self.testedApplication.buttons[@"Alerts"].exists);
}
- (void)testActiveApplication
{
XCUIApplication *systemApp = XCUIApplication.fb_systemApplication;
XCTAssertTrue([XCUIApplication fb_activeApplication].buttons[@"Alerts"].fb_isVisible);
[self goToSpringBoardFirstPage];
XCTAssertEqualObjects([XCUIApplication fb_activeApplication].bundleID, systemApp.bundleID);
XCTAssertTrue(systemApp.icons[@"Safari"].fb_isVisible);
}
- (void)testActiveElement
{
[self goToAttributesPage];
XCTAssertNil(self.testedApplication.fb_activeElement);
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
[textField tap];
FBAssertWaitTillBecomesTrue(nil != self.testedApplication.fb_activeElement);
XCTAssertEqualObjects(((id<FBElement>)self.testedApplication.fb_activeElement).wdUID,
((id<FBElement>)textField).wdUID);
}
- (void)testActiveApplicationsInfo
{
NSArray *appsInfo = [XCUIApplication fb_activeAppsInfo];
XCTAssertTrue(appsInfo.count > 0);
BOOL isAppActive = NO;
for (NSDictionary *appInfo in appsInfo) {
if ([appInfo[@"bundleId"] isEqualToString:self.testedApplication.bundleID]) {
isAppActive = YES;
break;
}
}
XCTAssertTrue(isAppActive);
}
- (void)testTestmanagerdVersion
{
XCTAssertGreaterThan(FBTestmanagerdVersion(), 0);
}
- (void)testAccessbilityAudit
{
if (SYSTEM_VERSION_LESS_THAN(@"17.0")) {
return;
}
NSError *error;
NSArray *auditIssues1 = [XCUIApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypes:~0UL
error:&error];
XCTAssertNotNil(auditIssues1);
XCTAssertNil(error);
NSMutableSet *set = [NSMutableSet new];
[set addObject:@"XCUIAccessibilityAuditTypeAll"];
NSArray *auditIssues2 = [XCUIApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypesSet:set.copy
error:&error];
// 'elementDescription' is not in this list because it could have
// different object id's debug description in XCTest.
NSArray *checkKeys = @[
@"auditType",
@"compactDescription",
@"detailedDescription",
@"element",
@"elementAttributes"
];
XCTAssertEqual([auditIssues1 count], [auditIssues2 count]);
for (int i = 1; i < [auditIssues1 count]; i++) {
for (NSString *k in checkKeys) {
XCTAssertEqualObjects(
[auditIssues1[i] objectForKey:k],
[auditIssues2[i] objectForKey:k]
);
}
}
XCTAssertNil(error);
}
@end

View File

@@ -0,0 +1,27 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "XCUIDevice+FBHealthCheck.h"
#import "XCUIElement.h"
@interface XCUIDeviceHealthCheckTests : FBIntegrationTestCase
@end
@implementation XCUIDeviceHealthCheckTests
- (void)testHealthCheck
{
[self launchApplication];
XCTAssertTrue(self.testedApplication.exists);
XCTAssertTrue([[XCUIDevice sharedDevice] fb_healthCheckWithApplication:self.testedApplication]);
}
@end

View File

@@ -0,0 +1,220 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBImageUtils.h"
#import "FBMacros.h"
#import "FBTestMacros.h"
#import "XCUIApplication.h"
#import "XCUIApplication+FBHelpers.h"
#import "XCUIDevice+FBHelpers.h"
#import "XCUIDevice+FBRotation.h"
#import "XCUIScreen.h"
@interface XCUIDeviceHelperTests : FBIntegrationTestCase
@end
@implementation XCUIDeviceHelperTests
- (void)restorePortraitOrientation
{
if ([XCUIDevice sharedDevice].orientation != UIDeviceOrientationPortrait) {
[[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationPortrait];
}
}
- (void)setUp
{
[super setUp];
[self launchApplication];
[self restorePortraitOrientation];
}
- (void)tearDown
{
[self restorePortraitOrientation];
[super tearDown];
}
- (void)testScreenshot
{
NSError *error = nil;
NSData *screenshotData = [[XCUIDevice sharedDevice] fb_screenshotWithError:&error];
XCTAssertNotNil(screenshotData);
XCTAssertNil(error);
XCTAssertTrue(FBIsPngImage(screenshotData));
UIImage *screenshot = [UIImage imageWithData:screenshotData];
XCTAssertNotNil(screenshot);
XCUIScreen *mainScreen = XCUIScreen.mainScreen;
UIImage *screenshotExact = ((XCUIScreenshot *)mainScreen.screenshot).image;
XCTAssertEqualWithAccuracy(screenshotExact.size.height * mainScreen.scale,
screenshot.size.height,
FLT_EPSILON);
XCTAssertEqualWithAccuracy(screenshotExact.size.width * mainScreen.scale,
screenshot.size.width,
FLT_EPSILON);
}
- (void)testLandscapeScreenshot
{
XCTAssertTrue([[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeLeft]);
NSError *error = nil;
NSData *screenshotData = [[XCUIDevice sharedDevice] fb_screenshotWithError:&error];
XCTAssertNotNil(screenshotData);
XCTAssertTrue(FBIsPngImage(screenshotData));
XCTAssertNil(error);
UIImage *screenshot = [UIImage imageWithData:screenshotData];
XCTAssertNotNil(screenshot);
XCTAssertTrue(screenshot.size.width > screenshot.size.height);
XCUIScreen *mainScreen = XCUIScreen.mainScreen;
UIImage *screenshotExact = ((XCUIScreenshot *)mainScreen.screenshot).image;
CGSize realMainScreenSize = screenshotExact.size.height > screenshot.size.width
? CGSizeMake(screenshotExact.size.height * mainScreen.scale, screenshotExact.size.width * mainScreen.scale)
: CGSizeMake(screenshotExact.size.width * mainScreen.scale, screenshotExact.size.height * mainScreen.scale);
XCTAssertEqualWithAccuracy(realMainScreenSize.height, screenshot.size.height, FLT_EPSILON);
XCTAssertEqualWithAccuracy(realMainScreenSize.width, screenshot.size.width, FLT_EPSILON);
}
- (void)testWifiAddress
{
NSString *adderss = [XCUIDevice sharedDevice].fb_wifiIPAddress;
if (!adderss) {
return;
}
NSRange range = [adderss rangeOfString:@"^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})" options:NSRegularExpressionSearch];
XCTAssertTrue(range.location != NSNotFound);
}
- (void)testGoToHomeScreen
{
NSError *error;
XCTAssertTrue([[XCUIDevice sharedDevice] fb_goToHomescreenWithError:&error]);
XCTAssertNil(error);
FBAssertWaitTillBecomesTrue([XCUIApplication fb_activeApplication].icons[@"Safari"].exists);
}
- (void)testLockUnlockScreen
{
XCTAssertFalse([[XCUIDevice sharedDevice] fb_isScreenLocked]);
NSError *error;
XCTAssertTrue([[XCUIDevice sharedDevice] fb_lockScreen:&error]);
XCTAssertTrue([[XCUIDevice sharedDevice] fb_isScreenLocked]);
XCTAssertNil(error);
XCTAssertTrue([[XCUIDevice sharedDevice] fb_unlockScreen:&error]);
XCTAssertFalse([[XCUIDevice sharedDevice] fb_isScreenLocked]);
XCTAssertNil(error);
}
- (void)testUrlSchemeActivation
{
if (SYSTEM_VERSION_LESS_THAN(@"16.4")) {
return;
}
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_openUrl:@"https://apple.com" error:&error]);
FBAssertWaitTillBecomesTrue([XCUIApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]);
XCTAssertNil(error);
}
- (void)testUrlSchemeActivationWithApp
{
if (SYSTEM_VERSION_LESS_THAN(@"16.4")) {
return;
}
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_openUrl:@"https://apple.com"
withApplication:@"com.apple.mobilesafari"
error:&error]);
FBAssertWaitTillBecomesTrue([XCUIApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]);
XCTAssertNil(error);
}
#if !TARGET_OS_TV
- (void)testSimulatedLocationSetup
{
if (SYSTEM_VERSION_LESS_THAN(@"16.4")) {
return;
}
CLLocation *simulatedLocation = [[CLLocation alloc] initWithLatitude:50 longitude:50];
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_setSimulatedLocation:simulatedLocation error:&error]);
XCTAssertNil(error);
CLLocation *currentLocation = [XCUIDevice.sharedDevice fb_getSimulatedLocation:&error];
XCTAssertNil(error);
XCTAssertNotNil(currentLocation);
XCTAssertEqualWithAccuracy(simulatedLocation.coordinate.latitude, currentLocation.coordinate.latitude, 0.1);
XCTAssertEqualWithAccuracy(simulatedLocation.coordinate.longitude, currentLocation.coordinate.longitude, 0.1);
XCTAssertTrue([XCUIDevice.sharedDevice fb_clearSimulatedLocation:&error]);
XCTAssertNil(error);
currentLocation = [XCUIDevice.sharedDevice fb_getSimulatedLocation:&error];
XCTAssertNil(error);
XCTAssertNotEqualWithAccuracy(simulatedLocation.coordinate.latitude, currentLocation.coordinate.latitude, 0.1);
XCTAssertNotEqualWithAccuracy(simulatedLocation.coordinate.longitude, currentLocation.coordinate.longitude, 0.1);
}
#endif
- (void)testPressingUnsupportedButton
{
NSError *error;
NSNumber *duration = nil;
XCTAssertFalse([XCUIDevice.sharedDevice fb_pressButton:@"volumeUpp"
forDuration:duration
error:&error]);
XCTAssertNotNil(error);
}
- (void)testPressingSupportedButton
{
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_pressButton:@"home"
forDuration:nil
error:&error]);
XCTAssertNil(error);
}
- (void)testPressingSupportedButtonNumber
{
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_pressButton:@"home"
forDuration:[NSNumber numberWithDouble:1.0]
error:&error]);
XCTAssertNil(error);
}
- (void)testLongPressHomeButton
{
NSError *error;
// kHIDPage_Consumer = 0x0C
// kHIDUsage_Csmr_Menu = 0x40
XCTAssertTrue([XCUIDevice.sharedDevice fb_performIOHIDEventWithPage:0x0C
usage:0x40
duration:1.0
error:&error]);
XCTAssertNil(error);
}
- (void)testAppearance
{
if (SYSTEM_VERSION_LESS_THAN(@"15.0")) {
return;
}
NSError *error;
XCTAssertTrue([XCUIDevice.sharedDevice fb_setAppearance:FBUIInterfaceAppearanceDark error:&error]);
XCTAssertNil(error);
}
@end

View File

@@ -0,0 +1,84 @@
/**
* 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 <XCTest/XCTest.h>
#import <UIKit/UIKit.h>
#import "FBIntegrationTestCase.h"
#import "XCUIDevice+FBRotation.h"
@interface XCUIDeviceRotationTests : FBIntegrationTestCase
@end
@implementation XCUIDeviceRotationTests
- (void)setUp
{
[super setUp];
[self launchApplication];
}
- (void)tearDown
{
[self resetOrientation];
[super tearDown];
}
- (void)testLandscapeRightOrientation
{
BOOL success = [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeRight];
XCTAssertTrue(success, @"Device should support LandscapeRight");
// Device rotation gives opposite interface rotation
XCTAssertTrue(self.testedApplication.staticTexts[@"LandscapeLeft"].exists);
}
- (void)testLandscapeLeftOrientation
{
BOOL success = [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeLeft];
XCTAssertTrue(success, @"Device should support LandscapeLeft");
// Device rotation gives opposite interface rotation
XCTAssertTrue(self.testedApplication.staticTexts[@"LandscapeRight"].exists);
}
- (void)testLandscapeRightRotation
{
BOOL success = [[XCUIDevice sharedDevice] fb_setDeviceRotation:@{
@"x" : @(0),
@"y" : @(0),
@"z" : @(90)
}];
XCTAssertTrue(success, @"Device should support LandscapeRight");
// Device rotation gives opposite interface rotation
XCTAssertTrue(self.testedApplication.staticTexts[@"LandscapeLeft"].exists);
}
- (void)testLandscapeLeftRotation
{
BOOL success = [[XCUIDevice sharedDevice] fb_setDeviceRotation:@{
@"x" : @(0),
@"y" : @(0),
@"z" : @(270)
}];
XCTAssertTrue(success, @"Device should support LandscapeLeft");
// Device rotation gives opposite interface rotation
XCTAssertTrue(self.testedApplication.staticTexts[@"LandscapeRight"].exists);
}
- (void)testRotationTiltRotation
{
UIDeviceOrientation currentRotation = [XCUIDevice sharedDevice].orientation;
BOOL success = [[XCUIDevice sharedDevice] fb_setDeviceRotation:@{
@"x" : @(15),
@"y" : @(0),
@"z" : @(0)}
];
XCTAssertFalse(success, @"Device should not support tilt");
XCTAssertEqual(currentRotation, [XCUIDevice sharedDevice].orientation, @"Device doesnt support tilt, should be at previous orientation");
}
@end

View File

@@ -0,0 +1,248 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "XCUIElement+FBFind.h"
#import "FBElementUtils.h"
#import "FBConfiguration.h"
#import "FBResponsePayload.h"
#import "FBXCodeCompatibility.h"
@interface XCUIElementAttributesTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *matchingElement;
@end
@implementation XCUIElementAttributesTests
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
});
XCUIElement *testedView = self.testedApplication.otherElements[@"MainView"];
FBAssertWaitTillBecomesTrue(testedView.exists);
self.matchingElement = [[testedView fb_descendantsMatchingIdentifier:@"Alerts" shouldReturnAfterFirstMatch:YES] firstObject];
XCTAssertNotNil(self.matchingElement);
}
- (void)verifyGettingAttributeWithShortcut:(NSString *)shortcutName expectedValue:(id)expectedValue
{
NSString *fullAttributeName = [NSString stringWithFormat:@"wd%@", [NSString stringWithFormat:@"%@%@", [[shortcutName substringToIndex:1] uppercaseString], [shortcutName substringFromIndex:1]]];
id actualValue = [self.matchingElement fb_valueForWDAttributeName:fullAttributeName];
id actualShortcutValue = [self.matchingElement fb_valueForWDAttributeName:shortcutName];
if (nil == expectedValue) {
XCTAssertNil(actualValue);
XCTAssertNil(actualShortcutValue);
return;
}
if ([actualValue isKindOfClass:NSString.class]) {
XCTAssertTrue([actualValue isEqualToString:expectedValue]);
XCTAssertTrue([actualShortcutValue isEqualToString:expectedValue]);
} else if ([actualValue isKindOfClass:NSNumber.class]) {
XCTAssertTrue([actualValue isEqualToNumber:expectedValue]);
XCTAssertTrue([actualShortcutValue isEqualToNumber:expectedValue]);
} else {
XCTAssertEqual(actualValue, expectedValue);
XCTAssertEqual(actualShortcutValue, expectedValue);
}
}
- (void)testGetNameAttribute
{
[self verifyGettingAttributeWithShortcut:@"name" expectedValue:self.matchingElement.wdName];
}
- (void)testGetValueAttribute
{
[self verifyGettingAttributeWithShortcut:@"value" expectedValue:self.matchingElement.wdValue];
}
- (void)testGetLabelAttribute
{
[self verifyGettingAttributeWithShortcut:@"label" expectedValue:self.matchingElement.wdLabel];
}
- (void)testGetTypeAttribute
{
[self verifyGettingAttributeWithShortcut:@"type" expectedValue:self.matchingElement.wdType];
}
- (void)testGetRectAttribute
{
NSString *shortcutName = @"rect";
for (NSString *key in @[@"x", @"y", @"width", @"height"]) {
NSNumber *actualValue = [self.matchingElement fb_valueForWDAttributeName:[FBElementUtils wdAttributeNameForAttributeName:shortcutName]][key];
NSNumber *actualShortcutValue = [self.matchingElement fb_valueForWDAttributeName:shortcutName][key];
NSNumber *expectedValue = self.matchingElement.wdRect[key];
XCTAssertTrue([actualValue isEqualToNumber:expectedValue]);
XCTAssertTrue([actualShortcutValue isEqualToNumber:expectedValue]);
}
}
- (void)testGetEnabledAttribute
{
[self verifyGettingAttributeWithShortcut:@"enabled" expectedValue:[NSNumber numberWithBool:self.matchingElement.wdEnabled]];
}
- (void)testGetAccessibleAttribute
{
[self verifyGettingAttributeWithShortcut:@"accessible" expectedValue:[NSNumber numberWithBool:self.matchingElement.wdAccessible]];
}
- (void)testGetUidAttribute
{
[self verifyGettingAttributeWithShortcut:@"UID" expectedValue:self.matchingElement.wdUID];
}
- (void)testGetVisibleAttribute
{
[self verifyGettingAttributeWithShortcut:@"visible" expectedValue:[NSNumber numberWithBool:self.matchingElement.wdVisible]];
}
- (void)testGetAccessibilityContainerAttribute
{
[self verifyGettingAttributeWithShortcut:@"accessibilityContainer" expectedValue:[NSNumber numberWithBool:self.matchingElement.wdAccessibilityContainer]];
}
- (void)testGetInvalidAttribute
{
XCTAssertThrowsSpecificNamed([self verifyGettingAttributeWithShortcut:@"invalid" expectedValue:@"blabla"], NSException, FBUnknownAttributeException);
}
@end
@interface XCUIElementFBFindTests_CompactResponses : FBIntegrationTestCase
@end
@implementation XCUIElementFBFindTests_CompactResponses
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
});
}
- (void)testCompactResponseYes
{
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, YES);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqual(fields.count, 2);
}
- (void)testCompactResponseNo
{
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, NO);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqualObjects(fields[@"type"], @"XCUIElementTypeButton");
XCTAssertEqualObjects(fields[@"label"], @"Alerts");
XCTAssertEqual(fields.count, 4);
}
@end
@interface XCUIElementFBFindTests_ResponseFields : FBIntegrationTestCase
@end
@implementation XCUIElementFBFindTests_ResponseFields
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
});
}
- (void)testCompactResponseYesWithResponseAttributesSet
{
[FBConfiguration setElementResponseAttributes:@"name,text,enabled"];
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, YES);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqual(fields.count, 2);
}
- (void)testCompactResponseNoWithResponseAttributesSet
{
[FBConfiguration setElementResponseAttributes:@"name,text,enabled"];
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, NO);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqualObjects(fields[@"name"], @"XCUIElementTypeButton");
XCTAssertEqualObjects(fields[@"text"], @"Alerts");
XCTAssertEqualObjects(fields[@"enabled"], @(YES));
XCTAssertEqual(fields.count, 5);
}
- (void)testInvalidAttribute
{
[FBConfiguration setElementResponseAttributes:@"invalid_field,name"];
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, NO);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqualObjects(fields[@"name"], @"XCUIElementTypeButton");
XCTAssertEqual(fields.count, 3);
}
- (void)testKnownAttributes
{
[FBConfiguration setElementResponseAttributes:@"name,type,label,text,rect,enabled,displayed,selected"];
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, NO);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqualObjects(fields[@"name"], @"XCUIElementTypeButton");
XCTAssertEqualObjects(fields[@"type"], @"XCUIElementTypeButton");
XCTAssertEqualObjects(fields[@"label"], @"Alerts");
XCTAssertEqualObjects(fields[@"text"], @"Alerts");
XCTAssertTrue(matchesRegex([fields[@"rect"] description], @"\\{\\s*height = [0-9]+;\\s*width = [0-9]+;\\s*x = [0-9]+;\\s*y = [0-9]+;\\s*\\}"));
XCTAssertEqualObjects(fields[@"enabled"], @(YES));
XCTAssertEqualObjects(fields[@"displayed"], @(YES));
XCTAssertEqualObjects(fields[@"selected"], @(NO));
XCTAssertEqual(fields.count, 10);
}
- (void)testArbitraryAttributes
{
[FBConfiguration setElementResponseAttributes:@"attribute/name,attribute/value"];
XCUIElement *alertsButton = self.testedApplication.buttons[@"Alerts"];
NSDictionary *fields = FBDictionaryResponseWithElement(alertsButton, NO);
XCTAssertNotNil(fields[@"ELEMENT"]);
XCTAssertNotNil(fields[@"element-6066-11e4-a52e-4f735466cecf"]);
XCTAssertEqualObjects(fields[@"attribute/name"], @"Alerts");
XCTAssertEqualObjects(fields[@"attribute/value"], [NSNull null]);
XCTAssertEqual(fields.count, 4);
}
static BOOL matchesRegex(NSString *target, NSString *pattern) {
if (!target)
return NO;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
return [regex numberOfMatchesInString:target options:0 range:NSMakeRange(0, target.length)] == 1;
}
@end

View File

@@ -0,0 +1,472 @@
/**
* 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 <XCTest/XCTest.h>
#import "FBIntegrationTestCase.h"
#import "FBElementUtils.h"
#import "FBExceptions.h"
#import "FBTestMacros.h"
#import "XCUIElement.h"
#import "XCUIElement+FBFind.h"
#import "XCUIElement+FBUID.h"
#import "FBXCElementSnapshotWrapper+Helpers.h"
#import "XCUIElement+FBIsVisible.h"
#import "XCUIElement+FBClassChain.h"
#import "XCUIElement+FBResolve.h"
#import "FBXPath.h"
#import "FBXCodeCompatibility.h"
@interface XCUIElementFBFindTests : FBIntegrationTestCase
@property (nonatomic, strong) XCUIElement *testedView;
@end
@implementation XCUIElementFBFindTests
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
});
self.testedView = self.testedApplication.otherElements[@"MainView"];
FBAssertWaitTillBecomesTrue(self.testedView.exists);
}
- (void)testDescendantsWithClassName
{
NSSet<NSString *> *expectedLabels = [NSSet setWithArray:@[
@"Alerts",
@"Attributes",
@"Scrolling",
@"Deadlock app",
@"Touch",
]];
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassName:@"XCUIElementTypeButton"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, expectedLabels.count);
NSArray<NSString *> *labels = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.label"];
XCTAssertEqualObjects([NSSet setWithArray:labels], expectedLabels);
NSArray<NSNumber *> *types = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.elementType"];
XCTAssertEqual(types.count, 1, @"matchingSnapshots should contain only one type");
XCTAssertEqualObjects(types.lastObject, @(XCUIElementTypeButton), @"matchingSnapshots should contain only one type");
}
- (void)testSingleDescendantWithClassName
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassName:@"XCUIElementTypeButton"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
}
- (void)testDescendantsWithIdentifier
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
shouldReturnAfterFirstMatch:NO];
int snapshotsCount = 2;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
NSArray<XCUIElement *> *selfElementsById = [matchingSnapshots.lastObject fb_descendantsMatchingIdentifier:@"Alerts" shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(selfElementsById.count, 1);
}
- (void)testSingleDescendantWithIdentifier
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testStableInstance
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
for (XCUIElement *el in @[
matchingSnapshots.lastObject,
[matchingSnapshots.lastObject fb_stableInstanceWithUid:[matchingSnapshots.lastObject fb_uid]]
]) {
XCTAssertEqual(el.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(el.label, @"Alerts");
}
}
- (void)testSingleDescendantWithMissingIdentifier
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"blabla" shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 0);
}
- (void)testDescendantsWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Alerts']"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testSelfWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeApplication"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeApplication);
}
- (void)testSingleDescendantWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@hittable='true']"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCUIElement *matchingSnapshot = [matchingSnapshots firstObject];
XCTAssertNotNil(matchingSnapshot);
XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshot.label, @"Alerts");
}
- (void)testSingleDescendantWithXPathQueryNoMatches
{
XCUIElement *matchingSnapshot = [[self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButtonnn"
shouldReturnAfterFirstMatch:YES] firstObject];
XCTAssertNil(matchingSnapshot);
}
- (void)testSingleLastDescendantWithXPathQuery
{
XCUIElement *matchingSnapshot = [[self.testedView fb_descendantsMatchingXPathQuery:@"(//XCUIElementTypeButton)[last()]"
shouldReturnAfterFirstMatch:YES] firstObject];
XCTAssertNotNil(matchingSnapshot);
XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
}
- (void)testDescendantsWithXPathQueryNoMatches
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Alerts1']"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 0);
}
- (void)testDescendantsWithComplexXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//*[@label='Scrolling']/preceding::*[boolean(string(@label))]"
shouldReturnAfterFirstMatch:NO];
int snapshotsCount = 6;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
}
- (void)testDescendantsWithWrongXPathQuery
{
XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingXPathQuery:@"//*[blabla(@label, Scrolling')]"
shouldReturnAfterFirstMatch:NO],
NSException, FBInvalidXPathException);
}
- (void)testFirstDescendantWithWrongXPathQuery
{
XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingXPathQuery:@"//*[blabla(@label, Scrolling')]"
shouldReturnAfterFirstMatch:YES],
NSException, FBInvalidXPathException);
}
- (void)testVisibleDescendantWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@name='Alerts' and @enabled='true' and @visible='true']" shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
XCTAssertTrue(matchingSnapshots.lastObject.isEnabled);
XCTAssertTrue(matchingSnapshots.lastObject.fb_isVisible);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testDescendantsWithPredicateString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label = 'Alerts'"];
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate
shouldReturnAfterFirstMatch:NO];
int snapshotsCount = 2;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
NSPredicate *selfPredicate = [NSPredicate predicateWithFormat:@"label == 'Alerts'"];
NSArray<XCUIElement *> *selfElementsByPredicate = [matchingSnapshots.lastObject fb_descendantsMatchingPredicate:selfPredicate
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(selfElementsByPredicate.count, 1);
}
- (void)testSelfWithPredicateString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == 'XCUIElementTypeApplication'"];
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingPredicate:predicate
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeApplication);
}
- (void)testSingleDescendantWithPredicateString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type = 'XCUIElementTypeButton'"];
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
}
- (void)testSingleDescendantWithPredicateStringByIndex
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == 'XCUIElementTypeButton' AND index == 2"];
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
}
- (void)testDescendantsWithPropertyStrict
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label"
value:@"Alert"
partialSearch:NO];
XCTAssertEqual(matchingSnapshots.count, 0);
matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO];
int snapshotsCount = 2;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testGlobalWithPropertyStrict
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingProperty:@"label"
value:@"Alert"
partialSearch:NO];
XCTAssertEqual(matchingSnapshots.count, 0);
matchingSnapshots = [self.testedApplication fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO];
int snapshotsCount = 2;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testDescendantsWithPropertyPartial
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label"
value:@"Alerts"
partialSearch:NO];
int snapshotsCount = 2;
XCTAssertEqual(matchingSnapshots.count, snapshotsCount);
XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts");
}
- (void)testDescendantsWithClassChain
{
NSArray<XCUIElement *> *matchingSnapshots;
NSString *queryString =@"XCUIElementTypeWindow/XCUIElementTypeOther/**/XCUIElementTypeButton";
matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 5); // /XCUIElementTypeButton
for (XCUIElement *matchingSnapshot in matchingSnapshots) {
XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
}
}
- (void)testDescendantsWithClassChainWithIndex
{
NSArray<XCUIElement *> *matchingSnapshots;
// iPhone
NSString *queryString = @"XCUIElementTypeWindow/*/*/*/*[2]/*/*/XCUIElementTypeButton";
matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
if (matchingSnapshots.count == 0) {
// iPad
queryString = @"XCUIElementTypeWindow/*/*/*/*/*[2]/*/*/XCUIElementTypeButton";
matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
}
XCTAssertEqual(matchingSnapshots.count, 5); // /XCUIElementTypeButton
for (XCUIElement *matchingSnapshot in matchingSnapshots) {
XCTAssertEqual(matchingSnapshot.elementType, XCUIElementTypeButton);
}
}
- (void)testDescendantsWithClassChainAndPredicates
{
NSArray<XCUIElement *> *matchingSnapshots;
NSString *queryString = @"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]";
matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 2);
XCTAssertEqualObjects([matchingSnapshots firstObject].label, @"Alerts");
XCTAssertEqualObjects([matchingSnapshots lastObject].label, @"Attributes");
}
- (void)testDescendantsWithIndirectClassChainAndPredicates
{
NSString *queryString = @"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]";
NSArray<XCUIElement *> *simpleQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
NSArray<XCUIElement *> *deepQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/**/XCUIElementTypeButton[`label BEGINSWITH 'A'`]"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(simpleQueryMatches.count, deepQueryMatches.count);
XCTAssertEqualObjects([simpleQueryMatches firstObject].label, [deepQueryMatches firstObject].label);
XCTAssertEqualObjects([simpleQueryMatches lastObject].label, [deepQueryMatches lastObject].label);
}
- (void)testClassChainWithDescendantPredicate
{
NSArray<XCUIElement *> *simpleQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/*/*[1]"
shouldReturnAfterFirstMatch:NO];
NSArray<XCUIElement *> *predicateQueryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow/*/*[$type == 'XCUIElementTypeButton' AND label BEGINSWITH 'A'$]"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(simpleQueryMatches.count, predicateQueryMatches.count);
XCTAssertEqual([simpleQueryMatches firstObject].elementType, [predicateQueryMatches firstObject].elementType);
XCTAssertEqual([simpleQueryMatches lastObject].elementType, [predicateQueryMatches lastObject].elementType);
}
- (void)testSingleDescendantWithComplexIndirectClassChain
{
NSArray<XCUIElement *> *queryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"**/*/XCUIElementTypeButton[2]"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(queryMatches.count, 1);
XCTAssertEqual(queryMatches.lastObject.elementType, XCUIElementTypeButton);
XCTAssertEqualObjects(queryMatches.lastObject.label, @"Deadlock app");
}
- (void)testSingleDescendantWithComplexIndirectClassChainAndZeroMatches
{
NSArray<XCUIElement *> *queryMatches = [self.testedApplication fb_descendantsMatchingClassChain:@"**/*/XCUIElementTypeWindow"
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(queryMatches.count, 0);
}
- (void)testDescendantsWithClassChainAndPredicatesAndIndexes
{
NSArray<XCUIElement *> *matchingSnapshots;
NSString *queryString = @"XCUIElementTypeWindow[`name != 'bla'`]/**/XCUIElementTypeButton[`label BEGINSWITH \"A\"`][1]";
matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqualObjects([matchingSnapshots firstObject].label, @"Alerts");
}
- (void)testSingleDescendantWithClassChain
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
XCTAssertTrue([matchingSnapshots.lastObject.label isEqualToString:@"Alerts"]);
}
- (void)testSingleDescendantWithClassChainAndNegativeIndex
{
NSArray<XCUIElement *> *matchingSnapshots;
matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton[-1]"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeButton);
XCTAssertTrue([matchingSnapshots.lastObject.label isEqualToString:@"Touch"]);
matchingSnapshots = [self.testedView fb_descendantsMatchingClassChain:@"XCUIElementTypeButton[-10]"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 0);
}
- (void)testInvalidQueryWithClassChain
{
XCTAssertThrowsSpecificNamed([self.testedView fb_descendantsMatchingClassChain:@"NoXCUIElementTypePrefix"
shouldReturnAfterFirstMatch:YES],
NSException, FBClassChainQueryParseException);
}
- (void)testHandleInvalidQueryWithClassChainAsNoElementWithoutError
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedView
fb_descendantsMatchingClassChain:@"XCUIElementTypeBlabla"
shouldReturnAfterFirstMatch:YES];
XCTAssertEqual(matchingSnapshots.count, 0);
}
- (void)testClassChainWithInvalidPredicate
{
XCTAssertThrowsSpecificNamed([self.testedApplication fb_descendantsMatchingClassChain:@"XCUIElementTypeWindow[`bla != 'bla'`]"
shouldReturnAfterFirstMatch:NO],
NSException, FBUnknownAttributeException);;
}
@end
@interface XCUIElementFBFindTests_AttributesPage : FBIntegrationTestCase
@end
@implementation XCUIElementFBFindTests_AttributesPage
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToAttributesPage];
});
}
- (void)testNestedQueryWithClassChain
{
NSString *queryString = @"XCUIElementTypePicker";
FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"Button"].fb_isVisible);
XCUIElement *datePicker = [self.testedApplication
descendantsMatchingType:XCUIElementTypeDatePicker].allElementsBoundByIndex.firstObject;
NSArray<XCUIElement *> *matches = [datePicker fb_descendantsMatchingClassChain:queryString
shouldReturnAfterFirstMatch:NO];
XCTAssertEqual(matches.count, 1);
XCUIElementType expectedType = XCUIElementTypePicker;
XCTAssertEqual([matches firstObject].elementType, expectedType);
}
@end
@interface XCUIElementFBFindTests_ScrollPage : FBIntegrationTestCase
@end
@implementation XCUIElementFBFindTests_ScrollPage
- (void)setUp
{
[super setUp];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self launchApplication];
[self goToScrollPageWithCells:YES];
});
}
- (void)testInvisibleDescendantWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeStaticText[@visible='false']"
shouldReturnAfterFirstMatch:NO];
XCTAssertGreaterThan(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeStaticText);
XCTAssertFalse(matchingSnapshots.lastObject.fb_isVisible);
}
- (void)testNonHittableDescendantWithXPathQuery
{
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeStaticText[@hittable='false']"
shouldReturnAfterFirstMatch:NO];
XCTAssertGreaterThan(matchingSnapshots.count, 1);
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeStaticText);
XCTAssertFalse(matchingSnapshots.lastObject.fb_isVisible);
}
@end

View File

@@ -0,0 +1,51 @@
/**
* 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 <XCTest/XCTest.h>
#import "XCTest/XCUIElementTypes.h"
#import "FBIntegrationTestCase.h"
#import "FBTestMacros.h"
#import "FBElement.h"
#import "FBElementUtils.h"
#import "FBXCElementSnapshot.h"
#import "XCUIElement+FBUtilities.h"
@interface XCUIElementHelperIntegrationTests : FBIntegrationTestCase
@end
@implementation XCUIElementHelperIntegrationTests
- (void)setUp
{
[super setUp];
[self launchApplication];
[self goToAlertsPage];
}
- (void)testDescendantsFiltering
{
NSArray<XCUIElement *> *buttons = self.testedApplication.buttons.allElementsBoundByIndex;
XCTAssertTrue(buttons.count > 0);
NSArray<XCUIElement *> *windows = self.testedApplication.windows.allElementsBoundByIndex;
XCTAssertTrue(windows.count > 0);
NSMutableArray<XCUIElement *> *allElements = [NSMutableArray array];
[allElements addObjectsFromArray:buttons];
[allElements addObjectsFromArray:windows];
NSMutableArray<id<FBXCElementSnapshot>> *buttonSnapshots = [NSMutableArray array];
[buttonSnapshots addObject:[buttons.firstObject fb_customSnapshot]];
NSArray<XCUIElement *> *result = [self.testedApplication fb_filterDescendantsWithSnapshots:buttonSnapshots
onlyChildren:NO];
XCTAssertEqual(1, result.count);
XCTAssertEqual([result.firstObject elementType], XCUIElementTypeButton);
}
@end