From ec9b1c910836907407e000872f15984e4f60a5e8 Mon Sep 17 00:00:00 2001 From: Yuan Zhu Date: Wed, 16 Dec 2015 15:56:28 -0800 Subject: [PATCH 1/3] Change regex api to accept NSRegularExpression. --- ResearchKit/Common/ORKAnswerFormat.h | 6 ++-- ResearchKit/Common/ORKAnswerFormat.m | 33 ++++++------------- ResearchKit/Common/ORKAnswerFormat_Private.h | 2 +- ResearchKit/Common/ORKHelpers.h | 3 ++ ResearchKit/Onboarding/ORKRegistrationStep.h | 4 +-- ResearchKit/Onboarding/ORKRegistrationStep.m | 6 ++-- Testing/ORKTest/ORKTest/MainViewController.m | 3 +- Testing/ORKTest/ORKTest/ORKESerialization.m | 19 ++++++++++- .../ORKTestTests/ORKJSONSerializationTests.m | 4 +++ .../ORKCatalog/Tasks/TaskListRow.swift | 9 ++--- 10 files changed, 51 insertions(+), 38 deletions(-) diff --git a/ResearchKit/Common/ORKAnswerFormat.h b/ResearchKit/Common/ORKAnswerFormat.h index 3d099c74..6405b7f8 100644 --- a/ResearchKit/Common/ORKAnswerFormat.h +++ b/ResearchKit/Common/ORKAnswerFormat.h @@ -247,7 +247,7 @@ ORK_CLASS_AVAILABLE + (ORKTextAnswerFormat *)textAnswerFormatWithMaximumLength:(NSInteger)maximumLength; -+ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegex:(NSString *)validationRegex ++ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegex:(NSRegularExpression *)validationRegex invalidMessage:(NSString *)invalidMessage; + (ORKEmailAnswerFormat *)emailAnswerFormat; @@ -1182,7 +1182,7 @@ ORK_CLASS_AVAILABLE @return An initialized validated text answer format. */ -- (instancetype)initWithValidationRegex:(NSString *)validationRegex +- (instancetype)initWithValidationRegex:(NSRegularExpression *)validationRegex invalidMessage:(NSString *)invalidMessage NS_DESIGNATED_INITIALIZER; /** @@ -1202,7 +1202,7 @@ ORK_CLASS_AVAILABLE The default value is nil. If set to nil, no validation will be performed. */ -@property (nonatomic, copy, nullable) NSString *validationRegex; +@property (nonatomic, copy, nullable) NSRegularExpression *validationRegex; /** The text presented to the user when invalid input is received. diff --git a/ResearchKit/Common/ORKAnswerFormat.m b/ResearchKit/Common/ORKAnswerFormat.m index 47309244..c90275e6 100644 --- a/ResearchKit/Common/ORKAnswerFormat.m +++ b/ResearchKit/Common/ORKAnswerFormat.m @@ -349,7 +349,7 @@ NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattingStyle return [[ORKTextAnswerFormat alloc] initWithMaximumLength:maximumLength]; } -+ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegex:(NSString *)validationRegex invalidMessage:(NSString *)invalidMessage { ++ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegex:(NSRegularExpression *)validationRegex invalidMessage:(NSString *)invalidMessage { return [[ORKTextAnswerFormat alloc] initWithValidationRegex:validationRegex invalidMessage:invalidMessage]; } @@ -1862,9 +1862,7 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { #pragma mark - ORKTextAnswerFormat -@implementation ORKTextAnswerFormat { - NSRegularExpression *_cachedRegEx; -} +@implementation ORKTextAnswerFormat - (Class)questionResultClass { return [ORKTextQuestionResult class]; @@ -1915,16 +1913,6 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { reason:@"Both regex and invalid message properties must be set." userInfo:nil]; } - - NSError *error; - if (self.validationRegex && ![[NSRegularExpression alloc] initWithPattern:self.validationRegex - options:NSRegularExpressionCaseInsensitive - error:&error]) { - @throw [NSException exceptionWithName:NSInvalidArgumentException - reason:@"Validation regex is not valid." - userInfo:error.userInfo]; - } - } - (instancetype)copyWithZone:(NSZone *)zone { @@ -1964,12 +1952,7 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { - (BOOL)isTextRegexValidWithString:(NSString *)text { BOOL isValid = YES; if (self.validationRegex) { - if (!_cachedRegEx) { - NSString *regExPattern = self.validationRegex; - _cachedRegEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil]; - } - - NSUInteger regExMatches = [_cachedRegEx numberOfMatchesInString:text options:0 range:NSMakeRange(0, [text length])]; + NSUInteger regExMatches = [self.validationRegex numberOfMatchesInString:text options:0 range:NSMakeRange(0, [text length])]; isValid = (regExMatches != 0); } return isValid; @@ -1996,7 +1979,7 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { if (self) { _multipleLines = YES; ORK_DECODE_INTEGER(aDecoder, maximumLength); - ORK_DECODE_OBJ_CLASS(aDecoder, validationRegex, NSString); + ORK_DECODE_REGEX(aDecoder, validationRegex); ORK_DECODE_OBJ_CLASS(aDecoder, invalidMessage, NSString); ORK_DECODE_ENUM(aDecoder, autocapitalizationType); ORK_DECODE_ENUM(aDecoder, autocorrectionType); @@ -2011,7 +1994,7 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { - (void)encodeWithCoder:(NSCoder *)aCoder { [super encodeWithCoder:aCoder]; ORK_ENCODE_INTEGER(aCoder, maximumLength); - ORK_ENCODE_OBJ(aCoder, validationRegex); + ORK_ENCODE_REGEX(aCoder, validationRegex); ORK_ENCODE_OBJ(aCoder, invalidMessage); ORK_ENCODE_ENUM(aCoder, autocapitalizationType); ORK_ENCODE_ENUM(aCoder, autocorrectionType); @@ -2056,7 +2039,11 @@ static NSArray *ork_processTextChoices(NSArray *textChoices) { - (ORKAnswerFormat *)impliedAnswerFormat { if (!_impliedAnswerFormat) { - _impliedAnswerFormat = [ORKTextAnswerFormat textAnswerFormatWithValidationRegex:EmailValidationRegex invalidMessage:ORKLocalizedString(@"INVALID_EMAIL_ALERT_MESSAGE", nil)]; + NSRegularExpression * emailRegex = [[NSRegularExpression alloc] initWithPattern:EmailValidationRegex + options:NSRegularExpressionCaseInsensitive + error:nil]; + _impliedAnswerFormat = [ORKTextAnswerFormat textAnswerFormatWithValidationRegex:emailRegex + invalidMessage:ORKLocalizedString(@"INVALID_EMAIL_ALERT_MESSAGE", nil)]; _impliedAnswerFormat.keyboardType = UIKeyboardTypeEmailAddress; _impliedAnswerFormat.multipleLines = NO; _impliedAnswerFormat.spellCheckingType = UITextSpellCheckingTypeNo; diff --git a/ResearchKit/Common/ORKAnswerFormat_Private.h b/ResearchKit/Common/ORKAnswerFormat_Private.h index e68c8ee7..97ea0f83 100644 --- a/ResearchKit/Common/ORKAnswerFormat_Private.h +++ b/ResearchKit/Common/ORKAnswerFormat_Private.h @@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithMaximumLength:(NSInteger)maximumLength NS_UNAVAILABLE; -- (instancetype)initWithValidationRegex:(NSString *)validationRegex +- (instancetype)initWithValidationRegex:(NSRegularExpression *)validationRegex invalidMessage:(NSString *)invalidMessage NS_UNAVAILABLE; /** diff --git a/ResearchKit/Common/ORKHelpers.h b/ResearchKit/Common/ORKHelpers.h index 1d1776b2..75ecc0bc 100644 --- a/ResearchKit/Common/ORKHelpers.h +++ b/ResearchKit/Common/ORKHelpers.h @@ -134,6 +134,9 @@ #define ORK_DECODE_COORDINATE(d,x) _ ## x = CLLocationCoordinate2DMake([d decodeDoubleForKey:@STRINGIFY(x.latitude)],[d decodeDoubleForKey:@STRINGIFY(x.longitude)]) #define ORK_ENCODE_COORDINATE(c,x) [c encodeDouble:_ ## x.latitude forKey:@STRINGIFY(x.latitude)];[c encodeDouble:_ ## x.longitude forKey:@STRINGIFY(x.longitude)]; +#define ORK_DECODE_REGEX(d,x) { if ([d decodeObjectForKey:@STRINGIFY(x.pattern)]) { _ ## x = [[NSRegularExpression alloc] initWithPattern:[d decodeObjectForKey:@STRINGIFY(x.pattern)] options:[d decodeIntegerForKey:@STRINGIFY(x.options)] error:nil]; } } +#define ORK_ENCODE_REGEX(c,x) [c encodeObject:_ ## x.pattern forKey:@STRINGIFY(x.pattern)];[c encodeInteger:_ ## x.options forKey:@STRINGIFY(x.options)]; + /* * Helpers for completions which call the block only if non-nil * diff --git a/ResearchKit/Onboarding/ORKRegistrationStep.h b/ResearchKit/Onboarding/ORKRegistrationStep.h index f4ecd4f1..3c2aedf5 100644 --- a/ResearchKit/Onboarding/ORKRegistrationStep.h +++ b/ResearchKit/Onboarding/ORKRegistrationStep.h @@ -94,7 +94,7 @@ ORK_CLASS_AVAILABLE - (instancetype)initWithIdentifier:(NSString *)identifier title:(nullable NSString *)title text:(nullable NSString *)text - passcodeValidationRegex:(nullable NSString *)passcodeValidationRegex + passcodeValidationRegex:(nullable NSRegularExpression *)passcodeValidationRegex passcodeInvalidMessage:(nullable NSString *)passcodeInvalidMessage options:(ORKRegistrationStepOption)options; @@ -128,7 +128,7 @@ ORK_CLASS_AVAILABLE The passcode invalid message property must also be set along with this property. By default, there is no validation on the passcode. */ -@property (nonatomic, copy, nullable) NSString *passcodeValidationRegex; +@property (nonatomic, copy, nullable) NSRegularExpression *passcodeValidationRegex; /** The invalid message displayed if the passcode does not match the validation regex. diff --git a/ResearchKit/Onboarding/ORKRegistrationStep.m b/ResearchKit/Onboarding/ORKRegistrationStep.m index 3328da74..a5de3650 100644 --- a/ResearchKit/Onboarding/ORKRegistrationStep.m +++ b/ResearchKit/Onboarding/ORKRegistrationStep.m @@ -184,7 +184,7 @@ static NSArray *ORKRegistrationFormItems(ORKRegistrationStepOptio - (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title text:(NSString *)text - passcodeValidationRegex:(NSString *)passcodeValidationRegex + passcodeValidationRegex:(NSRegularExpression *)passcodeValidationRegex passcodeInvalidMessage:(NSString *)passcodeInvalidMessage options:(ORKRegistrationStepOption)options { self = [super initWithIdentifier:identifier title:title text:text]; @@ -251,7 +251,7 @@ static NSArray *ORKRegistrationFormItems(ORKRegistrationStepOptio return [super formItems]; } -- (NSString *)passcodeValidationRegex { +- (NSRegularExpression *)passcodeValidationRegex { return [self passwordAnswerFormat].validationRegex; } @@ -259,7 +259,7 @@ static NSArray *ORKRegistrationFormItems(ORKRegistrationStepOptio return [self passwordAnswerFormat].invalidMessage; } -- (void)setPasscodeValidationRegex:(NSString *)passcodeValidationRegex { +- (void)setPasscodeValidationRegex:(NSRegularExpression *)passcodeValidationRegex { [self passwordAnswerFormat].validationRegex = passcodeValidationRegex; } diff --git a/Testing/ORKTest/ORKTest/MainViewController.m b/Testing/ORKTest/ORKTest/MainViewController.m index 9ad2c0d5..96e912f5 100644 --- a/Testing/ORKTest/ORKTest/MainViewController.m +++ b/Testing/ORKTest/ORKTest/MainViewController.m @@ -1643,7 +1643,8 @@ static const CGFloat HeaderSideLayoutMargin = 16.0; } { - ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithValidationRegex:@"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" invalidMessage:@"Invalid URL: %@"]; + NSRegularExpression *urlRegex = [NSRegularExpression regularExpressionWithPattern:@"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" options:NSRegularExpressionCaseInsensitive error:nil]; + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithValidationRegex:urlRegex invalidMessage:@"Invalid URL: %@"]; format.multipleLines = NO; format.keyboardType = UIKeyboardTypeURL; format.autocapitalizationType = UITextAutocapitalizationTypeNone; diff --git a/Testing/ORKTest/ORKTest/ORKESerialization.m b/Testing/ORKTest/ORKTest/ORKESerialization.m index fa8aa4a6..b6f07922 100644 --- a/Testing/ORKTest/ORKTest/ORKESerialization.m +++ b/Testing/ORKTest/ORKTest/ORKESerialization.m @@ -118,6 +118,21 @@ static CLLocationCoordinate2D coordinateFromDictionary(NSDictionary *dict) { return (CLLocationCoordinate2D){.latitude = ((NSNumber *)dict[@"latitude"]).doubleValue, .longitude = ((NSNumber *)dict[@"longitude"]).doubleValue }; } +static NSDictionary *dictionaryFromRegularExpression (NSRegularExpression *regex) { + if (regex.pattern) { + return @{ @"pattern" : regex.pattern, @"options" : @(regex.options) }; + } + return @{}; +} + +static NSRegularExpression *regularExpressionFromDictionary(NSDictionary *dict) { + NSRegularExpression *regex; + if (dict[@"pattern"]) { + regex = [[NSRegularExpression alloc] initWithPattern:dict[@"pattern"] options: ((NSNumber *)dict[@"options"]).unsignedIntegerValue error:nil]; + } + return regex; +} + static ORKNumericAnswerStyle ORKNumericAnswerStyleFromString(NSString *s) { return tableMapReverse(s, ORKNumericAnswerStyleTable()); } @@ -863,7 +878,9 @@ ret = }, (@{ PROPERTY(maximumLength, NSNumber, NSObject, NO, nil, nil), - PROPERTY(validationRegex, NSString, NSObject, YES, nil, nil), + PROPERTY(validationRegex, NSRegularExpression, NSObject, YES, + ^id(id regex) { return dictionaryFromRegularExpression(regex); }, + ^id(id dict) { return regularExpressionFromDictionary(dict); }), PROPERTY(invalidMessage, NSString, NSObject, YES, nil, nil), PROPERTY(autocapitalizationType, NSNumber, NSObject, YES, nil, nil), PROPERTY(autocorrectionType, NSNumber, NSObject, YES, nil, nil), diff --git a/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m b/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m index 9b504cf1..922f0975 100644 --- a/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m +++ b/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m @@ -423,6 +423,8 @@ ORK_MAKE_TEST_INIT(ORKLocation, (^{ [instance setValue:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] forKey:p.propertyName]; } else if (p.propertyClass == [ORKLocation class]) { [instance setValue:[[ORKLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(2.0, 3.0) region:[[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(2.0, 3.0) radius:100.0 identifier:@"identifier"] userInput:@"addressString" addressDictionary:@{@"city":@"city", @"street":@"street"}] forKey:p.propertyName]; + }else if (p.propertyClass == [NSRegularExpression class]) { + [instance setValue:[[NSRegularExpression alloc] initWithPattern:@"abc" options:NSRegularExpressionCaseInsensitive error:nil] forKey:p.propertyName]; } else { id itemInstance = [self instanceForClass:p.propertyClass]; [instance setValue:itemInstance forKey:p.propertyName]; @@ -534,6 +536,8 @@ ORK_MAKE_TEST_INIT(ORKLocation, (^{ } else if (equality && (p.propertyClass == [UIImage class])) { // do nothing - meaningless for the equality check return NO; + } else if (p.propertyClass == [NSRegularExpression class]) { + [instance setValue:[[NSRegularExpression alloc] initWithPattern:index? @"abc" : @"cde" options:NSRegularExpressionCaseInsensitive error:nil] forKey:p.propertyName]; } else { id instanceForChild = [self instanceForClass:p.propertyClass]; [instance setValue:instanceForChild forKey:p.propertyName]; diff --git a/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift b/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift index 4ca58b49..95f72d31 100644 --- a/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift +++ b/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift @@ -851,9 +851,9 @@ enum TaskListRow: Int, CustomStringConvertible { let stepEmail = ORKQuestionStep(identifier: String(Identifier.ValidatedTextQuestionStepEmail), title: NSLocalizedString("Email", comment: ""), answer: answerFormatEmail) stepEmail.text = exampleDetailText - let domainRegex = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" - - let answerFormatDomain = ORKAnswerFormat.textAnswerFormatWithValidationRegex(domainRegex, invalidMessage:"Invalid URL: %@") + let domainRegexPattern = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" + let domainRegularExpression = try? NSRegularExpression(pattern: domainRegexPattern, options: .CaseInsensitive) + let answerFormatDomain = ORKAnswerFormat.textAnswerFormatWithValidationRegex(domainRegularExpression!, invalidMessage:"Invalid URL: %@") answerFormatDomain.multipleLines = false answerFormatDomain.keyboardType = UIKeyboardType.URL answerFormatDomain.autocapitalizationType = UITextAutocapitalizationType.None @@ -1027,7 +1027,8 @@ enum TaskListRow: Int, CustomStringConvertible { If you wish to include any of the additional fields, then you can specify it through the `options` parameter. */ let registrationTitle = NSLocalizedString("Registration", comment: "") - let passcodeValidationRegex = "^(?=.*\\d).{4,8}$" + let passcodeValidationPattern = "^(?=.*\\d).{4,8}$" + let passcodeValidationRegex = try? NSRegularExpression(pattern: passcodeValidationPattern, options: .CaseInsensitive); let passcodeInvalidMessage = NSLocalizedString("A valid password must be 4 and 8 digits long and include at least one numeric character.", comment: "") let registrationOptions: ORKRegistrationStepOption = [.IncludeGivenName, .IncludeFamilyName, .IncludeGender, .IncludeDOB] let registrationStep = ORKRegistrationStep(identifier: String(Identifier.RegistrationStep), title: registrationTitle, text: exampleDetailText, passcodeValidationRegex: passcodeValidationRegex, passcodeInvalidMessage: passcodeInvalidMessage, options: registrationOptions) From 6e075cbfe31c40e58f8fbfcf828ef0ee70983b2c Mon Sep 17 00:00:00 2001 From: Jared Crawford Date: Thu, 11 Feb 2016 18:07:08 -0800 Subject: [PATCH 2/3] Add a result predicate for determining if the user selected accept or decline in a consent signature step, allowing for custom navigation rules, such as skipping to the end of a survey if the user does not consent. --- ResearchKit/Common/ORKResultPredicate.h | 13 ++++++++ ResearchKit/Common/ORKResultPredicate.m | 6 ++++ ResearchKitTests/ORKTaskTests.m | 44 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/ResearchKit/Common/ORKResultPredicate.h b/ResearchKit/Common/ORKResultPredicate.h index dbc43a5b..e9384141 100644 --- a/ResearchKit/Common/ORKResultPredicate.h +++ b/ResearchKit/Common/ORKResultPredicate.h @@ -514,6 +514,19 @@ within the specified `NSTimeInterval` values. minimumExpectedAnswerDate:(nullable NSDate *)minimumExpectedAnswerDate maximumExpectedAnswerDate:(nullable NSDate *)maximumExpectedAnswerDate; +/** + Returns a predicate matching a result of type `ORKConsentSignatureResult` whose consented value matched the + specified boolean value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param didConsent Whether the user consented to the + + @return A result predicate. + */ ++ (NSPredicate *)predicateForConsentWithResultSelector:(ORKResultSelector *)resultSelector + didConsent:(BOOL)didConsent; + @end NS_ASSUME_NONNULL_END diff --git a/ResearchKit/Common/ORKResultPredicate.m b/ResearchKit/Common/ORKResultPredicate.m index 2a6ce15a..b1c643c9 100644 --- a/ResearchKit/Common/ORKResultPredicate.m +++ b/ResearchKit/Common/ORKResultPredicate.m @@ -432,4 +432,10 @@ NSString *const ORKResultPredicateTaskIdentifierVariableName = @"ORK_TASK_IDENTI subPredicateFormatArgumentArray:subPredicateFormatArgumentArray]; } ++ (NSPredicate *)predicateForConsentWithResultSelector:(ORKResultSelector *)resultSelector didConsent:(BOOL)didConsent { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"consented == %@" ] + subPredicateFormatArgumentArray:@[ @(didConsent) ]]; +} + @end diff --git a/ResearchKitTests/ORKTaskTests.m b/ResearchKitTests/ORKTaskTests.m index c76c8c8b..19d5dc41 100644 --- a/ResearchKitTests/ORKTaskTests.m +++ b/ResearchKitTests/ORKTaskTests.m @@ -518,6 +518,9 @@ BOOL (^testStepBeforeStep)(ORKNavigableOrderedTask *, ORKTaskResult *, ORKStep * XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); } +ORKDefineStringKey(SignConsentStepIdentifier); +ORKDefineStringKey(SignatureIdentifier); + ORKDefineStringKey(ScaleStepIdentifier); ORKDefineStringKey(ContinuousScaleStepIdentifier); static const NSInteger IntegerValue = 6; @@ -587,6 +590,12 @@ static ORKStepResult *(^getStepResult)(NSString *, Class, ORKQuestionType, id) = return stepResult; }; +static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^ORKStepResult *(NSString *stepIdentifier, NSString *signatureIdentifier, BOOL consented) { + ORKConsentSignatureResult *consentSignatureResult = [[ORKConsentSignatureResult alloc] initWithIdentifier:signatureIdentifier]; + consentSignatureResult.consented = consented; + return [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[consentSignatureResult]]; +}; + - (ORKTaskResult *)getGeneralTaskResultTree { NSMutableArray *stepResults = [NSMutableArray new]; @@ -621,6 +630,19 @@ static ORKStepResult *(^getStepResult)(NSString *, Class, ORKQuestionType, id) = return taskResult; } +- (ORKTaskResult *)getTaskResultTreeWithConsent:(BOOL)consented { + NSMutableArray *stepResults = [NSMutableArray new]; + + [stepResults addObject:getConsentStepResult(SignConsentStepIdentifier, SignatureIdentifier, consented)]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + - (ORKTaskResult *)getSmallTaskResultTreeWithIsAdditionalTask:(BOOL)isAdditionalTask { NSMutableArray *stepResults = [NSMutableArray new]; @@ -1111,6 +1133,28 @@ static ORKStepResult *(^getStepResult)(NSString *, Class, ORKQuestionType, id) = XCTAssertFalse([[ORKResultPredicate predicateForNilQuestionResultWithResultSelector:resultSelector] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); } +- (void)testConsentPredicate { + ORKResultSelector *resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:OrderedTaskIdentifier + stepIdentifier:SignConsentStepIdentifier + resultIdentifier:SignatureIdentifier]; + { + ORKTaskResult *consentedTaskResult = [self getTaskResultTreeWithConsent:YES]; + XCTAssertTrue([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:YES] evaluateWithObject:@[consentedTaskResult] substitutionVariables:nil]); + XCTAssertFalse([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:NO] evaluateWithObject:@[consentedTaskResult] substitutionVariables:nil]); + } + + { + ORKTaskResult *didNotConsentTaskResult = [self getTaskResultTreeWithConsent:NO]; + + XCTAssertTrue([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:NO] evaluateWithObject:@[didNotConsentTaskResult] substitutionVariables:nil]); + XCTAssertFalse([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:YES] evaluateWithObject:@[didNotConsentTaskResult] substitutionVariables:nil]); + } +} + - (void)testResultPredicates { ORKTaskResult *taskResult = [self getGeneralTaskResultTree]; NSArray *taskResults = @[ taskResult ]; From b85182b372437a6ac26941f0f78e290daa52378e Mon Sep 17 00:00:00 2001 From: Jared Crawford Date: Fri, 12 Feb 2016 12:27:58 -0800 Subject: [PATCH 3/3] Fix typos --- ResearchKit/Common/ORKResultPredicate.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ResearchKit/Common/ORKResultPredicate.h b/ResearchKit/Common/ORKResultPredicate.h index e9384141..b4c7b325 100644 --- a/ResearchKit/Common/ORKResultPredicate.h +++ b/ResearchKit/Common/ORKResultPredicate.h @@ -515,12 +515,12 @@ within the specified `NSTimeInterval` values. maximumExpectedAnswerDate:(nullable NSDate *)maximumExpectedAnswerDate; /** - Returns a predicate matching a result of type `ORKConsentSignatureResult` whose consented value matched the - specified boolean value. + Returns a predicate matching a result of type `ORKConsentSignatureResult` whose `consented` value + matches the specified boolean value. @param resultSelector The result selector object which specifies the question result you are interested in. - @param didConsent Whether the user consented to the + @param didConsent Whether the user consented to the `ORKConsentReviewStep` @return A result predicate. */