PageRenderTime 40ms CodeModel.GetById 18ms app.highlight 19ms RepoModel.GetById 0ms app.codeStats 0ms

/actstream/tests.py

https://bitbucket.org/rafacouto/agora-ciudadana-fork
Python | 369 lines | 305 code | 42 blank | 22 comment | 6 complexity | 839eca24b1adf1d259c1edad6e0be846 MD5 | raw file
  1from random import choice
  2
  3from django.db import connection
  4from django.db.models import get_model
  5from django.test import TestCase
  6from django.conf import settings
  7from django.contrib.auth.models import User, AnonymousUser, Group
  8from django.contrib.contenttypes.models import ContentType
  9from django.contrib.sites.models import Site
 10from django.template.loader import Template, Context
 11
 12from actstream.models import Action, Follow, model_stream, user_stream,\
 13    setup_generic_relations
 14from actstream.actions import follow, unfollow
 15from actstream.exceptions import ModelNotActionable
 16from actstream.signals import action
 17from actstream import settings as actstream_settings
 18
 19
 20class ActivityBaseTestCase(TestCase):
 21    actstream_models = ()
 22
 23    def setUp(self):
 24        self.old_MODELS = actstream_settings.MODELS
 25        actstream_settings.MODELS = {}
 26        for model in self.actstream_models:
 27            actstream_settings.MODELS[model.lower()] = \
 28                get_model(*model.split('.'))
 29        setup_generic_relations()
 30
 31    def tearDown(self):
 32        actstream_settings.MODELS = self.old_MODELS
 33
 34
 35class ActivityTestCase(ActivityBaseTestCase):
 36    urls = 'actstream.urls'
 37    actstream_models = ('auth.User', 'auth.Group', 'sites.Site')
 38
 39    def setUp(self):
 40        super(ActivityTestCase, self).setUp()
 41        self.group = Group.objects.create(name='CoolGroup')
 42        self.user1 = User.objects.get_or_create(username='admin')[0]
 43        self.user1.set_password('admin')
 44        self.user1.is_superuser = self.user1.is_staff = True
 45        self.user1.save()
 46        self.user2 = User.objects.get_or_create(username='Two')[0]
 47
 48        # User1 joins group
 49        self.user1.groups.add(self.group)
 50        action.send(self.user1, verb='joined', target=self.group)
 51
 52        # User1 follows User2
 53        follow(self.user1, self.user2)
 54
 55        # User2 joins group
 56        self.user2.groups.add(self.group)
 57        action.send(self.user2, verb='joined', target=self.group)
 58
 59        # User2 follows group
 60        follow(self.user2, self.group)
 61
 62        # User1 comments on group
 63        # Use a site object here and predict the "__unicode__ method output"
 64        action.send(self.user1, verb='commented on', target=self.group)
 65        self.comment = Site.objects.create(
 66            domain="admin: Sweet Group!...")
 67
 68        # Group responds to comment
 69        action.send(self.group, verb='responded to', target=self.comment)
 70
 71    def test_aauser1(self):
 72        self.assertEqual(map(unicode, self.user1.actor_actions.all()), [
 73            u'admin commented on CoolGroup 0 minutes ago',
 74            u'admin started following Two 0 minutes ago',
 75            u'admin joined CoolGroup 0 minutes ago',
 76        ])
 77
 78    def test_user2(self):
 79        self.assertEqual(map(unicode, Action.objects.actor(self.user2)), [
 80            u'Two started following CoolGroup 0 minutes ago',
 81            u'Two joined CoolGroup 0 minutes ago',
 82        ])
 83
 84    def test_group(self):
 85        self.assertEqual(map(unicode, Action.objects.actor(self.group)),
 86            [u'CoolGroup responded to admin: Sweet Group!... 0 minutes ago'])
 87
 88    def test_empty_follow_stream(self):
 89        unfollow(self.user1, self.user2)
 90        self.assert_(not user_stream(self.user1))
 91
 92    def test_stream(self):
 93        self.assertEqual(map(unicode, Action.objects.user(self.user1)), [
 94            u'Two started following CoolGroup 0 minutes ago',
 95            u'Two joined CoolGroup 0 minutes ago',
 96        ])
 97        self.assertEqual(map(unicode, Action.objects.user(self.user2)),
 98            [u'CoolGroup responded to admin: Sweet Group!... 0 minutes ago'])
 99
