def test_add_idea_with_anonymous_option(self, render): """ Verify that the anonymous field auto-populates only for ideas where banner is preset and the banner is private """ banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today(), is_private=True) banner1.save() banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today()) banner2.save() views.add_idea(mock_req(), banner1.id) context = render.call_args[0][2] self.assertTrue(isinstance(context['form'], PrivateIdeaForm)) self.assertIn("is_anonymous", context['form'].fields) self.assertNotIn("is_anonymous", context['form'].initial) views.add_idea(mock_req(), banner2.id) context = render.call_args[0][2] self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertNotIn("is_anonymous", context['form'].fields) self.assertNotIn("is_anonymous", context['form'].initial)
def test_tags_active(self, render): """ Tag list should include if tag was active in this search. """ def add_tag(idea, nonce): tag = str(nonce % 3) idea.tags.add(tag) self._generate_data(postfn=add_tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("tags" in context) for tag in context["tags"]: self.assertFalse(tag.active) views.list(mock_req("/?tags=0")) context = render.call_args[0][2] for tag in context["tags"]: self.assertEqual(tag.name == "0", tag.active) views.list(mock_req("/?tags=1")) context = render.call_args[0][2] for tag in context["tags"]: self.assertEqual(tag.name == "1", tag.active) views.list(mock_req("/?tags=1,2")) context = render.call_args[0][2] for tag in context["tags"]: self.assertEqual(tag.name in ["1", "2"], tag.active)
def test_tag_filter(self, render): """ List of ideas should be filterable by tag. """ def add_tag(idea, nonce): tag = str(nonce % 3) idea.tags.add(tag) self._generate_data(postfn=add_tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(4, len(context["ideas"])) views.list(mock_req("/?tags=0")) context = render.call_args[0][2] self.assertEqual(2, len(context["ideas"])) self.assertEqual(set(["BBBB", "CCCC"]), set([i.title for i in context["ideas"]])) views.list(mock_req("/?tags=1")) context = render.call_args[0][2] self.assertEqual(1, len(context["ideas"])) self.assertEqual("DDDD", context["ideas"][0].title) views.list(mock_req("/?tags=1,2")) context = render.call_args[0][2] self.assertEqual(2, len(context["ideas"])) self.assertEqual(set(["DDDD", "AAAA"]), set([i.title for i in context["ideas"]]))
def test_tags_active(self, render): """ Tag list should include if tag was active in this search. """ def add_tag(idea, nonce): tag = str(nonce % 3) idea.tags.add(tag) self._generate_data(postfn=add_tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('tags' in context) for tag in context['tags']: self.assertFalse(tag.active) views.challenge_detail(mock_req('/?tags=0'), banner_id=1) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name == '0', tag.active) views.challenge_detail(mock_req('/?tags=1'), banner_id=1) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name == '1', tag.active) views.challenge_detail(mock_req('/?tags=1,2'), banner_id=1) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name in ['1','2'], tag.active)
def test_tags_active(self, render): """ Tag list should include if tag was active in this search. """ def add_tag(idea, nonce): tag = str(nonce % 3) idea.tags.add(tag) self._generate_data(postfn=add_tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('tags' in context) for tag in context['tags']: self.assertFalse(tag.active) views.list(mock_req('/?tags=0')) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name == '0', tag.active) views.list(mock_req('/?tags=1')) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name == '1', tag.active) views.list(mock_req('/?tags=1,2')) context = render.call_args[0][2] for tag in context['tags']: self.assertEqual(tag.name in ['1', '2'], tag.active)
def test_banner_is_current(self, render): """ Test boolean flag for banner status (active or not) """ yesterday = get_relative_date(-1) today = datetime.date.today() tomorrow = get_relative_date(+1) banner = models.Banner(id=1, title="XXXX", text="text", start_date=today) banner.save() banner2 = models.Banner(id=2, title="XXXX", text="text", start_date=tomorrow) banner2.save() banner3 = models.Banner(id=3, title="XXXX", text="text", start_date=yesterday, end_date=today) banner3.save() views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('is_current_banner' in context) self.assertTrue(context['is_current_banner']) views.challenge_detail(mock_req(), banner_id=2) context = render.call_args[0][2] self.assertTrue('is_current_banner' in context) self.assertFalse(context['is_current_banner']) views.challenge_detail(mock_req(), banner_id=3) context = render.call_args[0][2] self.assertTrue('is_current_banner' in context) self.assertTrue(context['is_current_banner'])
def test_edit_idea_with_private_banner(self, render): """ Verify that the private banner field auto-populates properly """ user = login(self) state = models.State.objects.get(name='Active') idea1 = models.Idea(creator=user, title='Transit subsidy to Venus', text='Aliens need assistance.', state=state) banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today(), is_private=True) banner1.save() idea1.banner = banner1 idea1.save() idea2 = models.Idea(creator=user, title='Transit subsidy to Venus', text='Aliens need assistance.', state=state) banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today()) banner2.save() idea2.banner = banner2 idea2.save() views.edit_idea(mock_req(user=user), idea1.id) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner1.id, selected) self.assertEqual( context['form'].fields['banner'].widget.choices.field.empty_label, None) self.assertIn(banner1, banner_field._queryset) self.assertNotIn(banner2, banner_field._queryset) views.edit_idea(mock_req(user=user), idea2.id) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertFalse(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner2.id, selected) self.assertEqual( context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertNotIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset)
def test_add_idea_with_banner(self, render): """ Verify that the banner field auto-populates properly """ banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today()) banner1.save() banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today(), end_date=date.today() + timedelta(days=1)) banner2.save() banner3 = models.Banner(id=3, title="BBBB", text="text3", start_date=date.today() - timedelta(days=2), end_date=date.today() - timedelta(days=1)) banner3.save() views.add_idea(mock_req()) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], IdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(None, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset) self.assertNotIn(banner3, banner_field._queryset) views.add_idea(mock_req(), banner1.id) context = render.call_args[0][2] banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner1.id, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset) self.assertNotIn(banner3, banner_field._queryset) views.add_idea(mock_req(), banner2.id) context = render.call_args[0][2] banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner2.id, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset) self.assertNotIn(banner3, banner_field._queryset) views.add_idea(mock_req(), banner3.id) context = render.call_args[0][2] banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(None, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset) self.assertNotIn(banner3, banner_field._queryset)
def test_add_idea_with_private_banner(self, render): """ Verify that the private banner field auto-populates properly """ banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today(), is_private=True) banner1.save() banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today()) banner2.save() views.add_idea(mock_req()) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertFalse(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(None, selected) self.assertEqual( context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertNotIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset) views.add_idea(mock_req(), banner1.id) context = render.call_args[0][2] self.assertTrue(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner1.id, selected) self.assertEqual( context['form'].fields['banner'].widget.choices.field.empty_label, None) self.assertIn(banner1, banner_field._queryset) self.assertNotIn(banner2, banner_field._queryset) views.add_idea(mock_req(), banner2.id) context = render.call_args[0][2] self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertFalse(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual( context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertEqual(banner2.id, selected) self.assertNotIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset)
def test_current_banner(self, render): """ Check that the current banner is populated """ views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("banner" in context) self.assertIsNone(context["banner"]) banner = create_banner("AAAA") views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("banner" in context) self.assertEqual(context["banner"], banner)
def test_current_banner(self, render): """ Check that the current banner is populated """ views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('banner' in context) self.assertIsNone(context['banner']) banner = create_banner('AAAA') views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('banner' in context) self.assertEqual(context['banner'], banner)
def test_tag_filter(self, render): """ List of ideas should be filterable by tag. """ def add_tag(idea, nonce): #entry_data=[(5, 'AAAA'), (9, 'BBBB'), (3, 'CCCC'), (7, 'DDDD'), # (1, 'EEEE'), (11, 'FFFF')]): tag = str(nonce % 3) # results: 2 0 0 1 1 2 idea.tags.add(tag) tag = str(nonce % 7) # results: 5 2 3 0 1 4 idea.tags.add(tag) self._generate_data(postfn=add_tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(6, len(context['ideas'])) self.assertEqual(6, len(context['tags'])) self.assertEqual(set(['0', '1', '2', '3', '4', '5']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=0'), banner_id=1) context = render.call_args[0][2] self.assertEqual(3, len(context['ideas'])) self.assertEqual(set(['BBBB', 'CCCC', 'DDDD']), set([i.title for i in context['ideas']])) self.assertEqual(4, len(context['tags'])) self.assertEqual(set(['0', '1', '2', '3']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=2'), banner_id=1) context = render.call_args[0][2] self.assertEqual(3, len(context['ideas'])) self.assertEqual(set(['AAAA', 'BBBB', 'FFFF']), set([i.title for i in context['ideas']])) self.assertEqual(4, len(context['tags'])) self.assertEqual(set(['0', '2', '4', '5']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=0,2'), banner_id=1) context = render.call_args[0][2] self.assertEqual(1, len(context['ideas'])) self.assertEqual(set(['BBBB']), set([i.title for i in context['ideas']])) self.assertEqual(2, len(context['tags'])) self.assertEqual(set(['0', '2']), set([t.name for t in context['tags']]))
def test_banner_list(self, render): """ Verify that the banner list works. """ def add_dates(kwargs, nonce): baseline_start = -7 baseline_end = -5 # -2 0 # 2 None # -4 None # 0 2 # -6 -4 # 4 6 kwargs['start_date'] = get_relative_date(baseline_start + nonce) if nonce % 3 == 0: kwargs['end_date'] = None else: kwargs['end_date'] = get_relative_date(baseline_end + nonce) self._generate_data(paramfn=add_dates) views.banner_list(mock_req()) context = render.call_args[0][2] self.assertTrue('current_banners' in context) self.assertTrue('past_banners' in context) self.assertEqual(3, len(context['current_banners'])) self.assertEqual(1, len(context['past_banners'])) self.assertEqual('AAAA', context['current_banners'][0].title) self.assertEqual('DDDD', context['current_banners'][1].title) self.assertEqual('CCCC', context['current_banners'][2].title) self.assertEqual('EEEE', context['past_banners'][0].title)
def test_tags_top_list(self, render): """ Tag list should be in proper order. """ user = random_user() state = models.State.objects.get(name='Active') state.save() # Make 13 tags, and assign each to a set of ideas for count in range(30): tag = str(count) * 4 for i in range(count + 1): idea = models.Idea(creator=user, title=str(i) * 4, text=str(i) * 4 + ' Text', state=state) idea.save() idea.tags.add(tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(25, len(context['tags'])) # 29292929, 28282828, 27272727, ... self.assertEqual([str(i) * 4 for i in range(29, 4, -1)], [t.name for t in context['tags']])
def test_tags_count(self, render): """ Tag list should include tag count. """ user = random_user() state = models.State.objects.get(name='Active') state.save() self._generate_data(entry_data=None) # Make 13 tags, and assign each to a set of ideas for count in range(13): tag = str(count) * 4 for i in range(count + 1): idea = models.Idea(creator=user, title=str(i) * 4, text=str(i) * 4 + ' Text', state=state, banner_id=1) idea.save() idea.tags.add(tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('tags' in context) for i in range(12, 2, -1): tag = context['tags'][12 - i] self.assertTrue(hasattr(tag, 'count')) self.assertEqual(i + 1, tag.count)
def test_sort_trending(self, render): """ Verify that the comments sort works. """ idea_type = ContentType.objects.get(app_label="idea", model="idea") site = Site.objects.get_current() def add_time(kwargs, nonce): # add future timestamp for item 3 if nonce == 3: kwargs['time'] = datetime.datetime( 2050, 1, nonce, tzinfo=get_default_timezone()) def create_timestamp_event(idea, nonce): # add future timestamp for vote for items 0, 2, 4 if nonce % 2 == 0: models.Vote(creator=idea.creator, idea=idea, time=datetime.datetime( 2050, 1, nonce, tzinfo=get_default_timezone())).save() # add future timestamp for comment for items 1, 5 elif nonce != 3: MPTTComment(content_type=idea_type, site=site, object_pk=idea.pk, user=idea.creator, comment='Blah', submit_date=datetime.datetime( 2050, 1, nonce, tzinfo=get_default_timezone())).save() self._generate_data(postfn=create_timestamp_event, paramfn=add_time) views.list(mock_req(), sort_or_state='trending') self._verify_order(render)
def test_similar(self, render): """ List of similar ideas should make sense. """ class Mock(): pass with patch('idea.views.more_like_text') as mlt: backend = connections['default'].get_backend() backend.clear() user = random_user() state = models.State.objects.get(name='Active') similar1 = models.Idea(creator=user, title='airplanes', state=state, text="Title is enough said.") similar1.save() similar2 = models.Idea(creator=user, title='exexex', state=state, text="I, too, love submarines.") similar2.save() models.Idea(creator=user, title='AAAAAA', state=state, text='BBBBBB').save() m1, m2 = Mock(), Mock() m1.object = similar1 m2.object = similar2 mlt.return_value = [m1, m2] views.add_idea(mock_req('/?idea_title=' + 'Airplanes%20and%20submarines')) context = render.call_args[0][2] self.assertTrue('similar' in context) self.assertEqual(2, len(context['similar'])) self.assertEqual(set(context['similar']), set([similar1, similar2]))
def test_tags_top_list(self, render): """ Tag list should be in proper order. """ user = random_user() state = models.State.objects.get(name='Active') state.save() self._generate_data(entry_data=None) # Make 13 tags, and assign each to a set of ideas for count in range(30): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4, text=str(i)*4 +' Text', state=state, banner_id=1) idea.save() idea.tags.add(tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(25, len(context['tags'])) # 29292929, 28282828, 27272727, ... self.assertEqual([str(i)*4 for i in range(29,4,-1)], [t.name for t in context['tags']])
def test_tags_count(self, render): """ Tag list should include tag count. """ user = random_user() state = models.State.objects.get(name='Active') state.save() self._generate_data(entry_data=None) # Make 13 tags, and assign each to a set of ideas for count in range(13): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4, text=str(i)*4 +' Text', state=state, banner_id=1) idea.save() idea.tags.add(tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('tags' in context) for i in range(12,2,-1): tag = context['tags'][12-i] self.assertTrue(hasattr(tag, 'count')) self.assertEqual(i+1, tag.count)
def test_similar(self, render): """ List of similar ideas should make sense. """ class Mock: pass with patch("idea.views.more_like_text") as mlt: backend.SearchBackend().clear() user = random_user() state = models.State.objects.get(name="Active") similar1 = models.Idea(creator=user, title="airplanes", state=state, text="Title is enough said.") similar1.save() similar2 = models.Idea(creator=user, title="exexex", state=state, text="I, too, love submarines.") similar2.save() models.Idea(creator=user, title="AAAAAA", state=state, text="BBBBBB").save() m1, m2 = Mock(), Mock() m1.object = similar1 m2.object = similar2 mlt.return_value = [m1, m2] views.add_idea(mock_req("/?idea_title=" + "Airplanes%20and%20submarines")) context = render.call_args[0][2] self.assertTrue("similar" in context) self.assertEqual(2, len(context["similar"])) self.assertEqual(set(context["similar"]), set([similar1, similar2]))
def test_exclude_private_tags(self, render): """ Check that the tag list does not include tags only used for private banners """ user = random_user() state = models.State.objects.get(name='Active') state.save() pub_banner = create_banner('Public') priv_banner = create_banner('Private', is_private=True) pub_idea = models.Idea(creator=user, title='AAAA', text='AAAA Text', state=state, banner_id=pub_banner.id) pub_idea.save() priv_idea = models.Idea(creator=user, title='BBBB', text='BBBB Text', state=state, banner_id=priv_banner.id) priv_idea.save() pub_idea.tags.add('bbb', 'ccc', 'ddd') priv_idea.tags.add('ddd', 'eee', 'fff') views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(3, len(context['tags'])) self.assertEqual(set(['bbb', 'ccc', 'ddd']), set([t.name for t in context['tags']]))
def test_sort_trending(self, render): """ Verify that the comments sort works. """ idea_type = ContentType.objects.get(app_label="idea", model="idea") site = Site.objects.get_current() def add_time(kwargs, nonce): # add future timestamp for item 3 if nonce == 3: kwargs["time"] = datetime.datetime(2050, 1, nonce, tzinfo=get_default_timezone()) def create_timestamp_event(idea, nonce): # add future timestamp for vote for items 0, 2, 4 if nonce % 2 == 0: models.Vote( creator=idea.creator, idea=idea, time=datetime.datetime(2050, 1, nonce, tzinfo=get_default_timezone()), ).save() # add future timestamp for comment for items 1, 5 elif nonce != 3: Comment( content_type=idea_type, site=site, object_pk=idea.pk, user=idea.creator, comment="Blah", submit_date=datetime.datetime(2050, 1, nonce, tzinfo=get_default_timezone()), ).save() self._generate_data(postfn=create_timestamp_event, paramfn=add_time) views.list(mock_req(), sort_or_state="trending") self._verify_order(render)
def test_tag_filter(self, render): """ List of ideas should be filterable by tag. """ def add_tag(idea, nonce): #entry_data=[(5, 'AAAA'), (9, 'BBBB'), (3, 'CCCC'), (7, 'DDDD'), # (1, 'EEEE'), (11, 'FFFF')]): tag = str(nonce % 3) # results: 2 0 0 1 1 2 idea.tags.add(tag) tag = str(nonce % 7) # results: 5 2 3 0 1 4 idea.tags.add(tag) self._generate_data(postfn=add_tag) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(6, len(context['ideas'])) self.assertEqual(6, len(context['tags'])) self.assertEqual(set(['0','1','2','3','4','5']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=0'), banner_id=1) context = render.call_args[0][2] self.assertEqual(3, len(context['ideas'])) self.assertEqual(set(['BBBB', 'CCCC', 'DDDD']), set([i.title for i in context['ideas']])) self.assertEqual(4, len(context['tags'])) self.assertEqual(set(['0','1','2','3']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=2'), banner_id=1) context = render.call_args[0][2] self.assertEqual(3, len(context['ideas'])) self.assertEqual(set(['AAAA', 'BBBB', 'FFFF']), set([i.title for i in context['ideas']])) self.assertEqual(4, len(context['tags'])) self.assertEqual(set(['0','2','4','5']), set([t.name for t in context['tags']])) views.challenge_detail(mock_req('/?tags=0,2'), banner_id=1) context = render.call_args[0][2] self.assertEqual(1, len(context['ideas'])) self.assertEqual(set(['BBBB']), set([i.title for i in context['ideas']])) self.assertEqual(2, len(context['tags'])) self.assertEqual(set(['0','2']), set([t.name for t in context['tags']]))
def test_paging(self, render): """ Verify that paging works as we would expect. """ letters = string.uppercase entry_data = [] ## current default ordering is based on most recently modified ## Count down from 12 to 1, so A has the most recent timestamp for i in range(12, -1, -1): entry_data.append((i + 1, letters[i] * 4)) self._generate_data(entry_data=entry_data) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.list(mock_req('/?page_num=1')) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.list(mock_req('/?page_num=sadasds')) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.list(mock_req('/?page_num=2')) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(3, len(context['ideas'])) self.assertEqual('KKKK', context['ideas'][0].title) self.assertEqual('MMMM', context['ideas'][2].title) views.list(mock_req('/?page_num=232432')) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(3, len(context['ideas'])) self.assertEqual('KKKK', context['ideas'][0].title) self.assertEqual('MMMM', context['ideas'][2].title)
def test_paging(self, render): """ Verify that paging works as we would expect. """ letters = string.uppercase entry_data = [] ## current default ordering is based on most recently modified ## Count down from 12 to 1, so A has the most recent timestamp for i in range(12, -1, -1): entry_data.append((i + 1, letters[i] * 4)) self._generate_data(entry_data=entry_data) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=1")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=sadasds")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=2")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(3, len(context["ideas"])) self.assertEqual("KKKK", context["ideas"][0].title) self.assertEqual("MMMM", context["ideas"][2].title) views.list(mock_req("/?page_num=232432")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(3, len(context["ideas"])) self.assertEqual("KKKK", context["ideas"][0].title) self.assertEqual("MMMM", context["ideas"][2].title)
def test_edit_idea_with_private_banner(self, render): """ Verify that the private banner field auto-populates properly """ user = login(self) state = models.State.objects.get(name='Active') idea1 = models.Idea(creator=user, title='Transit subsidy to Venus', text='Aliens need assistance.', state=state) banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today(), is_private=True) banner1.save() idea1.banner = banner1 idea1.save() idea2 = models.Idea(creator=user, title='Transit subsidy to Venus', text='Aliens need assistance.', state=state) banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today()) banner2.save() idea2.banner = banner2 idea2.save() views.edit_idea(mock_req(user=user), idea1.id) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner1.id, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, None) self.assertIn(banner1, banner_field._queryset) self.assertNotIn(banner2, banner_field._queryset) views.edit_idea(mock_req(user=user), idea2.id) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertFalse(isinstance(context['form'], PrivateIdeaForm)) banner_field = context['form'].fields['banner'] selected = context['form'].initial['banner'] self.assertEqual(banner2.id, selected) self.assertEqual(context['form'].fields['banner'].widget.choices.field.empty_label, 'Select') self.assertNotIn(banner1, banner_field._queryset) self.assertIn(banner2, banner_field._queryset)
def test_paging(self, render): """ Verify that paging works as we would expect. """ letters = string.uppercase entry_data = [] ## Count down from 12 to 1, so A has the most recent timestamp for i in range(12, -1, -1): entry_data.append((i+1, letters[i]*4)) self._generate_data(entry_data=entry_data) views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.challenge_detail(mock_req('/?page_num=1'), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.challenge_detail(mock_req('/?page_num=sadasds'), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(10, len(context['ideas'])) self.assertEqual('AAAA', context['ideas'][0].title) self.assertEqual('EEEE', context['ideas'][4].title) views.challenge_detail(mock_req('/?page_num=2'), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(3, len(context['ideas'])) self.assertEqual('KKKK', context['ideas'][0].title) self.assertEqual('MMMM', context['ideas'][2].title) views.challenge_detail(mock_req('/?page_num=232432'), banner_id=1) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(3, len(context['ideas'])) self.assertEqual('KKKK', context['ideas'][0].title) self.assertEqual('MMMM', context['ideas'][2].title)
def test_sort(self, render): """ Verify sort order. """ def add_time(kwargs, nonce): kwargs['time'] = datetime.datetime(2013, 1, nonce, tzinfo=get_default_timezone()) self._generate_data(paramfn=add_time) views.challenge_detail(mock_req(), banner_id=1) self._verify_order(render)
def test_sort_recent(self, render): """ Verify that the recent sort params works. """ def add_time(kwargs, nonce): kwargs['time'] = datetime(2013, 1, nonce, tzinfo=get_default_timezone()) self._generate_data(paramfn=add_time) views.list(mock_req(), sort_or_state='recent') self._verify_order(render)
def test_private_sort(self, render): """ Verify sort order. """ def add_time(kwargs, nonce): kwargs['time'] = datetime.datetime(2013, 1, nonce, tzinfo=get_default_timezone()) self._generate_data(paramfn=add_time) views.room_detail(mock_req(), slug='xxxx') self._verify_order(render)
def test_paging(self, render): """ Verify that paging works as we would expect. """ letters = string.uppercase entry_data = [] for i in range(13): entry_data.append((1, letters[i] * 4)) self._generate_data(entry_data=entry_data) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=1")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=sadasds")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(10, len(context["ideas"])) self.assertEqual("AAAA", context["ideas"][0].title) self.assertEqual("EEEE", context["ideas"][4].title) views.list(mock_req("/?page_num=2")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(3, len(context["ideas"])) self.assertEqual("KKKK", context["ideas"][0].title) self.assertEqual("MMMM", context["ideas"][2].title) views.list(mock_req("/?page_num=232432")) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(3, len(context["ideas"])) self.assertEqual("KKKK", context["ideas"][0].title) self.assertEqual("MMMM", context["ideas"][2].title)
def test_private_tags_count(self, render): """ Tag list should include tag count. """ user = random_user() state = models.State.objects.get(name='Active') state.save() self._generate_data(entry_data=None) # Make 13 tags, and assign each to a set of ideas for count in range(13): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4, text=str(i)*4 +' Text', state=state, banner_id=1) idea.save() idea.tags.add(tag) # create some dummy tags that are not part of this banner's ideas for count in range(2): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4+'2', text=str(i)*42 +' Text', state=state) idea.save() idea.tags.add(tag) banner = models.Banner(id=2, title="XXXX", text="text", is_private=True, start_date=datetime.date.today()) banner.save() for count in range(2): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4+'3', text=str(i)*4 +'3 Text', state=state, banner_id=2) idea.save() idea.tags.add(tag) banner = models.Banner(id=3, title="XXXX", text="text", is_private=True, start_date=datetime.date.today()) banner.save() for count in range(2): tag = str(count)*4 for i in range(count+1): idea = models.Idea(creator=user, title=str(i)*4+'4', text=str(i)*4 +'4 Text', state=state, banner_id=3) idea.save() idea.tags.add(tag) views.room_detail(mock_req(), slug='xxxx') context = render.call_args[0][2] self.assertTrue('tags' in context) for i in range(12,2,-1): tag = context['tags'][12-i] self.assertTrue(hasattr(tag, 'count')) self.assertEqual(i+1, tag.count)
def test_404s(self): """ Should get a 404 when using a bad idea_id. """ user = get_user_model().objects.create_user('example') state = models.State.objects.get(name='Active') idea = models.Idea(creator=user, title='title', text='text', state=state) idea.save() self.assertRaises(Http404, views.detail, mock_req(), '1234')
def test_sort_vote(self, render): """ Verify that the votes sort works. """ def create_votes(idea, nonce): for _ in range(nonce): models.Vote(creator=idea.creator, idea=idea).save() self._generate_data(postfn=create_votes) views.list(mock_req(), sort_or_state='vote') self._verify_order(render)
def test_404s(self): """ Should get a 404 when using a bad idea_id. """ user = User.objects.create_user('example') state = models.State.objects.get(name='Active') idea = models.Idea(creator=user, title='title', text='text', state=state) idea.save() self.assertRaises(Http404, views.detail, mock_req(), '1234')
def test_private_banner_is_not_current(self, render): """ Test boolean flag for banner status (active or not) """ banner = models.Banner(id=1, title="xxxx", text="text", is_private=True, start_date=datetime.date.today()) banner.save() views.room_detail(mock_req(), slug='xxxx') context = render.call_args[0][2] self.assertTrue('is_current_banner' in context) self.assertFalse(context['is_current_banner'])
def test_tag_form_exists(self, render): """ Detail page should have a form for adding tags. """ idea = models.Idea(creator=random_user(), title='AAAA', state = models.State.objects.get(name='Active')) idea.save() views.detail(mock_req(), str(idea.id)) context = render.call_args[0][2] self.assertTrue('tag_form' in context) self.assertTrue(isinstance(context['tag_form'], IdeaTagForm))
def test_tag_filter(self, render): """ List of ideas should be filterable by tag. """ def add_tag(idea, nonce): tag = str(nonce % 3) # results: 2 0 0 1 1 2 idea.tags.add(tag) tag = str(nonce % 7) # results: 5 2 3 0 1 4 idea.tags.add(tag) self._generate_data(postfn=add_tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(6, len(context["ideas"])) self.assertEqual(6, len(context["tags"])) self.assertEqual(set(["0", "1", "2", "3", "4", "5"]), set([t.name for t in context["tags"]])) views.list(mock_req("/?tags=0")) context = render.call_args[0][2] self.assertEqual(3, len(context["ideas"])) self.assertEqual(set(["BBBB", "CCCC", "DDDD"]), set([i.title for i in context["ideas"]])) self.assertEqual(4, len(context["tags"])) self.assertEqual(set(["0", "1", "2", "3"]), set([t.name for t in context["tags"]])) views.list(mock_req("/?tags=2")) context = render.call_args[0][2] self.assertEqual(3, len(context["ideas"])) self.assertEqual(set(["AAAA", "BBBB", "FFFF"]), set([i.title for i in context["ideas"]])) self.assertEqual(4, len(context["tags"])) self.assertEqual(set(["0", "2", "4", "5"]), set([t.name for t in context["tags"]])) views.list(mock_req("/?tags=0,2")) context = render.call_args[0][2] self.assertEqual(1, len(context["ideas"])) self.assertEqual(set(["BBBB"]), set([i.title for i in context["ideas"]])) self.assertEqual(2, len(context["tags"])) self.assertEqual(set(["0", "2"]), set([t.name for t in context["tags"]]))
def test_idea_state_filter(self, render): """ Verify that state filters work as we expect. """ def check_state(kwargs, nonce): if nonce % 2 == 0: kwargs['state'] = models.State.objects.get(name='Archive') self._generate_data(entry_data=[(1, 'AAAA'), (2, 'BBBB'), (3, 'CCCC')], paramfn=check_state) # defaults to active views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(2, len(context['ideas'])) # But archive works views.list(mock_req(), sort_or_state='archived') context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(1, len(context['ideas']))
def test_idea_state_filter(self, render): """ Verify that state filters work as we expect. """ def check_state(kwargs, nonce): if nonce % 2 == 0: kwargs["state"] = models.State.objects.get(name="Archive") self._generate_data(entry_data=[(1, "AAAA"), (2, "BBBB"), (3, "CCCC")], paramfn=check_state) # defaults to active views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(2, len(context["ideas"])) # But archive works views.list(mock_req(), sort_or_state="archived") context = render.call_args[0][2] self.assertTrue("ideas" in context) self.assertEqual(1, len(context["ideas"]))
def test_idea_state_filter(self, render): """ Verify that state filters work as we expect. """ def check_state(kwargs, nonce): if nonce % 2 == 0: kwargs['state'] = models.State.objects.get(name='Archive') self._generate_data(entry_data=[(1,'AAAA'), (2,'BBBB'), (3,'CCCC')], paramfn=check_state) # defaults to active views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(2, len(context['ideas'])) # But archive works views.list(mock_req(), sort_or_state='archived') context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(1, len(context['ideas']))
def test_sort_recent(self, render): """ Verify that the recent sort params works. """ def add_time(kwargs, nonce): kwargs['time'] = datetime.datetime(2013, 1, nonce, tzinfo=get_default_timezone()) self._generate_data(paramfn=add_time) views.list(mock_req(), sort_or_state='recent') self._verify_order(render)
def test_sort_comment(self, render): """ Verify that the comments sort works. """ idea_type = ContentType.objects.get(app_label="idea", model="idea") site = Site.objects.get_current() def create_comments(idea, nonce): for _ in range(nonce): Comment(content_type=idea_type, site=site, object_pk=idea.pk, user=idea.creator, comment="Blah").save() self._generate_data(postfn=create_comments) views.list(mock_req(), sort_or_state="comment") self._verify_order(render)
def test_browse_banners(self, render): """ Check that the banner list is populated if more than one active banner """ views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("browse_banners" in context) self.assertIsNone(context["browse_banners"]) create_banner("AAAA", 3) create_banner("BBBB", 2) create_banner("CCCC", 1) create_banner("DDDD", 6) create_banner("EEEE", 5) create_banner("FFFF", 4) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue("browse_banners" in context) self.assertEqual(len(context["browse_banners"]), 4) self.assertEqual(context["browse_banners"][0].title, "BBBB") self.assertEqual(context["browse_banners"][1].title, "AAAA") self.assertEqual(context["browse_banners"][2].title, "FFFF") self.assertEqual(context["browse_banners"][3].title, "EEEE")
def test_browse_banners(self, render): """ Check that the banner list is populated if more than one active banner """ views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('browse_banners' in context) self.assertIsNone(context['browse_banners']) create_banner('AAAA', 3) create_banner('BBBB', 2) create_banner('CCCC', 1) create_banner('DDDD', 6) create_banner('EEEE', 5) create_banner('FFFF', 4) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('browse_banners' in context) self.assertEqual(len(context['browse_banners']), 4) self.assertEqual(context['browse_banners'][0].title, 'BBBB') self.assertEqual(context['browse_banners'][1].title, 'AAAA') self.assertEqual(context['browse_banners'][2].title, 'FFFF') self.assertEqual(context['browse_banners'][3].title, 'EEEE')
def test_idea_correct(self, render): """ The idea passed to the ui should be that identified by the id. """ user = User.objects.create_user('example') state = models.State.objects.get(name='Active') idea1 = models.Idea(creator=user, title='title', text='text', state=state) idea2 = models.Idea(creator=user, title='title', text='text', state=state) idea1.save() idea2.save() views.detail(mock_req(), str(idea2.id)) context = render.call_args[0][2] self.assertTrue('idea' in context) self.assertEqual(idea2.id, context['idea'].id) self.assertEqual(idea2.title, context['idea'].title)
def test_idea_no_support(self, render): """ Check support = False if no votes. """ user = random_user() state = models.State.objects.get(name='Active') idea = models.Idea(creator=user, title='title', text='text', state=state) idea.save() for _ in range(7): models.Vote(creator=random_user(), idea=idea).save() views.detail(mock_req(), str(idea.id)) context = render.call_args[0][2] self.assertTrue('support' in context) self.assertFalse(context['support'])
def test_tags_count(self, render): """ Tag list should include tag count. """ user = random_user() state = models.State.objects.get(name='Active') state.save() # Make 13 tags, and assign each to a set of ideas for count in range(13): tag = str(count) * 4 for i in range(count + 1): idea = models.Idea(creator=user, title=str(i) * 4, text=str(i) * 4 + ' Text', state=state) idea.save() idea.tags.add(tag) # create some dummy tags for private banner ideas # these tags should not be reflected in the tag count banner = models.Banner(id=1, title="XXXX", text="text", is_private=True, start_date=datetime.date.today()) banner.save() for count in range(5): tag = str(count) * 4 for i in range(count + 1): idea = models.Idea(creator=user, title=str(i) * 4 + '2', text=str(i) * 42 + ' Text', state=state, banner_id=1) idea.save() idea.tags.add(tag) views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('tags' in context) for i in range(12, 2, -1): tag = context['tags'][12 - i] self.assertTrue(hasattr(tag, 'count')) self.assertEqual(i + 1, tag.count)
def test_idea_fields(self, render): """ Verify that the fields needed by the ui are available on all ideas. """ self._generate_data() views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('ideas' in context) self.assertEqual(6, len(context['ideas'])) for idea in context['ideas']: self.assertTrue(hasattr(idea, 'title')) self.assertTrue(hasattr(idea, 'url')) self.assertTrue(hasattr(idea.creator, 'first_name')) self.assertTrue(hasattr(idea.creator, 'last_name')) #self.assertTrue(hasattr(idea.creator, 'photo')) #self.assertTrue(hasattr(idea, 'comment_count')) self.assertTrue(hasattr(idea, 'vote_count')) self.assertTrue(hasattr(idea, 'time'))
def test_tags(self, render): """ Include a sorted list of tags for this idea. """ user = random_user() state = models.State.objects.get(name='Active') idea = models.Idea(creator=user, title='title', text='text', state=state) idea.save() tags = [str(random.randint(11111, 99999)) for _ in range(20)] idea.tags.add(*tags) views.detail(mock_req(), str(idea.id)) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(20, len(context['tags'])) tags.sort() self.assertEqual(tags, [tag.name for tag in context['tags']])
def test_idea_voters(self, render): """ The idea passed to the ui should have the correct voters. """ user = User.objects.create_user('example') state = models.State.objects.get(name='Active') idea = models.Idea(creator=user, title='title', text='text', state=state) idea.save() users = [] for i in range(5): users.append(User.objects.create_user('example' + str(i))) models.Vote(creator=users[i], idea=idea).save() views.detail(mock_req(), str(idea.id)) context = render.call_args[0][2] self.assertTrue('voters' in context) self.assertEqual(5, len(context['voters'])) self.assertEqual(set([u.id for u in users]), set([v.id for v in context['voters']]))
def test_tags_exist(self, render): """ Check that the tag list is populated and only shows the top ten tags. """ user = random_user() state = models.State.objects.get(name='Active') state.save() idea = models.Idea(creator=user, title='AAAA', text='AAAA Text', state=state) idea.save() idea.tags.add('bbb', 'ccc', 'ddd') views.list(mock_req()) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(3, len(context['tags'])) self.assertEqual(set(['bbb', 'ccc', 'ddd']), set([t.name for t in context['tags']]))
def test_similar(self, render): """ List of similar ideas should make sense. """ class Mock(): pass with patch('idea.views.more_like_text') as mlt: backend.SearchBackend().clear() user = random_user() state = models.State.objects.get(name='Active') similar1 = models.Idea(creator=user, title='airplanes', state=state, text="Title is enough said.") similar1.save() similar2 = models.Idea(creator=user, title='exexex', state=state, text="I, too, love submarines.") similar2.save() models.Idea(creator=user, title='AAAAAA', state=state, text='BBBBBB').save() m1, m2 = Mock(), Mock() m1.object = similar1 m2.object = similar2 mlt.return_value = [m1, m2] views.add_idea( mock_req('/?idea_title=' + 'Airplanes%20and%20submarines')) context = render.call_args[0][2] self.assertTrue('similar' in context) self.assertEqual(2, len(context['similar'])) self.assertEqual(set(context['similar']), set([similar1, similar2]))
def test_add_idea_with_no_banner(self, render): """ Verify that the banner field disappears if no current challenge """ banner1 = models.Banner(id=1, title="AAAA", text="text1", start_date=date.today() - timedelta(days=2), end_date=date.today() - timedelta(days=1)) banner1.save() banner2 = models.Banner(id=2, title="BBBB", text="text2", start_date=date.today() + timedelta(days=1)) banner2.save() views.add_idea(mock_req()) context = render.call_args[0][2] self.assertTrue('form' in context) self.assertTrue(isinstance(context['form'], IdeaForm)) self.assertNotIn('banner', context['form'].fields.keys())
def test_tags_exist(self, render): """ Check that the tag list is populated. """ user = random_user() state = models.State.objects.get(name='Active') state.save() self._generate_data(entry_data=None) idea = models.Idea(creator=user, title='AAAA', text='AAAA Text', state=state, banner_id=1) idea.save() idea.tags.add('bbb', 'ccc', 'ddd') views.challenge_detail(mock_req(), banner_id=1) context = render.call_args[0][2] self.assertTrue('tags' in context) self.assertEqual(3, len(context['tags'])) self.assertEqual(set(['bbb', 'ccc', 'ddd']), set([t.name for t in context['tags']]))