Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c5d295bd5 | |||
| b274d1f84e | |||
| 57427e8c7e | |||
| 6cfb995d83 | |||
| c71d1a56dd | |||
| 6c24a7e922 | |||
| b14e5cfcb0 | |||
| fee76c2d93 | |||
| a07041901b | |||
| c370011616 | |||
| b8f155974c | |||
| 2fb22a6256 | |||
| bd60d945bb | |||
| 8f58410af9 | |||
| fc67cc944c | |||
| c8473017ec | |||
| 2bc0033aa8 | |||
| 64a068596b | |||
| c10693930d | |||
| c0f309edf3 | |||
| b1cc631748 | |||
| a89059f5dc | |||
| 2cc8f9e7d5 |
@@ -0,0 +1,26 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'main', 'stable' ]
|
||||
pull_request:
|
||||
branches: [ 'main', 'stable' ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: macos-14
|
||||
strategy:
|
||||
matrix:
|
||||
destination: ['platform=iOS\ Simulator,OS=17.4,name=iPhone\ 15\ Pro']
|
||||
scheme: ['ResearchKit']
|
||||
name: ${{ matrix.scheme }} Unit Tests
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set Xcode Version
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.3.app
|
||||
- name: Test
|
||||
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -verbose -workspace RKWorkspace.xcworkspace -scheme ${{ matrix.scheme }} -destination ${{ matrix.destination }} build test | xcpretty
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||

|
||||
|
||||
ResearchKit Framework
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
# ResearchKit Release Notes
|
||||
|
||||
## ResearchKit 3.1.1 Release Notes
|
||||
General bug fixes for the following:
|
||||
|
||||
- **ORKMotionActivityPermissionType**
|
||||
Fixed issue that caused the next button to remain disabled after gaining permission from user.
|
||||
|
||||
- **ORKRegistrationStep**
|
||||
Removed yellow overlay that prevented password entry.
|
||||
|
||||
- **ORKdBHLToneAudiometryStep**
|
||||
Fixed issue that caused the tap button to appear twice.
|
||||
|
||||
|
||||
## ResearchKit 3.1 Release Notes
|
||||
In addition to general stability and performance improvements, ResearchKit 3.1 includes the following updates:
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 0BC672D92BD9C52D005798AC /* Build configuration list for PBXAggregateTarget "ResearchKitAllTargets" */;
|
||||
buildPhases = (
|
||||
0BC672E82BD9C69C005798AC /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
0BC672E02BD9C541005798AC /* PBXTargetDependency */,
|
||||
@@ -6017,24 +6018,6 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
0BC672DA2BD9C52D005798AC /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0BC672DC2BD9C52D005798AC /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
3FFF18691829DB1E00167070 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5D000ED12620F27100E5442A /* Project-Debug.xcconfig */;
|
||||
|
||||
@@ -43,25 +43,20 @@ static const uint32_t IconDarkTintColor = 0xEF6FD8;
|
||||
@property (nonatomic, readonly, assign) BOOL canContinue;
|
||||
@end
|
||||
|
||||
@implementation ORKMotionActivityPermissionType {
|
||||
__weak NSTimer *_checkStatusTimer;
|
||||
}
|
||||
@implementation ORKMotionActivityPermissionType
|
||||
|
||||
+ (instancetype)new {
|
||||
return [[ORKMotionActivityPermissionType alloc] init];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)cleanUp {
|
||||
[self _invalidateCheckStatusTimer];
|
||||
}
|
||||
|
||||
- (CMMotionActivityManager *)activityManager {
|
||||
if (!_activityManager) {
|
||||
_activityManager = [[CMMotionActivityManager alloc] init];
|
||||
@@ -110,33 +105,9 @@ static const uint32_t IconDarkTintColor = 0xEF6FD8;
|
||||
[self.activityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue]
|
||||
withHandler:^(CMMotionActivity * _Nullable activity) {}];
|
||||
[self.activityManager stopActivityUpdates];
|
||||
|
||||
if (self.permissionsStatusUpdateCallback != nil) {
|
||||
self.permissionsStatusUpdateCallback();
|
||||
}
|
||||
|
||||
if (!_checkStatusTimer) {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
_checkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
|
||||
target:weakSelf
|
||||
selector:@selector(_checkPermissionStatus)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_checkPermissionStatus {
|
||||
if ([self permissionState] == ORKRequestPermissionsStateConnected && self.permissionsStatusUpdateCallback != nil) {
|
||||
self.permissionsStatusUpdateCallback();
|
||||
[self _invalidateCheckStatusTimer];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_invalidateCheckStatusTimer {
|
||||
if (_checkStatusTimer) {
|
||||
[_checkStatusTimer invalidate];
|
||||
_checkStatusTimer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
|
||||
@@ -69,7 +69,6 @@ ORK_CLASS_AVAILABLE
|
||||
@property (nonatomic, assign, readonly) BOOL canContinue;
|
||||
|
||||
- (void)requestPermission;
|
||||
- (void)cleanUp;
|
||||
|
||||
+ (ORKHealthKitPermissionType *)healthKitPermissionTypeWithSampleTypesToWrite:(nullable NSSet<HKSampleType *> *)sampleTypesToWrite
|
||||
objectTypesToRead:(nullable NSSet<HKObjectType *> *)objectTypesToRead;
|
||||
|
||||
@@ -66,10 +66,6 @@
|
||||
ORKThrowMethodUnavailableException();
|
||||
}
|
||||
|
||||
- (void)cleanUp {
|
||||
// left empty for optional subclass override
|
||||
}
|
||||
|
||||
+ (ORKHealthKitPermissionType *)healthKitPermissionTypeWithSampleTypesToWrite:(NSSet<HKSampleType *> *)sampleTypesToWrite objectTypesToRead:(NSSet<HKObjectType *> *)objectTypesToRead {
|
||||
return [[ORKHealthKitPermissionType alloc] initWithSampleTypesToWrite:sampleTypesToWrite
|
||||
objectTypesToRead:objectTypesToRead];
|
||||
|
||||
@@ -180,14 +180,14 @@ ORK_CLASS_AVAILABLE API_AVAILABLE(ios(11.0), watchos(6.0))
|
||||
/**
|
||||
A property that gates automatic tint color image changes based on appearance changes.
|
||||
|
||||
The default value for this property is NO.
|
||||
The default value for this property is NO.
|
||||
*/
|
||||
@property (nonatomic) BOOL shouldAutomaticallyAdjustImageTintColor;
|
||||
|
||||
/**
|
||||
A property that determines whether to show progress for this step when presented.
|
||||
|
||||
The default is YES.
|
||||
The default is YES.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL showsProgress;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*] =
|
||||
SWIFT_VERSION = 5.0
|
||||
CLANG_STATIC_ANALYZER_MODE = deep
|
||||
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 3.1.1
|
||||
ORK_FRAMEWORK_VERSION_NUMBER = 3.1
|
||||
|
||||
ORK_FRAMEWORK_BUILD_NUMBER = $(ORK_FRAMEWORK_BUILD_NUMBER_CI_$(CI)) // ORK_FRAMEWORK_BUILD_NUMBER_CI_TRUE or ORK_FRAMEWORK_BUILD_NUMBER_CI_
|
||||
ORK_FRAMEWORK_BUILD_NUMBER_CI_TRUE = $(CI_BUILD_NUMBER)
|
||||
|
||||
@@ -73,8 +73,13 @@ static NSArray <ORKFormItem*> *ORKRegistrationFormItems(ORKRegistrationStepOptio
|
||||
answerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
answerFormat.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
answerFormat.spellCheckingType = UITextSpellCheckingTypeNo;
|
||||
answerFormat.textContentType = UITextContentTypeOneTimeCode;
|
||||
|
||||
|
||||
if (@available(iOS 12.0, *)) {
|
||||
answerFormat.textContentType = UITextContentTypeNewPassword;
|
||||
} else {
|
||||
answerFormat.textContentType = UITextContentTypePassword;
|
||||
}
|
||||
|
||||
ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierPassword
|
||||
text:ORKLocalizedString(@"PASSWORD_FORM_ITEM_TITLE", nil)
|
||||
answerFormat:answerFormat
|
||||
|
||||
@@ -18,7 +18,7 @@ Present a specific question and collect an answer.
|
||||
- ``ORKAnswerFormat``
|
||||
- ``ORKNumericPrecision``
|
||||
|
||||
### Height and Weight
|
||||
### Height, and Weight
|
||||
|
||||
- ``ORKHeightAnswerFormat``
|
||||
- ``ORKWeightAnswerFormat``
|
||||
|
||||
+10
-12
@@ -122,20 +122,18 @@ NSString * const ORKdBHLToneAudiometryStepViewAccessibilityIdentifier = @"ORKdBH
|
||||
- (void)configureStep {
|
||||
ORKdBHLToneAudiometryStep *dBHLTAStep = [self dBHLToneAudiometryStep];
|
||||
|
||||
if (!self.dBHLToneAudiometryContentView) {
|
||||
self.dBHLToneAudiometryContentView = [[ORKdBHLToneAudiometryContentView alloc] init];
|
||||
self.activeStepView.activeCustomView = self.dBHLToneAudiometryContentView;
|
||||
self.activeStepView.customContentFillsAvailableSpace = YES;
|
||||
[self.activeStepView.navigationFooterView setHidden:YES];
|
||||
self.dBHLToneAudiometryContentView = [[ORKdBHLToneAudiometryContentView alloc] init];
|
||||
self.activeStepView.activeCustomView = self.dBHLToneAudiometryContentView;
|
||||
self.activeStepView.customContentFillsAvailableSpace = YES;
|
||||
[self.activeStepView.navigationFooterView setHidden:YES];
|
||||
|
||||
[self.dBHLToneAudiometryContentView.tapButton addTarget:self action:@selector(tapButtonPressed) forControlEvents:UIControlEventTouchDown];
|
||||
|
||||
_audioChannel = dBHLTAStep.earPreference;
|
||||
_audioGenerator = [self createAudioGeneratorFromHeadphoneType:dBHLTAStep.headphoneType];
|
||||
_audioGenerator.delegate = self;
|
||||
[self.dBHLToneAudiometryContentView.tapButton addTarget:self action:@selector(tapButtonPressed) forControlEvents:UIControlEventTouchDown];
|
||||
|
||||
_audioChannel = dBHLTAStep.earPreference;
|
||||
_audioGenerator = [self createAudioGeneratorFromHeadphoneType:dBHLTAStep.headphoneType];
|
||||
_audioGenerator.delegate = self;
|
||||
|
||||
_hapticFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle: UIImpactFeedbackStyleHeavy];
|
||||
}
|
||||
_hapticFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle: UIImpactFeedbackStyleHeavy];
|
||||
}
|
||||
|
||||
- (void)addObservers {
|
||||
|
||||
@@ -55,7 +55,7 @@ static BOOL ORKIsResearchKitClass(Class class) {
|
||||
|
||||
+ (NSArray<NSString *> *)_fetchExclusionList {
|
||||
NSArray<NSString *> *classesToExclude = @[];
|
||||
|
||||
|
||||
#if !ORK_FEATURE_CLLOCATIONMANAGER_AUTHORIZATION
|
||||
NSArray<NSString *> *locationClasses = @[
|
||||
@"ORKLocation",
|
||||
@@ -485,7 +485,6 @@ ORK_MAKE_TEST_INIT(ORKAccuracyStroopStep, (^{ return [[ORKAccuracyStroopStep all
|
||||
[ORKTouchAbilityPinchStep class],
|
||||
[ORKTouchAbilitySwipeStep class],
|
||||
[ORKTouchAbilityTapResult class],
|
||||
[ORKTouchAbilityTouchTracker class],
|
||||
[ORKTouchAbilityRotationStep class],
|
||||
[ORKTouchAbilityLongPressStep class],
|
||||
[ORKTouchAbilityScrollStep class],
|
||||
@@ -620,7 +619,6 @@ ORK_MAKE_TEST_INIT(ORKAccuracyStroopStep, (^{ return [[ORKAccuracyStroopStep all
|
||||
@"ORKTimeIntervalAnswerFormat.defaultInterval",
|
||||
@"ORKTimeIntervalAnswerFormat.maximumInterval",
|
||||
@"ORKTimeIntervalAnswerFormat.step",
|
||||
@"ORKTouchAbilityTouchTracker.delegate",
|
||||
@"ORKVerificationStep.verificationViewControllerClass",
|
||||
@"ORKVideoCaptureStep.templateImage",
|
||||
@"ORKWeightAnswerFormat.useMetricSystem",
|
||||
|
||||
+2
-15
@@ -91,18 +91,9 @@ NSString * const ORKRequestPermissionsStepViewAccessibilityIdentifier = @"ORKReq
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self _cleanupPermissionTypes];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:ORKRequestPermissionsNotificationCardViewStatusChanged object:nil];
|
||||
}
|
||||
|
||||
- (void)_cleanupPermissionTypes {
|
||||
ORKRequestPermissionsStep *requestPermissionStep = [self requestPermissionsStep];
|
||||
|
||||
for (ORKPermissionType *permissionType in requestPermissionStep.permissionTypes) {
|
||||
[permissionType cleanUp];
|
||||
}
|
||||
}
|
||||
|
||||
- (ORKStepResult *)result {
|
||||
ORKStepResult *parentResult = [super result];
|
||||
|
||||
@@ -194,13 +185,9 @@ NSString * const ORKRequestPermissionsStepViewAccessibilityIdentifier = @"ORKReq
|
||||
NSMutableArray<ORKRequestPermissionView *> *cardViews = [NSMutableArray new];
|
||||
|
||||
for (ORKPermissionType *permissionType in requestPermissionStep.permissionTypes) {
|
||||
ORKRequestPermissionView *cardView = [[ORKRequestPermissionView alloc] initWithIconImage:permissionType.image
|
||||
title:permissionType.localizedTitle
|
||||
detailText:permissionType.localizedDetailText];
|
||||
ORKRequestPermissionView *cardView = [[ORKRequestPermissionView alloc] initWithIconImage:permissionType.image title:permissionType.localizedTitle detailText:permissionType.localizedDetailText];
|
||||
[cardView updateIconTintColor:permissionType.iconTintColor];
|
||||
[cardView.requestPermissionButton addTarget:permissionType
|
||||
action:@selector(requestPermission)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
[cardView.requestPermissionButton addTarget:permissionType action:@selector(requestPermission) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self permissionStatusUpdatedForPermissionType:permissionType cardView:cardView];
|
||||
|
||||
// create the update callback
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
51F210FE2B49D04F0072B536 /* TaskListRowConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F210FD2B49D04F0072B536 /* TaskListRowConstants.swift */; };
|
||||
863CCD821ACF545E009FD3B4 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 863CCD811ACF545E009FD3B4 /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
86B89AA51AB2C0A5001626A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */; };
|
||||
8C67958C2BC3B09B00DE7286 /* TaskListRowConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F210FD2B49D04F0072B536 /* TaskListRowConstants.swift */; };
|
||||
9622283924F04DBF0056E74D /* TaskScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283824F04DBF0056E74D /* TaskScreen.swift */; };
|
||||
9622283B24F04DFE0056E74D /* CommonElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283A24F04DFE0056E74D /* CommonElements.swift */; };
|
||||
9622283D24F04E6F0056E74D /* AllowScreens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283C24F04E6F0056E74D /* AllowScreens.swift */; };
|
||||
9622283F24F04EBA0056E74D /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622283E24F04EBA0056E74D /* Helpers.swift */; };
|
||||
9622284124F04EEF0056E74D /* PreSubmissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622284024F04EEF0056E74D /* PreSubmissionTests.swift */; };
|
||||
B125E3D41B1BA47600FF8759 /* tap.aif in Resources */ = {isa = PBXBuildFile; fileRef = B125E3D31B1BA47600FF8759 /* tap.aif */; };
|
||||
BAAC3FD620C4EF1C0065B9E1 /* ResearchKit.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BAAC3FD520C4EF1C0065B9E1 /* ResearchKit.pdf */; };
|
||||
BC2A3CD91C58F1CA00DA64B7 /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */; };
|
||||
@@ -43,6 +49,13 @@
|
||||
remoteGlobalIDString = 869230BD1AAA890A00BFE11B;
|
||||
remoteInfo = ORKCatalog;
|
||||
};
|
||||
9622282F24F04D780056E74D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 869230B61AAA890A00BFE11B /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 869230BD1AAA890A00BFE11B;
|
||||
remoteInfo = ORKCatalog;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -118,6 +131,14 @@
|
||||
869230BE1AAA890A00BFE11B /* ORKCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
86B89A981AB2C0A5001626A4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ORKCatalog/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
|
||||
9622282A24F04D780056E74D /* ORKCatalogUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ORKCatalogUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9622282E24F04D780056E74D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9622283824F04DBF0056E74D /* TaskScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskScreen.swift; sourceTree = "<group>"; };
|
||||
9622283A24F04DFE0056E74D /* CommonElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonElements.swift; sourceTree = "<group>"; };
|
||||
9622283C24F04E6F0056E74D /* AllowScreens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllowScreens.swift; sourceTree = "<group>"; };
|
||||
9622283E24F04EBA0056E74D /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
|
||||
9622284024F04EEF0056E74D /* PreSubmissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreSubmissionTests.swift; sourceTree = "<group>"; };
|
||||
9632B5D524F093070010818C /* ORKCatalogUI.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = ORKCatalogUI.xctestplan; sourceTree = "<group>"; };
|
||||
B125E3D31B1BA47600FF8759 /* tap.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = tap.aif; sourceTree = "<group>"; };
|
||||
BAAC3FD520C4EF1C0065B9E1 /* ResearchKit.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ResearchKit.pdf; sourceTree = "<group>"; };
|
||||
BAFAD7AA1EFB2907004DEC45 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-CA"; path = fr_CA.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -151,6 +172,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9622282724F04D780056E74D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@@ -205,6 +233,7 @@
|
||||
children = (
|
||||
5116D0BF2677FB780010FAB1 /* ResearchKit-Shared.xcconfig */,
|
||||
3E39B9E81ABF675000C2ABE5 /* README.md */,
|
||||
9622282B24F04D780056E74D /* ORKCatalogUITests */,
|
||||
51AF19782B59F1E500D3B399 /* ORKCatalogTests */,
|
||||
BC2A3C9E1C58E81500DA64B7 /* Frameworks */,
|
||||
869230C01AAA890A00BFE11B /* ORKCatalog */,
|
||||
@@ -216,6 +245,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
869230BE1AAA890A00BFE11B /* ORKCatalog.app */,
|
||||
9622282A24F04D780056E74D /* ORKCatalogUITests.xctest */,
|
||||
51AF19772B59F1E400D3B399 /* ORKCatalogTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
@@ -244,6 +274,28 @@
|
||||
path = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8CDBF98A2AFD9FC800AF767B /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9622283824F04DBF0056E74D /* TaskScreen.swift */,
|
||||
9622283A24F04DFE0056E74D /* CommonElements.swift */,
|
||||
9622283C24F04E6F0056E74D /* AllowScreens.swift */,
|
||||
);
|
||||
path = Screens;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9622282B24F04D780056E74D /* ORKCatalogUITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8CDBF98A2AFD9FC800AF767B /* Screens */,
|
||||
9622282E24F04D780056E74D /* Info.plist */,
|
||||
9622283E24F04EBA0056E74D /* Helpers.swift */,
|
||||
9622284024F04EEF0056E74D /* PreSubmissionTests.swift */,
|
||||
9632B5D524F093070010818C /* ORKCatalogUI.xctestplan */,
|
||||
);
|
||||
path = ORKCatalogUITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BC2A3C9E1C58E81500DA64B7 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -308,6 +360,24 @@
|
||||
productReference = 869230BE1AAA890A00BFE11B /* ORKCatalog.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
9622282924F04D780056E74D /* ORKCatalogUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9622283624F04D780056E74D /* Build configuration list for PBXNativeTarget "ORKCatalogUITests" */;
|
||||
buildPhases = (
|
||||
9622282624F04D780056E74D /* Sources */,
|
||||
9622282724F04D780056E74D /* Frameworks */,
|
||||
9622282824F04D780056E74D /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
9622283024F04D780056E74D /* PBXTargetDependency */,
|
||||
);
|
||||
name = ORKCatalogUITests;
|
||||
productName = ORKCatalogUITests;
|
||||
productReference = 9622282A24F04D780056E74D /* ORKCatalogUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@@ -328,6 +398,12 @@
|
||||
LastSwiftMigration = 1530;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
9622282924F04D780056E74D = {
|
||||
CreatedOnToolsVersion = 11.6;
|
||||
DevelopmentTeam = "";
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 869230BD1AAA890A00BFE11B;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 869230B91AAA890A00BFE11B /* Build configuration list for PBXProject "ORKCatalog" */;
|
||||
@@ -391,6 +467,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
869230BD1AAA890A00BFE11B /* ORKCatalog */,
|
||||
9622282924F04D780056E74D /* ORKCatalogUITests */,
|
||||
51AF19762B59F1E400D3B399 /* ORKCatalogTests */,
|
||||
);
|
||||
};
|
||||
@@ -418,6 +495,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9622282824F04D780056E74D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -447,6 +531,19 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9622282624F04D780056E74D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9622283924F04DBF0056E74D /* TaskScreen.swift in Sources */,
|
||||
9622283B24F04DFE0056E74D /* CommonElements.swift in Sources */,
|
||||
8C67958C2BC3B09B00DE7286 /* TaskListRowConstants.swift in Sources */,
|
||||
9622284124F04EEF0056E74D /* PreSubmissionTests.swift in Sources */,
|
||||
9622283F24F04EBA0056E74D /* Helpers.swift in Sources */,
|
||||
9622283D24F04E6F0056E74D /* AllowScreens.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
@@ -455,6 +552,11 @@
|
||||
target = 869230BD1AAA890A00BFE11B /* ORKCatalog */;
|
||||
targetProxy = 51AF197B2B59F1E500D3B399 /* PBXContainerItemProxy */;
|
||||
};
|
||||
9622283024F04D780056E74D /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 869230BD1AAA890A00BFE11B /* ORKCatalog */;
|
||||
targetProxy = 9622282F24F04D780056E74D /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
@@ -758,6 +860,68 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9622283124F04D780056E74D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ORKCatalogUITests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.HRP.ORKCatalogUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = ORKCatalog;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9622283424F04D780056E74D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ORKCatalogUITests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.HRP.ORKCatalogUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = ORKCatalog;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -788,6 +952,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
};
|
||||
9622283624F04D780056E74D /* Build configuration list for PBXNativeTarget "ORKCatalogUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9622283124F04D780056E74D /* Debug */,
|
||||
9622283424F04D780056E74D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Debug;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 869230B61AAA890A00BFE11B /* Project object */;
|
||||
|
||||
@@ -26,9 +26,24 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:ORKCatalogUITests/ORKCatalogUI.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "9622282924F04D780056E74D"
|
||||
BuildableName = "ORKCatalogUITests.xctest"
|
||||
BlueprintName = "ORKCatalogUITests"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1500"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "869230BD1AAA890A00BFE11B"
|
||||
BuildableName = "ORKCatalog.app"
|
||||
BlueprintName = "ORKCatalog"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:ORKCatalogUITests/ORKCatalogUI.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "9622282924F04D780056E74D"
|
||||
BuildableName = "ORKCatalogUITests.xctest"
|
||||
BlueprintName = "ORKCatalogUITests"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "51AF19762B59F1E400D3B399"
|
||||
BuildableName = "ORKCatalogTests.xctest"
|
||||
BlueprintName = "ORKCatalogTests"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "869230BD1AAA890A00BFE11B"
|
||||
BuildableName = "ORKCatalog.app"
|
||||
BlueprintName = "ORKCatalog"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "869230BD1AAA890A00BFE11B"
|
||||
BuildableName = "ORKCatalog.app"
|
||||
BlueprintName = "ORKCatalog"
|
||||
ReferencedContainer = "container:ORKCatalog.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -126,5 +126,3 @@ extension ResultViewController: ResultProviderDelegate {
|
||||
present(shareSheet, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -286,5 +286,3 @@ class TaskListViewController: UITableViewController, ORKTaskViewControllerDelega
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
Copyright (c) 2015, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
class Helpers: XCTestCase {
|
||||
let app = XCUIApplication()
|
||||
let commonElements = CommonElements()
|
||||
let taskScreen = TaskScreen()
|
||||
|
||||
enum SliderTesting {
|
||||
case slider1
|
||||
case slider2
|
||||
case slider3
|
||||
case slider4
|
||||
case slider5
|
||||
case slider6
|
||||
}
|
||||
enum SwipeDirection {
|
||||
case up
|
||||
case down
|
||||
case left
|
||||
case right
|
||||
case skip
|
||||
}
|
||||
|
||||
//Verify existence of any XCUIElement with an option to tap that element
|
||||
func verifyElement(_ element: XCUIElement, _ tap: Bool = false) -> Bool {
|
||||
if element.exists {
|
||||
if tap && element.isEnabled {
|
||||
element.tap()
|
||||
}
|
||||
return true
|
||||
}
|
||||
XCTFail("Unable to confirm \(element) exists")
|
||||
return false
|
||||
}
|
||||
|
||||
//Verify an element exists based on static text label, option to tap the element after verification
|
||||
func verifyElementByText(identifier: String, _ tap: Bool = false) -> Bool {
|
||||
let item = app.staticTexts["\(identifier)"]
|
||||
if item.exists {
|
||||
if tap && item.isEnabled {
|
||||
item.tap()
|
||||
}
|
||||
return true
|
||||
}
|
||||
XCTFail("Unable to locate Element based on text \(identifier)")
|
||||
return false
|
||||
}
|
||||
|
||||
//Verify an element matching XCUIElement.ElementType exists based on an identifying string existing in the label or value of the element.
|
||||
func verifyElementByType(_ elementType: XCUIElement.ElementType, _ identifier: String, _ tap: Bool = false) -> Bool {
|
||||
let identifyingOptions = ["label", "value"]
|
||||
for option in identifyingOptions {
|
||||
let predicate = NSPredicate(format: "\(option) CONTAINS '\(identifier)'")
|
||||
let target = app.descendants(matching: elementType).element(matching: predicate)
|
||||
if target.exists {
|
||||
if tap && target.isEnabled {
|
||||
target.tap()
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
XCTFail("Unable to locate Element based on text \(identifier)")
|
||||
return false
|
||||
}
|
||||
|
||||
//Verify any XCUIElement exists and return that element for assignment, option to tap available
|
||||
func verifyAndAssign(_ element: XCUIElement, _ tap: Bool = false) -> XCUIElement? {
|
||||
if element.exists {
|
||||
if tap && element.isEnabled {
|
||||
element.tap()
|
||||
}
|
||||
return element
|
||||
}
|
||||
XCTFail("Unable to confirm \(element) exists")
|
||||
return nil
|
||||
}
|
||||
|
||||
//Verify an element exists based on static text label, option to tap the element after verification. Element returned for assignment.
|
||||
func verifyAndAssignByText(_ identifier: String, _ tap: Bool = false) -> XCUIElement? {
|
||||
let item = app.staticTexts["\(identifier)"]
|
||||
if item.exists {
|
||||
if tap && item.isEnabled {
|
||||
item.tap()
|
||||
}
|
||||
return item
|
||||
}
|
||||
XCTFail("Unable to locate Element based on text \(identifier)")
|
||||
return nil
|
||||
}
|
||||
|
||||
//Verify an element matching XCUIElement.ElementType exists based on an identifying string existing in the label or value of the element.
|
||||
//Element returned for assignment.
|
||||
func verifyAndAssignByType(_ elementType: XCUIElement.ElementType, _ identifier: String, _ tap: Bool = false) -> XCUIElement? {
|
||||
let identifyingOptions = ["label", "value"]
|
||||
for option in identifyingOptions {
|
||||
let predicate = NSPredicate(format: "\(option) CONTAINS '\(identifier)'")
|
||||
let target = app.descendants(matching: elementType).element(matching: predicate)
|
||||
if target.exists {
|
||||
if tap && target.isEnabled {
|
||||
target.tap()
|
||||
}
|
||||
return target
|
||||
}
|
||||
}
|
||||
XCTFail("Unable to locate Element based on text \(identifier)")
|
||||
return nil
|
||||
}
|
||||
|
||||
//Enter any ORKCatalog task based on the name of the task and leave without taking action
|
||||
func launchAndLeave(_ task: String) -> Bool {
|
||||
XCTAssert(verifyElement(taskScreen.mainTaskScreen))
|
||||
let currentTask = verifyAndAssignByText(task)!
|
||||
currentTask.tap()
|
||||
|
||||
sleep(1)
|
||||
guard let cancelButton = commonElements.cancelButton else {
|
||||
XCTFail("Unable to locate Cancel Button")
|
||||
return false
|
||||
}
|
||||
cancelButton.tap()
|
||||
|
||||
sleep(1)
|
||||
guard let exitButton = commonElements.getExitButton() else {
|
||||
XCTFail("Unable to locate End Task or Discard Results button")
|
||||
return false
|
||||
}
|
||||
exitButton.tap()
|
||||
|
||||
return verifyElement(taskScreen.mainTaskScreen)
|
||||
}
|
||||
|
||||
//Deletes the ORKCatalog app from the simulator instance.
|
||||
func deleteORKCatalog() {
|
||||
app.terminate()
|
||||
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
|
||||
let icon = springboard.icons["ORKCatalog"]
|
||||
if icon.exists {
|
||||
icon.press(forDuration: 1.3)
|
||||
springboard.buttons["Delete App"].tap()
|
||||
sleep(2)
|
||||
springboard.buttons["Delete"].tap()
|
||||
}
|
||||
}
|
||||
|
||||
//Verify that the Navigation bar includes a page count in the form of "pageNumber of pageTotal"
|
||||
func verifyPageByCount(_ pageNumber: Int, _ pageTotal: Int) -> Bool {
|
||||
let pageCount = app.navigationBars["\(String(pageNumber)) of \(String(pageTotal))"]
|
||||
XCTAssert(pageCount.exists)
|
||||
return true
|
||||
}
|
||||
|
||||
//Return an XCUIElement based on page number of the Scale test
|
||||
func scaleTitle(_ pageNumber: Int) -> XCUIElement? {
|
||||
let titles: [Int: String] = [1: "Discrete Scale", 2: "Continuous Scale", 3: "Discrete Vertical Scale", 4: "Continuous Vertical Scale", 5: "Text Scale", 6: "Text Vertical Scale"]
|
||||
return app.scrollViews.otherElements.staticTexts[titles[pageNumber] ?? "Invalid Page Number"]
|
||||
}
|
||||
|
||||
//Select and interact with sliders in the Scale Question task. Function verifies expected outputs of each slider.
|
||||
func sliderValuesCheck(_ sliderScreen:SliderTesting, _ screenNum: Int, _ direction:SwipeDirection) -> Bool {
|
||||
let sliderValues: [SliderTesting:String] = [
|
||||
.slider1:"8",
|
||||
.slider3:"8",
|
||||
.slider4:"4.23",
|
||||
.slider5:"Above Average",
|
||||
.slider6:"Above Average"
|
||||
]
|
||||
|
||||
let slider = verifyAndAssignByType(.slider, "Response slider")!
|
||||
XCTAssert(slider.waitForExistence(timeout: 2), "Unable to locate slider on page \(screenNum)")
|
||||
XCTAssert(verifyPageByCount(screenNum, 6), "Unable to locate \"\(screenNum) of 6\"")
|
||||
XCTAssert(scaleTitle(screenNum)!.waitForExistence(timeout: 2), "Unable to locate \(scaleTitle(screenNum)!)")
|
||||
|
||||
switch direction {
|
||||
case .up:
|
||||
slider.swipeUp()
|
||||
case .right:
|
||||
slider.swipeRight()
|
||||
case .left:
|
||||
XCTFail("Unexpected Swipe Direction of Left Entered")
|
||||
case .down:
|
||||
XCTFail("Unexpected Swipe Direction of Down Entered")
|
||||
case .skip:
|
||||
XCTAssert(commonElements.skipButton!.waitForExistence(timeout: 2))
|
||||
commonElements.skipButton!.tap()
|
||||
|
||||
}
|
||||
|
||||
if sliderScreen != .slider2 {
|
||||
XCTAssert(verifyElementByType(.slider, sliderValues[sliderScreen]!))
|
||||
if commonElements.doneButton!.exists {
|
||||
commonElements.doneButton!.tap()
|
||||
return true
|
||||
}
|
||||
XCTAssert(commonElements.nextButton!.waitForExistence(timeout: 2))
|
||||
commonElements.nextButton!.tap()
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//Returns true if sliders behave as expected on any given screen in the Scale Question task.
|
||||
func sliderScreenCheck(_ sliderScreen:SliderTesting) -> Bool {
|
||||
XCTAssert(verifyElement(app.scrollViews.otherElements.staticTexts["Scale"]))
|
||||
XCTAssert(verifyElement(app.scrollViews.otherElements.staticTexts["Your question here."]))
|
||||
|
||||
switch sliderScreen {
|
||||
case .slider1:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 1, .right), "Slider1 Values Check Failed")
|
||||
case .slider2:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 2, .skip), "Slider2 Values Check Failed")
|
||||
case .slider3:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 3, .up), "Slider3 Values Check Failed")
|
||||
case .slider4:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 4, .up), "Slider4 Values Check Failed")
|
||||
case .slider5:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 5, .right), "Slider5 Values Check Failed")
|
||||
case .slider6:
|
||||
XCTAssert(sliderValuesCheck(sliderScreen, 6, .up), "Slider6 Values Check Failed")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//Monitors for any alerts that may appear and interupt the normal flow of the applicaiton.
|
||||
func monitorAlerts() {
|
||||
addUIInterruptionMonitor(withDescription: "Alert") { element in
|
||||
do {
|
||||
// Push Notification
|
||||
let button = element.buttons["Allow"]
|
||||
let title = element.staticTexts["“ORKCatalog” Would Like to Send You Notifications"]
|
||||
if title.exists && button.exists {
|
||||
button.tap()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
// Location
|
||||
let button = element.buttons["Allow While Using App"]
|
||||
if button.exists {
|
||||
button.tap()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
// Microphone
|
||||
let button = element.buttons["OK"]
|
||||
let title = element.staticTexts["“ORKCatalog” Would Like to Access the Microphone"]
|
||||
if title.exists && button.exists {
|
||||
button.tap()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func verifyElementByText(_ text: String, _ tap: Bool = false) -> Bool {
|
||||
let item = app.staticTexts["\(text)"]
|
||||
XCTAssert(item.waitForExistence(timeout: 3))
|
||||
if tap && item.isEnabled {
|
||||
item.tap()
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"configurations" : [
|
||||
{
|
||||
"id" : "CE2DCF31-672A-4F3F-A538-AF0ADA4806F4",
|
||||
"name" : "Configuration 1",
|
||||
"options" : {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultOptions" : {
|
||||
"codeCoverage" : false,
|
||||
"targetForVariableExpansion" : {
|
||||
"containerPath" : "container:ORKCatalog.xcodeproj",
|
||||
"identifier" : "869230BD1AAA890A00BFE11B",
|
||||
"name" : "ORKCatalog"
|
||||
}
|
||||
},
|
||||
"testTargets" : [
|
||||
{
|
||||
"selectedTests" : [
|
||||
"PreSubmissionTests\/testAccessActiveTasks()",
|
||||
"PreSubmissionTests\/testAccessSurveyQuestions()",
|
||||
"PreSubmissionTests\/testAccessSurveyTasks()",
|
||||
"PreSubmissionTests\/testImageMultipleChoice()",
|
||||
"PreSubmissionTests\/testSQPickerWheel()",
|
||||
"PreSubmissionTests\/testSQSliders()",
|
||||
"PreSubmissionTests\/testSQTextEntry()",
|
||||
"PreSubmissionTests\/testWrittenMultipleChoice()"
|
||||
],
|
||||
"target" : {
|
||||
"containerPath" : "container:ORKCatalog.xcodeproj",
|
||||
"identifier" : "9622282924F04D780056E74D",
|
||||
"name" : "ORKCatalogUITests"
|
||||
}
|
||||
},
|
||||
{
|
||||
"target" : {
|
||||
"containerPath" : "container:ORKCatalog.xcodeproj",
|
||||
"identifier" : "51AF19762B59F1E400D3B399",
|
||||
"name" : "ORKCatalogTests"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 1
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright (c) 2015, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import XCTest
|
||||
|
||||
class PreSubmissionTests: XCTestCase {
|
||||
let app = XCUIApplication()
|
||||
let commonElements = CommonElements()
|
||||
let allowScreens = AllowScreens()
|
||||
let helpers = Helpers()
|
||||
let taskScreen = TaskScreen()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
helpers.monitorAlerts()
|
||||
app.launch()
|
||||
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
|
||||
}
|
||||
|
||||
func testAccessSurveyTasks() throws {
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
for task in taskScreen.surveyTasks {
|
||||
XCTAssert(helpers.launchAndLeave(task))
|
||||
}
|
||||
}
|
||||
|
||||
func testAccessSurveyQuestions() throws {
|
||||
XCTAssert(allowScreens.triggerAllowScreens())
|
||||
|
||||
for task in taskScreen.surveyQuestions {
|
||||
XCTAssert(helpers.launchAndLeave(task))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func testAccessActiveTasks() throws {
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
for task in taskScreen.activeTasks {
|
||||
XCTAssert(helpers.launchAndLeave(task))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func testWrittenMultipleChoice() throws {
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
let options = ["Choice 1", "Choice 2", "Choice 3", "Other"]
|
||||
let required = ["Text Choice", "Additional text can go here.", "Your question here."]
|
||||
|
||||
XCTAssert(helpers.verifyElementByText("Text Choice Question", true))
|
||||
|
||||
for item in required {
|
||||
XCTAssert(app.tables.staticTexts[item].exists, "Unable to locate the \(item) element.")
|
||||
}
|
||||
|
||||
XCTAssert(helpers.verifyElementByText(options.randomElement()!, true))
|
||||
|
||||
XCTAssert(helpers.verifyElementByType(.button, "Done", true))
|
||||
return
|
||||
}
|
||||
|
||||
func testImageMultipleChoice() throws {
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
XCTAssert(helpers.verifyElementByText("Image Choice Question", true))
|
||||
|
||||
let required = ["Image Choice", "Additional text can go here."]
|
||||
for item in required {
|
||||
XCTAssert(helpers.verifyElementByText(item))
|
||||
}
|
||||
|
||||
let square = helpers.verifyAndAssignByType(.button, "Square Shape")!
|
||||
let circle = helpers.verifyAndAssignByType(.button, "Round Shape")!
|
||||
|
||||
square.tap()
|
||||
|
||||
XCTAssert(helpers.verifyElementByType(.button, "Next", true))
|
||||
XCTAssert(helpers.verifyPageByCount(2, 2))
|
||||
XCTAssert(helpers.verifyElementByType(.button, "Back", true))
|
||||
XCTAssert(helpers.verifyPageByCount(1, 2))
|
||||
square.tap()
|
||||
circle.tap()
|
||||
|
||||
XCTAssert(helpers.verifyElementByType(.button, "Next", true))
|
||||
XCTAssert(helpers.verifyPageByCount(2, 2))
|
||||
circle.tap()
|
||||
|
||||
XCTAssert(helpers.verifyElementByType(.button, "Done", true))
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
return
|
||||
}
|
||||
|
||||
func testSQPickerWheel() throws {
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
let dt = helpers.verifyAndAssignByText("Date and Time Question")!
|
||||
let elementsQuery = app.scrollViews.otherElements.staticTexts
|
||||
|
||||
dt.tap()
|
||||
XCTAssert(elementsQuery["Date and Time"].exists)
|
||||
XCTAssert(elementsQuery["Additional text can go here."].exists)
|
||||
XCTAssert(elementsQuery["Your question here."].exists)
|
||||
|
||||
let skip = helpers.verifyAndAssignByText("Skip")!
|
||||
XCTAssert(skip.isEnabled)
|
||||
|
||||
let done = helpers.verifyAndAssignByType(.button, "Done")!
|
||||
XCTAssert(done.isEnabled)
|
||||
|
||||
let now = Date()
|
||||
let formatter = DateFormatter()
|
||||
formatter.setLocalizedDateFormatFromTemplate("a")
|
||||
let datetime = formatter.string(from: now)
|
||||
formatter.setLocalizedDateFormatFromTemplate("MMM dd")
|
||||
let newDate = Calendar.current.date(byAdding: .day, value: 5, to: now)
|
||||
let newDateString = formatter.string(from: newDate!)
|
||||
|
||||
let firstPredicate = NSPredicate(format: "value BEGINSWITH 'Today'")
|
||||
let firstPicker = app.pickerWheels.element(matching: firstPredicate)
|
||||
XCTAssert(firstPicker.isEnabled)
|
||||
firstPicker.adjust(toPickerWheelValue: newDateString)
|
||||
|
||||
let secondPicker = helpers.verifyAndAssignByType(.pickerWheel, "clock")!
|
||||
XCTAssert((secondPicker.isEnabled))
|
||||
secondPicker.adjust(toPickerWheelValue: "5")
|
||||
|
||||
let thirdPicker = helpers.verifyAndAssignByType(.pickerWheel, "minute")!
|
||||
XCTAssert(thirdPicker.isEnabled)
|
||||
thirdPicker.adjust(toPickerWheelValue: "23")
|
||||
let fourthPredicate = NSPredicate(format: "value CONTAINS '\(datetime)'")
|
||||
let fourthPicker = app.pickerWheels.element(matching: fourthPredicate)
|
||||
XCTAssert(fourthPicker.isEnabled)
|
||||
datetime == "AM" ? fourthPicker.adjust(toPickerWheelValue: "PM") : fourthPicker.adjust(toPickerWheelValue: "AM")
|
||||
|
||||
XCTAssert(done.isEnabled)
|
||||
done.tap()
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
dt.tap()
|
||||
skip.tap()
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func testSQSliders() throws {
|
||||
XCTAssert(helpers.verifyElementByText("Scale Question", true))
|
||||
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider1))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider2))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider3))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider4))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider5))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider6))
|
||||
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider1))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider2))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider3))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider4))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider5))
|
||||
XCTAssert(helpers.sliderScreenCheck(.slider6))
|
||||
|
||||
XCTAssert(taskScreen.mainTaskScreen.waitForExistence(timeout: 5))
|
||||
return
|
||||
}
|
||||
|
||||
func testSQTextEntry() throws {
|
||||
let testString = "The wonderful thing about tiggers is tiggers are wonderful things! Their tops are made out of rubber, their bottoms are made out of springs!"
|
||||
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
XCTAssert(helpers.verifyElementByText("Text Question", true))
|
||||
guard let done = commonElements.doneButton else {
|
||||
XCTFail("Unable to locate done button")
|
||||
return
|
||||
}
|
||||
XCTAssertFalse(done.isEnabled)
|
||||
XCTAssert(helpers.verifyElementByText("Text"))
|
||||
XCTAssert(helpers.verifyElementByText("Additional text can go here."))
|
||||
|
||||
let textView = app.textViews.element(boundBy: 0)
|
||||
XCTAssert(textView.waitForExistence(timeout: 5))
|
||||
textView.tap()
|
||||
|
||||
app.typeText(testString)
|
||||
XCTAssert(helpers.verifyElementByText("140/280"))
|
||||
|
||||
let clear = app.buttons["Clear"]
|
||||
XCTAssert(clear.waitForExistence(timeout: 3))
|
||||
clear.tap()
|
||||
|
||||
XCTAssert(helpers.verifyElementByText("0/280"))
|
||||
app.typeText(testString)
|
||||
|
||||
XCTAssert(commonElements.doneButton!.firstMatch.exists)
|
||||
commonElements.doneButton!.firstMatch.tap()
|
||||
|
||||
done.tap()
|
||||
|
||||
XCTAssert(helpers.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (c) 2015, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
struct AllowScreens {
|
||||
let app = XCUIApplication()
|
||||
let commonElements = CommonElements()
|
||||
let taskScreen = TaskScreen()
|
||||
|
||||
var healthAccessScreen: XCUIElement {
|
||||
app.navigationBars.staticTexts["Health Access"]
|
||||
}
|
||||
|
||||
var locationAccessAlert: XCUIElement {
|
||||
app.alerts["Allow “ORKCatalog” to use your location?"]
|
||||
}
|
||||
|
||||
func allowHealthAccess() {
|
||||
if healthAccessScreen.exists {
|
||||
app.tables.staticTexts["Turn All Categories On"].tap()
|
||||
sleep(1)
|
||||
app.navigationBars["Health Access"].buttons["Allow"].tap()
|
||||
}
|
||||
}
|
||||
|
||||
func allowLocationServices() {
|
||||
if locationAccessAlert.exists {
|
||||
locationAccessAlert.scrollViews.otherElements.buttons["Allow While Using App"].tap()
|
||||
}
|
||||
}
|
||||
|
||||
func triggerAllowScreens() -> Bool {
|
||||
let healthTriggers = ["Height Question", "Weight Question"]
|
||||
XCTAssert(commonElements.verifyElement(taskScreen.mainTaskScreen))
|
||||
|
||||
for task in healthTriggers {
|
||||
let healthTask = app.tables.staticTexts[task]
|
||||
healthTask.tap()
|
||||
|
||||
sleep(3)
|
||||
allowHealthAccess()
|
||||
|
||||
sleep(2)
|
||||
guard let cancelButton = commonElements.cancelButton else {
|
||||
XCTFail("Unable to locate Cancel Button")
|
||||
return false
|
||||
}
|
||||
cancelButton.tap()
|
||||
|
||||
sleep(1)
|
||||
guard let exitButton = commonElements.getExitButton() else {
|
||||
XCTFail("Unable to locate End Task or Discard Results button")
|
||||
return false
|
||||
}
|
||||
exitButton.tap()
|
||||
|
||||
XCTAssert(taskScreen.mainTaskScreen.exists)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2015, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
struct CommonElements {
|
||||
let app = XCUIApplication()
|
||||
|
||||
var cancelButton: XCUIElement? {
|
||||
app.navigationBars.buttons["Cancel"]
|
||||
}
|
||||
|
||||
var exitTaskButton: XCUIElement {
|
||||
getExitButton()!
|
||||
}
|
||||
|
||||
var doneButton: XCUIElement? {
|
||||
app.buttons["Done"]
|
||||
}
|
||||
|
||||
var nextButton: XCUIElement? {
|
||||
app.scrollViews.otherElements.staticTexts["Next"]
|
||||
}
|
||||
|
||||
var backButton: XCUIElement? {
|
||||
app.navigationBars.buttons["Back"]
|
||||
}
|
||||
|
||||
var skipButton: XCUIElement? {
|
||||
app.scrollViews.otherElements.staticTexts["Skip"]
|
||||
}
|
||||
|
||||
func getExitButton() -> XCUIElement? {
|
||||
let otherElements = app.sheets.scrollViews.otherElements
|
||||
if otherElements.buttons["Discard Results"].exists {
|
||||
return otherElements.buttons["Discard Results"]
|
||||
}
|
||||
if otherElements.buttons["End Task"].exists {
|
||||
return otherElements.buttons["End Task"]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyElement(_ element: XCUIElement) -> Bool {
|
||||
if element.exists {
|
||||
return true
|
||||
}
|
||||
XCTFail("Unable to confrim \(element) exists")
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright (c) 2015, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission. No license is granted to the trademarks of
|
||||
the copyright holders even if such marks are included in this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
struct TaskScreen {
|
||||
let app = XCUIApplication()
|
||||
|
||||
var surveyTasks = [
|
||||
"Form Survey Example",
|
||||
"Grouped Form Survey Example",
|
||||
"Simple Survey Example"
|
||||
]
|
||||
|
||||
var surveyQuestions = [
|
||||
"Boolean Question",
|
||||
"Custom Boolean Question",
|
||||
"Date Question",
|
||||
"Date and Time Question",
|
||||
"Height Question",
|
||||
"Weight Question",
|
||||
"Image Choice Question",
|
||||
"Location Question",
|
||||
"Numeric Question",
|
||||
"Scale Question",
|
||||
"Text Question",
|
||||
"Text Choice Question",
|
||||
"Time Interval Question",
|
||||
"Value Picker Choice Question",
|
||||
"Validated Text Question",
|
||||
"Image Capture Step",
|
||||
"Video Capture Step",
|
||||
"Front Facing Camera Step",
|
||||
"Wait Step",
|
||||
"PDF Viewer Step",
|
||||
"Request Permissions Step"
|
||||
]
|
||||
|
||||
var activeTasks: [String] {
|
||||
var tasks = [
|
||||
"Audio",
|
||||
"Amsler Grid",
|
||||
"Fitness Check",
|
||||
"Hole Peg Test",
|
||||
"PSAT",
|
||||
"Reaction Time",
|
||||
"Short Walk",
|
||||
"Spatial Span Memory",
|
||||
"Speech Recognition",
|
||||
"Speech in Noise",
|
||||
"Stroop",
|
||||
"Timed Walk with Turn Around",
|
||||
"Tone Audiometry",
|
||||
"dBHL Tone Audiometry",
|
||||
//"Environment SPL Meter",
|
||||
"Tower of Hanoi",
|
||||
"Tremor Test",
|
||||
"Two Finger Tapping Interval",
|
||||
"Walk Back and Forth",
|
||||
"Knee Range of Motion",
|
||||
"Shoulder Range of Motion",
|
||||
"Trail Making Test"
|
||||
]
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
var mainTaskScreen: XCUIElement {
|
||||
app.navigationBars["ORKCatalog"].staticTexts["ORKCatalog"]
|
||||
}
|
||||
|
||||
func getCurrentTask(task: String) -> XCUIElement? {
|
||||
return app.tables.staticTexts[task]
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
// Copyright © 2021 researchkit.org. All rights reserved.
|
||||
//
|
||||
|
||||
ORK_CATALOG_VERSION_NUMBER = 3.1.1
|
||||
ORK_CATALOG_VERSION_NUMBER = 3.1
|
||||
|
||||
ORK_CATALOG_BUILD_NUMBER = $(ORK_CATALOG_BUILD_NUMBER_CI_$(CI)) // ORK_CATALOG_BUILD_NUMBER_CI_TRUE or ORK_CATALOG_BUILD_NUMBER_CI_
|
||||
ORK_CATALOG_BUILD_NUMBER_CI_TRUE = $(CI_BUILD_NUMBER)
|
||||
|
||||
Reference in New Issue
Block a user