From 3653ca288a54caca3457b8c2925a3daba81158cf Mon Sep 17 00:00:00 2001 From: Shannon Young Date: Mon, 25 Jan 2016 23:14:23 -0800 Subject: [PATCH 1/2] Fixed incorrectly defined bool. --- APCAppCore/APCAppCore/DataSubstrate/Model/APCUser+Bridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/APCAppCore/APCAppCore/DataSubstrate/Model/APCUser+Bridge.m b/APCAppCore/APCAppCore/DataSubstrate/Model/APCUser+Bridge.m index b06f8ea5..bdc962b3 100644 --- a/APCAppCore/APCAppCore/DataSubstrate/Model/APCUser+Bridge.m +++ b/APCAppCore/APCAppCore/DataSubstrate/Model/APCUser+Bridge.m @@ -352,7 +352,7 @@ - (void)signInOnCompletion:(void (^)(NSError *))completionBlock for (id key in consentStatuses) { NSDictionary *status = [consentStatuses objectForKey:key]; NSString *guid = status[@"subpopulationGuid"]; - BOOL required = status[@"required"]; + BOOL required = [status[@"required"] boolValue]; if (required) { self.subpopulationGuid = guid; } From 00d3ca9f533b5e98ae1ec45cf968ef42c5233bd7 Mon Sep 17 00:00:00 2001 From: Shannon Young Date: Mon, 25 Jan 2016 23:15:10 -0800 Subject: [PATCH 2/2] Allow the data groups survey questions to be optional --- .../UI/Model/APCDataGroupsManager.h | 1 - .../UI/Model/APCDataGroupsManager.m | 16 ++++- .../APCDataGroupsManagerTests.m | 60 +++++++++++++++++-- 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.h b/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.h index 4e3b7b0d..a09ad8e2 100644 --- a/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.h +++ b/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.h @@ -67,7 +67,6 @@ extern NSString * const APCDataGroupsStepIdentifier; - (void)setSurveyAnswerWithStepResult:(ORKStepResult *)result; - (void)setSurveyAnswerWithIdentifier:(NSString*)identifier selectedIndices:(NSArray*)selectedIndices; - @end NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.m b/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.m index e235796f..b8fb7fab 100644 --- a/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.m +++ b/APCAppCore/APCAppCore/UI/Model/APCDataGroupsManager.m @@ -44,8 +44,9 @@ NSString * const APCDataGroupsMappingSurveyDetailKey = @"detail"; NSString * const APCDataGroupsMappingSurveyQuestionIdentifierKey = @"identifier"; NSString * const APCDataGroupsMappingSurveyQuestionTypeKey = @"type"; -NSString * const APCDataGroupsMappingSurveyQuestionPromptKey = @"prompt"; -NSString * const APCDataGroupsMappingSurveyQuestionProfileCaptionKey = @"profileCaption"; +NSString * const APCDataGroupsMappingSurveyQuestionPromptKey = @"text"; +NSString * const APCDataGroupsMappingSurveyQuestionProfileCaptionKey = @"shortText"; +NSString * const APCDataGroupsMappingSurveyQuestionOptionalKey = @"optional"; NSString * const APCDataGroupsMappingSurveyQuestionValueMapKey = @"valueMap"; NSString * const APCDataGroupsMappingSurveyQuestionTypeBoolean = @"boolean"; NSString * const APCDataGroupsMappingSurveyQuestionValueMapValueKey = @"value"; @@ -139,9 +140,18 @@ - (ORKFormStep *)surveyStep { // Add the questions from the mapping NSMutableArray *formItems = [NSMutableArray new]; for (NSDictionary *question in questions) { + + // Get the default choices and add the skip choice if this question is optional + NSArray *textChoices = [self choicesForQuestion:question]; + if ([question[APCDataGroupsMappingSurveyQuestionOptionalKey] boolValue]) { + ORKTextChoice *skipChoice = [ORKTextChoice choiceWithText:NSLocalizedStringWithDefaultValue(@"APC_SKIP_CHOICE", @"APCAppCore", APCBundle(), @"Prefer not to answer", @"Choice text for skipping a question") value:@(NSNotFound)]; + textChoices = [textChoices arrayByAddingObject:skipChoice]; + } + ORKAnswerFormat *format = [ORKTextChoiceAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice - textChoices:[self choicesForQuestion:question]]; + textChoices:textChoices]; + NSString *text = !useQuestionPrompt ? question[APCDataGroupsMappingSurveyQuestionPromptKey] : nil; ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:question[APCDataGroupsMappingSurveyQuestionIdentifierKey] text:text diff --git a/APCAppCore/APCAppCoreTests/APCDataGroupsManagerTests.m b/APCAppCore/APCAppCoreTests/APCDataGroupsManagerTests.m index 523890cc..7b40313d 100644 --- a/APCAppCore/APCAppCoreTests/APCDataGroupsManagerTests.m +++ b/APCAppCore/APCAppCoreTests/APCDataGroupsManagerTests.m @@ -158,7 +158,7 @@ - (void)testSetSurveyAnswer_NoChange XCTAssertFalse(manager.hasChanges); } -- (void)testSurveySteps +- (void)testSurveySteps_NotOptional { APCDataGroupsManager * manager = [self createDataGroupsManagerWithDataGroups:nil]; @@ -167,7 +167,7 @@ - (void)testSurveySteps XCTAssertNotNil(step); XCTAssertFalse(step.optional); XCTAssertEqualObjects(step.title, @"Are you in Control?"); - XCTAssertEqualObjects(step.text, @"Engineers and scientists like classifications. To help us better classify you, please answer these required questions."); + XCTAssertEqualObjects(step.text, @"Engineers and scientists like classifications. To help us better classify you, please answer this question."); XCTAssertEqual(step.formItems.count, 1); ORKFormItem *item = step.formItems.firstObject; @@ -184,6 +184,33 @@ - (void)testSurveySteps XCTAssertEqualObjects(answerFormat.textChoices, expectedChoices); } +- (void)testSurveySteps_Optional +{ + APCDataGroupsManager * manager = [self createDataGroupsManagerWithDataGroups:nil required:NO questionOptional:YES]; + + ORKFormStep * step = [manager surveyStep]; + + XCTAssertNotNil(step); + XCTAssertFalse(step.optional); + XCTAssertEqualObjects(step.title, @"Are you in Control?"); + XCTAssertEqualObjects(step.text, @"Engineers and scientists like classifications. To help us better classify you, please answer this question."); + + XCTAssertEqual(step.formItems.count, 1); + ORKFormItem *item = step.formItems.firstObject; + XCTAssertEqualObjects(item.identifier, @"control_question"); + XCTAssertEqualObjects(item.text, @"Have you ever been diagnosed with XYZ?"); + + ORKTextChoiceAnswerFormat *answerFormat = (ORKTextChoiceAnswerFormat *)item.answerFormat; + XCTAssertTrue([answerFormat isKindOfClass:[ORKTextChoiceAnswerFormat class]]); + XCTAssertEqual(answerFormat.style, ORKChoiceAnswerStyleSingleChoice); + + NSArray *expectedChoices = @[[ORKTextChoice choiceWithText:@"Yes" value:@YES], + [ORKTextChoice choiceWithText:@"No" value:@NO], + [ORKTextChoice choiceWithText:@"Prefer not to answer" value:@(NSNotFound)]]; + XCTAssertEqual(answerFormat.textChoices.count, expectedChoices.count); + XCTAssertEqualObjects(answerFormat.textChoices, expectedChoices); +} + - (void)testSetSurveyAnswerWithStepResult_StudyA { APCDataGroupsManager * manager = [self createDataGroupsManagerWithDataGroups:nil]; @@ -220,9 +247,31 @@ - (void)testSetSurveyAnswerWithStepResult_Control XCTAssertEqualObjects(actualGroup, @"control"); } +- (void)testSetSurveyAnswerWithStepResult_Skipped +{ + APCDataGroupsManager * manager = [self createDataGroupsManagerWithDataGroups:nil required:NO questionOptional:YES]; + + // Change the survey answer + ORKChoiceQuestionResult *result = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"control_question"]; + result.choiceAnswers = @[@(NSNotFound)]; + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:APCDataGroupsStepIdentifier results:@[result]]; + + [manager setSurveyAnswerWithStepResult:stepResult]; + + // For a skipped question, the data groups are *not* set to anything + XCTAssertEqual(manager.dataGroups.count, 0); + XCTAssertFalse(manager.hasChanges); + +} + #pragma mark - heper methods - (APCDataGroupsManager*)createDataGroupsManagerWithDataGroups:(NSArray*)dataGroups { + return [self createDataGroupsManagerWithDataGroups:dataGroups required:YES questionOptional:NO]; +} + +- (APCDataGroupsManager*)createDataGroupsManagerWithDataGroups:(NSArray*)dataGroups required:(BOOL)required questionOptional:(BOOL)questionOptional { + NSDictionary *mapping = @{ @"items": @[@{ @"group_name" : @"control", @@ -235,15 +284,16 @@ - (APCDataGroupsManager*)createDataGroupsManagerWithDataGroups:(NSArray*)dataGro @"is_control_group" : @(false), } ], - @"required": @(true), + @"required": @(required), @"title": @"Are you in Control?", - @"detail": @"Engineers and scientists like classifications. To help us better classify you, please answer these required questions.", + @"detail": @"Engineers and scientists like classifications. To help us better classify you, please answer this question.", @"questions": @[ @{ @"identifier": @"control_question", - @"prompt": @"Have you ever been diagnosed with XYZ?", + @"text": @"Have you ever been diagnosed with XYZ?", @"type": @"boolean", + @"optional": @(questionOptional), @"valueMap": @[@{ @"value" : @YES, @"groups" : @[@"studyA"]}, @{ @"value" : @NO,