初始化提交
This commit is contained in:
15
WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h
Normal file
15
WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
15
WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m
Normal file
15
WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
@end
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
|
||||
@interface FBAlertViewController : UIViewController
|
||||
|
||||
@end
|
||||
@@ -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 "FBAlertViewController.h"
|
||||
|
||||
#import <Photos/Photos.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
@interface FBAlertViewController ()
|
||||
@property (nonatomic, strong) CLLocationManager *locationManager;
|
||||
@end
|
||||
|
||||
@implementation FBAlertViewController
|
||||
|
||||
- (IBAction)createAppAlert:(UIButton *)sender
|
||||
{
|
||||
[self presentAlertController];
|
||||
}
|
||||
|
||||
- (IBAction)createAppSheet:(UIButton *)sender
|
||||
{
|
||||
UIAlertController *alerController =
|
||||
[UIAlertController alertControllerWithTitle:@"Magic Sheet"
|
||||
message:@"Should read"
|
||||
preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
UIPopoverPresentationController *popPresenter = [alerController popoverPresentationController];
|
||||
popPresenter.sourceView = sender;
|
||||
[self presentViewController:alerController animated:YES completion:nil];
|
||||
|
||||
}
|
||||
|
||||
- (IBAction)createNotificationAlert:(UIButton *)sender
|
||||
{
|
||||
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
||||
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound|UNAuthorizationOptionAlert|UNAuthorizationOptionBadge)
|
||||
completionHandler:^(BOOL granted, NSError * _Nullable error)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)createCameraRollAccessAlert:(UIButton *)sender
|
||||
{
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)createGPSAccessAlert:(UIButton *)sender
|
||||
{
|
||||
self.locationManager = [CLLocationManager new];
|
||||
[self.locationManager requestAlwaysAuthorization];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[super touchesMoved:touches withEvent:event];
|
||||
for (UITouch *touch in touches) {
|
||||
if (fabs(touch.maximumPossibleForce - touch.force) < 0.0001) {
|
||||
[self presentAlertController];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)presentAlertController
|
||||
{
|
||||
UIAlertController *alerController =
|
||||
[UIAlertController alertControllerWithTitle:@"Magic"
|
||||
message:@"Should read"
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alerController addAction:[UIAlertAction actionWithTitle:@"Will do" style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alerController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface FBNavigationController : UINavigationController
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 "FBNavigationController.h"
|
||||
|
||||
@implementation FBNavigationController
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
|
||||
{
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL)shouldAutorotate
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface FBScrollViewController : UIViewController
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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 "FBScrollViewController.h"
|
||||
|
||||
#import "FBTableDataSource.h"
|
||||
|
||||
static const CGFloat FBSubviewHeight = 40.0;
|
||||
|
||||
@interface FBScrollViewController ()
|
||||
@property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
|
||||
@property (nonatomic, strong) IBOutlet FBTableDataSource *dataSource;
|
||||
@end
|
||||
|
||||
@implementation FBScrollViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
[self setupLabelViews];
|
||||
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.frame), self.dataSource.count * FBSubviewHeight);
|
||||
}
|
||||
|
||||
- (void)setupLabelViews
|
||||
{
|
||||
NSUInteger count = self.dataSource.count;
|
||||
for (NSInteger i = 0 ; i < count ; i++) {
|
||||
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, i * FBSubviewHeight, CGRectGetWidth(self.view.frame), FBSubviewHeight)];
|
||||
label.text = [self.dataSource textForElementAtIndex:i];
|
||||
label.textAlignment = NSTextAlignmentCenter;
|
||||
[self.scrollView addSubview:label];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface FBTableDataSource : NSObject <UITableViewDataSource>
|
||||
|
||||
- (NSUInteger)count;
|
||||
- (NSString *)textForElementAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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 "FBTableDataSource.h"
|
||||
|
||||
@implementation FBTableDataSource
|
||||
|
||||
- (NSUInteger)count
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
- (NSString *)textForElementAtIndex:(NSInteger)index
|
||||
{
|
||||
return [NSString stringWithFormat:@"%ld", (long)index];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return self.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
|
||||
cell.textLabel.text = [self textForElementAtIndex:indexPath.row];
|
||||
return cell;
|
||||
}
|
||||
|
||||
@end
|
||||
17
WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h
Normal file
17
WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TouchSpotView : UIView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
28
WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m
Normal file
28
WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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 "TouchSpotView.h"
|
||||
|
||||
@implementation TouchSpotView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.backgroundColor = UIColor.lightGrayColor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setBounds:(CGRect)newBounds
|
||||
{
|
||||
super.bounds = newBounds;
|
||||
self.layer.cornerRadius = newBounds.size.width / 2.0;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
#import "TouchableView.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TouchViewController : UIViewController
|
||||
|
||||
@property (weak, nonatomic) IBOutlet TouchableView *touchable;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *numberOfTapsLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *numberOfTouchesLabel;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 "TouchViewController.h"
|
||||
|
||||
@implementation TouchViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.touchable.delegate = self;
|
||||
self.numberOfTouchesLabel.text = @"0";
|
||||
self.numberOfTapsLabel.text = @"0";
|
||||
}
|
||||
|
||||
- (void)shouldHandleTapsNumber:(int)numberOfTaps {
|
||||
self.numberOfTapsLabel.text = [NSString stringWithFormat:@"%d", numberOfTaps];
|
||||
}
|
||||
|
||||
- (void)shouldHandleTouchesNumber:(int)touchesCount {
|
||||
self.numberOfTouchesLabel.text = [NSString stringWithFormat:@"%d", touchesCount];
|
||||
}
|
||||
|
||||
@end
|
||||
29
WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h
Normal file
29
WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
#import "TouchSpotView.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol TouchableViewDelegate <NSObject>
|
||||
|
||||
- (void)shouldHandleTouchesNumber:(int)touchesCount;
|
||||
- (void)shouldHandleTapsNumber:(int)numberOfTaps;
|
||||
|
||||
@end
|
||||
|
||||
@interface TouchableView : UIView
|
||||
|
||||
@property (nonatomic) NSMutableDictionary<NSNumber*, TouchSpotView*> *touchViews;
|
||||
@property (nonatomic) int numberOFTaps;
|
||||
@property (nonatomic) id delegate;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
108
WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m
Normal file
108
WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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 "TouchableView.h"
|
||||
|
||||
@implementation TouchableView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.multipleTouchEnabled = YES;
|
||||
self.numberOFTaps = 0;
|
||||
self.touchViews = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
if (self) {
|
||||
self.multipleTouchEnabled = YES;
|
||||
self.numberOFTaps = 0;
|
||||
self.touchViews = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
self.numberOFTaps += 1;
|
||||
[self.delegate shouldHandleTouchesNumber:(int)touches.count];
|
||||
for (UITouch *touch in touches)
|
||||
{
|
||||
[self createViewForTouch:touch];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches)
|
||||
{
|
||||
TouchSpotView *view = [self viewForTouch:touch];
|
||||
CGPoint newLocation = [touch locationInView:self];
|
||||
view.center = newLocation;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches)
|
||||
{
|
||||
[self removeViewForTouch:touch];
|
||||
}
|
||||
[self.delegate shouldHandleTapsNumber:self.numberOFTaps];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches)
|
||||
{
|
||||
[self removeViewForTouch:touch];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)createViewForTouch:(UITouch *)touch
|
||||
{
|
||||
if (touch)
|
||||
{
|
||||
TouchSpotView *newView = [[TouchSpotView alloc] init];
|
||||
newView.bounds = CGRectMake(0, 0, 1, 1);
|
||||
newView.center = [touch locationInView:self];
|
||||
[self addSubview:newView];
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
newView.bounds = CGRectMake(0, 0, 100, 100);
|
||||
}];
|
||||
|
||||
self.touchViews[[self touchHash:touch]] = newView;
|
||||
}
|
||||
}
|
||||
|
||||
- (TouchSpotView *)viewForTouch:(UITouch *)touch
|
||||
{
|
||||
return self.touchViews[[self touchHash:touch]];
|
||||
}
|
||||
|
||||
- (void)removeViewForTouch:(UITouch *)touch
|
||||
{
|
||||
NSNumber *touchHash = [self touchHash:touch];
|
||||
UIView *view = self.touchViews[touchHash];
|
||||
if (view)
|
||||
{
|
||||
[view removeFromSuperview];
|
||||
[self.touchViews removeObjectForKey:touchHash];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSNumber *)touchHash:(UITouch *)touch
|
||||
{
|
||||
return [NSNumber numberWithUnsignedInteger:touch.hash];
|
||||
}
|
||||
@end
|
||||
12
WebDriverAgentTests/IntegrationApp/Classes/ViewController.h
Normal file
12
WebDriverAgentTests/IntegrationApp/Classes/ViewController.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
@end
|
||||
66
WebDriverAgentTests/IntegrationApp/Classes/ViewController.m
Normal file
66
WebDriverAgentTests/IntegrationApp/Classes/ViewController.m
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 "ViewController.h"
|
||||
|
||||
@interface ViewController ()
|
||||
@property (weak, nonatomic) IBOutlet UILabel *orentationLabel;
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
- (IBAction)deadlockApp:(id)sender
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
// This will never execute
|
||||
});
|
||||
}
|
||||
|
||||
- (IBAction)didTapButton:(UIButton *)button
|
||||
{
|
||||
button.selected = !button.selected;
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
[self updateOrentationLabel];
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (void)updateOrentationLabel
|
||||
{
|
||||
NSString *orientation = nil;
|
||||
switch (UIDevice.currentDevice.orientation) {
|
||||
case UIInterfaceOrientationPortrait:
|
||||
orientation = @"Portrait";
|
||||
break;
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
orientation = @"PortraitUpsideDown";
|
||||
break;
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
orientation = @"LandscapeLeft";
|
||||
break;
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
orientation = @"LandscapeRight";
|
||||
break;
|
||||
case UIDeviceOrientationFaceUp:
|
||||
orientation = @"FaceUp";
|
||||
break;
|
||||
case UIDeviceOrientationFaceDown:
|
||||
orientation = @"FaceDown";
|
||||
break;
|
||||
case UIInterfaceOrientationUnknown:
|
||||
orientation = @"Unknown";
|
||||
break;
|
||||
}
|
||||
self.orentationLabel.text = orientation;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
56
WebDriverAgentTests/IntegrationApp/Info.plist
Normal file
56
WebDriverAgentTests/IntegrationApp/Info.plist
Normal file
@@ -0,0 +1,56 @@
|
||||
<?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>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Yo Yo</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>Yo Yo</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Yo Yo</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Yo Yo</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,617 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="nJd-IZ-bfU">
|
||||
<device id="retina6_5" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nbp-zX-Om1">
|
||||
<rect key="frame" x="186.66666666666666" y="117" width="41" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="GzF-4f-MaH"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Alerts"/>
|
||||
<connections>
|
||||
<segue destination="gK5-IX-eJx" kind="show" animates="NO" id="8RT-ON-yXm"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YgP-SF-TkS">
|
||||
<rect key="frame" x="159.66666666666666" y="155" width="95" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="wTu-YB-p22"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Deadlock app"/>
|
||||
<connections>
|
||||
<action selector="deadlockApp:" destination="BYZ-38-t0r" eventType="touchUpInside" id="53X-DJ-KNY"/>
|
||||
<action selector="showAlert:" destination="BYZ-38-t0r" eventType="touchUpInside" id="FEN-VX-MMc"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="M2N-Yn-ytb">
|
||||
<rect key="frame" x="173" y="193" width="68" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Sf6-pE-ROp"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Attributes"/>
|
||||
<connections>
|
||||
<segue destination="65L-2T-0zt" kind="show" animates="NO" id="7cJ-OE-YWn"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="S56-6U-3gG">
|
||||
<rect key="frame" x="177" y="231" width="60" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="7sH-TN-BNa"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Scrolling"/>
|
||||
<connections>
|
||||
<segue destination="YzO-du-v3Y" kind="show" animates="NO" id="Ds1-bA-25D"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Orientation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uiD-R4-b34">
|
||||
<rect key="frame" x="164.66666666666666" y="269" width="85" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Ht-AF-MGW">
|
||||
<rect key="frame" x="186" y="298" width="42" height="30"/>
|
||||
<state key="normal" title="Touch"/>
|
||||
<connections>
|
||||
<segue destination="XaE-eF-eIt" kind="show" id="q3u-B9-6R6"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" label="MainView"/>
|
||||
<constraints>
|
||||
<constraint firstItem="YgP-SF-TkS" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="41Q-cm-l5K"/>
|
||||
<constraint firstItem="S56-6U-3gG" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="8UW-Nz-F04"/>
|
||||
<constraint firstItem="1Ht-AF-MGW" firstAttribute="top" secondItem="uiD-R4-b34" secondAttribute="bottom" constant="8" id="8f1-dz-ei9"/>
|
||||
<constraint firstItem="nbp-zX-Om1" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Ahr-dg-qwa"/>
|
||||
<constraint firstItem="1Ht-AF-MGW" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="BDr-QP-nJQ"/>
|
||||
<constraint firstItem="nbp-zX-Om1" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="29" id="GcP-yp-Ze6"/>
|
||||
<constraint firstItem="uiD-R4-b34" firstAttribute="top" secondItem="S56-6U-3gG" secondAttribute="bottom" constant="8" id="SPc-4k-0MA"/>
|
||||
<constraint firstItem="M2N-Yn-ytb" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Yr3-Lt-qdn"/>
|
||||
<constraint firstItem="YgP-SF-TkS" firstAttribute="top" secondItem="nbp-zX-Om1" secondAttribute="bottom" constant="8" id="b56-i5-Lxo"/>
|
||||
<constraint firstItem="uiD-R4-b34" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="nFx-Xr-rGC"/>
|
||||
<constraint firstItem="S56-6U-3gG" firstAttribute="top" secondItem="M2N-Yn-ytb" secondAttribute="bottom" constant="8" id="rMW-LW-ejO"/>
|
||||
<constraint firstItem="M2N-Yn-ytb" firstAttribute="top" secondItem="YgP-SF-TkS" secondAttribute="bottom" constant="8" id="tMN-gl-smg"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="dmu-Fe-aoT"/>
|
||||
<connections>
|
||||
<outlet property="orentationLabel" destination="uiD-R4-b34" id="ysn-P0-ADp"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="39.375" y="612.67605633802816"/>
|
||||
</scene>
|
||||
<!--Touch View Controller-->
|
||||
<scene sceneID="Sg1-EQ-IAj">
|
||||
<objects>
|
||||
<viewController id="XaE-eF-eIt" customClass="TouchViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="gEY-Ha-hqz"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="eVV-dI-eru"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="aEY-AK-0k9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="C6B-Wo-jWm" customClass="TouchableView">
|
||||
<rect key="frame" x="16" y="96.000000000000028" width="382" height="356.66666666666674"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="touchableView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="C6B-Wo-jWm" secondAttribute="height" multiplier="288:269" id="LeW-u7-tWl"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Taps" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IV8-Ak-Z8e">
|
||||
<rect key="frame" x="139" y="458.66666666666669" width="131" height="21"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="numberOfTapsLabel"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Touches" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q4X-EY-aSL">
|
||||
<rect key="frame" x="125" y="487.33333333333331" width="159" height="21"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="numberOfTouchesLabel"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="C6B-Wo-jWm" firstAttribute="top" secondItem="gEY-Ha-hqz" secondAttribute="bottom" constant="8" id="1PW-tn-oTF"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IV8-Ak-Z8e" secondAttribute="trailing" constant="144" id="5Tn-XG-5OD"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Q4X-EY-aSL" secondAttribute="trailing" constant="130" id="6Rr-L0-eoR"/>
|
||||
<constraint firstItem="IV8-Ak-Z8e" firstAttribute="firstBaseline" secondItem="C6B-Wo-jWm" secondAttribute="baseline" constant="24.5" symbolType="layoutAnchor" id="77y-Kf-c0Y"/>
|
||||
<constraint firstAttribute="trailing" secondItem="C6B-Wo-jWm" secondAttribute="trailing" constant="16" id="CaC-dk-dbo"/>
|
||||
<constraint firstItem="Q4X-EY-aSL" firstAttribute="leading" secondItem="aEY-AK-0k9" secondAttribute="leading" constant="125" id="Ych-oZ-hmA"/>
|
||||
<constraint firstItem="Q4X-EY-aSL" firstAttribute="top" secondItem="IV8-Ak-Z8e" secondAttribute="bottom" constant="7.5" id="ktv-kW-VWI"/>
|
||||
<constraint firstItem="C6B-Wo-jWm" firstAttribute="leading" secondItem="aEY-AK-0k9" secondAttribute="leading" constant="16" id="pI7-Ds-hXG"/>
|
||||
<constraint firstItem="IV8-Ak-Z8e" firstAttribute="leading" secondItem="aEY-AK-0k9" secondAttribute="leading" constant="139" id="vbu-wn-Qvc"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="fDl-EC-1lc"/>
|
||||
<connections>
|
||||
<outlet property="numberOfTapsLabel" destination="IV8-Ak-Z8e" id="Ymh-Kr-C7w"/>
|
||||
<outlet property="numberOfTouchesLabel" destination="Q4X-EY-aSL" id="fZ9-sH-tVY"/>
|
||||
<outlet property="touchable" destination="C6B-Wo-jWm" id="6kR-LD-GPA"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="3Oz-AA-uE1" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-15" y="1514.7887323943662"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="bWj-vr-GrF">
|
||||
<objects>
|
||||
<navigationController id="nJd-IZ-bfU" customClass="FBNavigationController" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="hZx-8U-FDw">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="Xg3-pw-x32"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="lCH-qk-44t" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-669" y="613"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="0V0-cO-CI5">
|
||||
<objects>
|
||||
<viewController id="65L-2T-0zt" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="dDG-qA-kaN"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="i3S-l1-3Mf"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ucg-Ag-VpP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Value" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="mxs-lj-ChP">
|
||||
<rect key="frame" x="20" y="99" width="374" height="34"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="" label=""/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
|
||||
</textField>
|
||||
<pageControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="Kpo-oC-QzU">
|
||||
<rect key="frame" x="161" y="324" width="39" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</pageControl>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="749" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="LZF-72-rfb">
|
||||
<rect key="frame" x="20" y="499" width="374" height="327"/>
|
||||
<mutableString key="text">1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901</mutableString>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<datePicker contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" datePickerMode="dateAndTime" minuteInterval="1" style="wheels" translatesAutoresizingMaskIntoConstraints="NO" id="dxw-sJ-Dkr">
|
||||
<rect key="frame" x="20" y="365" width="374" height="126"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="126" id="QRU-5e-MQt"/>
|
||||
</constraints>
|
||||
</datePicker>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Exq-MB-zeu">
|
||||
<rect key="frame" x="103.66666666666667" y="201" width="46.000000000000014" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Otl-5O-2Nq"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Button"/>
|
||||
<connections>
|
||||
<action selector="didTapButton:" destination="65L-2T-0zt" eventType="touchUpInside" id="G9g-YC-Y4j"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NJh-8E-4En">
|
||||
<rect key="frame" x="106.66666666666667" y="242" width="42.000000000000014" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="VBZ-ac-GvI"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Wim-fT-xNl">
|
||||
<rect key="frame" x="64" y="267" width="131" height="29"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="28" id="IoK-dx-Y4W"/>
|
||||
</constraints>
|
||||
<segments>
|
||||
<segment title="First"/>
|
||||
<segment title="Second"/>
|
||||
</segments>
|
||||
</segmentedControl>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="U7D-NR-20N">
|
||||
<rect key="frame" x="207" y="276" width="118" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="114" id="vy6-tS-yHd"/>
|
||||
</constraints>
|
||||
</slider>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SjL-dx-Zsi">
|
||||
<rect key="frame" x="235" y="314" width="51" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="49" id="dRJ-Hb-qNW"/>
|
||||
</constraints>
|
||||
</switch>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="w6h-ic-qpa">
|
||||
<rect key="frame" x="134" y="353" width="150" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="150" id="7Tf-hh-LKX"/>
|
||||
</constraints>
|
||||
</progressView>
|
||||
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="u8X-Wb-Od3">
|
||||
<rect key="frame" x="69" y="311" width="94" height="29"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="94" id="bNi-xp-G14"/>
|
||||
<constraint firstAttribute="height" constant="29" id="f0s-Rr-QTt"/>
|
||||
</constraints>
|
||||
</stepper>
|
||||
<label opaque="NO" userInteractionEnabled="NO" alpha="0.0" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="alpha_invisible" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ucg-0s-c50">
|
||||
<rect key="frame" x="224.33333333333334" y="197" width="111.66666666666666" height="21"/>
|
||||
<color key="backgroundColor" red="1" green="0.0" blue="0.041046944598614132" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="664-Z3-V7W"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="hidden_invisible" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vt6-b1-U0h">
|
||||
<rect key="frame" x="221.66666666666666" y="226" width="122.66666666666666" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="51j-sl-XYd"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GsS-jO-scK">
|
||||
<rect key="frame" x="174" y="248" width="103" height="30"/>
|
||||
<accessibility key="accessibilityConfiguration">
|
||||
<bool key="isElement" value="NO"/>
|
||||
</accessibility>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="e1t-Kp-sno"/>
|
||||
</constraints>
|
||||
<state key="normal" title="not_accessible"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="point" keyPath="accessibilityActivationPoint">
|
||||
<point key="value" x="200" y="220"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="bQv-RY-wkj">
|
||||
<rect key="frame" x="171" y="320" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Value2" borderStyle="roundedRect" textAlignment="natural" clearsOnBeginEditing="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Rab-I8-2aU">
|
||||
<rect key="frame" x="20" y="141" width="374" height="34"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="aIdentifier" label="aLabel"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="GsS-jO-scK" firstAttribute="leading" secondItem="Ucg-Ag-VpP" secondAttribute="leadingMargin" constant="154" id="1RA-Fx-3Jh"/>
|
||||
<constraint firstItem="SjL-dx-Zsi" firstAttribute="top" secondItem="U7D-NR-20N" secondAttribute="bottom" constant="8" id="3NW-Hc-tPr"/>
|
||||
<constraint firstItem="mxs-lj-ChP" firstAttribute="top" secondItem="dDG-qA-kaN" secondAttribute="bottom" constant="11" id="4Fw-0B-UwC"/>
|
||||
<constraint firstItem="GsS-jO-scK" firstAttribute="top" secondItem="vt6-b1-U0h" secondAttribute="bottom" constant="1" id="4cH-4W-5qo"/>
|
||||
<constraint firstItem="dxw-sJ-Dkr" firstAttribute="trailing" secondItem="Ucg-Ag-VpP" secondAttribute="trailingMargin" id="7fI-ha-3sR"/>
|
||||
<constraint firstItem="mxs-lj-ChP" firstAttribute="leading" secondItem="Ucg-Ag-VpP" secondAttribute="leadingMargin" id="8mv-f6-WQ6"/>
|
||||
<constraint firstItem="Rab-I8-2aU" firstAttribute="leading" secondItem="Ucg-Ag-VpP" secondAttribute="leadingMargin" id="AcZ-6f-OjT"/>
|
||||
<constraint firstItem="LZF-72-rfb" firstAttribute="trailing" secondItem="Ucg-Ag-VpP" secondAttribute="trailingMargin" id="BPl-7D-KX8"/>
|
||||
<constraint firstItem="dxw-sJ-Dkr" firstAttribute="top" secondItem="w6h-ic-qpa" secondAttribute="bottom" constant="8" id="CdC-6B-Sak"/>
|
||||
<constraint firstItem="LZF-72-rfb" firstAttribute="leading" secondItem="Ucg-Ag-VpP" secondAttribute="leadingMargin" id="FXH-2O-HhB"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="GsS-jO-scK" secondAttribute="trailingMargin" id="GOy-RG-tCC"/>
|
||||
<constraint firstItem="w6h-ic-qpa" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="2" id="JAL-PW-u0w"/>
|
||||
<constraint firstItem="i3S-l1-3Mf" firstAttribute="top" secondItem="LZF-72-rfb" secondAttribute="bottom" constant="36" id="K1W-hh-eAI"/>
|
||||
<constraint firstItem="Exq-MB-zeu" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="-80.5" id="KBS-g2-6jH"/>
|
||||
<constraint firstItem="vt6-b1-U0h" firstAttribute="top" secondItem="ucg-0s-c50" secondAttribute="bottom" constant="8" id="Kgr-uw-g1y"/>
|
||||
<constraint firstItem="Rab-I8-2aU" firstAttribute="trailing" secondItem="Ucg-Ag-VpP" secondAttribute="trailingMargin" id="PhW-Vk-nlO"/>
|
||||
<constraint firstItem="u8X-Wb-Od3" firstAttribute="top" secondItem="Wim-fT-xNl" secondAttribute="bottom" constant="16" id="RFW-ZE-Wxe"/>
|
||||
<constraint firstItem="Wim-fT-xNl" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="-77.5" id="Sd1-7h-RwK"/>
|
||||
<constraint firstItem="Wim-fT-xNl" firstAttribute="top" secondItem="NJh-8E-4En" secondAttribute="bottom" constant="4" id="TXS-dN-R68"/>
|
||||
<constraint firstItem="NJh-8E-4En" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="-79.5" id="Xqj-5G-gWd"/>
|
||||
<constraint firstItem="w6h-ic-qpa" firstAttribute="top" secondItem="SjL-dx-Zsi" secondAttribute="bottom" constant="8" id="YmL-M2-lGN"/>
|
||||
<constraint firstItem="Exq-MB-zeu" firstAttribute="top" secondItem="Rab-I8-2aU" secondAttribute="bottom" constant="26" id="aLQ-Gz-cjx"/>
|
||||
<constraint firstItem="dxw-sJ-Dkr" firstAttribute="leading" secondItem="Ucg-Ag-VpP" secondAttribute="leadingMargin" id="amt-aZ-NnD"/>
|
||||
<constraint firstItem="mxs-lj-ChP" firstAttribute="trailing" secondItem="Ucg-Ag-VpP" secondAttribute="trailingMargin" id="b9B-Xj-ypz"/>
|
||||
<constraint firstItem="SjL-dx-Zsi" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="52.5" id="c5J-nU-AFi"/>
|
||||
<constraint firstItem="bQv-RY-wkj" firstAttribute="top" secondItem="Wim-fT-xNl" secondAttribute="bottom" constant="25" id="dOt-dS-sb7"/>
|
||||
<constraint firstItem="bQv-RY-wkj" firstAttribute="leading" secondItem="u8X-Wb-Od3" secondAttribute="trailing" constant="8" id="dq2-ZM-aAA"/>
|
||||
<constraint firstItem="LZF-72-rfb" firstAttribute="top" secondItem="dxw-sJ-Dkr" secondAttribute="bottom" constant="8" id="hqc-Vg-E1h"/>
|
||||
<constraint firstItem="U7D-NR-20N" firstAttribute="top" secondItem="vt6-b1-U0h" secondAttribute="bottom" constant="29" id="n1M-yh-Yr6"/>
|
||||
<constraint firstItem="u8X-Wb-Od3" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="-91" id="ocA-VF-afs"/>
|
||||
<constraint firstItem="vt6-b1-U0h" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="76" id="odm-dZ-IbR"/>
|
||||
<constraint firstItem="ucg-0s-c50" firstAttribute="top" secondItem="Rab-I8-2aU" secondAttribute="bottom" constant="22" id="pc0-2N-b6J"/>
|
||||
<constraint firstItem="NJh-8E-4En" firstAttribute="top" secondItem="Exq-MB-zeu" secondAttribute="bottom" constant="11" id="qTa-xu-PhV"/>
|
||||
<constraint firstItem="Rab-I8-2aU" firstAttribute="top" secondItem="mxs-lj-ChP" secondAttribute="bottom" constant="8" id="sDU-d6-48t"/>
|
||||
<constraint firstItem="U7D-NR-20N" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="59" id="spY-Aq-rh9"/>
|
||||
<constraint firstItem="ucg-0s-c50" firstAttribute="centerX" secondItem="Ucg-Ag-VpP" secondAttribute="centerX" constant="73" id="xoU-03-2dV"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="Hk7-AH-JlS"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="0f2-qL-RU6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1188.75" y="1217.9577464788733"/>
|
||||
</scene>
|
||||
<!--Alert View Controller-->
|
||||
<scene sceneID="sNK-H9-0Zl">
|
||||
<objects>
|
||||
<viewController id="gK5-IX-eJx" customClass="FBAlertViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Ew1-ik-0G1"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="LIO-6E-0HO"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="JWE-cA-TW0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="y1x-J5-Nkw">
|
||||
<rect key="frame" x="101.66666666666669" y="113" width="211" height="30"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="textField"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="B7B-wI-RFc"/>
|
||||
<constraint firstAttribute="width" constant="211" id="zSX-10-aQg"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4VK-4B-FEF">
|
||||
<rect key="frame" x="149.66666666666666" y="194" width="113.99999999999997" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="xsL-Fq-mly"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create App Alert"/>
|
||||
<connections>
|
||||
<action selector="createAppAlert:" destination="gK5-IX-eJx" eventType="touchUpInside" id="t44-BA-HSi"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OQt-5y-Tft">
|
||||
<rect key="frame" x="124" y="232" width="166" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Y5y-Th-63a"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create Notification Alert"/>
|
||||
<connections>
|
||||
<action selector="createNotificationAlert:" destination="gK5-IX-eJx" eventType="touchUpInside" id="haL-pV-hTV"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rG5-3k-LFe">
|
||||
<rect key="frame" x="122" y="270" width="169" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="im5-w3-Pgi"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create Camera Roll Alert"/>
|
||||
<connections>
|
||||
<action selector="createCameraRollAccessAlert:" destination="gK5-IX-eJx" eventType="touchUpInside" id="T8R-HK-sEe"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ntr-45-Ycd">
|
||||
<rect key="frame" x="123" y="308" width="168" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="4B7-LM-UwV"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create GPS access Alert"/>
|
||||
<connections>
|
||||
<action selector="createGPSAccessAlert:" destination="gK5-IX-eJx" eventType="touchUpInside" id="gcM-Ip-10b"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CZ1-7J-OGl">
|
||||
<rect key="frame" x="66.666666666666671" y="176" width="46" height="30"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="button"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="tJH-wr-O3J"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Button"/>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="plO-2e-XmX">
|
||||
<rect key="frame" x="304.66666666666669" y="180" width="42" height="21"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="label"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="2qA-NT-ddc"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3Zk-wE-jwj">
|
||||
<rect key="frame" x="144" y="346" width="126" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Mk4-bk-Y0L"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create Sheet Alert"/>
|
||||
<connections>
|
||||
<action selector="createAppSheet:" destination="gK5-IX-eJx" eventType="touchUpInside" id="U6X-fw-xU2"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="D7g-22-s49">
|
||||
<rect key="frame" x="116" y="384" width="182" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="TzV-CY-64y"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Create Alert (Force Touch)"/>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="3Zk-wE-jwj" firstAttribute="centerX" secondItem="JWE-cA-TW0" secondAttribute="centerX" id="83u-1W-xLt"/>
|
||||
<constraint firstItem="D7g-22-s49" firstAttribute="centerX" secondItem="JWE-cA-TW0" secondAttribute="centerX" id="9nT-k0-9gf"/>
|
||||
<constraint firstItem="ntr-45-Ycd" firstAttribute="top" secondItem="rG5-3k-LFe" secondAttribute="bottom" constant="8" id="DYt-NB-TSO"/>
|
||||
<constraint firstItem="3Zk-wE-jwj" firstAttribute="top" secondItem="ntr-45-Ycd" secondAttribute="bottom" constant="8" id="Edq-zL-Soc"/>
|
||||
<constraint firstItem="y1x-J5-Nkw" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="117.5" id="Ell-4O-Iqa"/>
|
||||
<constraint firstItem="4VK-4B-FEF" firstAttribute="top" secondItem="y1x-J5-Nkw" secondAttribute="bottom" constant="51" id="JnR-cD-vZE"/>
|
||||
<constraint firstItem="OQt-5y-Tft" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="117.5" id="LQq-Br-Fda"/>
|
||||
<constraint firstItem="y1x-J5-Nkw" firstAttribute="centerX" secondItem="JWE-cA-TW0" secondAttribute="centerX" id="M6w-gn-nXE"/>
|
||||
<constraint firstItem="ntr-45-Ycd" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="117.5" id="Qj1-d9-KDa"/>
|
||||
<constraint firstItem="CZ1-7J-OGl" firstAttribute="top" secondItem="y1x-J5-Nkw" secondAttribute="bottom" constant="33" id="UHk-wV-Ehk"/>
|
||||
<constraint firstItem="D7g-22-s49" firstAttribute="top" secondItem="3Zk-wE-jwj" secondAttribute="bottom" constant="8" id="eML-6C-Von"/>
|
||||
<constraint firstItem="plO-2e-XmX" firstAttribute="top" secondItem="y1x-J5-Nkw" secondAttribute="bottom" constant="37" id="f0Z-LP-5Dg"/>
|
||||
<constraint firstItem="4VK-4B-FEF" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="117" id="fDG-Jl-VER"/>
|
||||
<constraint firstItem="y1x-J5-Nkw" firstAttribute="top" secondItem="Ew1-ik-0G1" secondAttribute="bottom" constant="25" id="gaL-qu-PB6"/>
|
||||
<constraint firstItem="plO-2e-XmX" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="236" id="h2I-eE-doE"/>
|
||||
<constraint firstItem="OQt-5y-Tft" firstAttribute="top" secondItem="4VK-4B-FEF" secondAttribute="bottom" constant="8" id="q3k-Mr-OUS"/>
|
||||
<constraint firstItem="rG5-3k-LFe" firstAttribute="top" secondItem="OQt-5y-Tft" secondAttribute="bottom" constant="8" id="tBP-U5-8Lx"/>
|
||||
<constraint firstItem="rG5-3k-LFe" firstAttribute="centerX" secondItem="CZ1-7J-OGl" secondAttribute="centerX" constant="117" id="wCj-0t-gIY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="nfx-Tv-5Z0"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="B30-xl-1JX" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1216" y="-319"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="9RM-JC-4C4">
|
||||
<objects>
|
||||
<viewController id="YzO-du-v3Y" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="yvD-8P-ibI"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="REj-tv-GYS"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="55R-aH-x4M">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vYb-QB-vwU">
|
||||
<rect key="frame" x="172.66666666666666" y="108" width="69" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="ymh-D3-SCA"/>
|
||||
</constraints>
|
||||
<state key="normal" title="TableView"/>
|
||||
<connections>
|
||||
<segue destination="3ur-D9-8FT" kind="show" animates="NO" id="yJb-Fl-2fY"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FdB-fa-0bl">
|
||||
<rect key="frame" x="171" y="146" width="72" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Xas-AZ-Nyw"/>
|
||||
</constraints>
|
||||
<state key="normal" title="ScrollView"/>
|
||||
<connections>
|
||||
<segue destination="GI0-zX-z7l" kind="show" animates="NO" id="iVA-s3-kPd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="vYb-QB-vwU" firstAttribute="centerX" secondItem="55R-aH-x4M" secondAttribute="centerX" id="0MT-Eq-8dG"/>
|
||||
<constraint firstItem="vYb-QB-vwU" firstAttribute="top" secondItem="yvD-8P-ibI" secondAttribute="bottom" constant="20" id="c3y-G3-HCj"/>
|
||||
<constraint firstItem="FdB-fa-0bl" firstAttribute="centerX" secondItem="55R-aH-x4M" secondAttribute="centerX" id="gE9-Mi-Jcm"/>
|
||||
<constraint firstItem="FdB-fa-0bl" firstAttribute="top" secondItem="vYb-QB-vwU" secondAttribute="bottom" constant="8" id="zLx-S1-Tnz"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="6Qr-Yi-87y"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="CvZ-nE-CBk" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1216" y="422"/>
|
||||
</scene>
|
||||
<!--Table View Controller-->
|
||||
<scene sceneID="ow4-nH-afF">
|
||||
<objects>
|
||||
<tableViewController id="3ur-D9-8FT" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="jo0-3M-nUd">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="2mC-E2-VxB" style="IBUITableViewCellStyleDefault" id="wCs-18-PFf">
|
||||
<rect key="frame" x="0.0" y="50" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wCs-18-PFf" id="0KF-km-gbT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2mC-E2-VxB">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="scrollView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="TxP-Aa-p9i" id="IDu-Y4-oQL"/>
|
||||
<outlet property="delegate" destination="3ur-D9-8FT" id="saC-SY-CSo"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" id="szz-4K-52y"/>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="21y-mk-Cmx" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<customObject id="TxP-Aa-p9i" customClass="FBTableDataSource"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2302" y="97"/>
|
||||
</scene>
|
||||
<!--Scroll View Controller-->
|
||||
<scene sceneID="cZ2-Pn-cVV">
|
||||
<objects>
|
||||
<viewController id="GI0-zX-z7l" customClass="FBScrollViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="o0k-ze-PY2"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="1qn-YR-FCf"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="KLL-RT-L40">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xEQ-MI-a2g">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="862"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="scrollView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="xEQ-MI-a2g" firstAttribute="top" secondItem="KLL-RT-L40" secondAttribute="top" id="Bep-no-nwg"/>
|
||||
<constraint firstAttribute="trailing" secondItem="xEQ-MI-a2g" secondAttribute="trailing" id="akP-zz-jsv"/>
|
||||
<constraint firstItem="xEQ-MI-a2g" firstAttribute="leading" secondItem="KLL-RT-L40" secondAttribute="leading" id="eVn-mL-sBX"/>
|
||||
<constraint firstItem="1qn-YR-FCf" firstAttribute="top" secondItem="xEQ-MI-a2g" secondAttribute="bottom" id="kg2-Z3-oRO"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="QQ9-xy-IwS"/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Vxa-lD-ODn" id="ti0-a9-iaY"/>
|
||||
<outlet property="scrollView" destination="xEQ-MI-a2g" id="ZBD-iW-x6Q"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="fpw-oW-WXe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<customObject id="Vxa-lD-ODn" customClass="FBTableDataSource"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2302" y="746"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
15
WebDriverAgentTests/IntegrationApp/main.m
Normal file
15
WebDriverAgentTests/IntegrationApp/main.m
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, @"AppDelegate");
|
||||
}
|
||||
}
|
||||
188
WebDriverAgentTests/IntegrationTests/FBAlertTests.m
Normal file
188
WebDriverAgentTests/IntegrationTests/FBAlertTests.m
Normal 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
|
||||
@@ -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
|
||||
38
WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m
Normal file
38
WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m
Normal 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
|
||||
250
WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m
Normal file
250
WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m
Normal 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
|
||||
127
WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m
Normal file
127
WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
85
WebDriverAgentTests/IntegrationTests/FBForceTouchTests.m
Normal file
85
WebDriverAgentTests/IntegrationTests/FBForceTouchTests.m
Normal 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
|
||||
82
WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m
Normal file
82
WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m
Normal 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
|
||||
|
||||
76
WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h
Normal file
76
WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h
Normal 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
|
||||
140
WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m
Normal file
140
WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m
Normal 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
|
||||
61
WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m
Normal file
61
WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m
Normal 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
|
||||
91
WebDriverAgentTests/IntegrationTests/FBPasteboardTests.m
Normal file
91
WebDriverAgentTests/IntegrationTests/FBPasteboardTests.m
Normal 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
|
||||
|
||||
|
||||
@@ -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
|
||||
73
WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m
Normal file
73
WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m
Normal 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
|
||||
31
WebDriverAgentTests/IntegrationTests/FBScreenTests.m
Normal file
31
WebDriverAgentTests/IntegrationTests/FBScreenTests.m
Normal 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
|
||||
|
||||
126
WebDriverAgentTests/IntegrationTests/FBScrollingTests.m
Normal file
126
WebDriverAgentTests/IntegrationTests/FBScrollingTests.m
Normal 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
|
||||
|
||||
133
WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m
Normal file
133
WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m
Normal 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
|
||||
103
WebDriverAgentTests/IntegrationTests/FBTapTest.m
Normal file
103
WebDriverAgentTests/IntegrationTests/FBTapTest.m
Normal 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
|
||||
33
WebDriverAgentTests/IntegrationTests/FBTestMacros.h
Normal file
33
WebDriverAgentTests/IntegrationTests/FBTestMacros.h
Normal 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)
|
||||
68
WebDriverAgentTests/IntegrationTests/FBTypingTest.m
Normal file
68
WebDriverAgentTests/IntegrationTests/FBTypingTest.m
Normal 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
|
||||
64
WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m
Normal file
64
WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
184
WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m
Normal file
184
WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m
Normal 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
|
||||
157
WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m
Normal file
157
WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m
Normal 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
|
||||
24
WebDriverAgentTests/IntegrationTests/Info.plist
Normal file
24
WebDriverAgentTests/IntegrationTests/Info.plist
Normal 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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
220
WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m
Normal file
220
WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
472
WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m
Normal file
472
WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m
Normal 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
|
||||
@@ -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
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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>
|
||||
|
||||
@interface XCElementSnapshotDouble : NSObject<XCUIElementAttributes>
|
||||
@property (readwrite, nullable) id value;
|
||||
@property (readwrite, nullable, copy) NSString *label;
|
||||
@property (nonatomic, assign) UIAccessibilityTraits traits;
|
||||
@end
|
||||
114
WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m
Normal file
114
WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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 "XCElementSnapshotDouble.h"
|
||||
|
||||
#import "FBXCAccessibilityElement.h"
|
||||
#import "FBXCElementSnapshot.h"
|
||||
#import "XCUIHitPointResult.h"
|
||||
|
||||
@implementation XCElementSnapshotDouble
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
self->_value = @"magicValue";
|
||||
self->_label = @"testLabel";
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)identifier
|
||||
{
|
||||
return @"testName";
|
||||
}
|
||||
|
||||
- (CGRect)frame
|
||||
{
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
- (NSString *)title
|
||||
{
|
||||
return @"testTitle";
|
||||
}
|
||||
|
||||
- (XCUIElementType)elementType
|
||||
{
|
||||
return XCUIElementTypeOther;
|
||||
}
|
||||
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (XCUIUserInterfaceSizeClass)horizontalSizeClass
|
||||
{
|
||||
return XCUIUserInterfaceSizeClassUnspecified;
|
||||
}
|
||||
|
||||
- (XCUIUserInterfaceSizeClass)verticalSizeClass
|
||||
{
|
||||
return XCUIUserInterfaceSizeClassUnspecified;
|
||||
}
|
||||
|
||||
- (NSString *)placeholderValue
|
||||
{
|
||||
return @"testPlaceholderValue";
|
||||
}
|
||||
|
||||
- (BOOL)isSelected
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)hasFocus
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSDictionary *)additionalAttributes
|
||||
{
|
||||
return @{};
|
||||
}
|
||||
|
||||
- (id<FBXCAccessibilityElement>)accessibilityElement
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id<FBXCElementSnapshot>)parent
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (XCUIHitPointResult *)hitPoint:(NSError **)error
|
||||
{
|
||||
return [[XCUIHitPointResult alloc] initWithHitPoint:CGPointZero hittable:YES];
|
||||
}
|
||||
|
||||
- (NSArray *)children
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (NSArray *)_allDescendants
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (CGRect)visibleFrame
|
||||
{
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
- (UIAccessibilityTraits)traits
|
||||
{
|
||||
return UIAccessibilityTraitButton;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@interface XCUIApplicationDouble : NSObject
|
||||
@property (nonatomic, assign, readonly) BOOL didTerminate;
|
||||
@property (nonatomic, strong) NSString* bundleID;
|
||||
@property (nonatomic) BOOL fb_shouldWaitForQuiescence;
|
||||
|
||||
- (BOOL)running;
|
||||
@end
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 "XCUIApplicationDouble.h"
|
||||
|
||||
@interface XCUIApplicationDouble ()
|
||||
@property (nonatomic, assign, readwrite) BOOL didTerminate;
|
||||
@end
|
||||
|
||||
@implementation XCUIApplicationDouble
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_bundleID = @"some.bundle.identifier";
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)terminate
|
||||
{
|
||||
self.didTerminate = YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)processID
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSString *)bundleID
|
||||
{
|
||||
return @"com.facebook.awesome";
|
||||
}
|
||||
|
||||
- (void)fb_nativeResolve
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (id)query
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)fb_shouldWaitForQuiescence
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)setFb_shouldWaitForQuiescence:(BOOL)value
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)running
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
50
WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h
Normal file
50
WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 <Foundation/Foundation.h>
|
||||
#import <WebDriverAgentLib/FBElement.h>
|
||||
#import <XCTest/XCUIElementTypes.h>
|
||||
|
||||
@class XCUIApplication;
|
||||
|
||||
@interface XCUIElementDouble : NSObject<FBElement>
|
||||
@property (nonatomic, strong, nonnull) XCUIApplication *application;
|
||||
@property (nonatomic, readwrite, assign) CGRect frame;
|
||||
@property (nonatomic, readwrite, nullable) id lastSnapshot;
|
||||
@property (nonatomic, assign) BOOL fb_isObstructedByAlert;
|
||||
@property (nonatomic, readonly, nonnull) NSString *fb_cacheId;
|
||||
@property (nonatomic, readwrite, copy, nonnull) NSDictionary *wdRect;
|
||||
@property (nonatomic, readwrite, assign) CGRect wdFrame;
|
||||
@property (nonatomic, readwrite, copy, nonnull) NSString *wdUID;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdName;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdLabel;
|
||||
@property (nonatomic, copy, readwrite, nonnull) NSString *wdType;
|
||||
@property (nonatomic, strong, readwrite, nullable) NSString *wdValue;
|
||||
@property (nonatomic, readwrite, getter=isWDEnabled) BOOL wdEnabled;
|
||||
@property (nonatomic, readwrite, getter=isWDSelected) BOOL wdSelected;
|
||||
@property (nonatomic, readwrite, assign) CGRect wdNativeFrame;
|
||||
@property (nonatomic, readwrite) NSUInteger wdIndex;
|
||||
@property (nonatomic, readwrite, getter=isWDVisible) BOOL wdVisible;
|
||||
@property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible;
|
||||
@property (nonatomic, readwrite, getter = isWDFocused) BOOL wdFocused;
|
||||
@property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdPlaceholderValue;
|
||||
@property (copy, nonnull) NSArray *children;
|
||||
@property (nonatomic, readwrite, assign) XCUIElementType elementType;
|
||||
@property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdTraits;
|
||||
|
||||
- (void)resolve;
|
||||
- (id _Nonnull)fb_standardSnapshot;
|
||||
- (id _Nonnull)fb_customSnapshot;
|
||||
- (nullable id)query;
|
||||
|
||||
// Checks
|
||||
@property (nonatomic, assign, readonly) BOOL didResolve;
|
||||
|
||||
@end
|
||||
103
WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m
Normal file
103
WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m
Normal 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 "XCUIElementDouble.h"
|
||||
|
||||
@interface XCUIElementDouble ()
|
||||
@property (nonatomic, assign, readwrite) BOOL didResolve;
|
||||
@end
|
||||
|
||||
@implementation XCUIElementDouble
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.wdFrame = CGRectZero;
|
||||
self.wdNativeFrame = CGRectZero;
|
||||
self.wdName = @"testName";
|
||||
self.wdLabel = @"testLabel";
|
||||
self.wdValue = @"magicValue";
|
||||
self.wdPlaceholderValue = @"testPlaceholderValue";
|
||||
self.wdTraits = @"testTraits";
|
||||
self.wdVisible = YES;
|
||||
self.wdAccessible = YES;
|
||||
self.wdEnabled = YES;
|
||||
self.wdSelected = YES;
|
||||
self.wdFocused = YES;
|
||||
self.wdHittable = YES;
|
||||
self.wdIndex = 0;
|
||||
#if TARGET_OS_TV
|
||||
self.wdFocused = YES;
|
||||
#endif
|
||||
self.children = @[];
|
||||
self.wdRect = @{@"x": @0,
|
||||
@"y": @0,
|
||||
@"width": @0,
|
||||
@"height": @0,
|
||||
};
|
||||
self.wdAccessibilityContainer = NO;
|
||||
self.elementType = XCUIElementTypeOther;
|
||||
self.wdType = @"XCUIElementTypeOther";
|
||||
self.wdUID = @"0";
|
||||
self.lastSnapshot = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)fb_valueForWDAttributeName:(NSString *)name
|
||||
{
|
||||
return @"test";
|
||||
}
|
||||
|
||||
- (id)query
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)resolve
|
||||
{
|
||||
self.didResolve = YES;
|
||||
}
|
||||
|
||||
- (void)fb_nativeResolve
|
||||
{
|
||||
self.didResolve = YES;
|
||||
}
|
||||
|
||||
- (id _Nonnull)fb_standardSnapshot;
|
||||
{
|
||||
return [self lastSnapshot];
|
||||
}
|
||||
|
||||
- (id _Nonnull)fb_customSnapshot;
|
||||
{
|
||||
return [self lastSnapshot];
|
||||
}
|
||||
|
||||
- (NSString *)fb_cacheId
|
||||
{
|
||||
return self.wdUID;
|
||||
}
|
||||
|
||||
- (id)lastSnapshot
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)fb_uid
|
||||
{
|
||||
return self.wdUID;
|
||||
}
|
||||
|
||||
- (NSString *)wdTraits
|
||||
{
|
||||
return self.wdTraits;
|
||||
}
|
||||
|
||||
@end
|
||||
313
WebDriverAgentTests/UnitTests/FBClassChainTests.m
Normal file
313
WebDriverAgentTests/UnitTests/FBClassChainTests.m
Normal file
@@ -0,0 +1,313 @@
|
||||
/**
|
||||
* 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 "XCUIElementDouble.h"
|
||||
#import "FBClassChainQueryParser.h"
|
||||
|
||||
@interface FBClassChainTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBClassChainTests
|
||||
|
||||
- (void)testValidChain
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithStar
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[3]/*[4]/*[5]/XCUIElementTypeAlert" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 5);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertEqual(secondElement.position.integerValue, 3);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
|
||||
FBClassChainItem *thirdElement = [result.elements objectAtIndex:2];
|
||||
XCTAssertEqual(thirdElement.type, XCUIElementTypeAny);
|
||||
XCTAssertEqual(thirdElement.position.integerValue, 4);
|
||||
XCTAssertFalse(thirdElement.isDescendant);
|
||||
|
||||
FBClassChainItem *fourthElement = [result.elements objectAtIndex:3];
|
||||
XCTAssertEqual(fourthElement.type, XCUIElementTypeAny);
|
||||
XCTAssertEqual(fourthElement.position.integerValue, 5);
|
||||
XCTAssertFalse(fourthElement.isDescendant);
|
||||
|
||||
FBClassChainItem *fifthsElement = [result.elements objectAtIndex:4];
|
||||
XCTAssertEqual(fifthsElement.type, XCUIElementTypeAlert);
|
||||
XCTAssertNil(fifthsElement.position);
|
||||
XCTAssertFalse(fifthsElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidSingleStarChain
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 1);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidSingleStarIndirectChain
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/*/*/XCUIElementTypeButton" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 3);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeAny);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
|
||||
FBClassChainItem *thirdElement = [result.elements objectAtIndex:2];
|
||||
XCTAssertEqual(thirdElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(thirdElement.position);
|
||||
XCTAssertFalse(thirdElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidDoubleIndirectChainAndStar
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/*" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeAny);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertTrue(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidDoubleIndirectChainAndClassName
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeButton/**/XCUIElementTypeImage" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeImage);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertTrue(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithNegativeIndex
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow/XCUIElementTypeButton[-1]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertEqual(firstElement.predicates.count, 0);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertEqual(secondElement.position.integerValue, -1);
|
||||
XCTAssertEqual(secondElement.predicates.count, 0);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithSinglePredicate
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertEqual(firstElement.predicates.count, 1);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertEqual(secondElement.predicates.count, 0);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithMultiplePredicates
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"XCUIElementTypeWindow[`name == 'blabla'`]/XCUIElementTypeButton[`value == 'blabla'`]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeWindow);
|
||||
XCTAssertNil(firstElement.position);
|
||||
XCTAssertEqual(firstElement.predicates.count, 1);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertEqual(secondElement.predicates.count, 1);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithIndirectSearchAndPredicates
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[`name == 'blabla'`][10]/**/XCUIElementTypeButton[`value == 'blabla'`]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
|
||||
XCTAssertEqual(firstElement.position.integerValue, 10);
|
||||
XCTAssertEqual(firstElement.predicates.count, 1);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertNil(secondElement.position);
|
||||
XCTAssertEqual(secondElement.predicates.count, 1);
|
||||
XCTAssertTrue(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithMultiplePredicatesAndPositions
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"*[`name == \"к``ири````'лиця\"`][3]/XCUIElementTypeButton[`value == \"blabla\"`][-1]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 2);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeAny);
|
||||
XCTAssertEqual(firstElement.position.integerValue, 3);
|
||||
XCTAssertEqual(firstElement.predicates.count, 1);
|
||||
XCTAssertFalse(firstElement.isDescendant);
|
||||
|
||||
FBClassChainItem *secondElement = [result.elements objectAtIndex:1];
|
||||
XCTAssertEqual(secondElement.type, XCUIElementTypeButton);
|
||||
XCTAssertEqual(secondElement.position.integerValue, -1);
|
||||
XCTAssertEqual(secondElement.predicates.count, 1);
|
||||
XCTAssertFalse(secondElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithDescendantPredicate
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`name == 'blabla'`][10]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 1);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
|
||||
XCTAssertEqual(firstElement.position.integerValue, 10);
|
||||
XCTAssertEqual(firstElement.predicates.count, 2);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testValidChainWithMultipleDescendantPredicates
|
||||
{
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:@"**/XCUIElementTypeTable[$type == 'XCUIElementTypeImage' AND name == 'olala'$][`value == 'peace'`][$value == 'yolo'$][`name == 'blabla'`][10]" error:&error];
|
||||
XCTAssertNotNil(result);
|
||||
XCTAssertEqual(result.elements.count, 1);
|
||||
|
||||
FBClassChainItem *firstElement = [result.elements firstObject];
|
||||
XCTAssertEqual(firstElement.type, XCUIElementTypeTable);
|
||||
XCTAssertEqual(firstElement.position.integerValue, 10);
|
||||
XCTAssertEqual(firstElement.predicates.count, 4);
|
||||
XCTAssertTrue(firstElement.isDescendant);
|
||||
}
|
||||
|
||||
- (void)testInvalidChains
|
||||
{
|
||||
NSArray *invalidQueries = @[
|
||||
@"/XCUIElementTypeWindow"
|
||||
,@"XCUIElementTypeWindow/"
|
||||
,@"XCUIElementTypeWindow//*"
|
||||
,@"XCUIElementTypeWindow*/*"
|
||||
,@"**"
|
||||
,@"***"
|
||||
,@"**/*/**"
|
||||
,@"/**"
|
||||
,@"XCUIElementTypeWindow/**"
|
||||
,@"**[1]/XCUIElementTypeWindow"
|
||||
,@"**[`name == '1'`]/XCUIElementTypeWindow"
|
||||
,@"XCUIElementTypeWindow[0]"
|
||||
,@"XCUIElementTypeWindow[1][1]"
|
||||
,@"blabla"
|
||||
,@"XCUIElementTypeWindow/blabla"
|
||||
,@" XCUIElementTypeWindow"
|
||||
,@"XCUIElementTypeWindow[ 2 ]"
|
||||
,@"XCUIElementTypeWindow[[2]"
|
||||
,@"XCUIElementTypeWindow[2]]"
|
||||
,@"XCUIElementType[Window[2]]"
|
||||
,@"XCUIElementTypeWindow[visible = 1]"
|
||||
,@"XCUIElementTypeWindow[1][`visible = 1`]"
|
||||
,@"XCUIElementTypeWindow[1] [`visible = 1`]"
|
||||
,@"XCUIElementTypeWindow[ `visible = 1`]"
|
||||
,@"XCUIElementTypeWindow[`visible = 1][`name = \"bla\"`]"
|
||||
,@"XCUIElementTypeWindow[`visible = 1]"
|
||||
,@"XCUIElementTypeWindow[$visible = 1]"
|
||||
,@"XCUIElementTypeWindow[``]"
|
||||
,@"XCUIElementTypeWindow[$$]"
|
||||
,@"XCUIElementTypeWindow[`name = \"bla```bla\"`]"
|
||||
,@"XCUIElementTypeWindow[$name = \"bla$$$bla\"$]"
|
||||
];
|
||||
for (NSString *invalidQuery in invalidQueries) {
|
||||
NSError *error;
|
||||
FBClassChain *result = [FBClassChainQueryParser parseQuery:invalidQuery error:&error];
|
||||
XCTAssertNil(result);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
48
WebDriverAgentTests/UnitTests/FBConfigurationTests.m
Normal file
48
WebDriverAgentTests/UnitTests/FBConfigurationTests.m
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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 "FBConfiguration.h"
|
||||
|
||||
@interface FBConfigurationTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBConfigurationTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
unsetenv("USE_PORT");
|
||||
unsetenv("VERBOSE_LOGGING");
|
||||
}
|
||||
|
||||
- (void)testBindingPortDefault
|
||||
{
|
||||
XCTAssertTrue(NSEqualRanges([FBConfiguration bindingPortRange], NSMakeRange(8100, 100)));
|
||||
}
|
||||
|
||||
- (void)testBindingPortEnvironmentOverwrite
|
||||
{
|
||||
setenv("USE_PORT", "1000", 1);
|
||||
XCTAssertTrue(NSEqualRanges([FBConfiguration bindingPortRange], NSMakeRange(1000, 1)));
|
||||
}
|
||||
|
||||
- (void)testVerboseLoggingDefault
|
||||
{
|
||||
XCTAssertFalse([FBConfiguration verboseLoggingEnabled]);
|
||||
}
|
||||
|
||||
- (void)testVerboseLoggingEnvironmentOverwrite
|
||||
{
|
||||
setenv("VERBOSE_LOGGING", "YES", 1);
|
||||
XCTAssertTrue([FBConfiguration verboseLoggingEnabled]);
|
||||
}
|
||||
|
||||
@end
|
||||
124
WebDriverAgentTests/UnitTests/FBElementCacheTests.m
Normal file
124
WebDriverAgentTests/UnitTests/FBElementCacheTests.m
Normal 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 "FBElementCache.h"
|
||||
#import "XCUIElementDouble.h"
|
||||
#import "XCUIElement+FBCaching.h"
|
||||
#import "XCUIElement+FBUtilities.h"
|
||||
|
||||
@interface FBElementCacheTests : XCTestCase
|
||||
@property (nonatomic, strong) FBElementCache *cache;
|
||||
@end
|
||||
|
||||
@implementation FBElementCacheTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
self.cache = [FBElementCache new];
|
||||
}
|
||||
|
||||
- (void)testStoringElement
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
el1.wdUID = @"1";
|
||||
XCUIElementDouble *el2 = XCUIElementDouble.new;
|
||||
el2.wdUID = @"2";
|
||||
NSString *firstUUID = [self.cache storeElement:(XCUIElement *)el1];
|
||||
NSString *secondUUID = [self.cache storeElement:(XCUIElement *)el2];
|
||||
XCTAssertEqualObjects(firstUUID, el1.wdUID);
|
||||
XCTAssertEqualObjects(secondUUID, el2.wdUID);
|
||||
}
|
||||
|
||||
- (void)testFetchingElement
|
||||
{
|
||||
XCUIElement *element = (XCUIElement *)XCUIElementDouble.new;
|
||||
NSString *uuid = [self.cache storeElement:element];
|
||||
XCTAssertNotNil(uuid, @"Stored index should be higher than 0");
|
||||
XCUIElement *cachedElement = [self.cache elementForUUID:uuid];
|
||||
XCTAssertEqual(element, cachedElement);
|
||||
}
|
||||
|
||||
- (void)testFetchingBadIndex
|
||||
{
|
||||
XCTAssertThrows([self.cache elementForUUID:@"random"]);
|
||||
}
|
||||
|
||||
- (void)testLinearCacheExpulsion
|
||||
{
|
||||
const int ELEMENT_COUNT = 1050;
|
||||
|
||||
NSMutableArray *elements = [NSMutableArray arrayWithCapacity:ELEMENT_COUNT];
|
||||
NSMutableArray *elementIds = [NSMutableArray arrayWithCapacity:ELEMENT_COUNT];
|
||||
for(int i = 0; i < ELEMENT_COUNT; i++) {
|
||||
XCUIElementDouble *el = XCUIElementDouble.new;
|
||||
el.wdUID = [NSString stringWithFormat:@"%@", @(i)];
|
||||
[elements addObject:(XCUIElement *)el];
|
||||
}
|
||||
|
||||
// The capacity of the cache is limited to 1024 elements. Add 1050
|
||||
// elements and make sure:
|
||||
// - The first 26 elements are no longer present in the cache
|
||||
// - The remaining 1024 elements are present in the cache
|
||||
for(int i = 0; i < ELEMENT_COUNT; i++) {
|
||||
[elementIds addObject:[self.cache storeElement:elements[i]]];
|
||||
}
|
||||
|
||||
for(int i = 0; i < ELEMENT_COUNT - ELEMENT_CACHE_SIZE; i++) {
|
||||
XCTAssertThrows([self.cache elementForUUID:elementIds[i]]);
|
||||
}
|
||||
for(int i = ELEMENT_COUNT - ELEMENT_CACHE_SIZE; i < ELEMENT_COUNT; i++) {
|
||||
XCTAssertEqual(elements[i], [self.cache elementForUUID:elementIds[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testMRUCacheExpulsion
|
||||
{
|
||||
const int ELEMENT_COUNT = 1050;
|
||||
const int ACCESSED_ELEMENT_COUNT = 24;
|
||||
|
||||
NSMutableArray *elements = [NSMutableArray arrayWithCapacity:ELEMENT_COUNT];
|
||||
NSMutableArray *elementIds = [NSMutableArray arrayWithCapacity:ELEMENT_COUNT];
|
||||
for(int i = 0; i < ELEMENT_COUNT; i++) {
|
||||
XCUIElementDouble *el = XCUIElementDouble.new;
|
||||
el.wdUID = [NSString stringWithFormat:@"%@", @(i)];
|
||||
[elements addObject:(XCUIElement *)el];
|
||||
}
|
||||
|
||||
// The capacity of the cache is limited to 1024 elements. Add 1050
|
||||
// elements, but with a twist: access the first 24 elements before
|
||||
// adding the last 50 elements. Then, make sure:
|
||||
// - The first 24 elements are present in the cache
|
||||
// - The next 26 elements are not present in the cache
|
||||
// - The remaining 1000 elements are present in the cache
|
||||
for(int i = 0; i < ELEMENT_CACHE_SIZE; i++) {
|
||||
[elementIds addObject:[self.cache storeElement:elements[i]]];
|
||||
}
|
||||
|
||||
for(int i = 0; i < ACCESSED_ELEMENT_COUNT; i++) {
|
||||
[self.cache elementForUUID:elementIds[i]];
|
||||
}
|
||||
|
||||
for(int i = ELEMENT_CACHE_SIZE; i < ELEMENT_COUNT; i++) {
|
||||
[elementIds addObject:[self.cache storeElement:elements[i]]];
|
||||
}
|
||||
|
||||
for(int i = 0; i < ACCESSED_ELEMENT_COUNT; i++) {
|
||||
XCTAssertEqual(elements[i], [self.cache elementForUUID:elementIds[i]]);
|
||||
}
|
||||
for(int i = ACCESSED_ELEMENT_COUNT; i < ELEMENT_COUNT - ELEMENT_CACHE_SIZE + ACCESSED_ELEMENT_COUNT; i++) {
|
||||
XCTAssertThrows([self.cache elementForUUID:elementIds[i]]);
|
||||
}
|
||||
for(int i = ELEMENT_COUNT - ELEMENT_CACHE_SIZE + ACCESSED_ELEMENT_COUNT; i < ELEMENT_COUNT; i++) {
|
||||
XCTAssertEqual(elements[i], [self.cache elementForUUID:elementIds[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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 "FBElementTypeTransformer.h"
|
||||
|
||||
@interface FBElementTypeTransformerTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBElementTypeTransformerTests
|
||||
|
||||
- (void)testStringWithElementType
|
||||
{
|
||||
XCTAssertEqualObjects(@"XCUIElementTypeAny", [FBElementTypeTransformer stringWithElementType:XCUIElementTypeAny]);
|
||||
XCTAssertEqualObjects(@"XCUIElementTypeIcon", [FBElementTypeTransformer stringWithElementType:XCUIElementTypeIcon]);
|
||||
XCTAssertEqualObjects(@"XCUIElementTypeTab", [FBElementTypeTransformer stringWithElementType:XCUIElementTypeTab]);
|
||||
XCTAssertEqualObjects(@"XCUIElementTypeOther", [FBElementTypeTransformer stringWithElementType:XCUIElementTypeOther]);
|
||||
}
|
||||
|
||||
- (void)testShortStringWithElementType
|
||||
{
|
||||
XCTAssertEqualObjects(@"Any", [FBElementTypeTransformer shortStringWithElementType:XCUIElementTypeAny]);
|
||||
XCTAssertEqualObjects(@"Icon", [FBElementTypeTransformer shortStringWithElementType:XCUIElementTypeIcon]);
|
||||
XCTAssertEqualObjects(@"Tab", [FBElementTypeTransformer shortStringWithElementType:XCUIElementTypeTab]);
|
||||
XCTAssertEqualObjects(@"Other", [FBElementTypeTransformer shortStringWithElementType:XCUIElementTypeOther]);
|
||||
}
|
||||
|
||||
- (void)testElementTypeWithElementTypeName
|
||||
{
|
||||
XCTAssertEqual(XCUIElementTypeAny, [FBElementTypeTransformer elementTypeWithTypeName:@"XCUIElementTypeAny"]);
|
||||
XCTAssertEqual(XCUIElementTypeIcon, [FBElementTypeTransformer elementTypeWithTypeName:@"XCUIElementTypeIcon"]);
|
||||
XCTAssertEqual(XCUIElementTypeTab, [FBElementTypeTransformer elementTypeWithTypeName:@"XCUIElementTypeTab"]);
|
||||
XCTAssertEqual(XCUIElementTypeOther, [FBElementTypeTransformer elementTypeWithTypeName:@"XCUIElementTypeOther"]);
|
||||
XCTAssertThrows([FBElementTypeTransformer elementTypeWithTypeName:@"Whatever"]);
|
||||
XCTAssertThrows([FBElementTypeTransformer elementTypeWithTypeName:nil]);
|
||||
XCTAssertEqual(XCUIElementTypeOther, [FBElementTypeTransformer elementTypeWithTypeName:@"XCUIElementTypeNewType"]);
|
||||
}
|
||||
|
||||
@end
|
||||
36
WebDriverAgentTests/UnitTests/FBElementUtilitiesTests.m
Normal file
36
WebDriverAgentTests/UnitTests/FBElementUtilitiesTests.m
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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 "FBElement.h"
|
||||
#import "XCUIElementDouble.h"
|
||||
#import "FBElementUtils.h"
|
||||
|
||||
@interface FBElementUtilitiesTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBElementUtilitiesTests
|
||||
|
||||
- (void)testTypesFiltering {
|
||||
NSMutableArray *elements = [NSMutableArray new];
|
||||
XCUIElementDouble *el1 = [XCUIElementDouble new];
|
||||
[elements addObject:el1];
|
||||
XCUIElementDouble *el2 = [XCUIElementDouble new];
|
||||
el2.elementType = XCUIElementTypeAlert;
|
||||
el2.wdType = @"XCUIElementTypeAlert";
|
||||
[elements addObject:el2];
|
||||
XCUIElementDouble *el3 = [XCUIElementDouble new];
|
||||
[elements addObject:el3];
|
||||
|
||||
NSSet *result = [FBElementUtils uniqueElementTypesWithElements:elements];
|
||||
XCTAssertEqual([result count], 2);
|
||||
}
|
||||
|
||||
@end
|
||||
61
WebDriverAgentTests/UnitTests/FBErrorBuilderTests.m
Normal file
61
WebDriverAgentTests/UnitTests/FBErrorBuilderTests.m
Normal 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 "FBErrorBuilder.h"
|
||||
|
||||
@interface FBErrorBuilderTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBErrorBuilderTests
|
||||
|
||||
- (void)testErrorWithDescription
|
||||
{
|
||||
NSString *expectedDescription = @"Magic description";
|
||||
NSError *error =
|
||||
[[[FBErrorBuilder builder]
|
||||
withDescription:expectedDescription]
|
||||
build];
|
||||
XCTAssertNotNil(error);
|
||||
XCTAssertEqualObjects([error localizedDescription], expectedDescription);
|
||||
}
|
||||
|
||||
- (void)testErrorWithDescriptionFormat
|
||||
{
|
||||
NSError *error =
|
||||
[[[FBErrorBuilder builder]
|
||||
withDescriptionFormat:@"Magic %@", @"bob"]
|
||||
build];
|
||||
XCTAssertEqualObjects([error localizedDescription], @"Magic bob");
|
||||
}
|
||||
|
||||
- (void)testInnerError
|
||||
{
|
||||
NSError *innerError = [NSError errorWithDomain:@"Domain" code:1 userInfo:@{}];
|
||||
NSError *error =
|
||||
[[[FBErrorBuilder builder]
|
||||
withInnerError:innerError]
|
||||
build];
|
||||
XCTAssertEqual(error.userInfo[NSUnderlyingErrorKey], innerError);
|
||||
}
|
||||
|
||||
- (void)testBuildWithError
|
||||
{
|
||||
NSString *expectedDescription = @"Magic description";
|
||||
NSError *error;
|
||||
BOOL result =
|
||||
[[[FBErrorBuilder builder]
|
||||
withDescription:expectedDescription]
|
||||
buildError:&error];
|
||||
XCTAssertNotNil(error);
|
||||
XCTAssertEqualObjects(error.localizedDescription, expectedDescription);
|
||||
XCTAssertFalse(result);
|
||||
}
|
||||
|
||||
@end
|
||||
59
WebDriverAgentTests/UnitTests/FBExceptionHandlerTests.m
Normal file
59
WebDriverAgentTests/UnitTests/FBExceptionHandlerTests.m
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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 "FBExceptionHandler.h"
|
||||
#import "FBExceptions.h"
|
||||
|
||||
|
||||
@interface RouteResponseDouble : NSObject
|
||||
- (void)setHeader:(NSString *)field value:(NSString *)value;
|
||||
- (void)setStatusCode:(NSUInteger)code;
|
||||
- (void)respondWithData:(NSData *)data;
|
||||
@end
|
||||
|
||||
@implementation RouteResponseDouble
|
||||
- (void)setHeader:(NSString *)field value:(NSString *)value {}
|
||||
- (void)setStatusCode:(NSUInteger)code {}
|
||||
- (void)respondWithData:(NSData *)data {}
|
||||
@end
|
||||
|
||||
|
||||
@interface FBExceptionHandlerTests : XCTestCase
|
||||
@property (nonatomic) FBExceptionHandler *exceptionHandler;
|
||||
@end
|
||||
|
||||
@implementation FBExceptionHandlerTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
self.exceptionHandler = [FBExceptionHandler new];
|
||||
}
|
||||
|
||||
- (void)testMatchingErrorHandling
|
||||
{
|
||||
NSException *exception = [NSException exceptionWithName:FBElementNotVisibleException
|
||||
reason:@"reason"
|
||||
userInfo:@{}];
|
||||
[self.exceptionHandler handleException:exception
|
||||
forResponse:(RouteResponse *)[RouteResponseDouble new]];
|
||||
}
|
||||
|
||||
- (void)testNonMatchingErrorHandling
|
||||
{
|
||||
NSException *exception = [NSException exceptionWithName:@"something"
|
||||
reason:@"reason"
|
||||
userInfo:@{}];
|
||||
[self.exceptionHandler handleException:exception
|
||||
forResponse:(RouteResponse *)[RouteResponseDouble new]];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
127
WebDriverAgentTests/UnitTests/FBLRUCacheTests.m
Normal file
127
WebDriverAgentTests/UnitTests/FBLRUCacheTests.m
Normal 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 "LRUCache.h"
|
||||
|
||||
@interface FBLRUCacheTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLRUCacheTests
|
||||
|
||||
- (void)assertArray:(NSArray *)array1 equalsTo:(NSArray *)array2
|
||||
{
|
||||
XCTAssertEqualObjects(array1, array2);
|
||||
}
|
||||
|
||||
- (void)testRecentlyInsertedObjectReplacesTheOldestOne
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:1];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
XCTAssertEqualObjects(@[@"foo3"], cache.allObjects);
|
||||
}
|
||||
|
||||
- (void)testRecentObjectReplacementAndBump
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:2];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[self assertArray:@[@"foo2", @"foo"] equalsTo:cache.allObjects];
|
||||
XCTAssertNotNil([cache objectForKey:@"bar"]);
|
||||
[self assertArray:@[@"foo", @"foo2"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
[self assertArray:@[@"foo3", @"foo"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo0" forKey:@"bar"];
|
||||
[self assertArray:@[@"foo0", @"foo3"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo4" forKey:@"bar4"];
|
||||
[self assertArray:@[@"foo4", @"foo0"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testBumpFromHead
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:3];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
XCTAssertNotNil([cache objectForKey:@"bar3"]);
|
||||
[self assertArray:@[@"foo3", @"foo2", @"foo"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo4" forKey:@"bar4"];
|
||||
[cache setObject:@"foo5" forKey:@"bar5"];
|
||||
[self assertArray:@[@"foo5", @"foo4", @"foo3"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testBumpFromMiddle
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:3];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
XCTAssertNotNil([cache objectForKey:@"bar2"]);
|
||||
[self assertArray:@[@"foo2", @"foo3", @"foo"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo4" forKey:@"bar4"];
|
||||
[cache setObject:@"foo5" forKey:@"bar5"];
|
||||
[self assertArray:@[@"foo5", @"foo4", @"foo2"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testBumpFromTail
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:3];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
XCTAssertNotNil([cache objectForKey:@"bar3"]);
|
||||
[self assertArray:@[@"foo3", @"foo2", @"foo"] equalsTo:cache.allObjects];
|
||||
[cache setObject:@"foo4" forKey:@"bar4"];
|
||||
[cache setObject:@"foo5" forKey:@"bar5"];
|
||||
[self assertArray:@[@"foo5", @"foo4", @"foo3"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testInsertionLoop
|
||||
{
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:1];
|
||||
NSUInteger count = 100;
|
||||
for (NSUInteger i = 0; i <= count; ++i) {
|
||||
[cache setObject:@(i) forKey:@(i)];
|
||||
XCTAssertNotNil([cache objectForKey:@(i)]);
|
||||
}
|
||||
XCTAssertEqualObjects(@[@(count)], cache.allObjects);
|
||||
}
|
||||
|
||||
- (void)testRemoveExistingObjectForKey {
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:3];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
[self assertArray:@[@"foo3", @"foo2", @"foo"] equalsTo:cache.allObjects];
|
||||
[cache removeObjectForKey:@"bar2"];
|
||||
XCTAssertNil([cache objectForKey:@"bar2"]);
|
||||
[self assertArray:@[@"foo3", @"foo"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testRemoveNonExistingObjectForKey {
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:2];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache removeObjectForKey:@"nonExisting"];
|
||||
XCTAssertNotNil([cache objectForKey:@"bar"]);
|
||||
[self assertArray:@[@"foo"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
- (void)testRemoveAndInsertFlow {
|
||||
LRUCache *cache = [[LRUCache alloc] initWithCapacity:2];
|
||||
[cache setObject:@"foo" forKey:@"bar"];
|
||||
[cache setObject:@"foo2" forKey:@"bar2"];
|
||||
[cache removeObjectForKey:@"bar"];
|
||||
XCTAssertNil([cache objectForKey:@"bar"]);
|
||||
[cache setObject:@"foo3" forKey:@"bar3"];
|
||||
[self assertArray:@[@"foo3", @"foo2"] equalsTo:cache.allObjects];
|
||||
}
|
||||
|
||||
@end
|
||||
113
WebDriverAgentTests/UnitTests/FBMathUtilsTests.m
Normal file
113
WebDriverAgentTests/UnitTests/FBMathUtilsTests.m
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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 "FBMathUtils.h"
|
||||
|
||||
@interface FBMathUtilsTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBMathUtilsTests
|
||||
|
||||
- (void)testGetCenter
|
||||
{
|
||||
XCTAssertTrue(CGPointEqualToPoint(FBRectGetCenter(CGRectMake(0, 0, 4, 4)), CGPointMake(2, 2)));
|
||||
XCTAssertTrue(CGPointEqualToPoint(FBRectGetCenter(CGRectMake(1, 1, 4, 4)), CGPointMake(3, 3)));
|
||||
XCTAssertTrue(CGPointEqualToPoint(FBRectGetCenter(CGRectMake(1, 3, 6, 14)), CGPointMake(4, 10)));
|
||||
}
|
||||
|
||||
- (void)testFuzzyEqualFloats
|
||||
{
|
||||
XCTAssertTrue(FBFloatFuzzyEqualToFloat(0, 0, 0));
|
||||
XCTAssertTrue(FBFloatFuzzyEqualToFloat(0.5, 0.6, 0.2));
|
||||
XCTAssertTrue(FBFloatFuzzyEqualToFloat(0.6, 0.5, 0.2));
|
||||
XCTAssertTrue(FBFloatFuzzyEqualToFloat(0.5, 0.6, 0.10001));
|
||||
}
|
||||
|
||||
- (void)testFuzzyNotEqualFloats
|
||||
{
|
||||
XCTAssertFalse(FBFloatFuzzyEqualToFloat(0, 1, 0));
|
||||
XCTAssertFalse(FBFloatFuzzyEqualToFloat(1, 0, 0));
|
||||
XCTAssertFalse(FBFloatFuzzyEqualToFloat(0.5, 0.6, 0.05));
|
||||
XCTAssertFalse(FBFloatFuzzyEqualToFloat(0.6, 0.5, 0.05));
|
||||
}
|
||||
|
||||
- (void)testFuzzyEqualPoints
|
||||
{
|
||||
CGPoint referencePoint = CGPointMake(3, 3);
|
||||
XCTAssertTrue(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(3, 3), 2));
|
||||
XCTAssertTrue(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(3, 4), 2));
|
||||
XCTAssertTrue(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(4, 3), 2));
|
||||
}
|
||||
|
||||
- (void)testFuzzyNotEqualPoints
|
||||
{
|
||||
CGPoint referencePoint = CGPointMake(3, 3);
|
||||
XCTAssertFalse(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(5, 5), 1));
|
||||
XCTAssertFalse(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(3, 5), 1));
|
||||
XCTAssertFalse(FBPointFuzzyEqualToPoint(referencePoint, CGPointMake(5, 3), 1));
|
||||
}
|
||||
|
||||
- (void)testFuzzyEqualSizes
|
||||
{
|
||||
CGSize referenceSize = CGSizeMake(3, 3);
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(3, 3), 2));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(3, 4), 2));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(4, 3), 2));
|
||||
}
|
||||
|
||||
- (void)testFuzzyNotEqualSizes
|
||||
{
|
||||
CGSize referenceSize = CGSizeMake(3, 3);
|
||||
XCTAssertFalse(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(5, 5), 1));
|
||||
XCTAssertFalse(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(3, 5), 1));
|
||||
XCTAssertFalse(FBSizeFuzzyEqualToSize(referenceSize, CGSizeMake(5, 3), 1));
|
||||
}
|
||||
|
||||
- (void)testFuzzyEqualRects
|
||||
{
|
||||
CGRect referenceRect = CGRectMake(3, 3, 3, 3);
|
||||
XCTAssertTrue(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 3, 3, 3), 2));
|
||||
XCTAssertTrue(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 4, 3, 3), 2));
|
||||
XCTAssertTrue(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(4, 3, 3, 3), 2));
|
||||
XCTAssertTrue(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 3, 3, 4), 2));
|
||||
XCTAssertTrue(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 3, 4, 3), 2));
|
||||
}
|
||||
|
||||
- (void)testFuzzyNotEqualRects
|
||||
{
|
||||
CGRect referenceRect = CGRectMake(3, 3, 3, 3);
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(5, 5, 5, 5), 1));
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 5, 3, 3), 1));
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(5, 3, 3, 3), 1));
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 3, 3, 5), 1));
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(3, 3, 5, 3), 1));
|
||||
}
|
||||
|
||||
- (void)testFuzzyEqualRectsSymmetry
|
||||
{
|
||||
CGRect referenceRect = CGRectMake(0, 0, 2, 2);
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(1, 1, 3, 3), 1));
|
||||
XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(-1, -1, 1, 1), 1));
|
||||
}
|
||||
|
||||
- (void)testSizeInversion
|
||||
{
|
||||
const CGSize screenSizePortrait = CGSizeMake(10, 15);
|
||||
const CGSize screenSizeLandscape = CGSizeMake(15, 10);
|
||||
const CGFloat t = FBDefaultFrameFuzzyThreshold;
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizePortrait, FBAdjustDimensionsForApplication(screenSizePortrait, UIInterfaceOrientationPortrait), t));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizePortrait, FBAdjustDimensionsForApplication(screenSizePortrait, UIInterfaceOrientationPortraitUpsideDown), t));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizeLandscape, FBAdjustDimensionsForApplication(screenSizePortrait, UIInterfaceOrientationLandscapeLeft), t));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizeLandscape, FBAdjustDimensionsForApplication(screenSizePortrait, UIInterfaceOrientationLandscapeRight), t));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizeLandscape, FBAdjustDimensionsForApplication(screenSizeLandscape, UIInterfaceOrientationLandscapeLeft), t));
|
||||
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizeLandscape, FBAdjustDimensionsForApplication(screenSizeLandscape, UIInterfaceOrientationLandscapeRight), t));
|
||||
}
|
||||
|
||||
@end
|
||||
81
WebDriverAgentTests/UnitTests/FBProtocolHelpersTests.m
Normal file
81
WebDriverAgentTests/UnitTests/FBProtocolHelpersTests.m
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 "FBProtocolHelpers.h"
|
||||
|
||||
@interface FBProtocolHelpersTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBProtocolHelpersTests
|
||||
|
||||
- (void)testValidPrefixedCapsParsing
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *parsedCaps = FBParseCapabilities(@{
|
||||
@"firstMatch": @[@{
|
||||
@"appium:bundleId": @"com.example.id"
|
||||
}]
|
||||
}, &error);
|
||||
XCTAssertNil(error);
|
||||
XCTAssertEqualObjects(parsedCaps[@"bundleId"], @"com.example.id");
|
||||
}
|
||||
|
||||
- (void)testValidPrefixedCapsMerging
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *parsedCaps = FBParseCapabilities(@{
|
||||
@"firstMatch": @[@{
|
||||
@"bundleId": @"com.example.id"
|
||||
}],
|
||||
@"alwaysMatch": @{
|
||||
@"google:cap": @"super"
|
||||
}
|
||||
}, &error);
|
||||
XCTAssertNil(error);
|
||||
XCTAssertEqualObjects(parsedCaps[@"bundleId"], @"com.example.id");
|
||||
XCTAssertEqualObjects(parsedCaps[@"google:cap"], @"super");
|
||||
}
|
||||
|
||||
- (void)testEmptyCaps
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *parsedCaps = FBParseCapabilities(@{}, &error);
|
||||
XCTAssertNil(error);
|
||||
XCTAssertEqual(parsedCaps.count, 0);
|
||||
}
|
||||
|
||||
- (void)testCapsMergingFailure
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *parsedCaps = FBParseCapabilities(@{
|
||||
@"firstMatch": @[@{
|
||||
@"appium:bundleId": @"com.example.id"
|
||||
}],
|
||||
@"alwaysMatch": @{
|
||||
@"bundleId": @"other"
|
||||
}
|
||||
}, &error);
|
||||
XCTAssertNil(parsedCaps);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
|
||||
- (void)testPrefixingStandardCapability
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSDictionary<NSString *, id> *parsedCaps = FBParseCapabilities(@{
|
||||
@"firstMatch": @[@{
|
||||
@"appium:platformName": @"com.example.id"
|
||||
}]
|
||||
}, &error);
|
||||
XCTAssertNil(parsedCaps);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
|
||||
@end
|
||||
129
WebDriverAgentTests/UnitTests/FBRouteTests.m
Normal file
129
WebDriverAgentTests/UnitTests/FBRouteTests.m
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 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 "FBRoute.h"
|
||||
|
||||
@class RouteResponse;
|
||||
|
||||
@interface FBHandlerMock : NSObject
|
||||
@property (nonatomic, assign) BOOL didCallSomeSelector;
|
||||
@end
|
||||
|
||||
@implementation FBHandlerMock
|
||||
- (id)someSelector:(id)arg
|
||||
{
|
||||
self.didCallSomeSelector = YES;
|
||||
return nil;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
@interface FBRouteTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBRouteTests
|
||||
|
||||
- (void)testGetRoute
|
||||
{
|
||||
FBRoute *route = [FBRoute GET:@"/"];
|
||||
XCTAssertEqualObjects(route.verb, @"GET");
|
||||
}
|
||||
|
||||
- (void)testPostRoute
|
||||
{
|
||||
FBRoute *route = [FBRoute POST:@"/"];
|
||||
XCTAssertEqualObjects(route.verb, @"POST");
|
||||
}
|
||||
|
||||
- (void)testPutRoute
|
||||
{
|
||||
FBRoute *route = [FBRoute PUT:@"/"];
|
||||
XCTAssertEqualObjects(route.verb, @"PUT");
|
||||
}
|
||||
|
||||
- (void)testDeleteRoute
|
||||
{
|
||||
FBRoute *route = [FBRoute DELETE:@"/"];
|
||||
XCTAssertEqualObjects(route.verb, @"DELETE");
|
||||
}
|
||||
|
||||
- (void)testTargetAction
|
||||
{
|
||||
FBHandlerMock *mock = [FBHandlerMock new];
|
||||
FBRoute *route = [[FBRoute new] respondWithTarget:mock action:@selector(someSelector:)];
|
||||
[route mountRequest:(id)NSObject.new intoResponse:(id)NSObject.new];
|
||||
XCTAssertTrue(mock.didCallSomeSelector);
|
||||
}
|
||||
|
||||
- (void)testRespond
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Calling respond block works!"];
|
||||
FBRoute *route = [[FBRoute new] respondWithBlock:^id<FBResponsePayload>(FBRouteRequest *request) {
|
||||
[expectation fulfill];
|
||||
return nil;
|
||||
}];
|
||||
[route mountRequest:(id)NSObject.new intoResponse:(id)NSObject.new];
|
||||
[self waitForExpectationsWithTimeout:0.0 handler:nil];
|
||||
}
|
||||
|
||||
- (void)testRouteWithSessionWithSlash
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"/deactivateApp"] respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/session/:sessionID/deactivateApp");
|
||||
}
|
||||
|
||||
- (void)testRouteWithSession
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"deactivateApp"] respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/session/:sessionID/deactivateApp");
|
||||
}
|
||||
|
||||
- (void)testRouteWithoutSessionWithSlash
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"/deactivateApp"].withoutSession respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/deactivateApp");
|
||||
}
|
||||
|
||||
- (void)testRouteWithoutSession
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"deactivateApp"].withoutSession respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/deactivateApp");
|
||||
}
|
||||
|
||||
- (void)testEmptyRouteWithSession
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@""] respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/session/:sessionID");
|
||||
}
|
||||
|
||||
- (void)testEmptyRouteWithoutSession
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@""].withoutSession respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/");
|
||||
}
|
||||
|
||||
- (void)testEmptyRouteWithSessionWithSlash
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"/"] respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/session/:sessionID");
|
||||
}
|
||||
|
||||
- (void)testEmptyRouteWithoutSessionWithSlash
|
||||
{
|
||||
FBRoute *route = [[FBRoute POST:@"/"].withoutSession respondWithTarget:self action:@selector(dummyHandler:)];
|
||||
XCTAssertEqualObjects(route.path, @"/");
|
||||
}
|
||||
|
||||
+ (id<FBResponsePayload>)dummyHandler:(FBRouteRequest *)request
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
98
WebDriverAgentTests/UnitTests/FBRunLoopSpinnerTests.m
Normal file
98
WebDriverAgentTests/UnitTests/FBRunLoopSpinnerTests.m
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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 "FBRunLoopSpinner.h"
|
||||
|
||||
@interface FBRunLoopSpinnerTests : XCTestCase
|
||||
@property (nonatomic, strong) FBRunLoopSpinner *spinner;
|
||||
@end
|
||||
|
||||
/**
|
||||
Non of the test methods should block testing thread.
|
||||
If they do, that means they are broken
|
||||
*/
|
||||
@implementation FBRunLoopSpinnerTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
self.spinner = [[FBRunLoopSpinner new] timeout:0.1];
|
||||
}
|
||||
|
||||
- (void)testSpinUntilCompletion
|
||||
{
|
||||
__block BOOL _didExecuteBlock = NO;
|
||||
[FBRunLoopSpinner spinUntilCompletion:^(void (^completion)(void)) {
|
||||
_didExecuteBlock = YES;
|
||||
completion();
|
||||
}];
|
||||
XCTAssertTrue(_didExecuteBlock);
|
||||
}
|
||||
|
||||
- (void)testSpinUntilTrue
|
||||
{
|
||||
__block BOOL _didExecuteBlock = NO;
|
||||
BOOL didSucceed =
|
||||
[self.spinner spinUntilTrue:^BOOL{
|
||||
_didExecuteBlock = YES;
|
||||
return YES;
|
||||
}];
|
||||
XCTAssertTrue(didSucceed);
|
||||
XCTAssertTrue(_didExecuteBlock);
|
||||
}
|
||||
|
||||
- (void)testSpinUntilTrueTimeout
|
||||
{
|
||||
NSError *error;
|
||||
BOOL didSucceed =
|
||||
[self.spinner spinUntilTrue:^BOOL{
|
||||
return NO;
|
||||
} error:&error];
|
||||
XCTAssertFalse(didSucceed);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
|
||||
- (void)testSpinUntilTrueTimeoutMessage
|
||||
{
|
||||
NSString *expectedMessage = @"Magic message";
|
||||
NSError *error;
|
||||
BOOL didSucceed =
|
||||
[[self.spinner timeoutErrorMessage:expectedMessage]
|
||||
spinUntilTrue:^BOOL{
|
||||
return NO;
|
||||
} error:&error];
|
||||
XCTAssertFalse(didSucceed);
|
||||
XCTAssertEqual(error.localizedDescription, expectedMessage);
|
||||
}
|
||||
|
||||
- (void)testSpinUntilNotNil
|
||||
{
|
||||
__block id expectedObject = NSObject.new;
|
||||
NSError *error;
|
||||
id returnedObject =
|
||||
[self.spinner spinUntilNotNil:^id{
|
||||
return expectedObject;
|
||||
} error:&error];
|
||||
XCTAssertNil(error);
|
||||
XCTAssertEqual(returnedObject, expectedObject);
|
||||
}
|
||||
|
||||
- (void)testSpinUntilNotNilTimeout
|
||||
{
|
||||
NSError *error;
|
||||
id element =
|
||||
[self.spinner spinUntilNotNil:^id{
|
||||
return nil;
|
||||
} error:&error];
|
||||
XCTAssertNil(element);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
|
||||
@end
|
||||
45
WebDriverAgentTests/UnitTests/FBRuntimeUtilsTests.m
Normal file
45
WebDriverAgentTests/UnitTests/FBRuntimeUtilsTests.m
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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 "FBRuntimeUtils.h"
|
||||
#import "XCTestPrivateSymbols.h"
|
||||
|
||||
@protocol FBMagicProtocol <NSObject>
|
||||
@end
|
||||
|
||||
const NSString *FBRuntimeUtilsTestsConstString = @"FBRuntimeUtilsTestsConstString";
|
||||
|
||||
@interface FBRuntimeUtilsTests : XCTestCase <FBMagicProtocol>
|
||||
@end
|
||||
|
||||
@implementation FBRuntimeUtilsTests
|
||||
|
||||
- (void)testClassesThatConformsToProtocol
|
||||
{
|
||||
XCTAssertEqualObjects(@[self.class], FBClassesThatConformsToProtocol(@protocol(FBMagicProtocol)));
|
||||
}
|
||||
|
||||
- (void)testRetrievingFrameworkSymbols
|
||||
{
|
||||
NSString *binaryPath = [NSBundle bundleForClass:self.class].executablePath;
|
||||
NSString *symbolPointer = *(NSString*__autoreleasing*)FBRetrieveSymbolFromBinary(binaryPath.UTF8String, "FBRuntimeUtilsTestsConstString");
|
||||
XCTAssertNotNil(symbolPointer);
|
||||
XCTAssertEqualObjects(symbolPointer, FBRuntimeUtilsTestsConstString);
|
||||
}
|
||||
|
||||
- (void)testXCTestSymbols
|
||||
{
|
||||
XCTAssertTrue(XCDebugLogger != NULL);
|
||||
XCTAssertTrue(XCSetDebugLogger != NULL);
|
||||
XCTAssertNotNil(FB_XCAXAIsVisibleAttribute);
|
||||
XCTAssertNotNil(FB_XCAXAIsElementAttribute);
|
||||
}
|
||||
|
||||
@end
|
||||
66
WebDriverAgentTests/UnitTests/FBSDKVersionTests.m
Normal file
66
WebDriverAgentTests/UnitTests/FBSDKVersionTests.m
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 "FBRuntimeUtils.h"
|
||||
|
||||
@interface FBSDKVersionTests : XCTestCase
|
||||
@property (nonatomic, readonly) NSString *currentSDKVersion;
|
||||
@property (nonatomic, readonly) NSString *lowerSDKVersion;
|
||||
@property (nonatomic, readonly) NSString *higherSDKVersion;
|
||||
@end
|
||||
|
||||
@implementation FBSDKVersionTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
NSDictionary *bundleDict = [[NSBundle mainBundle] infoDictionary];
|
||||
[bundleDict setValue:@"11.0" forKey:@"DTSDKName"];
|
||||
_currentSDKVersion = FBSDKVersion();
|
||||
_lowerSDKVersion = [NSString stringWithFormat:@"%@", @((int)[self.currentSDKVersion doubleValue] - 1)];
|
||||
_higherSDKVersion = [NSString stringWithFormat:@"%@", @((int)[self.currentSDKVersion doubleValue] + 1)];
|
||||
}
|
||||
|
||||
- (void)testIsSDKVersionLessThanOrEqualTo
|
||||
{
|
||||
XCTAssertTrue(isSDKVersionLessThanOrEqualTo(self.higherSDKVersion));
|
||||
XCTAssertFalse(isSDKVersionLessThanOrEqualTo(self.lowerSDKVersion));
|
||||
XCTAssertTrue(isSDKVersionLessThanOrEqualTo(self.currentSDKVersion));
|
||||
}
|
||||
|
||||
- (void)testIsSDKVersionLessThan
|
||||
{
|
||||
XCTAssertTrue(isSDKVersionLessThan(self.higherSDKVersion));
|
||||
XCTAssertFalse(isSDKVersionLessThan(self.lowerSDKVersion));
|
||||
XCTAssertFalse(isSDKVersionLessThan(self.currentSDKVersion));
|
||||
}
|
||||
|
||||
- (void)testIsSDKVersionEqualTo
|
||||
{
|
||||
XCTAssertFalse(isSDKVersionEqualTo(self.higherSDKVersion));
|
||||
XCTAssertFalse(isSDKVersionEqualTo(self.lowerSDKVersion));
|
||||
XCTAssertTrue(isSDKVersionEqualTo(self.currentSDKVersion));
|
||||
}
|
||||
|
||||
- (void)testIsSDKVersionGreaterThanOrEqualTo
|
||||
{
|
||||
XCTAssertFalse(isSDKVersionGreaterThanOrEqualTo(self.higherSDKVersion));
|
||||
XCTAssertTrue(isSDKVersionGreaterThanOrEqualTo(self.lowerSDKVersion));
|
||||
XCTAssertTrue(isSDKVersionGreaterThanOrEqualTo(self.currentSDKVersion));
|
||||
}
|
||||
|
||||
- (void)testIsSDKVersionGreaterThan
|
||||
{
|
||||
XCTAssertFalse(isSDKVersionGreaterThan(self.higherSDKVersion));
|
||||
XCTAssertTrue(isSDKVersionGreaterThan(self.lowerSDKVersion));
|
||||
XCTAssertFalse(isSDKVersionGreaterThan(self.currentSDKVersion));
|
||||
}
|
||||
|
||||
@end
|
||||
67
WebDriverAgentTests/UnitTests/FBSessionTests.m
Normal file
67
WebDriverAgentTests/UnitTests/FBSessionTests.m
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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 "FBSession.h"
|
||||
#import "FBConfiguration.h"
|
||||
#import "XCUIApplicationDouble.h"
|
||||
|
||||
@interface FBSessionTests : XCTestCase
|
||||
@property (nonatomic, strong) FBSession *session;
|
||||
@property (nonatomic, strong) XCUIApplication *testedApplication;
|
||||
@property (nonatomic) BOOL shouldTerminateAppValue;
|
||||
@end
|
||||
|
||||
@implementation FBSessionTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
self.testedApplication = (id)XCUIApplicationDouble.new;
|
||||
self.shouldTerminateAppValue = FBConfiguration.shouldTerminateApp;
|
||||
[FBConfiguration setShouldTerminateApp:NO];
|
||||
self.session = [FBSession initWithApplication:self.testedApplication];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[self.session kill];
|
||||
[FBConfiguration setShouldTerminateApp:self.shouldTerminateAppValue];
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testSessionFetching
|
||||
{
|
||||
FBSession *fetchedSession = [FBSession sessionWithIdentifier:self.session.identifier];
|
||||
XCTAssertEqual(self.session, fetchedSession);
|
||||
}
|
||||
|
||||
- (void)testSessionFetchingBadIdentifier
|
||||
{
|
||||
XCTAssertNil([FBSession sessionWithIdentifier:@"FAKE_IDENTIFIER"]);
|
||||
}
|
||||
|
||||
- (void)testSessionCreation
|
||||
{
|
||||
XCTAssertNotNil(self.session.identifier);
|
||||
XCTAssertNotNil(self.session.elementCache);
|
||||
}
|
||||
|
||||
- (void)testActiveSession
|
||||
{
|
||||
XCTAssertEqual(self.session, [FBSession activeSession]);
|
||||
}
|
||||
|
||||
- (void)testActiveSessionIsNilAfterKilling
|
||||
{
|
||||
[self.session kill];
|
||||
XCTAssertNil([FBSession activeSession]);
|
||||
}
|
||||
|
||||
@end
|
||||
35
WebDriverAgentTests/UnitTests/FBXMLSafeStringTests.m
Normal file
35
WebDriverAgentTests/UnitTests/FBXMLSafeStringTests.m
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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 "NSString+FBXMLSafeString.h"
|
||||
|
||||
@interface FBXMLSafeStringTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBXMLSafeStringTests
|
||||
|
||||
- (void)testSafeXmlStringTransformationWithEmptyReplacement {
|
||||
NSString *withInvalidChar = [NSString stringWithFormat:@"bla%@", @"\uFFFF"];
|
||||
NSString *withoutInvalidChar = @"bla";
|
||||
XCTAssertNotEqualObjects(withInvalidChar, withoutInvalidChar);
|
||||
XCTAssertEqualObjects([withInvalidChar fb_xmlSafeStringWithReplacement:@""], withoutInvalidChar);
|
||||
}
|
||||
|
||||
- (void)testSafeXmlStringTransformationWithNonEmptyReplacement {
|
||||
NSString *withInvalidChar = [NSString stringWithFormat:@"bla%@", @"\uFFFF"];
|
||||
XCTAssertEqualObjects([withInvalidChar fb_xmlSafeStringWithReplacement:@"1"], @"bla1");
|
||||
}
|
||||
|
||||
- (void)testSafeXmlStringTransformationWithSmileys {
|
||||
NSString *validString = @"Yo👿";
|
||||
XCTAssertEqualObjects([validString fb_xmlSafeStringWithReplacement:@""], validString);
|
||||
}
|
||||
|
||||
@end
|
||||
152
WebDriverAgentTests/UnitTests/FBXPathTests.m
Normal file
152
WebDriverAgentTests/UnitTests/FBXPathTests.m
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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 "FBXPath.h"
|
||||
#import "FBXPath-Private.h"
|
||||
#import "XCUIElementDouble.h"
|
||||
#import "XCElementSnapshotDouble.h"
|
||||
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
||||
|
||||
@interface FBXPathTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBXPathTests
|
||||
|
||||
- (NSString *)xmlStringWithElement:(id<FBXCElementSnapshot>)snapshot
|
||||
xpathQuery:(nullable NSString *)query
|
||||
excludingAttributes:(nullable NSArray<NSString *> *)excludedAttributes
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
|
||||
xmlTextWriterPtr writer = xmlNewTextWriterDoc(&doc, 0);
|
||||
NSMutableDictionary *elementStore = [NSMutableDictionary dictionary];
|
||||
int buffersize;
|
||||
xmlChar *xmlbuff = NULL;
|
||||
int rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
|
||||
if (rc >= 0) {
|
||||
rc = [FBXPath xmlRepresentationWithRootElement:snapshot
|
||||
writer:writer
|
||||
elementStore:elementStore
|
||||
query:query
|
||||
excludingAttributes:excludedAttributes];
|
||||
if (rc >= 0) {
|
||||
rc = xmlTextWriterEndDocument(writer);
|
||||
}
|
||||
}
|
||||
if (rc >= 0) {
|
||||
xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
|
||||
}
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
XCTAssertTrue(rc >= 0);
|
||||
XCTAssertEqual(1, [elementStore count]);
|
||||
|
||||
NSString *result = [NSString stringWithCString:(const char *)xmlbuff encoding:NSUTF8StringEncoding];
|
||||
xmlFree(xmlbuff);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)testDefaultXPathPresentation
|
||||
{
|
||||
XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new];
|
||||
id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
|
||||
NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
|
||||
xpathQuery:nil
|
||||
excludingAttributes:nil];
|
||||
NSLog(@"[DefaultXPath] Result XML:\n%@", resultXml);
|
||||
NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\" private_indexPath=\"top\"/>\n",
|
||||
element.wdType, element.wdType, element.wdValue, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, element.wdTraits];
|
||||
XCTAssertTrue([resultXml isEqualToString: expectedXml]);
|
||||
}
|
||||
|
||||
- (void)testtXPathPresentationWithSomeAttributesExcluded
|
||||
{
|
||||
XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new];
|
||||
id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
|
||||
NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
|
||||
xpathQuery:nil
|
||||
excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits", @"nativeFrame"]];
|
||||
NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" private_indexPath=\"top\"/>\n",
|
||||
element.wdType, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"]];
|
||||
XCTAssertEqualObjects(resultXml, expectedXml);
|
||||
}
|
||||
|
||||
- (void)testXPathPresentationBasedOnQueryMatchingAllAttributes
|
||||
{
|
||||
XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new];
|
||||
snapshot.value = @"йоло<>&\"";
|
||||
snapshot.label = @"a\nb";
|
||||
id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
|
||||
NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
|
||||
xpathQuery:[NSString stringWithFormat:@"//%@[@*]", element.wdType]
|
||||
excludingAttributes:@[@"visible"]];
|
||||
NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" traits=\"%@\" nativeFrame=\"%@\" private_indexPath=\"top\"/>\n",
|
||||
element.wdType, element.wdType, @"йоло<>&"", element.wdName, @"a b", FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, FBBoolToString(element.wdHittable), element.wdTraits, NSStringFromCGRect(element.wdNativeFrame)];
|
||||
XCTAssertEqualObjects(expectedXml, resultXml);
|
||||
}
|
||||
|
||||
- (void)testXPathPresentationBasedOnQueryMatchingSomeAttributes
|
||||
{
|
||||
XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new];
|
||||
id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
|
||||
NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
|
||||
xpathQuery:[NSString stringWithFormat:@"//%@[@%@ and contains(@%@, 'blabla')]", element.wdType, @"value", @"name"]
|
||||
excludingAttributes:nil];
|
||||
NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ value=\"%@\" name=\"%@\" private_indexPath=\"top\"/>\n",
|
||||
element.wdType, element.wdValue, element.wdName];
|
||||
XCTAssertTrue([resultXml isEqualToString: expectedXml]);
|
||||
}
|
||||
|
||||
- (void)testSnapshotXPathResultsMatching
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
|
||||
xmlTextWriterPtr writer = xmlNewTextWriterDoc(&doc, 0);
|
||||
NSMutableDictionary *elementStore = [NSMutableDictionary dictionary];
|
||||
XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new];
|
||||
id<FBElement> root = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
|
||||
NSString *query = [NSString stringWithFormat:@"//%@", root.wdType];
|
||||
int rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
|
||||
if (rc >= 0) {
|
||||
rc = [FBXPath xmlRepresentationWithRootElement:(id<FBXCElementSnapshot>)root
|
||||
writer:writer
|
||||
elementStore:elementStore
|
||||
query:query
|
||||
excludingAttributes:nil];
|
||||
if (rc >= 0) {
|
||||
rc = xmlTextWriterEndDocument(writer);
|
||||
}
|
||||
}
|
||||
if (rc < 0) {
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlFreeDoc(doc);
|
||||
XCTFail(@"Unable to create the source XML document");
|
||||
}
|
||||
|
||||
xmlXPathObjectPtr queryResult = [FBXPath evaluate:query document:doc contextNode:NULL];
|
||||
if (NULL == queryResult) {
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlFreeDoc(doc);
|
||||
XCTAssertNotEqual(NULL, queryResult);
|
||||
}
|
||||
|
||||
NSArray *matchingSnapshots = [FBXPath collectMatchingSnapshots:queryResult->nodesetval
|
||||
elementStore:elementStore];
|
||||
xmlXPathFreeObject(queryResult);
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
XCTAssertNotNil(matchingSnapshots);
|
||||
XCTAssertEqual(1, [matchingSnapshots count]);
|
||||
}
|
||||
|
||||
@end
|
||||
24
WebDriverAgentTests/UnitTests/Info.plist
Normal file
24
WebDriverAgentTests/UnitTests/Info.plist
Normal 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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>
|
||||
34
WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m
Normal file
34
WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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 "NSDictionary+FBUtf8SafeDictionary.h"
|
||||
|
||||
@interface NSDictionaryFBUtf8SafeTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation NSDictionaryFBUtf8SafeTests
|
||||
|
||||
- (void)testEmptySafeDictConversion
|
||||
{
|
||||
NSDictionary *d = @{};
|
||||
XCTAssertEqualObjects(d, d.fb_utf8SafeDictionary);
|
||||
}
|
||||
|
||||
- (void)testNonEmptySafeDictConversion
|
||||
{
|
||||
NSDictionary *d = @{
|
||||
@"1": @[@3, @4],
|
||||
@"5": @{@"6": @7, @"8": @9},
|
||||
@"10": @"11"
|
||||
};
|
||||
XCTAssertEqualObjects(d, d.fb_utf8SafeDictionary);
|
||||
}
|
||||
|
||||
@end
|
||||
60
WebDriverAgentTests/UnitTests/NSExpressionFBFormatTests.m
Normal file
60
WebDriverAgentTests/UnitTests/NSExpressionFBFormatTests.m
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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 "NSExpression+FBFormat.h"
|
||||
#import "FBElementUtils.h"
|
||||
|
||||
@interface NSExpressionFBFormatTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation NSExpressionFBFormatTests
|
||||
|
||||
- (void)testFormattingForExistingProperty
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"wdName"];
|
||||
NSExpression *prop = [NSExpression fb_wdExpressionWithExpression:expr];
|
||||
XCTAssertEqualObjects([prop keyPath], @"wdName");
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingPropertyShortcut
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"visible"];
|
||||
NSExpression *prop = [NSExpression fb_wdExpressionWithExpression:expr];
|
||||
XCTAssertEqualObjects([prop keyPath], @"isWDVisible");
|
||||
}
|
||||
|
||||
- (void)testFormattingForValidExpressionWOKeys
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"1"];
|
||||
NSExpression *prop = [NSExpression fb_wdExpressionWithExpression:expr];
|
||||
XCTAssertEqualObjects([prop constantValue], [NSNumber numberWithInt:1]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingComplexProperty
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"wdRect.x"];
|
||||
NSExpression *prop = [NSExpression fb_wdExpressionWithExpression:expr];
|
||||
XCTAssertEqualObjects([prop keyPath], @"wdRect.x");
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingComplexPropertyWOPrefix
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"rect.x"];
|
||||
NSExpression *prop = [NSExpression fb_wdExpressionWithExpression:expr];
|
||||
XCTAssertEqualObjects([prop keyPath], @"wdRect.x");
|
||||
}
|
||||
|
||||
- (void)testFormattingForPredicateWithUnknownKey
|
||||
{
|
||||
NSExpression *expr = [NSExpression expressionWithFormat:@"title"];
|
||||
XCTAssertThrowsSpecificNamed([NSExpression fb_wdExpressionWithExpression:expr], NSException, FBUnknownAttributeException);
|
||||
}
|
||||
|
||||
@end
|
||||
72
WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m
Normal file
72
WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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 "NSPredicate+FBFormat.h"
|
||||
|
||||
@interface NSPredicateFBFormatTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation NSPredicateFBFormatTests
|
||||
|
||||
- (void)testFormattingForExistingProperty
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"wdName == 'blabla'"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingPropertyOnTheRightSide
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"0 == wdAccessible"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingPropertyShortcut
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"visible == 1"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForComplexExpression
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"visible == 1 AND NOT (type == 'blabla' OR NOT (label IN {'3', '4'}))"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForValidExpressionWOKeys
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"1 = 1"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingComplexProperty
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"wdRect.x == '0'"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForExistingComplexPropertyWOPrefix
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"rect.x == '0'"];
|
||||
XCTAssertNotNil([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testFormattingForPredicateWithUnknownKey
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"title == 'blabla'"];
|
||||
XCTAssertThrows([NSPredicate fb_formatSearchPredicate:expr]);
|
||||
}
|
||||
|
||||
- (void)testBlockPredicateCreation
|
||||
{
|
||||
NSPredicate *expr = [NSPredicate predicateWithFormat:@"rect.x == '0'"];
|
||||
XCTAssertNotNil([NSPredicate fb_snapshotBlockPredicateWithPredicate:expr]);
|
||||
}
|
||||
|
||||
@end
|
||||
50
WebDriverAgentTests/UnitTests/XCUIElementHelpersTests.m
Normal file
50
WebDriverAgentTests/UnitTests/XCUIElementHelpersTests.m
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 "FBElementUtils.h"
|
||||
|
||||
@interface XCUIElementHelpersTests : XCTestCase
|
||||
@property (nonatomic) NSDictionary *namesMapping;
|
||||
@end
|
||||
|
||||
@implementation XCUIElementHelpersTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
self.namesMapping = [FBElementUtils wdAttributeNamesMapping];
|
||||
}
|
||||
|
||||
- (void)testMappingContainsNamesAndAliases
|
||||
{
|
||||
XCTAssertTrue([self.namesMapping.allKeys containsObject:@"wdName"]);
|
||||
XCTAssertTrue([self.namesMapping.allKeys containsObject:@"name"]);
|
||||
}
|
||||
|
||||
- (void)testMappingContainsCorrectValueForAttrbutesWithoutGetters
|
||||
{
|
||||
XCTAssertTrue([[self.namesMapping objectForKey:@"label"] isEqualToString:@"wdLabel"]);
|
||||
XCTAssertTrue([[self.namesMapping objectForKey:@"wdLabel"] isEqualToString:@"wdLabel"]);
|
||||
}
|
||||
|
||||
- (void)testMappingContainsCorrectValueForAttrbutesWithGetters
|
||||
{
|
||||
XCTAssertTrue([[self.namesMapping objectForKey:@"visible"] isEqualToString:@"isWDVisible"]);
|
||||
XCTAssertTrue([[self.namesMapping objectForKey:@"wdVisible"] isEqualToString:@"isWDVisible"]);
|
||||
}
|
||||
|
||||
- (void)testEachPropertyHasAlias
|
||||
{
|
||||
NSArray *aliases = [self.namesMapping.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT(SELF beginsWith[c] 'wd')"]];
|
||||
NSArray *names = [self.namesMapping.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF beginsWith[c] 'wd'"]];
|
||||
XCTAssertEqual(aliases.count, names.count);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2018-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 <Foundation/Foundation.h>
|
||||
#import <WebDriverAgentLib/FBElement.h>
|
||||
#import <XCTest/XCUIElementTypes.h>
|
||||
|
||||
@class XCUIApplication;
|
||||
|
||||
@interface XCUIElementDouble : NSObject<FBElement>
|
||||
@property (nonatomic, strong, nonnull) XCUIApplication *application;
|
||||
@property (nonatomic, readwrite, assign) CGRect frame;
|
||||
@property (nonatomic, readwrite, nullable) id lastSnapshot;
|
||||
@property (nonatomic, assign) BOOL fb_isObstructedByAlert;
|
||||
@property (nonatomic, readwrite, copy, nonnull) NSDictionary *wdRect;
|
||||
@property (nonatomic, readwrite, assign) CGRect wdFrame;
|
||||
@property (nonatomic, readwrite, copy, nonnull) NSString *wdUID;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdName;
|
||||
@property (nonatomic, copy, readwrite, nullable) NSString *wdLabel;
|
||||
@property (nonatomic, copy, readwrite, nonnull) NSString *wdType;
|
||||
@property (nonatomic, strong, readwrite, nullable) NSString *wdValue;
|
||||
@property (nonatomic, readwrite, getter=isWDEnabled) BOOL wdEnabled;
|
||||
@property (nonatomic, readwrite, getter=isWDSelected) BOOL wdSelected;
|
||||
@property (nonatomic, readwrite) NSUInteger wdIndex;
|
||||
@property (nonatomic, readwrite, getter=isWDVisible) BOOL wdVisible;
|
||||
@property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible;
|
||||
@property (nonatomic, readwrite, getter=isWDFocused) BOOL wdFocused;
|
||||
@property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable;
|
||||
@property (copy, nonnull) NSArray *children;
|
||||
@property (nonatomic, readwrite, assign) XCUIElementType elementType;
|
||||
@property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer;
|
||||
|
||||
- (void)resolve;
|
||||
- (id _Nonnull)fb_standardSnapshot;
|
||||
- (id _Nonnull)fb_customSnapshot;
|
||||
|
||||
// Checks
|
||||
@property (nonatomic, assign, readonly) BOOL didResolve;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2018-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 "XCUIElementDouble.h"
|
||||
|
||||
@interface XCUIElementDouble ()
|
||||
@property (nonatomic, assign, readwrite) BOOL didResolve;
|
||||
@end
|
||||
|
||||
@implementation XCUIElementDouble
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.wdFrame = CGRectMake(0, 0, 0, 0);
|
||||
self.wdName = @"testName";
|
||||
self.wdLabel = @"testLabel";
|
||||
self.wdValue = @"magicValue";
|
||||
self.wdVisible = YES;
|
||||
self.wdAccessible = YES;
|
||||
self.wdEnabled = YES;
|
||||
self.wdSelected = YES;
|
||||
self.wdHittable = YES;
|
||||
self.wdIndex = 0;
|
||||
#if TARGET_OS_TV
|
||||
self.wdFocused = YES;
|
||||
#endif
|
||||
self.children = @[];
|
||||
self.wdRect = @{@"x": @0,
|
||||
@"y": @0,
|
||||
@"width": @0,
|
||||
@"height": @0,
|
||||
};
|
||||
self.wdAccessibilityContainer = NO;
|
||||
self.elementType = XCUIElementTypeOther;
|
||||
self.wdType = @"XCUIElementTypeOther";
|
||||
self.wdUID = @"0";
|
||||
self.lastSnapshot = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)fb_valueForWDAttributeName:(NSString *)name
|
||||
{
|
||||
return @"test";
|
||||
}
|
||||
|
||||
- (id)fb_standardSnapshot
|
||||
{
|
||||
return [self lastSnapshot];
|
||||
}
|
||||
|
||||
- (id)fb_customSnapshot
|
||||
{
|
||||
return [self lastSnapshot];
|
||||
}
|
||||
|
||||
- (void)resolve
|
||||
{
|
||||
self.didResolve = YES;
|
||||
}
|
||||
|
||||
- (id)lastSnapshot
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)fb_uid
|
||||
{
|
||||
return self.wdUID;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2018-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 "XCUIElementDouble.h"
|
||||
#import "FBTVNavigationTracker.h"
|
||||
#import "FBTVNavigationTracker-Private.h"
|
||||
|
||||
@interface FBTVNavigationTrackerTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBTVNavigationTrackerTests
|
||||
|
||||
- (void)testHorizontalDirectionWithItemShouldBeRight
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker horizontalDirectionWithItem:item andDelta:0.1];
|
||||
XCTAssertEqual(FBTVDirectionRight, direction);
|
||||
}
|
||||
|
||||
- (void)testHorizontalDirectionWithItemShouldBeLeft
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker horizontalDirectionWithItem:item andDelta:-0.1];
|
||||
XCTAssertEqual(FBTVDirectionLeft, direction);
|
||||
}
|
||||
|
||||
- (void)testHorizontalDirectionWithItemShouldBeNone
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker horizontalDirectionWithItem:item andDelta:DBL_EPSILON];
|
||||
XCTAssertEqual(FBTVDirectionNone, direction);
|
||||
}
|
||||
|
||||
- (void)testVerticalDirectionWithItemShouldBeDown
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker verticalDirectionWithItem:item andDelta:0.1];
|
||||
XCTAssertEqual(FBTVDirectionDown, direction);
|
||||
}
|
||||
|
||||
- (void)testVerticalDirectionWithItemShouldBeUp
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker verticalDirectionWithItem:item andDelta:-0.1];
|
||||
XCTAssertEqual(FBTVDirectionUp, direction);
|
||||
}
|
||||
|
||||
- (void)testVerticalDirectionWithItemShouldBeNone
|
||||
{
|
||||
XCUIElementDouble *el1 = XCUIElementDouble.new;
|
||||
|
||||
FBTVNavigationItem *item = [FBTVNavigationItem itemWithUid:@"123456789"];
|
||||
FBTVNavigationTracker *tracker = [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)el1];
|
||||
|
||||
FBTVDirection direction = [tracker verticalDirectionWithItem:item andDelta:DBL_EPSILON];
|
||||
XCTAssertEqual(FBTVDirectionNone, direction);
|
||||
}
|
||||
|
||||
@end
|
||||
24
WebDriverAgentTests/UnitTests_tvOS/Info.plist
Normal file
24
WebDriverAgentTests/UnitTests_tvOS/Info.plist
Normal 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.unitTests</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>
|
||||
Reference in New Issue
Block a user