867 lines
52 KiB
Objective-C
867 lines
52 KiB
Objective-C
/*
|
|
Copyright (c) 2015, Ricardo Sánchez-Sáez.
|
|
|
|
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/XCTest.h>
|
|
#import <ResearchKit/ResearchKit.h>
|
|
#import "ORKHelpers.h"
|
|
#import "ORKResult_Private.h"
|
|
#import "ORKStepNavigationRule_Private.h"
|
|
#import "ORKStepNavigationRule_Internal.h"
|
|
|
|
|
|
@interface ORKTaskTests : XCTestCase
|
|
|
|
@end
|
|
|
|
|
|
@implementation ORKTaskTests {
|
|
NSArray *_orderedTaskStepIdentifiers;
|
|
NSArray *_orderedTaskSteps;
|
|
ORKOrderedTask *_orderedTask;
|
|
|
|
NSArray *_navigableOrderedTaskStepIdentifiers;
|
|
NSArray *_navigableOrderedTaskSteps;
|
|
NSMutableDictionary *_stepNavigationRules;
|
|
ORKNavigableOrderedTask *_navigableOrderedTask;
|
|
}
|
|
|
|
ORKDefineStringKey(HeadacheChoiceValue);
|
|
ORKDefineStringKey(DizinessChoiceValue);
|
|
ORKDefineStringKey(NauseaChoiceValue);
|
|
|
|
ORKDefineStringKey(SymptomStepIdentifier);
|
|
ORKDefineStringKey(SeverityStepIdentifier);
|
|
ORKDefineStringKey(BlankStepIdentifier);
|
|
ORKDefineStringKey(SevereHeadacheStepIdentifier);
|
|
ORKDefineStringKey(LightHeadacheStepIdentifier);
|
|
ORKDefineStringKey(OtherSymptomStepIdentifier);
|
|
ORKDefineStringKey(EndStepIdentifier);
|
|
|
|
ORKDefineStringKey(OrderedTaskIdentifier);
|
|
ORKDefineStringKey(NavigableOrderedTaskIdentifier);
|
|
|
|
- (void)generateTaskSteps:(out NSArray **)outSteps stepIdentifiers:(out NSArray **)outStepIdentifiers {
|
|
if (outSteps == NULL || outStepIdentifiers == NULL) {
|
|
return;
|
|
}
|
|
|
|
NSMutableArray *stepIdentifiers = [NSMutableArray new];
|
|
NSMutableArray *steps = [NSMutableArray new];
|
|
|
|
ORKAnswerFormat *answerFormat = nil;
|
|
NSString *stepIdentifier = nil;
|
|
ORKStep *step = nil;
|
|
|
|
NSArray *textChoices =
|
|
@[
|
|
[ORKTextChoice choiceWithText:@"Headache" value:HeadacheChoiceValue],
|
|
[ORKTextChoice choiceWithText:@"Dizziness" value:DizinessChoiceValue],
|
|
[ORKTextChoice choiceWithText:@"Nausea" value:NauseaChoiceValue]
|
|
];
|
|
|
|
answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice
|
|
textChoices:textChoices];
|
|
stepIdentifier = SymptomStepIdentifier;
|
|
step = [ORKQuestionStep questionStepWithIdentifier:stepIdentifier title:@"What is your symptom?" answer:answerFormat];
|
|
step.optional = NO;
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
answerFormat = [ORKAnswerFormat booleanAnswerFormat];
|
|
stepIdentifier = SeverityStepIdentifier;
|
|
step = [ORKQuestionStep questionStepWithIdentifier:stepIdentifier title:@"Does your symptom interferes with your daily life?" answer:answerFormat];
|
|
step.optional = NO;
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
stepIdentifier = BlankStepIdentifier;
|
|
step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier];
|
|
step.title = @"This step is intentionally left blank (you should not see it)";
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
stepIdentifier = SevereHeadacheStepIdentifier;
|
|
step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier];
|
|
step.title = @"You have a severe headache";
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
stepIdentifier = LightHeadacheStepIdentifier;
|
|
step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier];
|
|
step.title = @"You have a light headache";
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
stepIdentifier = OtherSymptomStepIdentifier;
|
|
step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier];
|
|
step.title = @"You have other symptom";
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
stepIdentifier = EndStepIdentifier;
|
|
step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier];
|
|
step.title = @"You have finished the task";
|
|
[stepIdentifiers addObject:stepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
*outSteps = steps;
|
|
*outStepIdentifiers = stepIdentifiers;
|
|
}
|
|
|
|
- (void)setUpOrderedTask {
|
|
NSArray *orderedTaskSteps = nil;
|
|
NSArray *orderedTaskStepIdentifiers = nil;
|
|
[self generateTaskSteps:&orderedTaskSteps stepIdentifiers:&orderedTaskStepIdentifiers];
|
|
_orderedTaskSteps = orderedTaskSteps;
|
|
_orderedTaskStepIdentifiers = orderedTaskStepIdentifiers;
|
|
|
|
_orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:OrderedTaskIdentifier
|
|
steps:ORKArrayCopyObjects(_orderedTaskSteps)]; // deep copy to test step copying and equality
|
|
}
|
|
|
|
- (void)setUpNavigableOrderedTask {
|
|
NSArray *navigableOrderedTaskSteps = nil;
|
|
NSArray *navigableOrderedTaskStepIdentifiers = nil;
|
|
[self generateTaskSteps:&navigableOrderedTaskSteps stepIdentifiers:&navigableOrderedTaskStepIdentifiers];
|
|
_navigableOrderedTaskSteps = navigableOrderedTaskSteps;
|
|
_navigableOrderedTaskStepIdentifiers = navigableOrderedTaskStepIdentifiers;
|
|
|
|
_navigableOrderedTask = [[ORKNavigableOrderedTask alloc] initWithIdentifier:NavigableOrderedTaskIdentifier
|
|
steps:ORKArrayCopyObjects(_navigableOrderedTaskSteps)]; // deep copy to test step copying and equality
|
|
|
|
// Build navigation rules
|
|
_stepNavigationRules = [NSMutableDictionary new];
|
|
// Individual predicates
|
|
|
|
// User chose headache at the symptom step
|
|
NSPredicate *predicateHeadache = [ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:SymptomStepIdentifier expectedString:HeadacheChoiceValue];
|
|
// Equivalent to:
|
|
// [NSPredicate predicateWithFormat:
|
|
// @"SUBQUERY(SELF, $x, $x.identifier like 'symptom' \
|
|
// AND SUBQUERY($x.answer, $y, $y like 'headache').@count > 0).@count > 0"];
|
|
|
|
// User didn't chose headache at the symptom step
|
|
NSPredicate *predicateNotHeadache = [NSCompoundPredicate notPredicateWithSubpredicate:predicateHeadache];
|
|
|
|
// User chose YES at the severity step
|
|
NSPredicate *predicateSevereYes = [ORKResultPredicate predicateForBooleanQuestionResultWithIdentifier:SeverityStepIdentifier expectedAnswer:YES];
|
|
// Equivalent to:
|
|
// [NSPredicate predicateWithFormat:
|
|
// @"SUBQUERY(SELF, $x, $x.identifier like 'severity' AND $x.answer == YES).@count > 0"];
|
|
|
|
// User chose NO at the severity step
|
|
NSPredicate *predicateSevereNo = [ORKResultPredicate predicateForBooleanQuestionResultWithIdentifier:SeverityStepIdentifier expectedAnswer:NO];
|
|
|
|
|
|
// From the "symptom" step, go to "other_symptom" is user didn't chose headache.
|
|
// Otherwise, default to going to next step (when the defaultStepIdentifier argument is omitted,
|
|
// the regular ORKOrderedTask order applies).
|
|
NSMutableArray *resultPredicates = [NSMutableArray new];
|
|
NSMutableArray *matchingStepIdentifiers = [NSMutableArray new];
|
|
|
|
[resultPredicates addObject:predicateNotHeadache];
|
|
[matchingStepIdentifiers addObject:OtherSymptomStepIdentifier];
|
|
|
|
ORKPredicateStepNavigationRule *predicateRule =
|
|
[[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates
|
|
matchingStepIdentifiers:matchingStepIdentifiers];
|
|
|
|
[_navigableOrderedTask setNavigationRule:predicateRule forTriggerStepIdentifier:SymptomStepIdentifier];
|
|
_stepNavigationRules[SymptomStepIdentifier] = [predicateRule copy];
|
|
|
|
// From the "severity" step, go to "severe_headache" or "light_headache" depending on the user answer
|
|
resultPredicates = [NSMutableArray new];
|
|
matchingStepIdentifiers = [NSMutableArray new];
|
|
|
|
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateHeadache, predicateSevereYes]];
|
|
[resultPredicates addObject:predicate];
|
|
[matchingStepIdentifiers addObject:SevereHeadacheStepIdentifier];
|
|
|
|
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateHeadache, predicateSevereNo]];
|
|
[resultPredicates addObject:predicate];
|
|
[matchingStepIdentifiers addObject:LightHeadacheStepIdentifier];
|
|
|
|
predicateRule =
|
|
[[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates
|
|
matchingStepIdentifiers:matchingStepIdentifiers
|
|
defaultStepIdentifier:OtherSymptomStepIdentifier];
|
|
|
|
[_navigableOrderedTask setNavigationRule:predicateRule forTriggerStepIdentifier:SeverityStepIdentifier];
|
|
_stepNavigationRules[SeverityStepIdentifier] = [predicateRule copy];
|
|
|
|
|
|
// Add end direct rules to skip unneeded steps
|
|
ORKDirectStepNavigationRule *directRule =
|
|
[[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:EndStepIdentifier];
|
|
|
|
[_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:SevereHeadacheStepIdentifier];
|
|
[_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:LightHeadacheStepIdentifier];
|
|
[_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:OtherSymptomStepIdentifier];
|
|
|
|
_stepNavigationRules[SevereHeadacheStepIdentifier] = [directRule copy];
|
|
_stepNavigationRules[LightHeadacheStepIdentifier] = [directRule copy];
|
|
_stepNavigationRules[OtherSymptomStepIdentifier] = [directRule copy];
|
|
}
|
|
|
|
typedef NS_OPTIONS(NSUInteger, TestsTaskResultOptions) {
|
|
TestsTaskResultOptionSymptomHeadache = 1 << 0,
|
|
TestsTaskResultOptionSymptomDiziness = 2 << 0,
|
|
TestsTaskResultOptionSymptomNausea = 3 << 0,
|
|
|
|
TestsTaskResultOptionSeverityYes = 1 << 2,
|
|
TestsTaskResultOptionSeverityNo = 2 << 2
|
|
};
|
|
|
|
- (ORKTaskResult *)getResultTreeWithTaskIdentifier:(NSString *)taskIdentifier resultOptions:(TestsTaskResultOptions)resultOptions {
|
|
NSMutableArray *stepResults = [NSMutableArray new];
|
|
|
|
ORKQuestionResult *questionResult = nil;
|
|
ORKStepResult *stepResult = nil;
|
|
NSString *stepIdentifier = nil;
|
|
|
|
if (resultOptions & (TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSymptomDiziness | TestsTaskResultOptionSymptomNausea)) {
|
|
stepIdentifier = SymptomStepIdentifier;
|
|
questionResult = [[ORKChoiceQuestionResult alloc] init];
|
|
questionResult.identifier = stepIdentifier;
|
|
if (resultOptions & TestsTaskResultOptionSymptomHeadache) {
|
|
questionResult.answer = @[HeadacheChoiceValue];
|
|
} else if (resultOptions & TestsTaskResultOptionSymptomDiziness) {
|
|
questionResult.answer = @[DizinessChoiceValue];
|
|
} else if (resultOptions & TestsTaskResultOptionSymptomNausea) {
|
|
questionResult.answer = @[NauseaChoiceValue];
|
|
}
|
|
questionResult.questionType = ORKQuestionTypeSingleChoice;
|
|
|
|
stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]];
|
|
[stepResults addObject:stepResult];
|
|
}
|
|
|
|
if (resultOptions & (TestsTaskResultOptionSeverityYes | TestsTaskResultOptionSeverityNo)) {
|
|
stepIdentifier = SeverityStepIdentifier;
|
|
questionResult = [[ORKBooleanQuestionResult alloc] init];
|
|
questionResult.identifier = stepIdentifier;
|
|
if (resultOptions & TestsTaskResultOptionSeverityYes) {
|
|
questionResult.answer = @(YES);
|
|
} else if (resultOptions & TestsTaskResultOptionSeverityNo) {
|
|
questionResult.answer = @(NO);
|
|
}
|
|
questionResult.questionType = ORKQuestionTypeSingleChoice;
|
|
|
|
stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]];
|
|
[stepResults addObject:stepResult];
|
|
}
|
|
|
|
ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:taskIdentifier
|
|
taskRunUUID:[NSUUID UUID]
|
|
outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]];
|
|
taskResult.results = stepResults;
|
|
|
|
return taskResult;
|
|
}
|
|
|
|
- (void)setUp {
|
|
[super setUp];
|
|
[self setUpOrderedTask];
|
|
[self setUpNavigableOrderedTask];
|
|
}
|
|
|
|
- (void)testOrderedTask {
|
|
ORKTaskResult *mockTaskResult = [[ORKTaskResult alloc] init];
|
|
|
|
XCTAssertEqualObjects(_orderedTask.identifier, OrderedTaskIdentifier);
|
|
XCTAssertEqualObjects(_orderedTask.steps, _orderedTaskSteps);
|
|
|
|
NSUInteger expectedTotalProgress = [_orderedTaskSteps count];
|
|
|
|
for (NSUInteger stepIndex = 0; stepIndex < [_orderedTaskStepIdentifiers count]; stepIndex++) {
|
|
ORKStep *currentStep = _orderedTaskSteps[stepIndex];
|
|
XCTAssertEqualObjects(currentStep, [_orderedTask stepWithIdentifier:_orderedTaskStepIdentifiers[stepIndex]]);
|
|
|
|
const NSUInteger expectedCurrentProgress = stepIndex;
|
|
ORKTaskProgress currentProgress = [_orderedTask progressOfCurrentStep:currentStep withResult:mockTaskResult];
|
|
XCTAssertTrue(currentProgress.total == expectedTotalProgress && currentProgress.current == expectedCurrentProgress);
|
|
|
|
NSString *expectedPreviousStep = (stepIndex != 0) ? _orderedTaskSteps[stepIndex - 1] : nil;
|
|
NSString *expectedNextStep = (stepIndex < [_orderedTaskStepIdentifiers count] - 1) ? _orderedTaskSteps[stepIndex + 1] : nil;
|
|
XCTAssertEqualObjects(expectedPreviousStep, [_orderedTask stepBeforeStep:currentStep withResult:mockTaskResult]);
|
|
XCTAssertEqualObjects(expectedNextStep, [_orderedTask stepAfterStep:currentStep withResult:mockTaskResult]);
|
|
}
|
|
|
|
// Test duplicate step identifier validation
|
|
XCTAssertNoThrow([_orderedTask validateParameters]);
|
|
|
|
NSMutableArray *steps = [[NSMutableArray alloc] initWithArray:ORKArrayCopyObjects(_orderedTaskSteps)];
|
|
ORKStep *step = [[ORKInstructionStep alloc] initWithIdentifier:BlankStepIdentifier];
|
|
[steps addObject:step];
|
|
|
|
ORKOrderedTask *orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:OrderedTaskIdentifier
|
|
steps:steps];
|
|
XCTAssertThrows([orderedTask validateParameters]);
|
|
}
|
|
|
|
- (void)testFormStep {
|
|
// Test duplicate form step identifier validation
|
|
ORKFormStep *formStep = [[ORKFormStep alloc] initWithIdentifier:@"form" title:@"Form" text:@"Form test"];
|
|
NSMutableArray *items = [NSMutableArray new];
|
|
|
|
ORKFormItem *item = nil;
|
|
item = [[ORKFormItem alloc] initWithIdentifier:@"formItem1"
|
|
text:@"formItem1"
|
|
answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]];
|
|
[items addObject:item];
|
|
|
|
item = [[ORKFormItem alloc] initWithIdentifier:@"formItem2"
|
|
text:@"formItem2"
|
|
answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]];
|
|
[items addObject:item];
|
|
|
|
[formStep setFormItems:items];
|
|
XCTAssertNoThrow([formStep validateParameters]);
|
|
|
|
item = [[ORKFormItem alloc] initWithIdentifier:@"formItem2"
|
|
text:@"formItem2"
|
|
answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]];
|
|
[items addObject:item];
|
|
|
|
[formStep setFormItems:items];
|
|
XCTAssertThrows([formStep validateParameters]);
|
|
}
|
|
|
|
#define getIndividualNavigableOrderedTaskSteps() \
|
|
__unused ORKStep *symptomStep = _navigableOrderedTaskSteps[0];\
|
|
__unused ORKStep *severityStep = _navigableOrderedTaskSteps[1];\
|
|
__unused ORKStep *blankStep = _navigableOrderedTaskSteps[2];\
|
|
__unused ORKStep *severeHeadacheStep = _navigableOrderedTaskSteps[3];\
|
|
__unused ORKStep *lightHeadacheStep = _navigableOrderedTaskSteps[4];\
|
|
__unused ORKStep *otherSymptomStep = _navigableOrderedTaskSteps[5];\
|
|
__unused ORKStep *endStep = _navigableOrderedTaskSteps[6];
|
|
|
|
BOOL (^testStepAfterStep)(ORKNavigableOrderedTask *, ORKTaskResult *, ORKStep *, ORKStep *) = ^BOOL(ORKNavigableOrderedTask *task, ORKTaskResult *taskResult, ORKStep *fromStep, ORKStep *expectedStep) {
|
|
ORKStep *testedStep = [task stepAfterStep:fromStep withResult:taskResult];
|
|
return (testedStep == nil && expectedStep == nil) || [testedStep isEqual:expectedStep];
|
|
};
|
|
|
|
BOOL (^testStepBeforeStep)(ORKNavigableOrderedTask *, ORKTaskResult *, ORKStep *, ORKStep *) = ^BOOL(ORKNavigableOrderedTask *task, ORKTaskResult *taskResult, ORKStep *fromStep, ORKStep *expectedStep) {
|
|
ORKStep *testedStep = [task stepBeforeStep:fromStep withResult:taskResult];
|
|
return (testedStep == nil && expectedStep == nil) || [testedStep isEqual:expectedStep];
|
|
};
|
|
|
|
- (void)testNavigableOrderedTask {
|
|
XCTAssertEqualObjects(_navigableOrderedTask.identifier, NavigableOrderedTaskIdentifier);
|
|
XCTAssertEqualObjects(_navigableOrderedTask.steps, _navigableOrderedTaskSteps);
|
|
XCTAssertEqualObjects(_navigableOrderedTask.stepNavigationRules, _stepNavigationRules);
|
|
|
|
for (NSString *triggerStepIdentifier in [_stepNavigationRules allKeys]) {
|
|
XCTAssertEqualObjects(_stepNavigationRules[triggerStepIdentifier], [_navigableOrderedTask navigationRuleForTriggerStepIdentifier:triggerStepIdentifier]);
|
|
}
|
|
|
|
ORKDefineStringKey(MockTriggerStepIdentifier);
|
|
ORKDefineStringKey(MockDestinationStepIdentifier);
|
|
|
|
// Test adding and removing a step navigation rule
|
|
XCTAssertNil([_navigableOrderedTask navigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier]);
|
|
|
|
ORKDirectStepNavigationRule *mockNavigationRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:MockDestinationStepIdentifier];
|
|
[_navigableOrderedTask setNavigationRule:mockNavigationRule forTriggerStepIdentifier:MockTriggerStepIdentifier];
|
|
|
|
XCTAssertEqualObjects([_navigableOrderedTask navigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier], [mockNavigationRule copy]);
|
|
|
|
[_navigableOrderedTask removeNavigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier];
|
|
XCTAssertNil([_navigableOrderedTask navigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier]);
|
|
}
|
|
|
|
- (void)testNavigableOrderedTaskEmpty {
|
|
getIndividualNavigableOrderedTaskSteps();
|
|
|
|
//
|
|
// Empty task result
|
|
//
|
|
ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:0];
|
|
|
|
// Test forward navigation
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, otherSymptomStep, endStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil));
|
|
|
|
// Test backward navigation
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, symptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil));
|
|
|
|
// Test unreachable node (will reset navigation stack)
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, severityStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, nil));
|
|
|
|
// Test unreachable node (will reset navigation stack)
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, blankStep, severeHeadacheStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severeHeadacheStep, endStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, severeHeadacheStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severeHeadacheStep, blankStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, blankStep, nil));
|
|
|
|
// Test unreachable node (will reset navigation stack)
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, lightHeadacheStep, endStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, lightHeadacheStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, lightHeadacheStep, nil));
|
|
}
|
|
|
|
- (void)testNavigableOrderedTaskHeadache {
|
|
getIndividualNavigableOrderedTaskSteps();
|
|
|
|
//
|
|
// Only headache symptom question step answered
|
|
//
|
|
ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache];
|
|
|
|
// Test forward navigation
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, otherSymptomStep, endStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil));
|
|
|
|
// Test backward navigation
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, severityStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil));
|
|
}
|
|
|
|
- (void)testNavigableOrderedTaskDiziness {
|
|
getIndividualNavigableOrderedTaskSteps();
|
|
|
|
//
|
|
// Only diziness symptom question answered
|
|
//
|
|
ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomDiziness];
|
|
|
|
// Test forward navigation
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, otherSymptomStep, endStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil));
|
|
|
|
// Test backward navigation
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, otherSymptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, symptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil));
|
|
}
|
|
|
|
- (void)testNavigableOrderedTaskSevereHeadache {
|
|
getIndividualNavigableOrderedTaskSteps();
|
|
|
|
//
|
|
// Severe headache sequence
|
|
//
|
|
ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityYes];
|
|
|
|
// Test forward navigation
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, severeHeadacheStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severeHeadacheStep, endStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil));
|
|
|
|
// Test backward navigation
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, severeHeadacheStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severeHeadacheStep, severityStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil));
|
|
}
|
|
|
|
- (void)testNavigableOrderedTaskLightHeadache {
|
|
getIndividualNavigableOrderedTaskSteps();
|
|
|
|
//
|
|
// Light headache sequence
|
|
//
|
|
ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityNo];
|
|
|
|
// Test forward navigation
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, lightHeadacheStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, lightHeadacheStep, endStep));
|
|
XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil));
|
|
|
|
// Test backward navigation
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, lightHeadacheStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, lightHeadacheStep, severityStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep));
|
|
XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil));
|
|
}
|
|
|
|
ORKDefineStringKey(ScaleStepIdentifier);
|
|
ORKDefineStringKey(ContinuousScaleStepIdentifier);
|
|
static const NSInteger IntegerValue = 6;
|
|
static const float FloatValue = 6.5;
|
|
|
|
ORKDefineStringKey(SingleChoiceStepIdentifier);
|
|
ORKDefineStringKey(MultipleChoiceStepIdentifier);
|
|
ORKDefineStringKey(SingleChoiceValue);
|
|
ORKDefineStringKey(MultipleChoiceValue1);
|
|
ORKDefineStringKey(MultipleChoiceValue2);
|
|
|
|
ORKDefineStringKey(BooleanStepIdentifier);
|
|
static const BOOL BooleanValue = YES;
|
|
|
|
ORKDefineStringKey(TextStepIdentifier);
|
|
ORKDefineStringKey(TextValue);
|
|
ORKDefineStringKey(OtherTextValue);
|
|
|
|
ORKDefineStringKey(IntegerNumericStepIdentifier);
|
|
ORKDefineStringKey(FloatNumericStepIdentifier);
|
|
|
|
ORKDefineStringKey(TimeOfDayStepIdentifier);
|
|
ORKDefineStringKey(TimeIntervalStepIdentifier);
|
|
ORKDefineStringKey(DateStepIdentifier);
|
|
static NSDate *(^Date)() = ^NSDate *{ return [NSDate dateWithTimeIntervalSince1970:60*60*24]; };
|
|
static NSDateComponents *(^DateComponents)() = ^NSDateComponents *{
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
dateComponents.hour = 6;
|
|
dateComponents.minute = 6;
|
|
return dateComponents;
|
|
};
|
|
|
|
ORKStepResult *(^getStepResult)(NSString *, Class, ORKQuestionType, id) = ^ORKStepResult *(NSString *stepIdentifier, Class choiceQuestionResultClass, ORKQuestionType questionType, id answer) {
|
|
ORKQuestionResult *questionResult = [[choiceQuestionResultClass alloc] init];
|
|
questionResult.identifier = stepIdentifier;
|
|
questionResult.answer = answer;
|
|
questionResult.questionType = questionType;
|
|
|
|
ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]];
|
|
return stepResult;
|
|
};
|
|
|
|
- (ORKTaskResult *)getGeneralTaskResultTree {
|
|
NSMutableArray *stepResults = [NSMutableArray new];
|
|
|
|
[stepResults addObject:getStepResult(ScaleStepIdentifier, [ORKScaleQuestionResult class], ORKQuestionTypeScale, @(IntegerValue))];
|
|
[stepResults addObject:getStepResult(ContinuousScaleStepIdentifier, [ORKScaleQuestionResult class], ORKQuestionTypeScale, @(FloatValue))];
|
|
|
|
[stepResults addObject:getStepResult(SingleChoiceStepIdentifier, [ORKChoiceQuestionResult class], ORKQuestionTypeSingleChoice, @[SingleChoiceValue])];
|
|
[stepResults addObject:getStepResult(MultipleChoiceStepIdentifier, [ORKChoiceQuestionResult class], ORKQuestionTypeMultipleChoice, @[MultipleChoiceValue1, MultipleChoiceValue2])];
|
|
|
|
[stepResults addObject:getStepResult(BooleanStepIdentifier, [ORKBooleanQuestionResult class], ORKQuestionTypeBoolean, @(BooleanValue))];
|
|
|
|
[stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)];
|
|
|
|
[stepResults addObject:getStepResult(IntegerNumericStepIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeInteger, @(IntegerValue))];
|
|
[stepResults addObject:getStepResult(FloatNumericStepIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeDecimal, @(FloatValue))];
|
|
|
|
[stepResults addObject:getStepResult(DateStepIdentifier, [ORKDateQuestionResult class], ORKQuestionTypeDate, Date())];
|
|
|
|
[stepResults addObject:getStepResult(TimeIntervalStepIdentifier, [ORKTimeIntervalQuestionResult class], ORKQuestionTypeTimeInterval, @(IntegerValue))];
|
|
|
|
[stepResults addObject:getStepResult(TimeOfDayStepIdentifier, [ORKTimeOfDayQuestionResult class], ORKQuestionTypeTimeOfDay, DateComponents())];
|
|
|
|
ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier
|
|
taskRunUUID:[NSUUID UUID]
|
|
outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]];
|
|
taskResult.results = stepResults;
|
|
|
|
return taskResult;
|
|
}
|
|
|
|
ORKDefineStringKey(MatchedDestinationStepIdentifier);
|
|
ORKDefineStringKey(DefaultDestinationStepIdentifier);
|
|
|
|
ORKDefineStringKey(AdditionalTextStepIdentifier);
|
|
ORKDefineStringKey(AdditionalTextValue);
|
|
|
|
- (ORKTaskResult *)getSmallTaskResultTreeWithAdditionalOption:(BOOL)isAdditional {
|
|
NSMutableArray *stepResults = [NSMutableArray new];
|
|
|
|
if (!isAdditional) {
|
|
[stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)];
|
|
} else {
|
|
[stepResults addObject:getStepResult(AdditionalTextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, AdditionalTextValue)];
|
|
}
|
|
|
|
ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier
|
|
taskRunUUID:[NSUUID UUID]
|
|
outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]];
|
|
taskResult.results = stepResults;
|
|
|
|
return taskResult;
|
|
}
|
|
|
|
- (void)testPredicateStepNavigationRule {
|
|
NSPredicate *predicate = nil;
|
|
ORKPredicateStepNavigationRule *predicateRule = nil;
|
|
ORKTaskResult *taskResult = nil;
|
|
ORKTaskResult *additionalTaskResult = nil;
|
|
|
|
NSArray *resultPredicates = nil;
|
|
NSArray *matchingStepIdentifiers = nil;
|
|
NSString *defaultStepIdentifier = nil;
|
|
|
|
// Test predicate step navigation rule initializers
|
|
predicate = [ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:TextValue];
|
|
resultPredicates = @[ predicate ];
|
|
matchingStepIdentifiers = @[ MatchedDestinationStepIdentifier ];
|
|
predicate = [ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:TextValue];
|
|
|
|
predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates
|
|
matchingStepIdentifiers:matchingStepIdentifiers];
|
|
|
|
XCTAssertEqualObjects(predicateRule.resultPredicates, ORKArrayCopyObjects(resultPredicates));
|
|
XCTAssertEqualObjects(predicateRule.matchingStepIdentifiers, ORKArrayCopyObjects(matchingStepIdentifiers));
|
|
XCTAssertNil(predicateRule.defaultStepIdentifier);
|
|
|
|
defaultStepIdentifier = DefaultDestinationStepIdentifier;
|
|
predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates
|
|
matchingStepIdentifiers:matchingStepIdentifiers
|
|
defaultStepIdentifier:defaultStepIdentifier];
|
|
|
|
XCTAssertEqualObjects(predicateRule.resultPredicates, ORKArrayCopyObjects(resultPredicates));
|
|
XCTAssertEqualObjects(predicateRule.matchingStepIdentifiers, ORKArrayCopyObjects(matchingStepIdentifiers));
|
|
XCTAssertEqualObjects(predicateRule.defaultStepIdentifier, defaultStepIdentifier);
|
|
|
|
// Predicate matching, no additional task results
|
|
resultPredicates = @[ predicate ];
|
|
matchingStepIdentifiers = @[ MatchedDestinationStepIdentifier ];
|
|
predicate = [ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:TextValue];
|
|
defaultStepIdentifier = DefaultDestinationStepIdentifier;
|
|
predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates
|
|
matchingStepIdentifiers:matchingStepIdentifiers
|
|
defaultStepIdentifier:defaultStepIdentifier];
|
|
|
|
taskResult = [ORKTaskResult new];
|
|
XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier);
|
|
|
|
taskResult = [self getSmallTaskResultTreeWithAdditionalOption:NO];
|
|
XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier);
|
|
|
|
// Predicate matching, additional task results
|
|
NSPredicate *currentPredicate = [ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:TextValue];
|
|
NSPredicate *additionalPredicate = [ORKResultPredicate predicateForTextQuestionResultWithIdentifier:AdditionalTextStepIdentifier
|
|
expectedString:AdditionalTextValue];
|
|
predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[currentPredicate, additionalPredicate]];
|
|
predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ]
|
|
matchingStepIdentifiers:@[ MatchedDestinationStepIdentifier ]
|
|
defaultStepIdentifier:DefaultDestinationStepIdentifier];
|
|
|
|
taskResult = [ORKTaskResult new];
|
|
XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier);
|
|
|
|
taskResult = [self getSmallTaskResultTreeWithAdditionalOption:NO];
|
|
XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier);
|
|
|
|
additionalTaskResult = [self getSmallTaskResultTreeWithAdditionalOption:YES];
|
|
predicateRule.additionalTaskResults = @[ additionalTaskResult ];
|
|
XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier);
|
|
|
|
// Test duplicate predicate identifiers check
|
|
predicateRule.additionalTaskResults = @[ taskResult ];
|
|
XCTAssertThrows([predicateRule identifierForDestinationStepWithTaskResult:taskResult]);
|
|
}
|
|
|
|
- (void)testDirectStepNavigationRule {
|
|
ORKDirectStepNavigationRule *directRule = nil;
|
|
ORKTaskResult *mockTaskResult = [ORKTaskResult new];
|
|
|
|
directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:MatchedDestinationStepIdentifier];
|
|
XCTAssertEqualObjects(directRule.destinationStepIdentifier, [MatchedDestinationStepIdentifier copy] );
|
|
XCTAssertEqualObjects([directRule identifierForDestinationStepWithTaskResult:mockTaskResult], [MatchedDestinationStepIdentifier copy]);
|
|
}
|
|
|
|
- (void)testResultPredicates {
|
|
ORKTaskResult *taskResult = [self getGeneralTaskResultTree];
|
|
NSArray *leafResults = [ORKPredicateStepNavigationRule leafResultsFromTaskResult:taskResult];
|
|
|
|
// ORKScaleQuestionResult
|
|
XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ScaleStepIdentifier
|
|
expectedAnswer:IntegerValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ScaleStepIdentifier
|
|
expectedAnswer:IntegerValue + 1] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue - 0.01
|
|
maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue + 0.05
|
|
maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithIdentifier:ContinuousScaleStepIdentifier
|
|
maximumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:leafResults]);
|
|
|
|
// ORKChoiceQuestionResult (strings)
|
|
XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:SingleChoiceStepIdentifier
|
|
expectedString:SingleChoiceValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:SingleChoiceStepIdentifier
|
|
expectedString:OtherTextValue] evaluateWithObject:leafResults]);
|
|
|
|
NSArray *expectedAnswers = nil;
|
|
expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2];
|
|
XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:MultipleChoiceStepIdentifier
|
|
expectedStrings:expectedAnswers] evaluateWithObject:leafResults]);
|
|
expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2, OtherTextValue];
|
|
XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:MultipleChoiceStepIdentifier
|
|
expectedStrings:expectedAnswers] evaluateWithObject:leafResults]);
|
|
|
|
// ORKChoiceQuestionResult (regular expressions)
|
|
XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:SingleChoiceStepIdentifier
|
|
matchingPattern:@"...gleChoiceValue"] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:SingleChoiceStepIdentifier
|
|
expectedString:@"...SingleChoiceValue"] evaluateWithObject:leafResults]);
|
|
|
|
expectedAnswers = @[@"...tipleChoiceValue1", @"...tipleChoiceValue2"];
|
|
XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:MultipleChoiceStepIdentifier
|
|
matchingPatterns:expectedAnswers] evaluateWithObject:leafResults]);
|
|
expectedAnswers = @[@"...MultipleChoiceValue1", @"...MultipleChoiceValue2", @"...OtherTextValue"];
|
|
XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithIdentifier:MultipleChoiceStepIdentifier
|
|
matchingPatterns:expectedAnswers] evaluateWithObject:leafResults]);
|
|
|
|
// ORKBooleanQuestionResult
|
|
XCTAssertTrue([[ORKResultPredicate predicateForBooleanQuestionResultWithIdentifier:BooleanStepIdentifier
|
|
expectedAnswer:BooleanValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForBooleanQuestionResultWithIdentifier:BooleanStepIdentifier
|
|
expectedAnswer:!BooleanValue] evaluateWithObject:leafResults]);
|
|
|
|
// ORKTextQuestionResult (strings)
|
|
XCTAssertTrue([[ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:TextValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
expectedString:OtherTextValue] evaluateWithObject:leafResults]);
|
|
|
|
// ORKTextQuestionResult (regular expressions)
|
|
XCTAssertTrue([[ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
matchingPattern:@"...tValue"] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForTextQuestionResultWithIdentifier:TextStepIdentifier
|
|
matchingPattern:@"...TextValue"] evaluateWithObject:leafResults]);
|
|
|
|
// ORKNumericQuestionResult
|
|
XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:IntegerNumericStepIdentifier
|
|
expectedAnswer:IntegerValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:IntegerNumericStepIdentifier
|
|
expectedAnswer:IntegerValue + 1] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue - 0.01
|
|
maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue + 0.05
|
|
maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue - 0.01
|
|
maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue + 0.05
|
|
maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
minimumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithIdentifier:FloatNumericStepIdentifier
|
|
maximumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:leafResults]);
|
|
|
|
// ORKTimeOfDayQuestionResult
|
|
NSDateComponents *expectedDateComponentsMinimum = DateComponents();
|
|
NSDateComponents *expectedDateComponentsMaximum = DateComponents();
|
|
XCTAssertTrue([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithIdentifier:TimeOfDayStepIdentifier
|
|
minimumExpectedAnswerHour:expectedDateComponentsMinimum.hour
|
|
minimumExpectedAnswerMinute:expectedDateComponentsMinimum.minute
|
|
maximumExpectedAnswerHour:expectedDateComponentsMaximum.hour
|
|
maximumExpectedAnswerMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:leafResults]);
|
|
expectedDateComponentsMinimum.minute -= 2;
|
|
expectedDateComponentsMaximum.minute += 2;
|
|
XCTAssertTrue([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithIdentifier:TimeOfDayStepIdentifier
|
|
minimumExpectedAnswerHour:expectedDateComponentsMinimum.hour
|
|
minimumExpectedAnswerMinute:expectedDateComponentsMinimum.minute
|
|
maximumExpectedAnswerHour:expectedDateComponentsMaximum.hour
|
|
maximumExpectedAnswerMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:leafResults]);
|
|
|
|
expectedDateComponentsMinimum.minute += 3;
|
|
XCTAssertFalse([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithIdentifier:TimeOfDayStepIdentifier
|
|
minimumExpectedAnswerHour:expectedDateComponentsMinimum.hour
|
|
minimumExpectedAnswerMinute:expectedDateComponentsMinimum.minute
|
|
maximumExpectedAnswerHour:expectedDateComponentsMaximum.hour
|
|
maximumExpectedAnswerMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:leafResults]);
|
|
|
|
expectedDateComponentsMinimum.minute -= 3;
|
|
expectedDateComponentsMinimum.hour += 1;
|
|
expectedDateComponentsMaximum.hour += 2;
|
|
XCTAssertFalse([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithIdentifier:TimeOfDayStepIdentifier
|
|
minimumExpectedAnswerHour:expectedDateComponentsMinimum.hour
|
|
minimumExpectedAnswerMinute:expectedDateComponentsMinimum.minute
|
|
maximumExpectedAnswerHour:expectedDateComponentsMaximum.hour
|
|
maximumExpectedAnswerMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:leafResults]);
|
|
|
|
// ORKTimeIntervalQuestionResult
|
|
XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithIdentifier:TimeIntervalStepIdentifier
|
|
expectedAnswer:IntegerValue] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithIdentifier:TimeIntervalStepIdentifier
|
|
expectedAnswer:IntegerValue + 1] evaluateWithObject:leafResults]);
|
|
|
|
// ORKDateQuestionResult
|
|
NSDate *expectedDate = Date();
|
|
XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-60]
|
|
maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60]] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60]
|
|
maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+120]] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-60]
|
|
maximumExpectedAnswerDate:nil] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+1]
|
|
maximumExpectedAnswerDate:nil] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:nil
|
|
maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60]] evaluateWithObject:leafResults]);
|
|
XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:nil
|
|
maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-1]] evaluateWithObject:leafResults]);
|
|
|
|
XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithIdentifier:DateStepIdentifier
|
|
minimumExpectedAnswerDate:nil
|
|
maximumExpectedAnswerDate:nil] evaluateWithObject:leafResults]);
|
|
}
|
|
|
|
@end
|