def test_is_section_complete(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s3", "list_item_id": "abc123", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s4", "list_item_id": "123abc", "status": CompletionStatus.COMPLETED, "block_ids": ["not-three"], }, ] store = ProgressStore(completed) assert store.is_section_complete(section_id="s1", list_item_id=None) is True assert store.is_section_complete(section_id="s4", list_item_id="123abc") is True
def _deserialise(self, data): json_data = json.loads(data, use_decimal=True) self.progress_store = ProgressStore(json_data.get("PROGRESS")) self.set_metadata(json_data.get("METADATA", {})) self.answer_store = AnswerStore(json_data.get("ANSWERS")) self.list_store = ListStore.deserialise(json_data.get("LISTS")) self.collection_metadata = json_data.get("COLLECTION_METADATA", {})
def test_update_section_status(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.COMPLETED, "block_ids": ["three"], }, ] store = ProgressStore(completed) store.update_section_status( section_status=CompletionStatus.IN_PROGRESS, section_id="s1" ) store.update_section_status( section_status=CompletionStatus.IN_PROGRESS, section_id="s2", list_item_id="abc123", ) assert store.get_section_status(section_id="s1") == CompletionStatus.IN_PROGRESS assert ( store.get_section_status(section_id="s2", list_item_id="abc123") == CompletionStatus.IN_PROGRESS ) assert store.is_dirty
def test_remove_final_completed_location_removes_section(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.COMPLETED, "block_ids": ["three"], }, ] store = ProgressStore(completed) non_repeating_location = Location(section_id="s1", block_id="one") repeating_location = Location( section_id="s2", block_id="three", list_name="people", list_item_id="abc123" ) store.remove_completed_location(non_repeating_location) store.remove_completed_location(repeating_location) assert ("s1", None) not in store assert store.get_completed_block_ids(section_id="s1") == [] assert ("s2", "abc123") not in store assert store.get_completed_block_ids(section_id="s1", list_item_id="abc123") == [] assert store.is_dirty
def test_context_for_driving_question_summary_empty_list(): schema = load_schema_from_name("test_list_collector_driving_question") current_location = Location(block_id="summary", section_id="section") list_collector_summary_context = ListCollectorSummaryContext( DEFAULT_LANGUAGE_CODE, schema, AnswerStore([{"answer_id": "anyone-usually-live-at-answer", "value": "No"}]), ListStore(), ProgressStore(), {}, ) context = list_collector_summary_context.get_list_summaries(current_location) expected = [ { "add_link": "/questionnaire/anyone-usually-live-at/", "add_link_text": "Add someone to this household", "empty_list_text": "There are no householders", "title": "Household members", "list_name": "people", } ] assert context == expected
def setUp(self): super().setUp() self.schema = load_schema_from_name("test_section_summary") self.answer_store = AnswerStore() self.list_store = ListStore() self.progress_store = ProgressStore() self.block_type = "SectionSummary"
def test_routing_path_with_repeating_sections(self): schema = load_schema_from_name("test_repeating_sections_with_hub_and_spoke") progress_store = ProgressStore( [ { "section_id": "section", "status": CompletionStatus.COMPLETED, "block_ids": [ "primary-person-list-collector", "list-collector", "next-interstitial", "another-list-collector-block", ], } ] ) path_finder = PathFinder( schema, self.answer_store, self.list_store, progress_store, self.metadata ) repeating_section_id = "personal-details-section" routing_path = path_finder.routing_path( section_id=repeating_section_id, list_item_id="abc123" ) expected_path = RoutingPath( ["proxy", "date-of-birth", "confirm-dob", "sex", "personal-summary"], section_id="personal-details-section", list_name="people", list_item_id="abc123", ) self.assertEqual(routing_path, expected_path)
def test_routing_path_empty_routing_rules(self): schema = load_schema_from_name("test_checkbox") section_id = schema.get_section_id_for_block_id("mandatory-checkbox") expected_path = RoutingPath( ["mandatory-checkbox", "non-mandatory-checkbox", "summary"], section_id="default-section", ) answer_1 = Answer(answer_id="mandatory-checkbox-answer", value="Cheese") answer_2 = Answer(answer_id="non-mandatory-checkbox-answer", value="deep pan") answer_store = AnswerStore() answer_store.add_or_update(answer_1) answer_store.add_or_update(answer_2) progress_store = ProgressStore( [ { "section_id": "default-section", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["mandatory-checkbox"], } ] ) path_finder = PathFinder( schema, answer_store, self.list_store, progress_store, self.metadata ) routing_path = path_finder.routing_path(section_id=section_id) self.assertEqual(routing_path, expected_path)
def test_routing_path_with_conditional_path(self): schema = load_schema_from_name("test_routing_number_equals") section_id = schema.get_section_id_for_block_id("number-question") expected_path = RoutingPath( ["number-question", "correct-answer", "summary"], section_id="default-section", ) answer = Answer(answer_id="answer", value=123) answer_store = AnswerStore() answer_store.add_or_update(answer) progress_store = ProgressStore( [ { "section_id": "default-section", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["number-question"], } ] ) path_finder = PathFinder( schema, answer_store, self.list_store, progress_store, self.metadata ) routing_path = path_finder.routing_path(section_id=section_id) self.assertEqual(routing_path, expected_path)
def test_get_first_incomplete_location_in_section(self): schema = load_schema_from_name("test_section_summary") progress_store = ProgressStore([{ "section_id": "property-details-section", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["insurance-type"], }]) router = Router(schema, self.answer_store, self.list_store, progress_store, self.metadata) section_routing_path = RoutingPath( ["insurance-type", "insurance-address"], section_id="property-details-section", ) incomplete = router.get_first_incomplete_location_for_section( routing_path=section_routing_path) self.assertEqual( incomplete, Location(section_id="property-details-section", block_id="insurance-address"), )
def __init__(self, storage, version=None): self._storage = storage if version is None: version = self.get_latest_version_number() self.version = version self._metadata = {} # self.metadata is a read-only view over self._metadata self.metadata = MappingProxyType(self._metadata) self.collection_metadata = {} self.list_store = ListStore() self.answer_store = AnswerStore() self.progress_store = ProgressStore() raw_data, version = self._storage.get_user_data() if raw_data: self._deserialise(raw_data) if version is not None: self.version = version
def get_view_submission(schema): session_data = get_session_store().session_data if _is_submission_viewable(schema.json, session_data.submitted_time): submitted_data = current_app.eq["storage"].get_by_key( SubmittedResponse, session_data.tx_id ) if submitted_data: metadata_context = build_metadata_context_for_survey_completed(session_data) pepper = current_app.eq["secret_store"].get_secret_by_name( "EQ_SERVER_SIDE_STORAGE_ENCRYPTION_USER_PEPPER" ) encrypter = StorageEncryption( current_user.user_id, current_user.user_ik, pepper ) submitted_data = encrypter.decrypt_data(submitted_data.data) # for backwards compatibility # submitted data used to be base64 encoded before encryption try: submitted_data = base64url_decode(submitted_data.decode()).decode() except ValueError: pass submitted_data = json.loads(submitted_data) answer_store = AnswerStore(submitted_data.get("answers")) list_store = ListStore(submitted_data.get("lists")) progress_store = ProgressStore(submitted_data.get("progress")) metadata = submitted_data.get("metadata") language_code = get_session_store().session_data.language_code questionnaire_summary_context = QuestionnaireSummaryContext( language_code, schema, answer_store, list_store, progress_store, metadata, ) context = questionnaire_summary_context(answers_are_editable=False) return render_template( template="view-submission", metadata=metadata_context, content=context, survey_id=schema.json["survey_id"], ) return redirect(url_for("post_submission.get_thank_you"))
def test_clear(): in_progress_sections = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.COMPLETED, "block_ids": ["three", "four"], }, ] store = ProgressStore(in_progress_sections) store.clear() assert store.serialise() == [] assert store.is_dirty
def test_in_progress_and_completed_section_ids(section_ids, expected_section_keys): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s3", "list_item_id": "abc123", "status": CompletionStatus.NOT_STARTED, "block_ids": ["three"], }, { "section_id": "s4", "list_item_id": "123abc", "status": CompletionStatus.COMPLETED, "block_ids": ["not-three"], }, { "section_id": "s5", "list_item_id": "456def", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["not-three"], }, ] store = ProgressStore(completed) statuses = {CompletionStatus.COMPLETED, CompletionStatus.IN_PROGRESS} section_keys = store.section_keys(section_ids=section_ids, statuses=statuses) assert sorted(section_keys) == expected_section_keys
def test_deserialisation(): in_progress_sections = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.COMPLETED, "block_ids": ["three", "four"], }, ] store = ProgressStore(in_progress_sections) assert store.get_section_status(section_id="s1") == CompletionStatus.IN_PROGRESS assert store.get_completed_block_ids("s1") == ["one", "two"] assert ( store.get_section_status(section_id="s2", list_item_id="abc123") == CompletionStatus.COMPLETED ) assert store.get_completed_block_ids(section_id="s2", list_item_id="abc123") == [ "three", "four", ]
def test_section_keys(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s3", "list_item_id": "abc123", "status": CompletionStatus.NOT_STARTED, "block_ids": ["three"], }, { "section_id": "s4", "list_item_id": "123abc", "status": CompletionStatus.COMPLETED, "block_ids": ["not-three"], }, { "section_id": "s5", "list_item_id": "456def", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["not-three"], }, ] store = ProgressStore(completed) section_keys = store.section_keys(section_ids={"s1", "s2", "s3"}) assert sorted(section_keys) == sorted( [("s1", None), ("s2", None), ("s3", "abc123")] )
def test_get_section_status(): existing_progress = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, ] store = ProgressStore(existing_progress) assert store.get_section_status(section_id="s1") == CompletionStatus.COMPLETED assert ( store.get_section_status(section_id="s2", list_item_id="abc123") == CompletionStatus.IN_PROGRESS )
def test_get_section_locations(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, ] store = ProgressStore(completed) assert store.get_completed_block_ids(section_id="s1") == ["one"] assert store.get_completed_block_ids(section_id="s2", list_item_id="abc123") == [ "three" ]
def test_questionnaire_store_updates_storage(self): # Given expected = get_basic_input() store = QuestionnaireStore(self.storage) store.set_metadata(expected["METADATA"]) store.answer_store = AnswerStore(expected["ANSWERS"]) store.collection_metadata = expected["COLLECTION_METADATA"] store.progress_store = ProgressStore(expected["PROGRESS"]) # When store.save() # See setUp - populates self.output_data # Then self.assertEqual(expected, json.loads(self.output_data))
def test_add_completed_location_new(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one"], }, { "section_id": "s2", "list_item_id": "abc123", "status": CompletionStatus.COMPLETED, "block_ids": ["three", "four"], }, ] store = ProgressStore(completed) non_repeating_location = Location(section_id="s1", block_id="two") repeating_location = Location( section_id="s2", block_id="five", list_name="people", list_item_id="abc123" ) store.add_completed_location(non_repeating_location) store.add_completed_location(repeating_location) assert store.get_section_status(section_id="s1") == CompletionStatus.COMPLETED assert ( store.get_section_status(section_id="s2", list_item_id="abc123") == CompletionStatus.COMPLETED ) assert len(store.get_completed_block_ids(section_id="s1")) == 2 assert ( len(store.get_completed_block_ids(section_id="s2", list_item_id="abc123")) == 3 ) assert store.is_dirty
def setUp(self): super().setUp() self.schema = load_schema_from_name("test_summary") self.answer_store = AnswerStore() self.list_store = ListStore() self.progress_store = ProgressStore() self.block_type = "Summary" self.rendered_block = { "parent_id": "summary-group", "id": "summary", "type": "Summary", "collapsible": True, } self.current_location = Location(section_id="default-section", block_id="summary")
def test_add_primary_person(self): list_store = fake_list_store() questionnaire_store = MagicMock( spec=QuestionnaireStore, completed_blocks=[], answer_store=self.answer_store, list_store=list_store, progress_store=ProgressStore(), ) questionnaire_store_updater = QuestionnaireStoreUpdater( self.location, self.schema, questionnaire_store, self.current_question ) questionnaire_store_updater.add_primary_person("people")
def test_is_survey_complete(self): schema = load_schema_from_name("test_textfield") progress_store = ProgressStore([{ "section_id": "default-section", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["name-block"], }]) router = Router(schema, self.answer_store, self.list_store, progress_store, self.metadata) is_survey_complete = router.is_survey_complete() self.assertTrue(is_survey_complete)
def test_questionnaire_store_errors_on_invalid_object(self): # Given class NotSerializable: pass non_serializable_metadata = {"test": NotSerializable()} expected = get_basic_input() store = QuestionnaireStore(self.storage) store.set_metadata(non_serializable_metadata) store.collection_metadata = expected["COLLECTION_METADATA"] store.answer_store = AnswerStore(expected["ANSWERS"]) store.progress_store = ProgressStore(expected["PROGRESS"]) # When / Then self.assertRaises(TypeError, store.save)
def test_context_for_driving_question_summary(): schema = load_schema_from_name("test_list_collector_driving_question") current_location = Location(block_id="summary", section_id="section") list_collector_summary_context = ListCollectorSummaryContext( DEFAULT_LANGUAGE_CODE, schema, AnswerStore( [ {"answer_id": "anyone-usually-live-at-answer", "value": "Yes"}, {"answer_id": "first-name", "value": "Toni", "list_item_id": "PlwgoG"}, { "answer_id": "last-name", "value": "Morrison", "list_item_id": "PlwgoG", }, ] ), ListStore([{"items": ["PlwgoG"], "name": "people"}]), ProgressStore(), {}, ) context = list_collector_summary_context.get_list_summaries(current_location) expected = [ { "add_link": "/questionnaire/people/add-person/?return_to=summary", "add_link_text": "Add someone to this household", "empty_list_text": "There are no householders", "list": { "list_items": [ { "edit_link": "/questionnaire/people/PlwgoG/edit-person/?return_to=summary", "item_title": "Toni Morrison", "primary_person": False, "remove_link": "/questionnaire/people/PlwgoG/remove-person/?return_to=summary", } ], "editable": True, }, "title": "Household members", "list_name": "people", } ] assert context == expected
def test_is_path_complete(self): schema = load_schema_from_name("test_textfield") progress_store = ProgressStore([{ "section_id": "default-section", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["name-block"], }]) router = Router(schema, self.answer_store, self.list_store, progress_store, self.metadata) routing_path = router.routing_path(section_id="default-section") is_path_complete = router.is_path_complete(routing_path) self.assertTrue(is_path_complete)
def test_questionnaire_store_deletes(self): # Given expected = get_basic_input() store = QuestionnaireStore(self.storage) store.set_metadata(expected["METADATA"]) store.collection_metadata = expected["COLLECTION_METADATA"] store.answer_store = AnswerStore(expected["ANSWERS"]) store.progress_store = ProgressStore(expected["PROGRESS"]) # When store.delete() # See setUp - populates self.output_data # Then self.assertNotIn("a-test-section", store.progress_store) self.assertEqual(store.metadata.copy(), {}) self.assertEqual(len(store.answer_store), 0) self.assertEqual(store.collection_metadata, {})
def test_context_for_driving_question_summary_empty_list(): schema = load_schema_from_name("test_list_collector_driving_question") current_location = Location(block_id="summary", section_id="section") summary_context = SectionSummaryContext( DEFAULT_LANGUAGE_CODE, schema, AnswerStore([{ "answer_id": "anyone-usually-live-at-answer", "value": "No" }]), ListStore(), ProgressStore(), {}, ) context = summary_context(current_location) expected = { "summary": { "answers_are_editable": True, "collapsible": False, "custom_summary": [{ "add_link": "/questionnaire/anyone-usually-live-at/?return_to=summary", "add_link_text": "Add someone to this household", "empty_list_text": "There are no householders", "list": { "editable": True, "list_items": [] }, "title": "Household members", "list_name": "people", "type": "List", }], "summary_type": "SectionSummary", "title": "List Collector Driving Question Summary", } } assert context == expected
def test_remove_progress_for_list_item_id(): completed = [ { "section_id": "s1", "list_item_id": None, "status": CompletionStatus.COMPLETED, "block_ids": ["one", "two"], }, { "section_id": "s2", "list_item_id": None, "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s3", "list_item_id": "abc123", "status": CompletionStatus.IN_PROGRESS, "block_ids": ["three"], }, { "section_id": "s4", "list_item_id": "123abc", "status": CompletionStatus.COMPLETED, "block_ids": ["not-three"], }, ] store = ProgressStore(completed) store.remove_progress_for_list_item_id(list_item_id="abc123") assert ("s3", "abc123") not in store assert store.get_completed_block_ids(section_id="s3", list_item_id="abc123") == [] assert ("s4", "123abc") in store store.remove_progress_for_list_item_id(list_item_id="123abc") assert ("s4", "123abc") not in store assert store.get_completed_block_ids(section_id="s4", list_item_id="123abc") == []
def test_add_completed_location(): store = ProgressStore() non_repeating_location = Location(section_id="s1", block_id="one") repeating_location = Location( section_id="s2", block_id="another-one", list_name="people", list_item_id="abc123", ) store.add_completed_location(non_repeating_location) store.add_completed_location(repeating_location) assert store.get_completed_block_ids(section_id="s1") == [ non_repeating_location.block_id ] assert store.get_completed_block_ids(section_id="s2", list_item_id="abc123") == [ repeating_location.block_id ] assert store.is_dirty