def _question_graph_with_decision_null_retrieval_keys(): q1 = QuestionFactory.create( retrieval_key=None, short_label='Yes or no?', label='Yes or no, what do you choose?', ) q_yes = QuestionFactory.create(retrieval_key=None, short_label='yes', label='The yes question. Happy now?') q_no = QuestionFactory.create(retrieval_key=None, short_label='no', label='The no question. Still unhappy?') graph = QuestionGraphFactory.create( name='Graph with decision and null keys', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q_yes, choice__payload='yes', choice__question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q_no, choice__payload='no', choice__question=q1) return graph
def _get_questionnaire(self): q1 = QuestionFactory.create(analysis_key='q1', label='q1', short_label='q1') choice1_q2 = ChoiceFactory(question=q1, payload='q2', display='q2') choice1_q3 = ChoiceFactory(question=q1, payload='q3', display='q3') q2 = QuestionFactory.create(analysis_key='q2', label='q2', short_label='q2') q3 = QuestionFactory.create(analysis_key='q3', label='q3', short_label='q3') q4 = QuestionFactory.create(analysis_key='q4', label='q4', short_label='q4', required=True) q5 = QuestionFactory.create(analysis_key='q5', label='q5', short_label='q5') # sketch: # q1 <- first_question # / \ # q2 q3 # \ / # q4 # | # q5 graph = QuestionGraphFactory.create(name='testgraph', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice=choice1_q2) EdgeFactory.create(graph=graph, question=q2, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q1, next_question=q3, choice=choice1_q3) EdgeFactory.create(graph=graph, question=q3, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q4, next_question=q5, choice=None) return QuestionnaireFactory.create(graph=graph, name='diamond', flow=Questionnaire.EXTRA_PROPERTIES)
def _question_graph_with_decision_with_default(): q1 = QuestionFactory.create( retrieval_key='q_yesno', short_label='Yes or no?', label='Yes or no, what do you choose?', ) q_yes = QuestionFactory.create(retrieval_key='q_yes', short_label='yes', label='The yes question. Happy now?') q_no = QuestionFactory.create(retrieval_key='q_no', short_label='no', label='The no question. Still unhappy?') graph = QuestionGraphFactory.create( name='Graph with decision with default', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q_yes, choice__payload='yes', choice__question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q_no, choice__payload='no', choice__question=q1) # Default option, last edge without choice property: EdgeFactory.create(graph=graph, question=q1, next_question=q_yes, choice=None) return graph
def _create_graph_no_defaults(graph_name='diamond'): """ Seed the database with a diamond shaped graph formed by questions. """ q1 = QuestionFactory.create() q2 = QuestionFactory.create() q3 = QuestionFactory.create() # sketch: # q1 <- first_question # / \ # q2 q3 graph = QuestionGraphFactory.create(name=graph_name, first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice__payload='yes', choice__question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q3, choice__payload='no', choice__question=q1) return graph
def create_diamond(graph_name='diamond'): """ Seed the database with a diamond shaped graph formed by questions. """ q1 = QuestionFactory.create(analysis_key='q1') q2 = QuestionFactory.create(analysis_key='q2') q3 = QuestionFactory.create(analysis_key='q3') q4 = QuestionFactory.create(analysis_key='q4') q5 = QuestionFactory.create(analysis_key='q5') # sketch: # q1 <- first_question # / \ # q2 q3 # \ / # q4 # | # q5 graph = QuestionGraphFactory.create(name=graph_name, first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice=None) EdgeFactory.create(graph=graph, question=q2, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q1, next_question=q3, choice=None) EdgeFactory.create(graph=graph, question=q3, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q4, next_question=q5, choice=None) return graph
def setUp(self): q1 = QuestionFactory.create(field_type='plain_text') self.graph = QuestionGraphFactory.create(name='info_trigger_order', first_question=q1) choice_payloads = ['one', 'two', 'three'] for payload in choice_payloads: ChoiceFactory.create(question=q1, payload=payload)
def _question_graph_one_question(): q1 = QuestionFactory.create( retrieval_key='only', short_label='Only question.', label='Only question.', ) return QuestionGraphFactory.create(name='Graph with only one question', first_question=q1)
def setUp(self): q1 = QuestionFactory.create(field_type='plain_text') self.graph = QuestionGraphFactory.create(name='trigger_order', first_question=q1) trigger_payloads = ['one', 'two', 'three'] for payload in trigger_payloads: TriggerFactory.create(graph=self.graph, question=q1, payload=payload)
def create_too_many_questions(graph_name='too_many'): questions = [QuestionFactory.create() for i in range(100) ] # TODO: make MAX_QUESTIONS an app setting graph = QuestionGraphFactory.create(name=graph_name, first_question=questions[0]) for i in range(len(questions) - 1): EdgeFactory.create(graph=graph, question=questions[i], next_question=questions[i + 1], choice=None) return graph
def create_cycle(graph_name='cycle'): q1 = QuestionFactory.create(analysis_key='q1') q2 = QuestionFactory.create(analysis_key='q2') # sketch: # q1 <- first_question # ( ) # q2 graph = QuestionGraphFactory.create(name=graph_name, first_question=q1) EdgeFactory(graph=graph, question=q1, next_question=q2, choice=None) EdgeFactory(graph=graph, question=q2, next_question=q1, choice=None) return graph
def setUp(self): self.question = QuestionFactory.create() graph = QuestionGraphFactory.create(first_question=self.question) self.questionnaire = QuestionnaireFactory.create(graph=graph) self.detail_schema = self.load_json_schema( os.path.join(THIS_DIR, '../../json_schema/public_get_question_detail.json') ) self.list_schema = self.load_json_schema( os.path.join(THIS_DIR, '../../json_schema/public_get_question_list.json') ) self.post_answer_schema = self.load_json_schema( os.path.join(THIS_DIR, '../../json_schema/public_post_question_answer_response.json') )
def setUp(self): # sketch: # q1 <- first question (PlainText) # | # q2 <- second question (Image) self.q1 = QuestionFactory.create(analysis_key='q1', label='q1', short_label='q1', required=True) self.q2 = QuestionFactory.create(analysis_key='q2', label='q2', short_label='q2', field_type='image', required=True) graph = QuestionGraphFactory.create(name='testgraph', first_question=self.q1) EdgeFactory.create(graph=graph, question=self.q1, next_question=self.q2) self.questionnaire = QuestionnaireFactory.create(graph=graph, name='test', flow=Questionnaire.EXTRA_PROPERTIES) self.session = SessionFactory(questionnaire=self.questionnaire, submit_before=None, duration=None, frozen=False)
def create_disconnected(graph_name='disconnected'): q1 = QuestionFactory.create(analysis_key='q1') q2 = QuestionFactory.create(analysis_key='q2') q3 = QuestionFactory.create(analysis_key='q3') # sketch: # q1 <- first_question # # q2 # | # q3 graph = QuestionGraphFactory.create(name=graph_name, first_question=q1) EdgeFactory.create(graph=graph, question=q2, next_question=q3, choice=None) return graph
def _question_graph_with_cycle(): q1 = QuestionFactory.create( retrieval_key='one', short_label='First question.', label='First question.', ) q2 = QuestionFactory.create( retrieval_key='two', short_label='Second question.', label='Second question.', ) graph = QuestionGraphFactory.create(name='Graph with cycle', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice=None) EdgeFactory.create(graph=graph, question=q2, next_question=q1, choice=None) return graph
def _question_graph_no_required_answers(): q1 = QuestionFactory.create( retrieval_key='one', required=False, short_label='First not required', label='First not required', ) q2 = QuestionFactory( retrieval_key='two', required=False, short_label='Second not required', label='Second not required', ) graph = QuestionGraphFactory.create( name='Graph with questions that are not required.', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice=None) return graph
def test_create_session_for_questionnaire(self): q1 = QuestionFactory.create(analysis_key='q1', label='q1', short_label='q1') choice1_q2 = ChoiceFactory(question=q1, payload='q2', display='q2') choice1_q3 = ChoiceFactory(question=q1, payload='q3', display='q3') q2 = QuestionFactory.create(analysis_key='q2', label='q2', short_label='q2') q3 = QuestionFactory.create(analysis_key='q3', label='q3', short_label='q3') q4 = QuestionFactory.create(analysis_key='q4', label='q4', short_label='q4', required=True) q5 = QuestionFactory.create(analysis_key='q5', label='q5', short_label='q5') # sketch: # q1 <- first_question # / \ # q2 q3 # \ / # q4 # | # q5 graph = QuestionGraphFactory.create(name='testgraph', first_question=q1) EdgeFactory.create(graph=graph, question=q1, next_question=q2, choice=choice1_q2) EdgeFactory.create(graph=graph, question=q2, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q1, next_question=q3, choice=choice1_q3) EdgeFactory.create(graph=graph, question=q3, next_question=q4, choice=None) EdgeFactory.create(graph=graph, question=q4, next_question=q5, choice=None) questionnaire = QuestionnaireFactory.create(graph=graph, name='diamond', flow=Questionnaire.EXTRA_PROPERTIES) response = self.client.post(f'{self.base_endpoint}{questionnaire.uuid}/session', data=None, format='json') self.assertEqual(response.status_code, 201) response_json = response.json() self.assertIn('path_questions', response_json) self.assertEqual(len(response_json['path_questions']), 1) self.assertIn('path_answered_question_uuids', response_json) self.assertEqual(len(response_json['path_answered_question_uuids']), 0) self.assertIn('path_unanswered_question_uuids', response_json) self.assertEqual(len(response_json['path_unanswered_question_uuids']), 1) self.assertIn('path_validation_errors_by_uuid', response_json) self.assertEqual(len(response_json['path_validation_errors_by_uuid']), 0) self.assertIn('can_freeze', response_json) self.assertEqual(response_json['can_freeze'], False)
def test_handle_frozen_session_on_commit_triggered(self): question = QuestionFactory.create( field_type='plain_text', label='Is het goed weer?', short_label='Goed weer?', analysis_key='reaction', ) graph = QuestionGraphFactory.create(name='Reactie gevraagd.', first_question=question) session = SessionFactory.create( questionnaire__flow=Questionnaire.REACTION_REQUEST, questionnaire__graph=graph, frozen=False, _signal=self.signal_reaction_requested ) answer = AnswerFactory(session=session, payload='Het antwoord!') service = get_session_service(session.uuid) self.assertIsInstance(service, ReactionRequestSessionService) service.freeze() self.signal_reaction_requested.refresh_from_db() self.assertEqual(self.signal_reaction_requested.status.state, workflow.REACTIE_ONTVANGEN) self.assertEqual(self.signal_reaction_requested.status.text, answer.payload)
def setUp(self): # q1 # / | \ # q2 q3 q4 q1 = QuestionFactory.create() q2 = QuestionFactory.create() q3 = QuestionFactory.create() q4 = QuestionFactory.create() self.graph = QuestionGraphFactory.create(name='edge_order', first_question=q1) EdgeFactory.create(graph=self.graph, question=q1, next_question=q2, choice=None) EdgeFactory.create(graph=self.graph, question=q1, next_question=q3, choice=None) EdgeFactory.create(graph=self.graph, question=q1, next_question=q4, choice=None)
def test_get_next_question_private(self): q_start = QuestionFactory.create(retrieval_key='start', field_type='plain_text') # No next rules: empty_graph = QuestionGraphFactory.create(first_question=q_start) session = SessionFactory.create(questionnaire__graph=empty_graph) session_service = get_session_service(session.uuid) session_service.refresh_from_db() next_q = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'ANSWER') self.assertIsNone(next_q) # Unconditional next: q2 = QuestionFactory.create() unconditional_graph = QuestionGraphFactory.create( first_question=q_start) EdgeFactory(graph=unconditional_graph, question=q_start, next_question=q2, choice=None) session = SessionFactory.create( questionnaire__graph=unconditional_graph) session_service = get_session_service(session.uuid) session_service.refresh_from_db() next_q = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'ANSWER') self.assertEqual(next_q, q2) # Conditional next, no default option: q_no = QuestionFactory.create(retrieval_key='NO') q_yes = QuestionFactory.create(retrieval_key='YES') conditional_graph = QuestionGraphFactory.create(first_question=q_start) EdgeFactory(graph=conditional_graph, question=q_start, next_question=q_no, choice__payload='no', choice__question=q_start) EdgeFactory(graph=conditional_graph, question=q_start, next_question=q_yes, choice__payload='yes', choice__question=q_start) session = SessionFactory.create(questionnaire__graph=conditional_graph) session_service = get_session_service(session.uuid) session_service.refresh_from_db() no_choice_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'ANSWER') self.assertIsNone( no_choice_question) # consider whether this is useful yes_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'yes') self.assertEqual(q_yes, yes_question) no_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'no') self.assertEqual(q_no, no_question) # Conditional next with default option defined: q_default = QuestionFactory.create(retrieval_key='DEFAULT') conditional_with_default_graph = QuestionGraphFactory.create( first_question=q_start) EdgeFactory(graph=conditional_with_default_graph, question=q_start, next_question=q_no, choice__payload='no', choice__question=q_start) EdgeFactory(graph=conditional_with_default_graph, question=q_start, next_question=q_yes, choice__payload='yes', choice__question=q_start) EdgeFactory(graph=conditional_with_default_graph, question=q_start, next_question=q_default, choice=None) session = SessionFactory.create( questionnaire__graph=conditional_with_default_graph) session_service = get_session_service(session.uuid) session_service.refresh_from_db() no_choice_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'ANSWER') self.assertEqual(no_choice_question, q_default) yes_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'yes') self.assertEqual(yes_question, q_yes) no_question = session_service._get_next_question( session_service.question_graph_service._nx_graph, session_service.question_graph_service._questions_by_id, q_start, 'no') self.assertEqual(no_question, q_no)
def test_answer_a_complete_questionnaire(self): self.assertEqual(0, Answer.objects.count()) self.assertEqual(0, Session.objects.count()) # Setup questions test_question_1 = QuestionFactory(retrieval_key='test-question-1') test_question_2 = QuestionFactory(retrieval_key='test-question-2') test_question_3 = QuestionFactory(retrieval_key='test-question-3') test_question_4 = QuestionFactory(retrieval_key='test-question-4') test_question_5 = QuestionFactory(retrieval_key='test-question-5') # Setup graph relations between questions graph = QuestionGraphFactory.create(first_question=test_question_1) EdgeFactory.create(graph=graph, question=test_question_1, next_question=test_question_2, choice=None) EdgeFactory.create(graph=graph, question=test_question_2, next_question=test_question_3, choice=None) EdgeFactory.create(graph=graph, question=test_question_3, next_question=test_question_4, choice=None) EdgeFactory.create(graph=graph, question=test_question_4, next_question=test_question_5, choice=None) # Create our questionnaire questionnaire = QuestionnaireFactory.create(graph=graph) # Answer our questionnaire data = {'payload': 'answer-1', 'questionnaire': questionnaire.uuid} first_post_answer_endpoint = f'{self.base_endpoint}{questionnaire.first_question.uuid}/answer' response = self.client.post(first_post_answer_endpoint, data=data, format='json') self.assertEqual(response.status_code, 201) response_data = response.json() self.assertJsonSchema(self.post_answer_schema, response_data) self.assertIsNotNone(response_data['next_question']) self.assertEqual(1, Answer.objects.count()) self.assertEqual(1, Session.objects.count()) next_post_answer_endpoint = response_data['next_question']['_links']['sia:post-answer']['href'] session = Session.objects.first() for x in range(2, 6): data = {'payload': f'answer-{x}', 'session': session.uuid} response = self.client.post(next_post_answer_endpoint, data=data, format='json') self.assertEqual(response.status_code, 201) response_data = response.json() self.assertJsonSchema(self.post_answer_schema, response_data) self.assertEqual(x, Answer.objects.count()) self.assertEqual(1, Session.objects.count()) if x < 5: self.assertIsNotNone(response_data['next_question']) next_post_answer_endpoint = response_data['next_question']['_links']['sia:post-answer']['href'] else: self.assertIsNone(response_data['next_question']) # session must be frozen using ../submit endpoint answer_qs = Answer.objects.filter( question_id__in=[ questionnaire.graph.first_question.id, test_question_2.id, test_question_3.id, test_question_4.id, test_question_5.id, ], session_id=session.pk, ) self.assertTrue(answer_qs.exists()) self.assertEqual(5, answer_qs.count())
def create_one(graph_name='one'): q1 = QuestionFactory.create(analysis_key='q1') # sketch: # q1 <- first_question return QuestionGraphFactory.create(name=graph_name, first_question=q1)
def create_empty(graph_name='empty'): return QuestionGraphFactory.create(name=graph_name, first_question=None)
def test_answer_a_complete_questionnaire_branching_flow(self): self.assertEqual(0, Answer.objects.count()) self.assertEqual(0, Session.objects.count()) # Setup questions test_question_1 = QuestionFactory(retrieval_key='test-question-1') test_question_2 = QuestionFactory(retrieval_key='test-question-2') test_question_3 = QuestionFactory(retrieval_key='test-question-3') test_question_4 = QuestionFactory(retrieval_key='test-question-4') # Setup graph relations between questions graph = QuestionGraphFactory.create(first_question=test_question_1) EdgeFactory.create(graph=graph, question=test_question_1, next_question=test_question_2, choice__payload='yes', choice__question=test_question_1) EdgeFactory.create(graph=graph, question=test_question_1, next_question=test_question_3, choice__payload='no', choice__question=test_question_1) EdgeFactory.create(graph=graph, question=test_question_1, next_question=test_question_4, choice=None) # Create our questionnaire questionnaire = QuestionnaireFactory.create(graph=graph) # Answer our questionnaire first_post_answer_endpoint = f'{self.base_endpoint}{questionnaire.first_question.uuid}/answer' # Flow: question 1 -> question 2 -> done data = {'payload': 'yes', 'questionnaire': questionnaire.uuid} response = self.client.post(first_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertEqual(response_data['next_question']['uuid'], str(test_question_2.uuid)) data = {'payload': 'test', 'session': response_data['session']} second_post_answer_endpoint = response_data['next_question']['_links']['sia:post-answer']['href'] response = self.client.post(second_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertIsNone(response_data['next_question']) # Flow: question 1 -> question 3 -> done data = {'payload': 'no', 'questionnaire': questionnaire.uuid} response = self.client.post(first_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertEqual(response_data['next_question']['uuid'], str(test_question_3.uuid)) data = {'payload': 'test', 'session': response_data['session']} response = self.client.post(second_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertIsNone(response_data['next_question']) # Flow: question 1 -> question 4 -> done data = {'payload': 'default', 'questionnaire': questionnaire.uuid} response = self.client.post(first_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertEqual(response_data['next_question']['uuid'], str(test_question_4.uuid)) data = {'payload': 'test', 'session': response_data['session']} second_post_answer_endpoint = response_data['next_question']['_links']['sia:post-answer']['href'] response = self.client.post(second_post_answer_endpoint, data=data, format='json') response_data = response.json() self.assertEqual(response.status_code, 201) self.assertIsNone(response_data['next_question']) self.assertEqual(3, Session.objects.count()) self.assertEqual(6, Answer.objects.count())