Files
srinathtm-apple 01cc7ed79d Project updates (#1264)
* overall updates to ResearchKit, new textChoiceOtherAnswerFormat, unit tests and more..
2019-04-15 14:42:02 -07:00

738 lines
48 KiB
Objective-C

/*
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;
@import ResearchKit.Private;
@interface ORKAnswerFormatTests : XCTestCase
@end
@protocol ORKComfirmAnswerFormat_Private <NSObject>
@property (nonatomic, copy, readonly) NSString *originalItemIdentifier;
@property (nonatomic, copy, readonly) NSString *errorMessage;
@end
@implementation ORKAnswerFormatTests
- (void)testValidEmailAnswerFormat {
// Test email regular expression validation with correct input.
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone@researchkit.org"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some.one@researchkit.org"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone@researchkit.org.uk"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some_one@researchkit.org"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some-one@researchkit.org"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone1@researchkit.org"]);
XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"Someone1@ResearchKit.org"]);
}
- (void)testInvalidEmailAnswerFormat {
// Test email regular expression validation with incorrect input.
XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest"]);
XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@"]);
XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@researchkit"]);
XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@.org"]);
XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"12345"]);
}
- (void)testInvalidRegularExpressionAnswerFormat {
// Setup an answer format
ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat];
answerFormat.multipleLines = NO;
answerFormat.keyboardType = UIKeyboardTypeASCIICapable;
NSRegularExpression *validationRegularExpression =
[NSRegularExpression regularExpressionWithPattern:@"^[A-F,0-9]+$"
options:(NSRegularExpressionOptions)0
error:nil];
answerFormat.validationRegularExpression = validationRegularExpression;
answerFormat.invalidMessage = @"Only hexidecimal values in uppercase letters are accepted.";
answerFormat.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
XCTAssertFalse([answerFormat isAnswerValidWithString:@"Q2"]);
XCTAssertFalse([answerFormat isAnswerValidWithString:@"abcd"]);
XCTAssertTrue([answerFormat isAnswerValidWithString:@"ABCD1234FFED0987654321"]);
}
- (void)testConfirmAnswerFormat {
// Setup an answer format
ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat];
answerFormat.multipleLines = NO;
answerFormat.secureTextEntry = YES;
answerFormat.keyboardType = UIKeyboardTypeASCIICapable;
if (@available(iOS 12.0, *)) {
answerFormat.textContentType = UITextContentTypeNewPassword;
} else {
answerFormat.textContentType = UITextContentTypePassword;
}
answerFormat.maximumLength = 12;
NSRegularExpression *validationRegularExpression =
[NSRegularExpression regularExpressionWithPattern:@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{10,}"
options:(NSRegularExpressionOptions)0
error:nil];
answerFormat.validationRegularExpression = validationRegularExpression;
answerFormat.invalidMessage = @"Invalid password";
answerFormat.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
// Note: setting these up incorrectly for a password to test that the values are *not* copied.
// DO NOT setup a real password field with these options.
answerFormat.autocorrectionType = UITextAutocorrectionTypeDefault;
answerFormat.spellCheckingType = UITextSpellCheckingTypeDefault;
ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:NO];
// -- method under test
ORKFormItem *confirmItem = [item confirmationAnswerFormItemWithIdentifier:@"bar"
text:@"enter again"
errorMessage:@"doesn't match"];
XCTAssertEqualObjects(confirmItem.identifier, @"bar");
XCTAssertEqualObjects(confirmItem.text, @"enter again");
XCTAssertFalse(confirmItem.optional);
// Inspect the answer format
ORKAnswerFormat *confirmFormat = confirmItem.answerFormat;
// ORKAnswerFormat that is returned should be a subclass of ORKTextAnswerFormat.
// The actual subclass that is returned is private to the API and should not be accessed directly.
XCTAssertNotNil(confirmFormat);
XCTAssertTrue([confirmFormat isKindOfClass:[ORKTextAnswerFormat class]]);
if (![confirmFormat isKindOfClass:[ORKTextAnswerFormat class]]) { return; }
ORKTextAnswerFormat *confirmAnswer = (ORKTextAnswerFormat*)confirmFormat;
// These properties should match the original format
XCTAssertFalse(confirmAnswer.multipleLines);
XCTAssertTrue(confirmAnswer.secureTextEntry);
XCTAssertEqual(confirmAnswer.keyboardType, UIKeyboardTypeASCIICapable);
if (@available(iOS 12.0, *)) {
XCTAssertEqual(confirmAnswer.textContentType, UITextContentTypeNewPassword);
} else {
XCTAssertEqual(confirmAnswer.textContentType, UITextContentTypePassword);
}
XCTAssertEqual(confirmAnswer.maximumLength, 12);
// This property should match the input answer format so that cases that
// require all-upper or all-lower (for whatever reason) can be met.
XCTAssertEqual(confirmAnswer.autocapitalizationType, UITextAutocapitalizationTypeAllCharacters);
// These properties should always be set to not autocorrect
XCTAssertEqual(confirmAnswer.autocorrectionType, UITextAutocorrectionTypeNo);
XCTAssertEqual(confirmAnswer.spellCheckingType, UITextSpellCheckingTypeNo);
// These properties should be nil
XCTAssertNil(confirmAnswer.validationRegularExpression);
XCTAssertNil(confirmAnswer.invalidMessage);
// Check that the confirmation answer format responds to the internal methods
XCTAssertTrue([confirmFormat respondsToSelector:@selector(originalItemIdentifier)]);
XCTAssertTrue([confirmFormat respondsToSelector:@selector(errorMessage)]);
if (![confirmFormat respondsToSelector:@selector(originalItemIdentifier)] ||
![confirmFormat respondsToSelector:@selector(errorMessage)]) {
return;
}
NSString *originalItemIdentifier = [(id)confirmFormat originalItemIdentifier];
XCTAssertEqualObjects(originalItemIdentifier, @"foo");
NSString *errorMessage = [(id)confirmFormat errorMessage];
XCTAssertEqualObjects(errorMessage, @"doesn't match");
}
- (void)testConfirmAnswerFormat_Optional_YES {
// Setup an answer format
ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat];
answerFormat.multipleLines = NO;
ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:YES];
// -- method under test
ORKFormItem *confirmItem = [item confirmationAnswerFormItemWithIdentifier:@"bar"
text:@"enter again"
errorMessage:@"doesn't match"];
// Check that the confirm item optional value matches the input item
XCTAssertTrue(confirmItem.optional);
}
- (void)testConfirmAnswerFormat_MultipleLines_YES {
// Setup an answer format
ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat];
answerFormat.multipleLines = YES;
ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:YES];
// -- method under test
XCTAssertThrows([item confirmationAnswerFormItemWithIdentifier:@"bar"
text:@"enter again"
errorMessage:@"doesn't match"]);
}
- (void)testContinuousScaleAnswerFormat {
XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10
minimumValue:100
defaultValue:10
maximumFractionDigits:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max < min");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10001
minimumValue:100
defaultValue:10
maximumFractionDigits:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max > effectiveUpperBound");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:100
minimumValue:-10001
defaultValue:10
maximumFractionDigits:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since min < effectiveLowerBound");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10
minimumValue:100
defaultValue:10
maximumFractionDigits:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max < min");
ORKContinuousScaleAnswerFormat *answerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:1
minimumValue:0
defaultValue:10
maximumFractionDigits:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL];
XCTAssertEqual([answerFormat maximum], 1);
XCTAssertEqual([answerFormat minimum], 0);
XCTAssertEqual([answerFormat defaultValue], 10);
XCTAssertEqual([answerFormat maximumFractionDigits], 4, @"Should return 4 since the maximumFractionDigits needs to 0 <= maximumFractionDigits <= 4");
XCTAssertEqual([answerFormat isVertical], YES);
XCTAssertEqual([answerFormat maximumValueDescription], NULL);
XCTAssertEqual([answerFormat minimumValueDescription], NULL);
ORKContinuousScaleAnswerFormat *answerFormatTwo = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:1
minimumValue:0
defaultValue:10
maximumFractionDigits:-1
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL];
XCTAssertEqual([answerFormatTwo maximumFractionDigits], 0, @"Should return 0 since the maximumFractionDigits needs to 0 <= maximumFractionDigits <= 4");
}
- (void)testScaleAnswerFormat {
ORKScaleAnswerFormat *answerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100
minimumValue:0
defaultValue:10
step:10
vertical:YES
maximumValueDescription:@"MAX"
minimumValueDescription:@"MIN"];
XCTAssertEqual([answerFormat maximum], 100);
XCTAssertEqual([answerFormat minimum], 0);
XCTAssertEqual([answerFormat defaultValue], 10);
XCTAssertEqual([answerFormat step], 10);
XCTAssertEqual([answerFormat isVertical], YES);
XCTAssertEqual([answerFormat maximumValueDescription], @"MAX");
XCTAssertEqual([answerFormat minimumValueDescription], @"MIN");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:25
minimumValue:50
defaultValue:10
step:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since max < min");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100
minimumValue:10
defaultValue:200
step:0
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step < 1");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100
minimumValue:0
defaultValue:10
step:3
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step is not divisible by the difference of max and min");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:25
minimumValue:-20000
defaultValue:10
step:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since min < -10000");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:20000
minimumValue:0
defaultValue:10
step:10
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since max > 10000");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100
minimumValue:0
defaultValue:10
step:1
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step count > 13");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100
minimumValue:100
defaultValue:10
step:1
vertical:YES
maximumValueDescription:NULL
minimumValueDescription:NULL],
NSException, NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step count < 1");
}
- (void)testTextScaleAnswerFormat {
ORKTextChoice *choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value:[NSNumber numberWithInteger:1]];
ORKTextChoice *choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value:[NSNumber numberWithInteger:2]];
NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil];
ORKTextScaleAnswerFormat *answerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:choices defaultIndex:0 vertical:YES];
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] value],[NSNumber numberWithInteger:1]);
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value],[NSNumber numberWithInteger:2]);
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] text], @"Choice One");
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] text], @"Choice Two");
XCTAssertEqual([answerFormat defaultIndex], 0);
XCTAssertEqual([answerFormat isVertical], YES);
}
- (void)testTimeOfDayAnswerFormat {
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.month = 01;
dateComponents.day = 24;
dateComponents.year = 1984;
ORKTimeOfDayAnswerFormat *answerFormat = [ORKAnswerFormat timeOfDayAnswerFormatWithDefaultComponents:dateComponents];
XCTAssertEqual([[answerFormat defaultComponents] month], 01);
XCTAssertEqual([[answerFormat defaultComponents] day], 24);
XCTAssertEqual([[answerFormat defaultComponents] year], 1984);
}
- (void)testNumericAnswerFormat {
ORKNumericAnswerFormat *answerFormatWithIntegerStyle = [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger
unit:@"Units"
minimum:[NSNumber numberWithInteger:0]
maximum:[NSNumber numberWithInteger:100]
maximumFractionDigits:@(0)];
XCTAssertEqual([answerFormatWithIntegerStyle style], ORKNumericAnswerStyleInteger);
XCTAssertEqual([answerFormatWithIntegerStyle unit], @"Units");
XCTAssertEqual([answerFormatWithIntegerStyle minimum], [NSNumber numberWithInteger:0]);
XCTAssertEqual([answerFormatWithIntegerStyle maximum], [NSNumber numberWithInteger:100]);
XCTAssertEqual([answerFormatWithIntegerStyle maximumFractionDigits], @(0));
ORKNumericAnswerFormat *answerFormatWithDecimalStyle = [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal];
XCTAssertEqual([answerFormatWithDecimalStyle style ], ORKNumericAnswerStyleDecimal);
XCTAssertThrowsSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger
unit:@"Integers"
minimum:[NSNumber numberWithInteger:100]
maximum:[NSNumber numberWithInteger:0]], NSException, NSInvalidArgumentException, @"Should throw NSInvalidArgumentException since max < min");
XCTAssertThrowsSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal
unit:@"Doubles"
minimum:[NSNumber numberWithDouble:10.2]
maximum:[NSNumber numberWithDouble:10]], NSException, NSInvalidArgumentException, @"Should throw NSInvalidArgumentException since max < min");
XCTAssertNoThrowSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger
unit:@"Integers"
minimum:NULL
maximum:NULL],
NSException, NSInvalidArgumentException,
@"Should not throw exception for null values");
}
- (void)testBooleanAnswerFormat {
ORKBooleanAnswerFormat *answerFormat = [ORKAnswerFormat booleanAnswerFormatWithYesString:@"YES" noString:@"NO"];
XCTAssertEqual([answerFormat yes], @"YES");
XCTAssertEqual([answerFormat no], @"NO");
}
- (void)testHeightAnswerFormat {
ORKHeightAnswerFormat *answerFormat = [ORKAnswerFormat heightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric];
XCTAssert([answerFormat measurementSystem] == ORKMeasurementSystemMetric);
}
- (void)testTimeIntervalAnswerFormat {
NSTimeInterval defaultTimeInterval = 40;
ORKTimeIntervalAnswerFormat *answerFormat = [ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval
step:1];
XCTAssertEqual([answerFormat defaultInterval], defaultTimeInterval);
XCTAssertEqual([answerFormat step], 1);
XCTAssertThrowsSpecificNamed([ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval step:-1],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step is lower than the recommended minimuim: 0");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval step:31],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since step is lower than the recommended maximum: 30");
}
- (void)testImageChoiceAnswerFormat {
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"org.researchkit.ResearchKit"];
UIImage *imageOne = [UIImage imageNamed:@"heart-fitness" inBundle:bundle compatibleWithTraitCollection:nil];
UIImage *imageTwo = [UIImage imageNamed:@"phoneshake" inBundle:bundle compatibleWithTraitCollection:nil];
ORKImageChoice *choiceOne = [ORKImageChoice choiceWithNormalImage:imageOne selectedImage:imageOne text:@"Heart" value:@"ImageTwo"];
ORKImageChoice *choiceTwo = [ORKImageChoice choiceWithNormalImage:imageTwo selectedImage:imageTwo text:@"Phone Shake" value:@"ImageOne"];
NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil];
ORKImageChoiceAnswerFormat *answerChoice = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:choices];
XCTAssertEqual([[answerChoice imageChoices] objectAtIndex:0], choiceOne);
XCTAssertEqual([[answerChoice imageChoices] objectAtIndex:1], choiceTwo);
NSArray *wrongChoices = [NSArray arrayWithObjects:@"Wrong Choice One", @"Wrong Choice Two", nil];
XCTAssertThrowsSpecificNamed([ORKAnswerFormat choiceAnswerFormatWithImageChoices:wrongChoices], NSException, NSInvalidArgumentException, "Should throw NSInvalidArgumentException since choices were not ORKImageChoice objects");
}
- (void)testTextAnswerFormat {
ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormatWithMaximumLength:10];
XCTAssertEqual([answerFormat questionType], ORKQuestionTypeText);
XCTAssertEqual(answerFormat.maximumLength, 10);
XCTAssertEqual([answerFormat isAnswerValidWithString:@"CORRECT"], YES, @"Should return YES since the string length is less than max");
XCTAssertEqual([answerFormat isAnswerValidWithString:@"REALLY LONG STRING! I THINK?"], NO, @"Should return NO since the string length is more than max");
XCTAssert([answerFormat isEqual:answerFormat], @"Should be equal");
ORKTextAnswerFormat *noMaxAnswerFormat = [ORKAnswerFormat textAnswerFormat];
XCTAssertEqual(noMaxAnswerFormat.maximumLength, 0);
NSString *pattern = @"^[2-9]\\d{2}-\\d{3}-\\d{4}$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:NULL];
ORKTextAnswerFormat *regexAnswerFormat = [ORKAnswerFormat textAnswerFormatWithValidationRegularExpression:regex invalidMessage:@"NOT A PHONENUMBER!"];
XCTAssertEqual(regexAnswerFormat.validationRegularExpression, regex);
XCTAssertEqual(regexAnswerFormat.invalidMessage, @"NOT A PHONENUMBER!");
NSString *correctPhoneNumber = @"333-444-5555";
NSString *incorrectPhoneNumber = @"123-456-7890";
XCTAssertEqual([regexAnswerFormat isAnswerValidWithString:correctPhoneNumber], YES, @"Should return YES since it is in the correct format");
XCTAssertEqual([regexAnswerFormat isAnswerValidWithString:incorrectPhoneNumber], NO, @"Should return NO since it is not in the correct format");
}
- (void)testLocationAnswerFormat {
ORKLocationAnswerFormat *answerFormat = [ORKAnswerFormat locationAnswerFormat];
[answerFormat setUseCurrentLocation:YES];
XCTAssertEqual(answerFormat.useCurrentLocation, YES);
}
- (void)testWeightAnswerFormat {
ORKWeightAnswerFormat *answerFormat = [ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric
numericPrecision:ORKNumericPrecisionHigh
minimumValue:0
maximumValue:300
defaultValue: 150];
XCTAssertEqual(answerFormat.measurementSystem, ORKMeasurementSystemMetric);
XCTAssertEqual(answerFormat.numericPrecision, ORKNumericPrecisionHigh);
XCTAssertEqual(answerFormat.minimumValue, 0);
XCTAssertEqual(answerFormat.maximumValue, 300);
XCTAssertEqual(answerFormat.defaultValue, 150);
XCTAssertThrowsSpecificNamed([ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric
numericPrecision:ORKNumericPrecisionHigh
minimumValue:100
maximumValue:50
defaultValue:25],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since min > max");
}
- (void)testMultipleValuePickerAnswerFormat {
ORKTextChoice *choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value: [NSNumber numberWithInteger:1]];
ORKTextChoice *choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:2]];
ORKTextChoice *choiceThree = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:3]];
ORKTextChoice *choiceFour = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:4]];
NSArray *firstChoices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil];
NSArray *secondChoices = [NSArray arrayWithObjects:choiceThree, choiceFour, nil];
ORKValuePickerAnswerFormat *valuePickerOne = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:firstChoices];
ORKValuePickerAnswerFormat *valuePickerTwo = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:secondChoices];
NSArray *valuePickerFormats = [NSArray arrayWithObjects:valuePickerOne, valuePickerTwo, nil];
ORKMultipleValuePickerAnswerFormat *multiplePickerAnswerFormat = [[ORKMultipleValuePickerAnswerFormat alloc] initWithValuePickers:valuePickerFormats separator:@"S"];
XCTAssertEqualObjects(multiplePickerAnswerFormat.valuePickers, valuePickerFormats);
XCTAssert([multiplePickerAnswerFormat.separator isEqualToString:@"S"]);
}
- (void)testValuePickerAnswerFormat {
ORKTextChoice *choiceOne, *choiceTwo;
choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value:[NSNumber numberWithInteger:1]];
choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value:[NSNumber numberWithInteger:2]];
NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil];
ORKValuePickerAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:choices];
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] value], [NSNumber numberWithInteger:1]);
XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value], [NSNumber numberWithInteger:2]);
}
- (void)testHealthKitCharacteristicTypeAnswerFormat {
HKCharacteristicType *biologicalSex = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
ORKHealthKitCharacteristicTypeAnswerFormat *answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:biologicalSex];
NSArray *options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_FEMALE", nil) value: ORKBiologicalSexIdentifierFemale],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_MALE", nil) value:ORKBiologicalSexIdentifierMale],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_OTHER", nil) value:ORKBiologicalSexIdentifierOther]
];
ORKAnswerFormat *expectedFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:options];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
HKCharacteristicType *bloodType = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType];
answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:bloodType];
options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A+", nil) value:ORKBloodTypeIdentifierAPositive],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A-", nil) value:ORKBloodTypeIdentifierANegative],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B+", nil) value:ORKBloodTypeIdentifierBPositive],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B-", nil) value:ORKBloodTypeIdentifierBNegative],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB+", nil) value:ORKBloodTypeIdentifierABPositive],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB-", nil) value:ORKBloodTypeIdentifierABNegative],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O+", nil) value:ORKBloodTypeIdentifierOPositive],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O-", nil) value:ORKBloodTypeIdentifierONegative]
];
expectedFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
HKCharacteristicType *dateOfBirth = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];
answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:dateOfBirth];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *defaultDate = [NSDate date];
NSDate *minimumDate = [NSDate dateWithTimeIntervalSinceNow:-1000];
NSDate *maximumDate = [NSDate dateWithTimeIntervalSinceNow:1000];
answerFormat.defaultDate = defaultDate;
answerFormat.minimumDate = minimumDate;
answerFormat.maximumDate = maximumDate;
expectedFormat = [ORKDateAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate
minimumDate:minimumDate
maximumDate:maximumDate
calendar:calendar];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
HKCharacteristicType *fitzpatrickSkin = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType];
answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:fitzpatrickSkin];
options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_I", nil) value:@(HKFitzpatrickSkinTypeI)],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_II", nil) value:@(HKFitzpatrickSkinTypeII)],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_III", nil) value:@(HKFitzpatrickSkinTypeIII)],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_IV", nil) value:@(HKFitzpatrickSkinTypeIV)],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_V", nil) value:@(HKFitzpatrickSkinTypeV)],
[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_VI", nil) value:@(HKFitzpatrickSkinTypeVI)],
];
expectedFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
HKCharacteristicType *wheelchairUse = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierWheelchairUse];
answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:wheelchairUse];
expectedFormat = [ORKAnswerFormat booleanAnswerFormat];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], [expectedFormat impliedAnswerFormat]);
XCTAssertEqual([answerFormat questionType], ORKQuestionTypeSingleChoice);
XCTAssert([answerFormat isEqual:answerFormat]);
}
- (void)testHealthKitQuantityTypeAnswerFormat {
HKQuantityType *height = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
ORKHealthKitQuantityTypeAnswerFormat *answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:height unit:NULL style:ORKNumericAnswerStyleInteger];
ORKAnswerFormat *expectedFormat = [ORKHeightAnswerFormat heightAnswerFormat];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
XCTAssertEqual([answerFormat unit], [HKUnit meterUnitWithMetricPrefix:(HKMetricPrefixCenti)]);
HKQuantityType *weight = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:weight unit:NULL style:ORKNumericAnswerStyleInteger];
expectedFormat = [ORKWeightAnswerFormat weightAnswerFormat];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
XCTAssertEqual([answerFormat unit], [HKUnit gramUnitWithMetricPrefix:(HKMetricPrefixKilo)]);
HKUnit *unit = [HKUnit unitFromEnergyFormatterUnit:(NSEnergyFormatterUnitCalorie)];
HKQuantityType *calories = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:calories unit:unit style:ORKNumericAnswerStyleDecimal];
expectedFormat = [ORKNumericAnswerFormat decimalAnswerFormatWithUnit:[unit localizedUnitString]];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:calories unit:unit style:ORKNumericAnswerStyleInteger];
expectedFormat = [ORKNumericAnswerFormat integerAnswerFormatWithUnit:[unit localizedUnitString]];
XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat);
XCTAssertEqual([answerFormat unit], unit);
XCTAssertEqual([answerFormat numericAnswerStyle], ORKNumericAnswerStyleInteger);
XCTAssertEqual([answerFormat quantityType], calories);
}
- (void)testDateAnswerFormat {
NSDateComponents *earlierDateComponents = [[NSDateComponents alloc] init];
[earlierDateComponents setDay: 24];
[earlierDateComponents setMonth: 1];
[earlierDateComponents setYear: 1984];
NSDate *earlierDate = [[NSCalendar currentCalendar] dateFromComponents: earlierDateComponents];
NSDate *middleDate = [NSDate date];
NSDateComponents *laterDateComponents = [[NSDateComponents alloc] init];
[laterDateComponents setDay: 01];
[laterDateComponents setMonth: 01];
[laterDateComponents setYear: 3000];
NSDate *laterDate = [[NSCalendar currentCalendar] dateFromComponents: laterDateComponents];
NSCalendar *calendar = [NSCalendar currentCalendar];
ORKDateAnswerFormat *answerFormat = [ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate
minimumDate:earlierDate
maximumDate:laterDate
calendar:calendar];
XCTAssertEqual([answerFormat minimumDate], earlierDate);
XCTAssertEqual([answerFormat defaultDate], middleDate);
XCTAssertEqual([answerFormat maximumDate], laterDate);
XCTAssertEqual([answerFormat questionType], ORKQuestionTypeDate);
XCTAssert([answerFormat isAnswerValidWithString:NULL]);
answerFormat = [ORKAnswerFormat dateTimeAnswerFormat];
XCTAssertEqual([answerFormat questionType], ORKQuestionTypeDateAndTime);
XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate
minimumDate:laterDate
maximumDate:earlierDate
calendar:calendar],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since maximum date is less than minimum date");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:laterDate
minimumDate:earlierDate
maximumDate:middleDate
calendar:calendar],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since default date is more than maximum date");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:earlierDate
minimumDate:middleDate
maximumDate:laterDate
calendar:calendar],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since default date is less than minimum date");
XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:nil
minimumDate:laterDate
maximumDate:earlierDate
calendar:calendar],
NSException,
NSInvalidArgumentException,
@"Should throw NSInvalidArgumentException since minimum date is later than maximum date");
XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:nil
minimumDate:earlierDate
maximumDate:laterDate
calendar:calendar],
NSException,
NSInvalidArgumentException);
XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate
minimumDate:nil
maximumDate:laterDate
calendar:calendar],
NSException,
NSInvalidArgumentException);
XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate
minimumDate:earlierDate
maximumDate:nil
calendar:calendar],
NSException,
NSInvalidArgumentException);
}
@end