def test_put_finalize_dvcs_feature_disabled(self): """Testing the PUT <URL> API with finalize_commit_series=1 when the DVCS feature is disabled """ with override_feature_check(dvcs_feature.feature_id, enabled=False): review_request = self.create_review_request( create_repository=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) cumulative_diff = SimpleUploadedFile('diff', b'', content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info({}), }, expected_mimetype=diff_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.compare_item(rsp['diff'], diffset)
def test_put_finalize_empty_commit_series(self): """Testing the PUT <URL> API with finalize_commit_series=1 for an empty commit series """ with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) cumulative_diff = SimpleUploadedFile('diff', b'', content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info({}), }, expected_status=400) self.assertEqual( rsp, { 'stat': 'fail', 'err': { 'code': INVALID_ATTRIBUTE.code, 'msg': INVALID_ATTRIBUTE.msg, }, 'reason': 'Cannot finalize an empty commit series.', })
def test_put_finalized_with_parent(self): """Testing the PUT <URL> API with finalize_commit_series=1 and a parent diff """ def _get_file_exists(repository, path, revision, base_commit_id=None, request=None): self.assertEqual(path, 'README') self.assertEqual(revision, 'f00f00') return True self.spy_on(Repository.get_file_exists, call_fake=_get_file_exists) with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) commit = self.create_diffcommit(diffset=diffset) filediff = FileDiff.objects.get() filediff.parent_diff = (b'diff --git a/README b/README\n' b'index f00f00..94bdd3e\n' b'--- a/README\n' b'+++ b/README\n') filediff.extra_data[FileDiff._IS_PARENT_EMPTY_KEY] = True filediff.save(update_fields=('extra_data', )) cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') parent_diff = SimpleUploadedFile('parent_diff', filediff.parent_diff, content_type='text/x-patch') validation_info = update_validation_info( {}, commit_id=commit.commit_id, parent_id=commit.parent_id, filediffs=[filediff]) rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'parent_diff': parent_diff, 'validation_info': serialize_validation_info(validation_info), }, expected_mimetype=diff_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.compare_item(rsp['diff'], diffset)
def test_post_subsequent(self): """Testing the POST <URL> API with a subsequent commit""" repository = self.create_repository(tool_name='Git') review_request = self.create_review_request( repository=repository, submitter=self.user, create_with_history=True) diffset = self.create_diffset(review_request, draft=True) commit = self.create_diffcommit( repository, diffset, diff_contents=self._DEFAULT_DIFF_CONTENTS) validation_info = serialize_validation_info({ commit.commit_id: { 'parent_id': commit.parent_id, 'tree': { 'added': [], 'modified': [{ 'filename': 'readme', 'revision': '5b50866', }], 'removed': [], }, }, }) diff = SimpleUploadedFile( 'diff', (b'diff --git a/readme b/readme\n' b'index 5b50866..f00f00f 100644\n' b'--- a/readme\n' b'+++ a/readme\n' b'@@ -1 +1,4 @@\n' b' Hello there\n' b' \n' b' Oh hi!\n' b'+Goodbye!\n'), content_type='text/x-patch') with override_feature_checks(self.override_features): rsp = self.api_post( get_draft_diffcommit_list_url(review_request, diffset.revision), dict(self._DEFAULT_POST_DATA, **{ 'commit_id': 'r2', 'parent_id': 'r1', 'diff': diff, 'validation_info': validation_info, }), expected_mimetype=draft_diffcommit_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.assertIn('draft_commit', rsp) item_rsp = rsp['draft_commit'] self.compare_item(item_rsp, DiffCommit.objects.get(pk=item_rsp['id']))
def test_put_finalize_adds_default_reviewers(self): """Testing the PUT <URL> API with finalize_commit_series=1 adds default reviewers """ @self.spy_for(Repository.get_file_exists, owner=Repository) def _get_file_exists(repository, path, revision, **kwargs): self.assertEqual(path, 'README') self.assertEqual(revision, '94bdd3e') return True with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) # Create the state needed for the default reviewer. group = self.create_review_group(name='group1') default_reviewer = DefaultReviewer.objects.create(name='default1', file_regex='.') default_reviewer.groups.add(group) default_reviewer.repository.add(review_request.repository) # Create the state needed for the diff to post. diffset = self.create_diffset(review_request=review_request, draft=True) commit = self.create_diffcommit(diffset=diffset) filediff = FileDiff.objects.get() cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') validation_info = update_validation_info( {}, commit_id=commit.commit_id, parent_id=commit.parent_id, filediffs=[filediff]) # Post the diff. rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info(validation_info), }, expected_mimetype=diff_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.compare_item(rsp['diff'], diffset) draft = review_request.get_draft() self.assertEqual(list(draft.target_groups.all()), [group])
def test_post_subsequent(self): """Testing the POST <URL> API with a subsequent commit""" repository = self.create_repository(tool_name='Git') review_request = self.create_review_request(repository=repository, submitter=self.user, create_with_history=True) diffset = self.create_diffset(review_request, draft=True) commit = self.create_diffcommit( repository, diffset, diff_contents=self._DEFAULT_DIFF_CONTENTS) validation_info = serialize_validation_info({ commit.commit_id: { 'parent_id': commit.parent_id, 'tree': { 'added': [], 'modified': [{ 'filename': 'readme', 'revision': '5b50866', }], 'removed': [], }, }, }) diff = SimpleUploadedFile('diff', (b'diff --git a/readme b/readme\n' b'index 5b50866..f00f00f 100644\n' b'--- a/readme\n' b'+++ a/readme\n' b'@@ -1 +1,4 @@\n' b' Hello there\n' b' \n' b' Oh hi!\n' b'+Goodbye!\n'), content_type='text/x-patch') with override_feature_checks(self.override_features): rsp = self.api_post( get_draft_diffcommit_list_url(review_request, diffset.revision), dict( self._DEFAULT_POST_DATA, **{ 'commit_id': 'r2', 'parent_id': 'r1', 'diff': diff, 'validation_info': validation_info, }), expected_mimetype=draft_diffcommit_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.assertIn('draft_commit', rsp) item_rsp = rsp['draft_commit'] self.compare_item(item_rsp, DiffCommit.objects.get(pk=item_rsp['id']))
def test_put_finalize_validation_info_missing_commits(self): """Testing the PUT <URL> API with finalize_commit_series=1 when validation_info does not contain all commits """ with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) commits = [ self.create_diffcommit(diffset=diffset, **kwargs) for kwargs in ( {'commit_id': 'r1', 'parent_id': 'r0'}, {'commit_id': 'r2', 'parent_id': 'r1'}, ) ] filediff = commits[0].files.first() validation_info = update_validation_info( {}, commit_id=commits[0].commit_id, parent_id=commits[0].parent_id, filediffs=[filediff]) cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info( validation_info), }, expected_status=400) self.assertEqual(rsp, { 'stat': 'fail', 'err': { 'code': INVALID_FORM_DATA.code, 'msg': INVALID_FORM_DATA.msg, }, 'fields': { 'validation_info': [ 'The following commits exist but are not present in ' 'validation_info: r2', ], } })
def test_put_finalize_validation_info_extra_commits(self): """Testing the PUT <URL> API with finalize_commit_series=1 when validation_info contains commits that do not exist """ with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) commit = self.create_diffcommit(diffset=diffset) filediff = commit.files.first() validation_info = update_validation_info( {}, commit_id=commit.commit_id, parent_id=commit.parent_id, filediffs=[filediff]) validation_info = update_validation_info( validation_info, commit_id='f00', parent_id=commit.commit_id, filediffs=[]) cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info(validation_info), }, expected_status=400) self.assertEqual( rsp, { 'stat': 'fail', 'err': { 'code': INVALID_FORM_DATA.code, 'msg': INVALID_FORM_DATA.msg, }, 'fields': { 'validation_info': [ 'The following commits are specified in validation_info ' 'but do not exist: f00' ], }, })
def test_put_finalize(self): """Testing the PUT <URL> API with finalize_commit_series=1""" def _get_file_exists(repository, path, revision, base_commit_id=None, request=None): self.assertEqual(path, 'README') self.assertEqual(revision, '94bdd3e') return True self.spy_on(Repository.get_file_exists, owner=Repository, call_fake=_get_file_exists) with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) commit = self.create_diffcommit(diffset=diffset) filediff = FileDiff.objects.get() cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') validation_info = update_validation_info( {}, commit_id=commit.commit_id, parent_id=commit.parent_id, filediffs=[filediff]) rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info(validation_info), }, expected_mimetype=diff_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.compare_item(rsp['diff'], diffset)
def test_post_added_in_parent(self): """Testing the POST <URL> API with a subsequent commit that contains a file added in the parent diff """ def _exists(repository, filename, revision, *args, **kwargs): return filename == 'README' and revision == '94bdd3e' initial_validation_info = { 'r1': { 'parent_id': 'r0', 'tree': { 'added': [], 'modified': [], 'removed': [], }, }, } repo = self.create_repository(name='repo') self.spy_on(Repository.get_file_exists, owner=Repository, call_fake=_exists) diff = SimpleUploadedFile('diff', self.DEFAULT_GIT_FILEDIFF_DATA_DIFF, content_type='text/x-patch') with override_feature_checks(self.override_features): rsp = self.api_post(get_validate_diffcommit_url(), { 'commit_id': 'r2', 'parent_id': 'r1', 'diff': diff, 'repository': repo.name, 'validation_info': serialize_validation_info(initial_validation_info), }, expected_mimetype=validate_diffcommit_mimetype, expected_status=200) self.assertEqual(rsp['stat'], 'ok')
def test_post_finalized(self): """Testing the POST <URL> API after the parent DiffSet has been finalized """ with override_feature_checks(self.override_features): review_request = self.create_review_request( create_repository=True, submitter=self.user, create_with_history=True) diffset = self.create_diffset(review_request, draft=True) diffset.finalize_commit_series( cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF, validation_info=None, validate=False, save=True) diff = SimpleUploadedFile('diff', self._DEFAULT_DIFF_CONTENTS, content_type='text/x-patch') rsp = self.api_post(get_draft_diffcommit_list_url( review_request, diffset.revision), dict( self._DEFAULT_POST_DATA, **{ 'validation_info': serialize_validation_info({}), 'diff': diff, }), expected_status=400) self.assertEqual( rsp, { 'stat': 'fail', 'err': { 'code': INVALID_ATTRIBUTE.code, 'msg': INVALID_ATTRIBUTE.msg, }, 'reason': 'The diff has already been finalized.', })
def setup_basic_post_test(self, user, with_local_site, local_site_name, post_valid_data): repository = self.create_repository(tool_name='Git', with_local_site=with_local_site) post_data = {} if post_valid_data: self.spy_on(Repository.get_file_exists, owner=Repository, call_fake=lambda *args, **kwargs: True) validation_info = serialize_validation_info({ 'r1': { 'parent_id': 'r0', 'tree': { 'added': [{ 'filename': 'README', 'revision': '94bdd3e', }], 'modified': [], 'removed': [], }, }, }) diff = SimpleUploadedFile('diff', self.DEFAULT_GIT_FILEDIFF_DATA_DIFF, content_type='text/x-patch') post_data = { 'commit_id': 'r2', 'parent_id': 'r1', 'diff': diff, 'validation_info': validation_info, 'repository': repository.pk, } return (get_validate_diffcommit_url(local_site_name=local_site_name), validate_diffcommit_mimetype, post_data, [])
def test_put_finalize_again(self): """Testing the PUT <URL> API with finalize_commit_series=1 when the diff is already finalized """ with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) self.create_diffcommit(diffset=diffset) diffset.finalize_commit_series( cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF, validation_info=None, validate=False, save=True) cumulative_diff = SimpleUploadedFile('diff', b'', content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info({}), }, expected_status=400) self.assertEqual( rsp, { 'stat': 'fail', 'err': { 'code': INVALID_ATTRIBUTE.code, 'msg': INVALID_ATTRIBUTE.msg, }, 'reason': 'This diff is already finalized.', })
def test_post_finalized(self): """Testing the POST <URL> API after the parent DiffSet has been finalized """ with override_feature_checks(self.override_features): review_request = self.create_review_request( create_repository=True, submitter=self.user, create_with_history=True) diffset = self.create_diffset(review_request, draft=True) diffset.finalize_commit_series( cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF, validation_info=None, validate=False, save=True) diff = SimpleUploadedFile( 'diff', self._DEFAULT_DIFF_CONTENTS, content_type='text/x-patch') rsp = self.api_post( get_draft_diffcommit_list_url(review_request, diffset.revision), dict(self._DEFAULT_POST_DATA, **{ 'validation_info': serialize_validation_info({}), 'diff': diff, }), expected_status=400) self.assertEqual(rsp, { 'stat': 'fail', 'err': { 'code': INVALID_ATTRIBUTE.code, 'msg': INVALID_ATTRIBUTE.msg, }, 'reason': 'The diff has already been finalized.', })
def test_put_finalize_invalid_validation_info_json_format(self): """Testing the PUT <URL> API with finalize_commit_series=1 when validation_info is invalid json """ with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) diffset = self.create_diffset(review_request=review_request, draft=True) self.create_diffcommit(diffset=diffset) cumulative_diff = SimpleUploadedFile('diff', b'', content_type='text/x-patch') rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info('foo'), }, expected_status=400) self.assertEqual( rsp, { 'stat': 'fail', 'err': { 'code': INVALID_FORM_DATA.code, 'msg': INVALID_FORM_DATA.msg, }, 'fields': { 'validation_info': [ 'Could not parse field: Invalid format.', ], }, })
def create(self, request, repository, commit_id, parent_id, base_commit_id=None, local_site_name=None, *args, **kwargs): """Validate a diff for a commit. This API has a similar signature to the :ref:`Draft DiffCommit resource <webapi2.0-draft-diff-commit-list-resource>` POST API, but instead of actually creating commits, it will return a result representing whether or not the included diff file parsed and validated correctly. This API must be called before posting to the :ref:`Draft DiffCommit resource <webapi2.0-draft-diff-commit-list-resource>` because the ``validation_info`` field returned by this resource is required for posting to that resource. """ local_site = self._get_local_site(local_site_name) try: q = Q(pk=int(repository)) except ValueError: q = (Q(path=repository) | Q(mirror_path=repository) | Q(name=repository)) repository_qs = (Repository.objects.accessible( request.user, local_site=local_site).filter(q)) repository_count = len(repository_qs) if repository_count == 0: return INVALID_REPOSITORY, { 'repository': repository, } elif repository_count > 1: msg = ('Too many repositories matched "%s". Try specifying the ' 'repository by name instead.' % repository) return INVALID_REPOSITORY.with_message(msg), { 'repository': repository, } repository = repository_qs.first() if not repository.scmtool_class.supports_history: return INVALID_ATTRIBUTE, { 'reason': ('The "%s" repository does not support review requests ' 'created with history.' % repository.name), } form = ValidateCommitForm(repository=repository, request=request, data=request.POST, files=request.FILES) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: filediffs = form.validate_diff() except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision), } except EmptyDiffError: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except DiffParserError as e: return DIFF_PARSE_ERROR, { 'reason': six.text_type(e), 'linenum': e.linenum, } except ShortSHA1Error as e: return REPO_FILE_NOT_FOUND, { 'reason': six.text_type(e), 'file': e.path, 'revision': six.text_type(e.revision), } except SCMError as e: return DIFF_PARSE_ERROR.with_message(six.text_type(e)) except Exception as e: logger.exception( 'Unexpected exception occurred while validating commit "%s" ' 'in repository "%s" (id %d) with base_commit_id="%s"', commit_id, repository.name, repository.pk, base_commit_id, request=request) return DIFF_PARSE_ERROR.with_message( 'Unexpected error while validating the diff: %s' % e) validation_info = update_validation_info( form.cleaned_data.get('validation_info', {}), commit_id, parent_id, filediffs) return 200, { self.item_result_key: { 'validation_info': serialize_validation_info(validation_info), } }
def create(self, request, repository, commit_id, parent_id, base_commit_id=None, local_site_name=None, *args, **kwargs): """Validate a diff for a commit. This API has a similar signature to the :ref:`Draft DiffCommit resource <webapi2.0-draft-diff-commit-list-resource>` POST API, but instead of actually creating commits, it will return a result representing whether or not the included diff file parsed and validated correctly. This API must be called before posting to the :ref:`Draft DiffCommit resource <webapi2.0-draft-diff-commit-list-resource>` because the ``validation_info`` field returned by this resource is required for posting to that resource. """ local_site = self._get_local_site(local_site_name) try: q = Q(pk=int(repository)) except ValueError: q = (Q(path=repository) | Q(mirror_path=repository) | Q(name=repository)) repository_qs = ( Repository.objects .accessible(request.user, local_site=local_site) .filter(q) ) repository_count = len(repository_qs) if repository_count == 0: return INVALID_REPOSITORY, { 'repository': repository, } elif repository_count > 1: msg = ( 'Too many repositories matched "%s". Try specifying the ' 'repository by name instead.' % repository ) return INVALID_REPOSITORY.with_message(msg), { 'repository': repository, } repository = repository_qs.first() if not repository.scmtool_class.supports_history: return INVALID_ATTRIBUTE, { 'reason': ( 'The "%s" repository does not support review requests ' 'created with history.' % repository.name ), } form = ValidateCommitForm(repository=repository, request=request, data=request.POST, files=request.FILES) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: filediffs = form.validate_diff() except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision), } except EmptyDiffError: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except DiffParserError as e: return DIFF_PARSE_ERROR, { 'reason': six.text_type(e), 'linenum': e.linenum, } except ShortSHA1Error as e: return REPO_FILE_NOT_FOUND, { 'reason': six.text_type(e), 'file': e.path, 'revision': six.text_type(e.revision), } except SCMError as e: return DIFF_PARSE_ERROR.with_message(six.text_type(e)) except Exception as e: logger.exception( 'Unexpected exception occurred while validating commit "%s" ' 'in repository "%s" (id %d) with base_commit_id="%s"', commit_id, repository.name, repository.pk, base_commit_id, request=request) return DIFF_PARSE_ERROR.with_message( 'Unexpected error while validating the diff: %s' % e) validation_info = update_validation_info( form.cleaned_data.get('validation_info', {}), commit_id, parent_id, filediffs) return 200, { self.item_result_key: { 'validation_info': serialize_validation_info( validation_info), } }
def test_put_finalize_adds_default_reviewers_first_time_only(self): """Testing the PUT <URL> API with finalize_commit_series=1 doesn't add default reviewers a second time """ def _get_file_exists(repository, path, revision, base_commit_id=None, request=None): self.assertEqual(path, 'README') self.assertEqual(revision, '94bdd3e') return True self.spy_on(Repository.get_file_exists, call_fake=_get_file_exists) with override_feature_check(dvcs_feature.feature_id, enabled=True): review_request = self.create_review_request( create_repository=True, create_with_history=True, submitter=self.user) # Create the state needed for the default reviewer. group = self.create_review_group(name='group1') default_reviewer = DefaultReviewer.objects.create(name='default1', file_regex='.') default_reviewer.groups.add(group) default_reviewer.repository.add(review_request.repository) # Create the initial diffset. This should prevent a default # reviewer from being applied, since we're not publishing the first # diff on a review request. self.create_diffset(review_request=review_request) # Create the state needed for the diff to post. diffset = self.create_diffset(review_request=review_request, draft=True) commit = self.create_diffcommit(diffset=diffset) filediff = FileDiff.objects.get() cumulative_diff = SimpleUploadedFile('diff', filediff.diff, content_type='text/x-patch') validation_info = update_validation_info( {}, commit_id=commit.commit_id, parent_id=commit.parent_id, filediffs=[filediff]) # Post the diff. rsp = self.api_put( get_draft_diff_item_url(review_request, diffset.revision), { 'finalize_commit_series': True, 'cumulative_diff': cumulative_diff, 'validation_info': serialize_validation_info(validation_info), }, expected_mimetype=diff_item_mimetype) self.assertEqual(rsp['stat'], 'ok') self.compare_item(rsp['diff'], diffset) draft = review_request.get_draft() self.assertEqual(list(draft.target_groups.all()), [])