def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data, self.domain) expected_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" restore_payload = generate_restore_payload( project=Domain(name=self.domain), user=dummy_user(), items=True, version=V3 ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def test_conflicting_ids(self): """ If a form and a case share an ID it's a conflict """ xml_data = self.get_xml('id_conflicts') with self.assertRaises(BulkSaveError): FormProcessorInterface.submit_form_locally(xml_data)
def test_cant_own_case(self): _, _, [case] = FormProcessorInterface.submit_form_locally(ALICE_XML, ALICE_DOMAIN) response, form, cases = FormProcessorInterface.submit_form_locally(EVE_XML, EVE_DOMAIN) self.assertIn('IllegalCaseId', response.content) self.assertFalse(hasattr(FormProcessorInterface.get_case(case.id), 'plan_to_buy_gun')) FormProcessorInterface.submit_form_locally(ALICE_UPDATE_XML, ALICE_DOMAIN) self.assertEqual(FormProcessorInterface.get_case(case.id).plan_to_buy_gun, 'no')
def testTopLevelExclusion(self): """ Entire forms tagged as device logs should be excluded """ file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual(0, get_total_case_count())
def testDuplicateCasePropertiesBug(self): """ Submit multiple values for the same property in an update block """ xml_data = self.get_xml('duplicate_case_properties') response, form, [case] = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual("", case.foo) xml_data = self.get_xml('duplicate_case_properties_2') response, form, [case] = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual("2", case.bar)
def testOutOfOrderSubmissions(self): dir = os.path.join(os.path.dirname(__file__), "data", "ordering") for fname in ('update_oo.xml', 'create_oo.xml'): with open(os.path.join(dir, fname), "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data) case = FormProcessorInterface.get_case('30bc51f6-3247-4966-b4ae-994f572e85fe') self.assertEqual('from the update form', case.pupdate) self.assertEqual('from the create form', case.pcreate) self.assertEqual('overridden by the update form', case.pboth)
def testCasesInRepeats(self): file_path = os.path.join(os.path.dirname(__file__), "data", "multicase", "case_in_repeats.xml") with open(file_path, "rb") as f: xml_data = f.read() _, form, cases = FormProcessorInterface.submit_form_locally(xml_data, domain=self.domain) self.assertEqual(3, len(cases)) self._check_ids(form, cases)
def test_empty_case_id(self): """ Ensure that form processor fails on empty id """ xml_data = self.get_xml('empty_id') response, form, cases = FormProcessorInterface.submit_form_locally(xml_data) self.assertIn('IllegalCaseId', response.content)
def testLotsOfSubcases(self): """ How do we do when submitting a form with multiple blocks for the same case? """ xml_data = self.get_xml('lots_of_subcases') response, form, cases = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual(11, len(cases))
def testNestedExclusion(self): """ Blocks inside forms tagged as device logs should be excluded """ file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "nested_device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() _, _, [case] = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual(1, get_total_case_count()) self.assertEqual("form case", case.name)
def testMultipleCaseBlocks(self): """ How do we do when submitting a form with multiple blocks for the same case? """ xml_data = self.get_xml('multiple_case_blocks') response, form, [case] = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual('1630005', case.community_code) self.assertEqual('SantaMariaCahabon', case.district_name) self.assertEqual('TAMERLO', case.community_name) ids = case.xform_ids self.assertEqual(1, len(ids)) self.assertEqual(form.id, ids[0])
def _test(custom_format_args): case_id = uuid.uuid4().hex format_args = { 'case_id': case_id, 'form_id': uuid.uuid4().hex, 'user_id': uuid.uuid4().hex, 'case_name': 'data corner cases', 'case_type': 'datatype-check', } format_args.update(custom_format_args) for filename in ['bugs_in_case_create_datatypes', 'bugs_in_case_update_datatypes']: xml_data = self.get_xml(filename).format(**format_args) response, form, [case] = FormProcessorInterface.submit_form_locally(xml_data) self.assertEqual(format_args['user_id'], case.user_id) self.assertEqual(format_args['case_name'], case.name) self.assertEqual(format_args['case_type'], case.type)
def bootstrap_case_from_xml(test_class, filename, case_id_override=None, domain=None): starttime = utcnow_sans_milliseconds() file_path = os.path.join(os.path.dirname(__file__), "data", filename) with open(file_path, "rb") as f: xml_data = f.read() updated_xml, uid, case_id = _replace_ids_in_xform_xml( xml_data, case_id_override=case_id_override, ) domain = domain or 'test-domain' _, _, [case] = FormProcessorInterface.submit_form_locally(updated_xml, domain=domain) test_class.assertLessEqual(starttime, case.server_modified_on) test_class.assertGreaterEqual(datetime.utcnow(), case.server_modified_on) test_class.assertEqual(case_id, case.id) return case
def testRestoreAttributes(self): file_path = os.path.join(os.path.dirname(__file__), "data", "attributes.xml") with open(file_path, "rb") as f: xml_data = f.read() _, _, [newcase] = FormProcessorInterface.submit_form_locally(xml_data, domain=self.project.name) self.assertTrue(isinstance(newcase.adate, dict)) self.assertEqual(date(2012, 02, 01), newcase.adate["#text"]) self.assertEqual("i am an attribute", newcase.adate["@someattr"]) self.assertTrue(isinstance(newcase.dateattr, dict)) self.assertEqual("this shouldn't break", newcase.dateattr["#text"]) self.assertEqual(date(2012, 01, 01), newcase.dateattr["@somedate"]) self.assertTrue(isinstance(newcase.stringattr, dict)) self.assertEqual("neither should this", newcase.stringattr["#text"]) self.assertEqual("i am a string", newcase.stringattr["@somestring"]) restore_payload = generate_restore_payload(self.project, dummy_user()) # ghetto self.assertTrue('<dateattr somedate="2012-01-01">' in restore_payload) self.assertTrue('<stringattr somestring="i am a string">' in restore_payload)
def _test_sync_token(self, items): """ Tests sync token / sync mode support """ file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data, domain=self.project.name) time.sleep(1) restore_payload = generate_restore_payload(self.project, dummy_user(), items=items) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).one().get_id expected_restore_payload = dummy_restore_xml( sync_log_id, const.CREATE_SHORT, items=4 if items else None, ) check_xml_line_by_line(self, expected_restore_payload, restore_payload) time.sleep(1) sync_restore_payload = generate_restore_payload( project=self.project, user=dummy_user(), restore_id=sync_log_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [latest_log] = [log for log in all_sync_logs if log.get_id != sync_log_id] # should no longer have a case block in the restore XML check_xml_line_by_line( self, dummy_restore_xml(latest_log.get_id, items=3 if items else None), sync_restore_payload, ) # apply an update time.sleep(1) file_path = os.path.join(os.path.dirname(__file__), "data", "update_short.xml") with open(file_path, "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data, domain=self.project.name) time.sleep(1) sync_restore_payload = generate_restore_payload( self.project, user=dummy_user(), restore_id=latest_log.get_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [even_latest_log] = [log for log in all_sync_logs if log.get_id != sync_log_id and log.get_id != latest_log.get_id] # case block should come back expected_sync_restore_payload = dummy_restore_xml( even_latest_log.get_id, const.UPDATE_SHORT, items=4 if items else None, ) check_xml_line_by_line(self, expected_sync_restore_payload, sync_restore_payload)
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() # implicit length assertion _, _, [newcase] = FormProcessorInterface.submit_form_locally(xml_data, domain=self.project.name) user = dummy_user() self.assertEqual(1, len(list( BatchedCaseSyncOperation(RestoreState(self.project, user, RestoreParams())).get_all_case_updates() ))) expected_case_block = """ <case> <case_id>asdf</case_id> <date_modified>2010-06-29T13:42:50.000000Z</date_modified> <create> <case_type_id>test_case_type</case_type_id> <user_id>foo</user_id> <case_name>test case name</case_name> <external_id>someexternal</external_id> </create> </case>""" check_xml_line_by_line(self, expected_case_block, xml.get_case_xml(newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE])) # check v2 expected_v2_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2" > <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( project=self.project, user=dummy_user(), items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )