def testOtherUserUpdatesIndex(self): # create a parent and child case (with index) from one user parent_id = "other_updates_index_parent" case_id = "other_updates_index_child" self._createCaseStubs([parent_id]) child = CaseBlock( create=True, case_id=case_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) # assign the parent case away from same user parent_update = CaseBlock( create=False, case_id=parent_id, user_id=USER_ID, owner_id=OTHER_USER_ID, update={"greeting": "hello"}, version=V2).as_xml() self._postFakeWithSyncToken(parent_update, self.sync_log.get_id) self.sync_log = SyncLog.get(self.sync_log.get_id) # these tests added to debug another issue revealed by this test self.assertTrue(self.sync_log.phone_has_case(case_id)) self.assertTrue(self.sync_log.phone_has_dependent_case(parent_id)) self.assertTrue(self.sync_log.phone_is_holding_case(case_id)) self.assertTrue(self.sync_log.phone_is_holding_case(parent_id)) # original user syncs again # make sure there are no new changes assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id, purge_restore_cache=True) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id, purge_restore_cache=True) # update the parent case from another user self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID) other_parent_update = CaseBlock( create=False, case_id=parent_id, user_id=OTHER_USER_ID, update={"greeting2": "hi"}, version=V2 ).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # make sure the indexed case syncs again self.sync_log = SyncLog.last_for_user(USER_ID) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id, purge_restore_cache=True)
def testArchiveUpdates(self): """ Tests that archiving a form (and changing a case) causes the case to be included in the next sync. """ case_id = "archive_syncs" self._createCaseStubs([case_id]) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) update_block = CaseBlock(create=False, case_id=case_id, user_id=USER_ID, version=V2, update={ "greeting": "hello" }).as_xml() form = self._postFakeWithSyncToken(update_block, self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) form.archive() assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testIndexesSync(self): # create a parent and child case (with index) from one user parent_id = "indexes_sync_parent" case_id = "indexes_sync" self._createCaseStubs([parent_id]) child = CaseBlock( create=True, case_id=case_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) # make sure the second user doesn't get either assert_user_doesnt_have_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id) assert_user_doesnt_have_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) # assign just the child case to a second user child_update = CaseBlock( create=False, case_id=case_id, user_id=USER_ID, owner_id=OTHER_USER_ID, version=V2, update={"greeting": "hello"} ).as_xml() self._postFakeWithSyncToken(child_update, self.sync_log.get_id) # second user syncs # make sure both cases restore assert_user_has_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id) assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id)
def testOtherUserUpdatesUnowned(self): # create a case from one user and assign ownership elsewhere case_id = "other_user_updates_unowned" self._createCaseStubs([case_id], owner_id=OTHER_USER_ID) # sync and update from another user assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID) update = CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID, version=V2, update={ 'greeting': 'hello' }).as_xml() self._postFakeWithSyncToken(update, self.other_sync_log.get_id) # original user syncs again # make sure there are no new changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testOtherUserEdits(self): # create a case by one user case_id = "other_user_edits" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync to the other's phone to be able to edit assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) latest_sync = SyncLog.last_for_user(OTHER_USER_ID) # update from another self._postFakeWithSyncToken( CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID, version=V2, update={ 'greeting': "Hello!" }).as_xml(), latest_sync.get_id) # original user syncs again # make sure updates take match = assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) self.assertTrue("Hello!" in ElementTree.tostring(match))
def testOtherUserAddsIndex(self): time = datetime.utcnow() # create a case from one user case_id = "other_user_adds_index" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync to the other's phone to be able to edit assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) latest_sync = SyncLog.last_for_user(OTHER_USER_ID) mother_id = "other_user_adds_index_mother" parent_case = CaseBlock( create=True, date_modified=time, case_id=mother_id, user_id=OTHER_USER_ID, case_type=PARENT_TYPE, version=V2, ).as_xml(format_datetime=json_format_datetime) self._postFakeWithSyncToken( parent_case, latest_sync.get_id ) # the original user should not get the parent case assert_user_doesnt_have_case(self, self.user, mother_id, restore_id=self.sync_log.get_id) # update the original case from another, adding an indexed case self._postFakeWithSyncToken( CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=USER_ID, version=V2, index={'mother': ('mother', mother_id)} ).as_xml(format_datetime=json_format_datetime), latest_sync.get_id ) # original user syncs again # make sure index updates take and indexed case also syncs expected_parent_case = CaseBlock( create=True, date_modified=time, case_id=mother_id, user_id=OTHER_USER_ID, case_type=PARENT_TYPE, owner_id=OTHER_USER_ID, version=V2, ).as_xml(format_datetime=json_format_datetime) check_user_has_case(self, self.user, expected_parent_case, restore_id=self.sync_log.get_id, version=V2, purge_restore_cache=True) _, orig = assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) self.assertTrue("index" in ElementTree.tostring(orig))
def testSharedCase(self): # create a case by one user case_id = "shared_case" self._createCaseStubs([case_id], owner_id=SHARED_ID) # should sync to the other owner assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id)
def testUserRestoreWithCase(self): restore_user = create_restore_user(domain=self.domain) expected_case_block = CaseBlock( create=True, case_id='my-case-id', user_id=restore_user.user_id, owner_id=restore_user.user_id, case_type='test-case-type', update={'external_id': 'someexternal'}, ) _, [case] = post_case_blocks([expected_case_block.as_xml()], {'domain': self.domain}) assert_user_has_case(self, restore_user, case.case_id)
def testIndexesSync(self): # create a parent and child case (with index) from one user parent_id = "indexes_sync_parent" case_id = "indexes_sync" self._createCaseStubs([parent_id]) child = CaseBlock(create=True, case_id=case_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={ 'mother': ('mother', parent_id) }).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) # make sure the second user doesn't get either assert_user_doesnt_have_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id) assert_user_doesnt_have_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) # assign just the child case to a second user child_update = CaseBlock(create=False, case_id=case_id, user_id=USER_ID, owner_id=OTHER_USER_ID, version=V2, update={ "greeting": "hello" }).as_xml() self._postFakeWithSyncToken(child_update, self.sync_log.get_id) # second user syncs # make sure both cases restore assert_user_has_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id) assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id)
def testClosedParentIndex(self): """ Tests that things work properly when you have a reference to the parent case in a child, even if it's closed. """ # first create the parent case parent_id = "mommy" self._createCaseStubs([parent_id]) self._testUpdate(self.sync_log.get_id, {parent_id: []}) # create the child child_id = "baby" index_id = 'my_mom_is' child = CaseBlock( create=True, case_id=child_id, user_id=USER_ID, version=V2, index={ index_id: (PARENT_TYPE, parent_id) }, ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) index_ref = CommCareCaseIndex(identifier=index_id, referenced_type=PARENT_TYPE, referenced_id=parent_id) self._testUpdate(self.sync_log.get_id, { parent_id: [], child_id: [index_ref] }) # close the mother case close = CaseBlock(create=False, case_id=parent_id, user_id=USER_ID, version=V2, close=True).as_xml() self._postFakeWithSyncToken(close, self.sync_log.get_id) self._testUpdate(self.sync_log.get_id, {child_id: [index_ref]}, {parent_id: []}) # try a clean restore again assert_user_has_case(self, self.user, parent_id) assert_user_has_case(self, self.user, child_id)
def testOtherUserEdits(self): # create a case by one user case_id = "other_user_edits" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync to the other's phone to be able to edit assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) latest_sync = SyncLog.last_for_user(OTHER_USER_ID) # update from another self._postFakeWithSyncToken( CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID, version=V2, update={'greeting': "Hello!"} ).as_xml(), latest_sync.get_id) # original user syncs again # make sure updates take match = assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) self.assertTrue("Hello!" in ElementTree.tostring(match))
def testArchiveUpdates(self): """ Tests that archiving a form (and changing a case) causes the case to be included in the next sync. """ case_id = "archive_syncs" self._createCaseStubs([case_id]) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) update_block = CaseBlock( create=False, case_id=case_id, user_id=USER_ID, version=V2, update={"greeting": "hello"} ).as_xml() form = self._postFakeWithSyncToken(update_block, self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) form.archive() assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testOtherUserCloses(self): # create a case from one user case_id = "other_user_closes" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync then close case from another user self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user)) close_block = CaseBlock(create=False, case_id=case_id, user_id=USER_ID, version=V2, close=True).as_xml() self._postFakeWithSyncToken(close_block, self.other_sync_log.get_id) # original user syncs again # make sure close block appears assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testClosedParentIndex(self): """ Tests that things work properly when you have a reference to the parent case in a child, even if it's closed. """ # first create the parent case parent_id = "mommy" self._createCaseStubs([parent_id]) self._testUpdate(self.sync_log.get_id, {parent_id: []}) # create the child child_id = "baby" index_id = 'my_mom_is' child = CaseBlock( create=True, case_id=child_id, user_id=USER_ID, version=V2, index={index_id: (PARENT_TYPE, parent_id)}, ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) index_ref = CommCareCaseIndex(identifier=index_id, referenced_type=PARENT_TYPE, referenced_id=parent_id) self._testUpdate(self.sync_log.get_id, {parent_id: [], child_id: [index_ref]}) # close the mother case close = CaseBlock(create=False, case_id=parent_id, user_id=USER_ID, version=V2, close=True ).as_xml() self._postFakeWithSyncToken(close, self.sync_log.get_id) self._testUpdate(self.sync_log.get_id, {child_id: [index_ref]}, {parent_id: []}) # try a clean restore again assert_user_has_case(self, self.user, parent_id) assert_user_has_case(self, self.user, child_id)
def testUserLoggedIntoMultipleDevices(self): # test that a child case created by the same user from a different device # gets included in the sync parent_id = "parent" child_id = "child" self._createCaseStubs([parent_id]) # create child case using a different sync log ID other_sync_log = synclog_from_restore_payload(generate_restore_payload(self.user, version="2.0")) child = CaseBlock( create=True, case_id=child_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, other_sync_log.get_id) # ensure child case is included in sync using original sync log ID assert_user_has_case(self, self.user, child_id, restore_id=self.sync_log.get_id)
def testOtherUserCloses(self): # create a case from one user case_id = "other_user_closes" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync then close case from another user self.other_sync_log = synclog_from_restore_payload(generate_restore_payload(self.other_user)) close_block = CaseBlock( create=False, case_id=case_id, user_id=USER_ID, version=V2, close=True ).as_xml() self._postFakeWithSyncToken( close_block, self.other_sync_log.get_id ) # original user syncs again # make sure close block appears assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testOtherUserUpdatesUnowned(self): # create a case from one user and assign ownership elsewhere case_id = "other_user_updates_unowned" self._createCaseStubs([case_id], owner_id=OTHER_USER_ID) # sync and update from another user assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID) update = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, version=V2, update={'greeting': 'hello'} ).as_xml() self._postFakeWithSyncToken( update, self.other_sync_log.get_id ) # original user syncs again # make sure there are no new changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testOtherUserReassignsIndexed(self): # create a parent and child case (with index) from one user parent_id = "other_reassigns_index_parent" case_id = "other_reassigns_index_child" self._createCaseStubs([parent_id]) child = CaseBlock( create=True, case_id=case_id, user_id=USER_ID, owner_id=SHARED_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) # assign the parent case away from the same user parent_update = CaseBlock( create=False, case_id=parent_id, user_id=USER_ID, owner_id=OTHER_USER_ID, update={"greeting": "hello"}, version=V2).as_xml() self._postFakeWithSyncToken(parent_update, self.sync_log.get_id) # sync cases to second user self.other_sync_log = synclog_from_restore_payload(generate_restore_payload(self.other_user)) # change the child's owner from another user child_reassignment = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={"childgreeting": "hi!"}, ).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # also change the parent from the second user other_parent_update = CaseBlock( create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={"other_greeting": "something new"}, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should sync to original user with updated ownership / edits assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # Ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something new" in payload) self.assertTrue("hi!" in payload) # change the parent again from the second user other_parent_update = CaseBlock( create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={"other_greeting": "something different"}, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change the child again from the second user other_child_update = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={"childgreeting": "hi changed!"}, ).as_xml() self._postFakeWithSyncToken(other_child_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change owner of child back to orginal user from second user child_reassignment = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=USER_ID, version=V2 ).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should now sync assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something different" in payload) self.assertTrue("hi changed!" in payload)
def testOtherUserAddsIndex(self): time = datetime.now() # create a case from one user case_id = "other_user_adds_index" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync to the other's phone to be able to edit assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id) latest_sync = SyncLog.last_for_user(OTHER_USER_ID) mother_id = "other_user_adds_index_mother" parent_case = CaseBlock( create=True, date_modified=time, case_id=mother_id, user_id=OTHER_USER_ID, case_type=PARENT_TYPE, version=V2, ).as_xml(format_datetime=json_format_datetime) self._postFakeWithSyncToken(parent_case, latest_sync.get_id) # the original user should not get the parent case assert_user_doesnt_have_case(self, self.user, mother_id, restore_id=self.sync_log.get_id) # update the original case from another, adding an indexed case self._postFakeWithSyncToken( CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=USER_ID, version=V2, index={ 'mother': ('mother', mother_id) }).as_xml(format_datetime=json_format_datetime), latest_sync.get_id) # original user syncs again # make sure index updates take and indexed case also syncs expected_parent_case = CaseBlock( create=True, date_modified=time, case_id=mother_id, user_id=OTHER_USER_ID, case_type=PARENT_TYPE, owner_id=OTHER_USER_ID, version=V2, ).as_xml(format_datetime=json_format_datetime) check_user_has_case(self, self.user, expected_parent_case, restore_id=self.sync_log.get_id, version=V2) orig = assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) self.assertTrue("index" in ElementTree.tostring(orig))
def testOtherUserUpdatesIndex(self): # create a parent and child case (with index) from one user parent_id = "other_updates_index_parent" case_id = "other_updates_index_child" self._createCaseStubs([parent_id]) parent = CaseBlock(case_id=parent_id, version=V2).as_xml() child = CaseBlock(create=True, case_id=case_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={ 'mother': ('mother', parent_id) }).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) # assign the parent case away from same user parent_update = CaseBlock(create=False, case_id=parent_id, user_id=USER_ID, owner_id=OTHER_USER_ID, update={ "greeting": "hello" }, version=V2).as_xml() self._postFakeWithSyncToken(parent_update, self.sync_log.get_id) self.sync_log = SyncLog.get(self.sync_log.get_id) # these tests added to debug another issue revealed by this test self.assertTrue(self.sync_log.phone_has_case(case_id)) self.assertTrue(self.sync_log.phone_has_dependent_case(parent_id)) self.assertTrue(self.sync_log.phone_is_holding_case(case_id)) self.assertTrue(self.sync_log.phone_is_holding_case(parent_id)) # original user syncs again # make sure there are no new changes assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) # update the parent case from another user assert_user_has_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id) self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID) other_parent_update = CaseBlock(create=False, case_id=parent_id, user_id=OTHER_USER_ID, update={ "greeting2": "hi" }, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # make sure the indexed case syncs again self.sync_log = SyncLog.last_for_user(USER_ID) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)
def testSharedCase(self): # create a case by one user case_id = "shared_case" self._createCaseStubs([case_id], owner_id=SHARED_ID) # should sync to the other owner assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id)
def testOtherUserReassignsIndexed(self): # create a parent and child case (with index) from one user parent_id = "other_reassigns_index_parent" case_id = "other_reassigns_index_child" self._createCaseStubs([parent_id]) child = CaseBlock(create=True, case_id=case_id, user_id=USER_ID, owner_id=SHARED_ID, version=V2, index={ 'mother': ('mother', parent_id) }).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) # assign the parent case away from the same user parent_update = CaseBlock(create=False, case_id=parent_id, user_id=USER_ID, owner_id=OTHER_USER_ID, update={ "greeting": "hello" }, version=V2).as_xml() self._postFakeWithSyncToken(parent_update, self.sync_log.get_id) # sync cases to second user self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user)) # change the child's owner from another user child_reassignment = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={ "childgreeting": "hi!" }, ).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # also change the parent from the second user other_parent_update = CaseBlock(create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={ "other_greeting": "something new" }, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should sync to original user with updated ownership / edits assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # Ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something new" in payload) self.assertTrue("hi!" in payload) # change the parent again from the second user other_parent_update = CaseBlock(create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={ "other_greeting": "something different" }, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change the child again from the second user other_child_update = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={ "childgreeting": "hi changed!" }, ).as_xml() self._postFakeWithSyncToken(other_child_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change owner of child back to orginal user from second user child_reassignment = CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=USER_ID, version=V2).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should now sync assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something different" in payload) self.assertTrue("hi changed!" in payload)