def test_can_have_cover(any_series, is_comics, is_indexed, result): i = Issue(number='1', series=any_series) i.series.is_comics_publication = is_comics i.is_indexed = is_indexed can = i.can_have_cover() assert can is result
def test_cant_upload_variants_no_covers(any_series): with mock.patch('%s.has_covers' % ISSUE_PATH) as hc_mock: hc_mock.return_value = False i = Issue(number='1', series=any_series) can_upload_variants = i.can_upload_variants() assert can_upload_variants is False
def test_variant_covers_variant_of(any_series): with mock.patch('apps.gcd.models.cover.Cover.objects') as cobj_mock, \ mock.patch('%s.variant_of' % ISSUE_PATH) as vo_mock: vo_mock.active_variants.return_value.exclude.return_value \ .values_list.return_value = [1, 2] cobj_qs_mock = mock.MagicMock() cobj_mock.filter.return_value.exclude.return_value = cobj_qs_mock ac_qs_mock = mock.MagicMock(spec=QuerySet) vo_mock.active_covers.return_value = ac_qs_mock i = Issue(number='1', series=any_series) vc = i.variant_covers() vo_mock.active_variants.return_value\ .exclude.assert_called_once_with(id=i.id) vo_mock.active_variants.return_value\ .exclude.return_value \ .values_list.assert_called_once_with('id', flat=True) cobj_mock.filter.assert_called_once_with(issue__id__in=[1, 2]) cobj_mock.filter.return_value \ .exclude.assert_called_once_with(deleted=True) # __ior__ implements |= cobj_qs_mock.__ior__.assert_called_once_with(ac_qs_mock) assert vc == cobj_qs_mock.__ior__.return_value
def test_set_first_last_issues_empty(): with mock.patch('apps.gcd.models.series.Series.save'), \ mock.patch('apps.gcd.models.series.models.QuerySet.order_by') \ as order_mock, \ mock.patch('apps.gcd.models.issue.Issue.series'): # Create some issues that are set as first/last even though no longer # attached to the series. i1 = Issue(number='1', sort_code=0) i2 = Issue(number='2', sort_code=1) issue_list = [i1, i2] s = Series(issue_count=0, first_issue=i1, last_issue=i2) # Ensure that the active issues list is empty (i1 & i2 not attached). def index_faker(index): return issue_list[index] qs = mock.MagicMock(spec=QuerySet) qs.count.return_value = 0 qs.__getitem__.side_effect = index_faker order_mock.return_value = qs s.set_first_last_issues() assert s.first_issue is None assert s.last_issue is None s.save.assert_called_once_with()
def test_has_dependents_variant_set(any_series, del_issue_mocks, which_exists): del_issue_mocks[which_exists].return_value = True i = Issue(number='1', series=any_series) has_dependents = i.has_dependents() assert has_dependents is True
def test_has_no_dependents_no_stories(any_series, del_issue_mocks): del_issue_mocks['as'].return_value = [] i = Issue(number='1', series=any_series) has_dependents = i.has_dependents() assert has_dependents is False
def test_set_first_last_issues_nonempty(): with mock.patch('apps.gcd.models.series.Series.save'), \ mock.patch('apps.gcd.models.series.models.QuerySet.order_by') \ as order_mock, \ mock.patch('apps.gcd.models.issue.Issue.series'): s = Series(issue_count=0) # Create some issues attached to the series (but not first/last). i1 = Issue(number='1', sort_code=0, series=s) i2 = Issue(number='2', sort_code=1, series=s) issue_list = [i1, i2] # Ensure that the active issues list is empty (i1 & i2 not attached). def index_faker(index): return issue_list[index] qs = mock.MagicMock(spec=QuerySet) qs.count.return_value = 2 qs.__getitem__.side_effect = index_faker qs.__iter__.return_value = iter(issue_list) order_mock.return_value = qs s.set_first_last_issues() assert s.first_issue is i1 assert s.last_issue is i2 s.save.assert_called_once_with()
def test_active_stories(any_series): with mock.patch('%s.story_set' % ISSUE_PATH) as ss_mock: qs = mock.MagicMock(spec=QuerySet) ss_mock.exclude.return_value = qs i = Issue(number='1', series=any_series) active_stories = i.active_stories() assert active_stories is qs
def test_has_dependents_has_revisions(any_series, del_issue_mocks, which_exists): del_issue_mocks[which_exists].active_set.return_value \ .exists.return_value = True i = Issue(number='1', series=any_series) has_dependents = i.has_dependents() assert has_dependents is True
def test_delete(): with mock.patch('%s.save' % ISSUE_PATH): i = Issue() i.delete() assert i.deleted is True i.save.assert_called_once_with()
def test_cant_upload_variants_active_revisions(any_series): with mock.patch('%s.active_set' % REVMGR_PATH) as rev_mock, \ mock.patch('%s.has_covers' % ISSUE_PATH) as hc_mock: hc_mock.return_value = True rev_mock.return_value.exists.return_value = True i = Issue(number='1', series=any_series) can_upload_variants = i.can_upload_variants() assert can_upload_variants is False
def test_stat_counts_base_skeleton(any_series, stat_count_mocks): i = Issue(number='1', series=any_series, is_indexed=INDEXED['skeleton']) counts = i.stat_counts() assert counts == { 'issues': 1, 'series issues': 1, 'covers': 0, 'stories': 0, }
def test_active_covers(any_series): with mock.patch('%s.cover_set' % ISSUE_PATH) as cs_mock: qs = mock.MagicMock(spec=QuerySet) cs_mock.exclude.return_value = qs i = Issue(number='1', series=any_series) active_covers = i.active_covers() assert active_covers is qs cs_mock.exclude.assert_called_once_with(deleted=True)
def test_has_keywords(any_series): with mock.patch('%s.keywords' % ISSUE_PATH) as kw_mock: i = Issue(series=any_series) kw_mock.exists.return_value = False assert i.has_keywords() is False kw_mock.exists.return_value = True assert i.has_keywords() is True
def test_has_covers(any_series, can_have, active): with mock.patch('%s.can_have_cover' % ISSUE_PATH) as cs_mock, \ mock.patch('%s.active_covers' % ISSUE_PATH) as ac_mock: cs_mock.return_value = can_have ac_mock.return_value.exists.return_value = active i = Issue(number='1', series=any_series) has = i.has_covers() assert has is all((can_have, active))
def test_stat_counts_variant_partial(any_series, stat_count_mocks): i = Issue(number='1', series=any_series, is_indexed=INDEXED['partial'], variant_of_id=1234) counts = i.stat_counts() assert counts == { 'variant issues': 1, 'covers': 0, 'stories': 0, }
def test_stat_counts_non_comics(any_series, stat_count_mocks): as_mock, ac_mock = stat_count_mocks as_mock.return_value.count.return_value = 10 ac_mock.return_value.count.return_value = 2 any_series.is_comics_publication = False i = Issue(number='1', series=any_series) counts = i.stat_counts() assert counts == { 'series issues': 1, 'covers': 2, 'stories': 10, }
def test_shown_covers(any_series): with mock.patch('%s.active_covers' % ISSUE_PATH) as ac_mock, \ mock.patch('%s.variant_covers' % ISSUE_PATH) as vc_mock: v1, v2, v3, v4, v5 = [mock.MagicMock(spec=Cover) for x in range(0, 5)] # Should really be QuerySets and not lists, but close enough for # unit testing purposes. ac_mock.return_value = [v1, v2] vc_mock.return_value = [v3, v4, v5] i = Issue(number='1', series=any_series) first, second = i.shown_covers() assert first == [v1, v2] assert second == [v3, v4, v5]
def test_stat_counts_base_indexed_covers_stories(any_series, stat_count_mocks): as_mock, ac_mock = stat_count_mocks as_mock.return_value.count.return_value = 10 ac_mock.return_value.count.return_value = 2 i = Issue(number='1', series=any_series, is_indexed=INDEXED['full']) counts = i.stat_counts() assert counts == { 'issues': 1, 'series issues': 1, 'issue indexes': 1, 'covers': 2, 'stories': 10, }
def patched_for_save(): def story_uni(self): return self.title def issue_uni(self): return self.number # with mock.patch('apps.oi.models.LinkRevision.save') as save_mock, \ with mock.patch('django.db.models.base.Model.save') as save_mock, \ mock.patch('apps.gcd.models.story.Story.__str__', story_uni), \ mock.patch('apps.gcd.models.issue.Issue.__str__', issue_uni): s = Series(name='Test Series') yield (save_mock, Story(title='origin', issue=Issue(number='1', title='o issue', series=s)), Story(title='target', issue=Issue(number='9', title='t issue', series=s)))
def patched_edit(story_revs): with mock.patch(RECENT) as recent_mock, mock.patch(SAVE), \ mock.patch('%s.storyrevisions' % CSET) as story_mock: story_mock.filter.return_value = story_revs ish = Issue(is_indexed=INDEXED['full']) prev = IssueRevision(changeset=Changeset(), issue=ish) rev = IssueRevision(changeset=Changeset(), previous_revision=prev, issue=ish) yield (rev, recent_mock)
def pre_commit_rev(): with mock.patch('%s._same_series_revisions' % IREV), \ mock.patch('%s._same_series_open_with_after' % IREV): s = Series(name='Some Series') i = Issue(number='1', series=s) rev = IssueRevision( changeset=Changeset(), issue=i, series=s, previous_revision=IssueRevision(changeset=Changeset(), issue=i)) yield rev
def test_has_no_dependents(any_series, del_issue_mocks): i = Issue(number='1', series=any_series) has_dependents = i.has_dependents() assert has_dependents is False # For this basic positive test case only, check that the right calls # were made. We don't need to do this every time, as from this point # on, all we change are return values so clearly things still get called. del_issue_mocks['hv'].assert_called_once_with() del_issue_mocks['issue_hr'].assert_called_once_with(ignore=None) del_issue_mocks['story_hr'].assert_called_once_with(notes=False) del_issue_mocks['issue_or'].active_set.return_value \ .exists.assert_called_once_with() del_issue_mocks['issue_tr'].active_set.return_value \ .exists.assert_called_once_with() del_issue_mocks['story_or'].active_set.return_value \ .exists.assert_called_once_with() del_issue_mocks['story_tr'].active_set.return_value \ .exists.assert_called_once_with()
def _build_reprint(origin_story, target_story, origin_base, notes): s = Series(name='Test Series') origin_issue = Issue(id=1, number='1', series=s) target_issue = Issue(id=2, number='2', series=s) origin = Story(id=1, title='origin', issue=origin_issue) target = Story(id=2, title='target', issue=target_issue) assert '%s' % origin == 'origin' r = Reprint(origin_issue=origin_issue, target_issue=target_issue, origin=(origin if origin_story else None), target=(target if target_story else None), notes=notes) base_issue = origin_issue if origin_base else target_issue # Pull stories from the reprint because they may be None. far_story = r.target if origin_base else r.origin far_issue = target_issue if origin_base else origin_issue return r, base_issue, far_issue, far_story
def test_soo_image(any_series, image_and_content_type): image_obj_mock, image_qs, ct_obj_mock, ct_mock = image_and_content_type i = Issue(number='1', series=any_series) img = i.soo_image assert img == image_qs.get.return_value image_obj_mock.filter.assert_called_once_with(object_id=i.id, deleted=False, content_type=ct_mock, type__id=2) image_qs.get.assert_called_once_with()
def test_handle_dependents_add(story_revs): with mock.patch(SAVE), \ mock.patch('%s.storyrevisions' % CSET) as story_mock: story_mock.filter.return_value = story_revs rev = IssueRevision(changeset=Changeset(), issue=Issue(is_indexed=INDEXED['full'])) rev._handle_dependents({}) for story in story_revs: assert story.issue == rev.issue story.save.assert_called_once_with()
def test_other_variants(): with mock.patch('%s.variant_of' % ISSUE_PATH, spec=Issue) as vo_mock, \ mock.patch('%s.active_variants' % ISSUE_PATH, spec=QuerySet) as vs_mock: v1, v2, v3, v4 = [mock.MagicMock(spec=Issue) for x in range(0, 4)] vo_mock.active_variants.return_value.exclude.return_value = [v1, v2] vs_mock.return_value = [v3, v4] i = Issue() assert i.other_variants() == [v1, v2] i.variant_of.active_variants.return_value.exclude\ .assert_called_once_with(id=i.id) i.variant_of.active_variants.assert_called_once_with() i.variant_of = None assert i.other_variants() == [v3, v4] i.active_variants.assert_called_once_with() i.active_variants.assert_called_once_with()
def test_save_fields_origin_with_story(patched_for_save): save_mock, origin, target = patched_for_save # Put in nonsense target_issue to show that save() properly ignores it # as target is not in the update_fields list. It would be weird but # possible for a caller to do this. nonsense = Issue(number='[nn]') r = Reprint(origin=origin, target=target, target_issue=nonsense) r.save(update_fields=['origin']) save_mock.assert_called_once_with(update_fields=['origin', 'origin_issue']) assert r.origin == origin assert r.target == target assert r.origin_issue == origin.issue assert r.target_issue == nonsense
def test_variant_covers_base(any_series): with mock.patch('apps.gcd.models.cover.Cover.objects') as cobj_mock, \ mock.patch('%s.variant_set' % ISSUE_PATH) as vs_mock: vs_mock.exclude.return_value.values_list.return_value = [3, 4, 5] cobj_qs_mock = mock.MagicMock() cobj_mock.filter.return_value.exclude.return_value = cobj_qs_mock i = Issue(variant_of=None, number='1', series=any_series) vc = i.variant_covers() vs_mock.exclude.assert_called_once_with(deleted=True) vs_mock.exclude.return_value \ .values_list.assert_called_once_with('id', flat=True) cobj_mock.filter.assert_called_once_with(issue__id__in=[3, 4, 5]) cobj_mock.filter.return_value \ .exclude.assert_called_once_with(deleted=True) # __ior__ implements |= assert not cobj_qs_mock.__ior__.called assert vc == cobj_qs_mock
def test_post_save_no_series_changed(patch_for_optional_move): patch_for_optional_move.return_value = False s = Series(name="Test Series") i = Issue(series=s) rev = IssueRevision(changeset=Changeset(), issue=i, series=s, previous_revision=IssueRevision(issue=i, series=s)) rev._post_save_object({}) # If we fail the check, there will be two calls here instead of one. s.set_first_last_issues.assert_called_once_with()
def test_create_move_revision(any_edit_story_rev, story_add_values, any_editing_changeset, keywords, old_is_comics, new_is_comics, old_pre_status, old_post_status, new_pre_status, new_post_status): rev = any_edit_story_rev rev.issue.is_indexed = old_pre_status rev.issue.series.is_comics_publication = old_is_comics rev.issue.series.save() # Changing country and language ensures that the stats are updated # (we are not interested in the path where they are not, as it is a # decision made in common code post-refactor). old_country = rev.issue.series.country old_language = rev.issue.series.language new_country = Country.objects.get_or_create(code='XZX', name='Other Country')[0] new_language = Language.objects.get_or_create(code='XZX', name='Other Language')[0] # Ensure we already have stats for new country and language or else # we get different calls in the tests due to init logic. CountStats.objects.init_stats(country=new_country) CountStats.objects.init_stats(language=new_language) new_publisher = Publisher.objects.create(name='Other Test Publisher', country=new_country, year_began=1990, series_count=1, issue_count=1) new_series = Series.objects.create(name='New Test Series', publisher=new_publisher, country=new_country, language=new_language, year_began=2000, is_comics_publication=new_is_comics, issue_count=1) new_issue = Issue(number='[nn]', series=new_series, publication_date='January 2000', key_date='2000-01-00', sort_code=0, is_indexed=new_pre_status) new_issue.save() rev.issue = new_issue rev.save() def set_indexed_status(self): if self.series.name == 'New Test Series': # Destination series always ends up indexed. delta = _get_indexed_delta(self.is_indexed, new_post_status, new_is_comics) self.is_indexed = new_post_status else: delta = _get_indexed_delta(self.is_indexed, old_post_status, old_is_comics) self.is_indexed = old_post_status self.save() return delta with mock.patch(UPDATE_ALL) as updater_mock, \ mock.patch('apps.gcd.models.issue.Issue.set_indexed_status', set_indexed_status): rev.commit_to_display() # TODO: Verify that reprint links still have story/issue fields agreeing. expected_calls = [mock.call({'stories': 1}, language=new_language, country=new_country), mock.call({'stories': 1}, language=old_language, country=old_country, negate=True)] if old_is_comics and (old_pre_status != INDEXED['skeleton'] and old_post_status == INDEXED['skeleton']): expected_calls.append(mock.call({'issue indexes': -1}, language=old_language, country=old_country)) if new_is_comics and (new_pre_status == INDEXED['skeleton'] and new_post_status != INDEXED['skeleton']): expected_calls.append(mock.call({'issue indexes': 1}, language=new_language, country=new_country)) elif new_is_comics and (new_pre_status != INDEXED['skeleton'] and new_post_status == INDEXED['skeleton']): expected_calls.append(mock.call({'issue indexes': 1}, language=new_language, country=new_country)) updater_mock.assert_has_calls(expected_calls, any_order=True) assert updater_mock.call_count == len(expected_calls)