100    def test_stream_stale_follows(self):
101        """
102        Action.objects.user() should ignore Follow objects with stale actor
103        references.
104        """
105        self.user2.delete()
106        self.assert_(not 'Two' in str(Action.objects.user(self.user1)))
107
108    def test_rss(self):
109        rss = self.client.get('/feed/').content
110        self.assert_(rss.startswith('<?xml version="1.0" encoding="utf-8"?>\n'
111            '<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">'))
112        self.assert_(rss.find('Activity feed for your followed actors') > -1)
113
114    def test_atom(self):
115        atom = self.client.get('/feed/atom/').content
116        self.assert_(atom.startswith('<?xml version="1.0" encoding="utf-8"?>\n'
117            '<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="%s">' %
118                                     settings.LANGUAGE_CODE))
119        self.assert_(atom.find('Activity feed for your followed actors') > -1)
120
121    def test_action_object(self):
122        action.send(self.user1, verb='created comment',
123            action_object=self.comment, target=self.group)
124        created_action = Action.objects.get(verb='created comment')
125
126        self.assertEqual(created_action.actor, self.user1)
127        self.assertEqual(created_action.action_object, self.comment)
128        self.assertEqual(created_action.target, self.group)
129        self.assertEqual(unicode(created_action),
130            u'admin created comment admin: Sweet Group!... on CoolGroup 0 '
131                'minutes ago')
132
133    def test_doesnt_generate_duplicate_follow_records(self):
134        g = Group.objects.get_or_create(name='DupGroup')[0]
135        s = User.objects.get_or_create(username='dupuser')[0]
136
137        f1 = follow(s, g)
138        self.assertTrue(f1 is not None, "Should have received a new follow "
139            "record")
140        self.assertTrue(isinstance(f1, Follow), "Returns a Follow object")
141
142        self.assertEquals(1, Follow.objects.filter(user=s, object_id=g.pk,
143            content_type=ContentType.objects.get_for_model(g)).count(),
144            "Should only have 1 follow record here")
145
146        f2 = follow(s, g)
147        self.assertEquals(1, Follow.objects.filter(user=s, object_id=g.pk,
148            content_type=ContentType.objects.get_for_model(g)).count(),
149            "Should still only have 1 follow record here")
150        self.assertTrue(f2 is not None, "Should have received a Follow object")
151        self.assertTrue(isinstance(f2, Follow), "Returns a Follow object")
152        self.assertEquals(f1, f2, "Should have received the same Follow "
153            "object that I first submitted")
154
155    def test_zzzz_no_orphaned_actions(self):
156        actions = self.user1.actor_actions.count()
157        self.user2.delete()
158        self.assertEqual(actions, self.user1.actor_actions.count() + 1)
159
160    def test_generic_relation_accessors(self):
161        self.assertEqual(self.user2.actor_actions.count(), 2)
162        self.assertEqual(self.user2.target_actions.count(), 1)
163        self.assertEqual(self.user2.action_object_actions.count(), 0)
164
165    def test_bad_actionable_model(self):
166        self.assertRaises(ModelNotActionable, follow, self.user1,
167                          ContentType.objects.get_for_model(self.user1))
168
169    def test_hidden_action(self):
170        action = self.user1.actor_actions.all()[0]
171        action.public = False
172        action.save()
173        self.assert_(not action in self.user1.actor_actions.public())
174
175    def test_tag_follow_url(self):
176        src = '{% load activity_tags %}{% activity_follow_url user %}'
177        output = Template(src).render(Context({'user': self.user1}))
178        ct = ContentType.objects.get_for_model(User)
179        self.assertEqual(output, '/follow/%s/%s/' % (ct.pk, self.user1.pk))
180
181    def test_tag_follow_label(self):
182        src = '{% load activity_tags %}'\
183            '{% activity_follow_label other_user yup nope %}'
184
185        # Anonymous.
186        output = Template(src).render(Context({'other_user': self.user1}))
187        self.assertEqual(output, 'nope')
188
189        output = Template(src).render(Context({'user': AnonymousUser(),
190            'other_user': self.user1}))
191        self.assertEqual(output, 'nope')
192
193        # Non follower (user2 does not follow user1).
194        output = Template(src).render(Context({'user': self.user2,
195            'other_user': self.user1}))
196        self.assertEqual(output, 'nope')
197
198        # Follower (user1 follows user2).
199        output = Template(src).render(Context({'user': self.user1,
200            'other_user': self.user2}))
201        self.assertEqual(output, 'yup')
202
203    def test_model_actions_with_kwargs(self):
204        """
205        Testing the model_actions method of the ActionManager
206        by passing kwargs
207        """
208        self.assertEqual(map(unicode, model_stream(self.user1, verb='commented on')), [
209                u'admin commented on CoolGroup 0 minutes ago',
210                ])
211
212    def test_user_stream_with_kwargs(self):
213        """
214        Testing the user method of the ActionManager by passing additional
215        filters in kwargs
216        """
217        self.assertEqual(map(unicode, Action.objects.user(self.user1, verb='joined')), [
218                u'Two joined CoolGroup 0 minutes ago',
219                ])
220
221    def test_is_following_filter(self):
222        src = '{% load activity_tags %}{% if user|is_following:group %}yup{% endif %}'
223        self.assertEqual(Template(src).render(Context({
224            'user': self.user2, 'group': self.group
225        })), u'yup')
226        self.assertEqual(Template(src).render(Context({
227            'user': self.user1, 'group': self.group
228        })), u'')
229
230
231class ZombieTest(ActivityBaseTestCase):
232    actstream_models = ('auth.User',)
233    human = 10
234    zombie = 1
235
236    def setUp(self):
237        super(ZombieTest, self).setUp()
238        settings.DEBUG = True
239
240        player_generator = lambda n, count: [User.objects.create(
241            username='%s%d' % (n, i)) for i in range(count)]
242
243        self.humans = player_generator('human', self.human)
244        self.zombies = player_generator('zombie', self.zombie)
245
246        self.zombie_apocalypse()
247
248    def tearDown(self):
249        settings.DEBUG = False
250        super(ZombieTest, self).tearDown()
251
252    def zombie_apocalypse(self):
253        humans = self.humans[:]
254        zombies = self.zombies[:]
255        while humans:
256            for z in self.zombies:
257                victim = choice(humans)
258                humans.remove(victim)
259                zombies.append(victim)
260                action.send(z, verb='killed', target=victim)
261                if not humans:
262                    break
263
264    def check_query_count(self, queryset):
265        ci = len(connection.queries)
266
267        result = list([map(unicode, (x.actor, x.target, x.action_object))
268            for x in queryset])
269        self.assertTrue(len(connection.queries) - ci <= 4,
270            'Too many queries, got %d expected no more than 4' %
271                len(connection.queries))
272        return result
273
274    def test_query_count(self):
275        queryset = model_stream(User)
276        result = self.check_query_count(queryset)
277        self.assertEqual(len(result), 10)
278
279    def test_query_count_sliced(self):
280        queryset = model_stream(User)[:5]
281        result = self.check_query_count(queryset)
282        self.assertEqual(len(result), 5)
283
284
285class GFKManagerTestCase(TestCase):
286
287    def setUp(self):
288        self.user_ct = ContentType.objects.get_for_model(User)
289        self.group_ct = ContentType.objects.get_for_model(Group)
290        self.group, _ = Group.objects.get_or_create(name='CoolGroup')
291        self.user1, _ = User.objects.get_or_create(username='admin')
292        self.user2, _ = User.objects.get_or_create(username='Two')
293        self.user3, _ = User.objects.get_or_create(username='Three')
294        self.user4, _ = User.objects.get_or_create(username='Four')
295        Action.objects.get_or_create(
296            actor_content_type=self.user_ct,
297            actor_object_id=self.user1.id,
298            verb='followed',
299            target_content_type=self.user_ct,
300            target_object_id=self.user2.id
301        )
302        Action.objects.get_or_create(
303            actor_content_type=self.user_ct,
304            actor_object_id=self.user1.id,
305            verb='followed',
306            target_content_type=self.user_ct,
307            target_object_id=self.user3.id
308        )
309        Action.objects.get_or_create(
310            actor_content_type=self.user_ct,
311            actor_object_id=self.user1.id,
312            verb='followed',
313            target_content_type=self.user_ct,
314            target_object_id=self.user4.id
315        )
316        Action.objects.get_or_create(
317            actor_content_type=self.user_ct,
318            actor_object_id=self.user1.id,
319            verb='joined',
320            target_content_type=self.group_ct,
321            target_object_id=self.group.id
322        )
323
324    def test_fetch_generic_relations(self):
325        # baseline without fetch_generic_relations
326        _actions = Action.objects.filter(actor_content_type=self.user_ct,
327            actor_object_id=self.user1.id)
328        actions = lambda: _actions._clone()
329        num_content_types = len(set(actions().values_list(
330            'target_content_type_id', flat=True)))
331        n = actions().count()
332
333        # compare to fetching only 1 generic relation
334        self.assertNumQueries(n + 1,
335            lambda: [a.target for a in actions()])
336        self.assertNumQueries(num_content_types + 2,
337            lambda: [a.target for a in
338                actions().fetch_generic_relations('target')])
339
340        action_targets = [(a.id, a.target) for a in actions()]
341        action_targets_fetch_generic = [(a.id, a.target) for a in
342                actions().fetch_generic_relations('target')]
343        self.assertEqual(action_targets, action_targets_fetch_generic)
344
345        # compare to fetching all generic relations
346        num_content_types = len(set(sum(actions().values_list(
347            'actor_content_type_id', 'target_content_type_id'), ())))
348        self.assertNumQueries(2 * n + 1,
349            lambda: [(a.actor, a.target) for a in actions()])
350        self.assertNumQueries(num_content_types + 2,
351            lambda: [(a.actor, a.target) for a in
352                actions().fetch_generic_relations()])
353
354        action_actor_targets = [(a.id, a.actor, a.target) for a in actions()]
355        action_actor_targets_fetch_generic_all = [
356            (a.id, a.actor, a.target) for a in
357                actions().fetch_generic_relations()]
358        self.assertEqual(action_actor_targets,
359            action_actor_targets_fetch_generic_all)
360
361        # fetch only 1 generic relation, but access both gfks
362        self.assertNumQueries(n + num_content_types + 2,
363            lambda: [(a.actor, a.target) for a in
364                actions().fetch_generic_relations('target')])
365        action_actor_targets_fetch_generic_target = [
366            (a.id, a.actor, a.target) for a in
367                actions().fetch_generic_relations('target')]
368        self.assertEqual(action_actor_targets,
369            action_actor_targets_fetch_generic_target)