Esempio n. 1
0
    def test_follow_disabled(self):
        '''
        Verify that follows don't show up when you disable them in the settings
        '''
        from user.models import UserNotificationSetting
        # disable the follow notifications
        user_id = self.bogus_user.id
        self.set_setting(user_id, FollowVerb,
                         dict(notify_mobile=False, enabled=False))

        # verify that we disabled
        enabled = UserNotificationSetting.objects.enabled_for(
            user_id, FollowVerb)
        self.assertFalse(enabled)

        notification_feedly = NotificationFeedly()
        follows = Follow.objects.all()[:10]

        # clear the feed
        notification_feed = NotificationFeed(user_id)
        notification_feed.delete()

        # make sure that notifications for follows don't show up
        for follow in follows:
            follow.user_id = self.bogus_user2.id
            follow.target_id = user_id
            follow.created_at = datetime.datetime.now()
            activity = follow.create_activity()
            feed = notification_feedly._follow(follow)
            if feed:
                assert not feed.contains(activity)

        # the count should be zero
        self.assertEqual(notification_feed.count_unseen(), 0)
Esempio n. 2
0
    def test_love(self):
        love = Love.objects.all()[:10][0]
        love.created_at = datetime.datetime.now()
        love.influencer_id = self.bogus_user.id
        influencer_feed = NotificationFeed(self.bogus_user.id)
        love.entity.created_by_id = self.bogus_user2.id
        creator_feed = NotificationFeed(self.bogus_user2.id)
        # we want to write two notifications
        # someone loved your find
        # someone loved your love
        notification_feedly = NotificationFeedly()
        # clean slate for testing
        influencer_feed.delete()
        creator_feed.delete()

        # comparison activity
        activity = love.create_activity()
        notification_feedly.add_love(love)

        # influencer feed
        assert influencer_feed.contains(activity)

        # creator feed
        creator_activity = copy.deepcopy(activity)
        creator_activity.extra_context['find'] = True
        assert creator_feed.contains(creator_activity)
Esempio n. 3
0
File: tests.py Progetto: etel/Feedly
    def test_follow_disabled(self):
        '''
        Verify that follows don't show up when you disable them in the settings
        '''
        from user.models import UserNotificationSetting
        # disable the follow notifications
        user_id = self.bogus_user.id
        self.set_setting(
            user_id, FollowVerb, dict(notify_mobile=False, enabled=False))

        # verify that we disabled
        enabled = UserNotificationSetting.objects.enabled_for(
            user_id, FollowVerb)
        self.assertFalse(enabled)

        notification_feedly = NotificationFeedly()
        follows = Follow.objects.all()[:10]

        # clear the feed
        notification_feed = NotificationFeed(user_id)
        notification_feed.delete()

        # make sure that notifications for follows don't show up
        for follow in follows:
            follow.user_id = self.bogus_user2.id
            follow.target_id = user_id
            follow.created_at = datetime.datetime.now()
            activity = follow.create_activity()
            feed = notification_feedly._follow(follow)
            if feed:
                assert not feed.contains(activity)

        # the count should be zero
        self.assertEqual(notification_feed.count_unseen(), 0)
Esempio n. 4
0
    def test_add_love(self):
        # disable the follow notifications
        user_id = self.bogus_user.id
        self.set_setting(user_id, LoveVerb,
                         dict(notify_mobile=False, enabled=False))

        love = Love.objects.all()[:10][0]
        love.created_at = datetime.datetime.now()
        love.influencer_id = user_id
        influencer_feed = NotificationFeed(user_id)
        love.entity.created_by_id = self.bogus_user2.id
        creator_feed = NotificationFeed(self.bogus_user2.id)
        # we want to write two notifications
        # someone loved your find
        # someone loved your love
        notification_feedly = NotificationFeedly()
        # clean slate for testing
        influencer_feed.delete()
        creator_feed.delete()

        # comparison activity
        activity = love.create_activity()
        notification_feedly.add_love(love)

        # influencer is equal to user_id and shouldnt contain the activity
        assert not influencer_feed.contains(activity)

        # creator feed should contain since the settings hasn't been disabled
        creator_activity = copy.deepcopy(activity)
        creator_activity.extra_context['find'] = True
        assert creator_feed.contains(creator_activity)
Esempio n. 5
0
 def _follow(self, follow):
     '''
     Thierry and 3 other people started following you
     '''
     activity = follow.create_activity()
     feed = NotificationFeed(follow.target_id)
     feed.add(activity)
     return feed
Esempio n. 6
0
    def test_add_to_list(self):
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        list_items = ListItem.objects.all()[:1]

        for list_item in list_items:
            list_item.entity.created_by_id = self.bogus_user.id
            notification_feedly.add_to_list(list_item)
            activity = list_item.create_activity()

        assert notification_feed.contains(activity)
Esempio n. 7
0
    def test_add_to_list(self):
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        list_items = ListItem.objects.all()[:1]

        for list_item in list_items:
            list_item.entity.created_by_id = self.bogus_user.id
            notification_feedly.add_to_list(list_item)
            activity = list_item.create_activity()

        assert notification_feed.contains(activity)
Esempio n. 8
0
 def _add_to_list(self, list_item):
     '''
     Guyon added your find to their list back in black
     Guyon and 3 other people added your finds to their lists
     '''
     activity = list_item.create_activity()
     user_id = list_item.list.user_id
     created_by_id = list_item.entity.created_by_id
     if user_id != created_by_id:
         feed = NotificationFeed(created_by_id)
         feed.add(activity)
         return feed
Esempio n. 9
0
 def _add_to_list(self, list_item):
     '''
     Guyon added your find to their list back in black
     Guyon and 3 other people added your finds to their lists
     '''
     activity = list_item.create_activity()
     user_id = list_item.list.user_id
     created_by_id = list_item.entity.created_by_id
     if user_id != created_by_id:
         feed = NotificationFeed(created_by_id)
         feed.add(activity)
         return feed
Esempio n. 10
0
 def _follow(self, follow):
     '''
     Thierry and 3 other people started following you
     '''
     from user.models import UserNotificationSetting
     feed = None
     enabled = UserNotificationSetting.objects.enabled_for(
         follow.target_id, FollowVerb)
     if enabled:
         activity = follow.create_activity()
         feed = NotificationFeed(follow.target_id)
         feed.add(activity)
     return feed
Esempio n. 11
0
 def _follow(self, follow):
     '''
     Thierry and 3 other people started following you
     '''
     from user.models import UserNotificationSetting
     feed = None
     enabled = UserNotificationSetting.objects.enabled_for(
         follow.target_id, FollowVerb)
     if enabled:
         activity = follow.create_activity()
         feed = NotificationFeed(follow.target_id)
         feed.add(activity)
     return feed
Esempio n. 12
0
File: tests.py Progetto: etel/Feedly
    def test_add_love(self):
        # disable the follow notifications
        user_id = self.bogus_user.id
        self.set_setting(
            user_id, LoveVerb, dict(notify_mobile=False, enabled=False))

        love = Love.objects.all()[:10][0]
        love.created_at = datetime.datetime.now()
        love.influencer_id = user_id
        influencer_feed = NotificationFeed(user_id)
        love.entity.created_by_id = self.bogus_user2.id
        creator_feed = NotificationFeed(self.bogus_user2.id)
        # we want to write two notifications
        # someone loved your find
        # someone loved your love
        notification_feedly = NotificationFeedly()
        # clean slate for testing
        influencer_feed.delete()
        creator_feed.delete()

        # comparison activity
        activity = love.create_activity()
        notification_feedly.add_love(love)

        # influencer is equal to user_id and shouldnt contain the activity
        assert not influencer_feed.contains(activity)

        # creator feed should contain since the settings hasn't been disabled
        creator_activity = copy.deepcopy(activity)
        creator_activity.extra_context['find'] = True
        assert creator_feed.contains(creator_activity)
Esempio n. 13
0
    def test_love(self):
        love = Love.objects.all()[:10][0]
        love.created_at = datetime.datetime.now()
        love.influencer_id = self.bogus_user.id
        influencer_feed = NotificationFeed(self.bogus_user.id)
        love.entity.created_by_id = self.bogus_user2.id
        creator_feed = NotificationFeed(self.bogus_user2.id)
        # we want to write two notifications
        # someone loved your find
        # someone loved your love
        notification_feedly = NotificationFeedly()
        # clean slate for testing
        influencer_feed.delete()
        creator_feed.delete()

        # comparison activity
        activity = love.create_activity()
        notification_feedly.add_love(love)

        # influencer feed
        assert influencer_feed.contains(activity)

        # creator feed
        creator_activity = copy.deepcopy(activity)
        creator_activity.extra_context['find'] = True
        assert creator_feed.contains(creator_activity)
Esempio n. 14
0
    def _add_love(self, love):
        '''
        We want to write two notifications
        - someone loved your find
        - someone loved your love
        '''
        from user.models import UserNotificationSetting
        feeds = []
        activity = love.create_notification_activity()

        # send notification about the find
        created_by_id = love.entity.created_by_id
        if love.user_id != created_by_id:
            enabled = UserNotificationSetting.objects.enabled_for(
                created_by_id, LoveVerb)
            if enabled:
                feed = NotificationFeed(created_by_id)
                activity.extra_context['find'] = True
                logger.info('notifying item finder %s', created_by_id)
                feed.add(activity)
                feeds.append(activity)

        # send notification about the love
        if love.user_id != love.influencer_id and love.influencer_id:
            if love.influencer_id != created_by_id:
                enabled = UserNotificationSetting.objects.enabled_for(
                    love.influencer_id, LoveVerb)
                if enabled:
                    logger.info('notifying influencer %s', love.influencer_id)
                    feed = NotificationFeed(love.influencer_id)
                    activity.extra_context.pop('find', True)
                    feed.add(activity)
                    feeds.append(feed)

            return feeds
Esempio n. 15
0
    def test_serialization(self):
        '''
        Test if serialization doesnt take up too much memory
        '''
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]
        follow = Follow.objects.all()[:10][0]
        list_item = ListItem.objects.all()[:1][0]
        notification_feed.add(love.create_activity())
        notification_feed.add(follow.create_activity())
        notification_feed.add(list_item.create_activity())
        size = notification_feed.size()
        self.assertLess(size, 500)
Esempio n. 16
0
    def test_follow(self):
        notification_feedly = NotificationFeedly()
        follows = Follow.objects.all()[:10]

        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        for follow in follows:
            follow.user_id = self.bogus_user2.id
            follow.target_id = self.bogus_user.id
            follow.created_at = datetime.datetime.now()
            activity = follow.create_activity()
            feed = notification_feedly._follow(follow)
            assert feed.contains(activity)

        # influencer feed
        self.assertEqual(notification_feed.count_unseen(), 1)
Esempio n. 17
0
    def test_follow(self):
        notification_feedly = NotificationFeedly()
        follows = Follow.objects.all()[:10]

        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        for follow in follows:
            follow.user_id = self.bogus_user2.id
            follow.target_id = self.bogus_user.id
            follow.created_at = datetime.datetime.now()
            activity = follow.create_activity()
            feed = notification_feedly._follow(follow)
            assert feed.contains(activity)

        # influencer feed
        self.assertEqual(notification_feed.count_unseen(), 1)
Esempio n. 18
0
    def test_scalability(self):
        '''
        Test if everything works if aggregating more than 50 activities
        in one aggregated activity
        '''
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]
        activities = []
        activity = love.create_activity()
        for x in range(110):
            activity = copy.deepcopy(activity)
            activity.extra_context['entity_id'] = x
            activities.append(activity)

        # add them all
        notification_feed.add_many(activities)

        # verify that our feed size doesn't escalate
        for aggregated in notification_feed[:notification_feed.max_length]:
            full_activities = len(aggregated.activities)
            activity_count = aggregated.activity_count
            self.assertEqual(full_activities, 99)
            self.assertEqual(activity_count, 110)
            actor_count = aggregated.actor_count
            self.assertLess(actor_count, 110)

        size = notification_feed.size()
        self.assertLess(size, 6000)
Esempio n. 19
0
    def test_duplicates(self):
        '''
        The task system can often attempt to duplicate an insert
        This should raise an error to prevent weird data
        '''
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]

        for x in range(3):
            love.influencer_id = self.bogus_user.id
            notification_feedly.add_love(love)

        for aggregated in notification_feed[:notification_feed.max_length]:
            activity_count = aggregated.activity_count
            self.assertEqual(activity_count, 1)
Esempio n. 20
0
    def test_duplicates(self):
        '''
        The task system can often attempt to duplicate an insert
        This should raise an error to prevent weird data
        '''
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]

        for x in range(3):
            love.influencer_id = self.bogus_user.id
            notification_feedly.add_love(love)

        for aggregated in notification_feed[:notification_feed.max_length]:
            activity_count = aggregated.activity_count
            self.assertEqual(activity_count, 1)
Esempio n. 21
0
    def test_duplicate_love_unlove(self):
        '''
        Test to verify that we dont end up with multiple notifications
        When users love and unlove the same data
        '''
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]

        for x in range(3):
            love.id = x
            love.influencer_id = self.bogus_user.id
            notification_feedly.add_love(love)

        for aggregated in notification_feed[:notification_feed.max_length]:
            activity_count = aggregated.activity_count
            self.assertEqual(activity_count, 1)
Esempio n. 22
0
    def test_duplicate_love_unlove(self):
        '''
        Test to verify that we dont end up with multiple notifications
        When users love and unlove the same data
        '''
        notification_feedly = NotificationFeedly()
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]

        for x in range(3):
            love.id = x
            love.influencer_id = self.bogus_user.id
            notification_feedly.add_love(love)

        for aggregated in notification_feed[:notification_feed.max_length]:
            activity_count = aggregated.activity_count
            self.assertEqual(activity_count, 1)
Esempio n. 23
0
    def _add_love(self, love):
        '''
        We want to write two notifications
        - someone loved your find
        - someone loved your love
        '''
        from user.models import UserNotificationSetting
        feeds = []
        activity = love.create_notification_activity()

        # send notification about the find
        created_by_id = love.entity.created_by_id
        if love.user_id != created_by_id:
            enabled = UserNotificationSetting.objects.enabled_for(
                created_by_id, LoveVerb)
            if enabled:
                feed = NotificationFeed(created_by_id)
                activity.extra_context['find'] = True
                logger.info('notifying item finder %s', created_by_id)
                feed.add(activity)
                feeds.append(activity)

        # send notification about the love
        if love.user_id != love.influencer_id and love.influencer_id:
            if love.influencer_id != created_by_id:
                enabled = UserNotificationSetting.objects.enabled_for(
                    love.influencer_id, LoveVerb)
                if enabled:
                    logger.info('notifying influencer %s', love.influencer_id)
                    feed = NotificationFeed(love.influencer_id)
                    activity.extra_context.pop('find', True)
                    feed.add(activity)
                    feeds.append(feed)

            return feeds
Esempio n. 24
0
    def test_scalability(self):
        '''
        Test if everything works if aggregating more than 50 activities
        in one aggregated activity
        '''
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]
        activities = []
        activity = love.create_activity()
        for x in range(110):
            activity = copy.deepcopy(activity)
            activity.extra_context['entity_id'] = x
            activities.append(activity)

        # add them all
        notification_feed.add_many(activities)

        # verify that our feed size doesn't escalate
        for aggregated in notification_feed[:notification_feed.max_length]:
            full_activities = len(aggregated.activities)
            activity_count = aggregated.activity_count
            self.assertEqual(full_activities, 99)
            self.assertEqual(activity_count, 110)
            actor_count = aggregated.actor_count
            self.assertLess(actor_count, 110)

        size = notification_feed.size()
        self.assertLess(size, 6000)
Esempio n. 25
0
 def test_add_remove(self):
     '''
     Try to remove an aggregated activity
     '''
     from datetime import datetime, time, timedelta
     love = Love.objects.all()[:1][0]
     feed = NotificationFeed(13)
     # slow version
     activities = []
     feed.delete()
     activity = love.create_activity()
     activities.append(activity)
     feed.add(activity)
     assert feed.contains(activity)
     # sticking in the same activity with a different time should fail
     # within the same day should fail
     activity.time = activity.time - timedelta(seconds=120)
     try:
         feed.add(activity)
         raise ValueError(
             'DuplicateActivityException should have been raised')
     except feedly_exceptions.DuplicateActivityException, e:
         pass
Esempio n. 26
0
 def test_add_remove(self):
     '''
     Try to remove an aggregated activity
     '''
     from datetime import datetime, time, timedelta
     love = Love.objects.all()[:1][0]
     feed = NotificationFeed(13)
     # slow version
     activities = []
     feed.delete()
     activity = love.create_activity()
     activities.append(activity)
     feed.add(activity)
     assert feed.contains(activity)
     # sticking in the same activity with a different time should fail
     # within the same day should fail
     activity.time = activity.time - timedelta(seconds=120)
     try:
         feed.add(activity)
         raise ValueError(
             'DuplicateActivityException should have been raised')
     except feedly_exceptions.DuplicateActivityException, e:
         pass
Esempio n. 27
0
    def test_actor_count(self):
        love = Love.objects.all()[:1][0]
        feed = NotificationFeed(13)
        # setup the activities, all in the same aggregated activity
        activities = []
        feed.delete()
        for x in range(150):
            activity = Activity(love.user, LoveVerb, love, love.user,
                                time=love.created_at, extra_context=dict(x=x))
            activities.append(activity)

        # now the fast insert
        self.assertEqual(int(feed.count()), 0)
        feed.add_many(activities)
        self.assertEqual(int(feed.count()), 1)

        aggregated_activity = feed[:1][0]
        # test our Guesstimate
        self.assertEqual(aggregated_activity.minimized_activities, 51)
        self.assertEqual(aggregated_activity.actor_count, 52)
Esempio n. 28
0
    def test_actor_count(self):
        love = Love.objects.all()[:1][0]
        feed = NotificationFeed(13)
        # setup the activities, all in the same aggregated activity
        activities = []
        feed.delete()
        for x in range(150):
            activity = Activity(love.user,
                                LoveVerb,
                                love,
                                love.user,
                                time=love.created_at,
                                extra_context=dict(x=x))
            activities.append(activity)

        # now the fast insert
        self.assertEqual(int(feed.count()), 0)
        feed.add_many(activities)
        self.assertEqual(int(feed.count()), 1)

        aggregated_activity = feed[:1][0]
        # test our Guesstimate
        self.assertEqual(aggregated_activity.minimized_activities, 51)
        self.assertEqual(aggregated_activity.actor_count, 52)
Esempio n. 29
0
    def test_mark_all(self):
        loves = Love.objects.all()[:3]
        feed = NotificationFeed(13)
        feed.delete()
        activities = [l.create_activity() for l in loves]

        # so we have something to compare to
        aggregator = RecentVerbAggregator()
        aggregated_activities = aggregator.aggregate(activities)

        # insert into the feed
        feed.add_many(activities)

        self.assertEqual(feed.count_unseen(), len(aggregated_activities))
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())
        # sanity check
        self.assertNotEqual(feed.count_unseen(), 0)

        # Activity gets inserted and marked read
        # a new activity is appended which updates the last_seen field
        # the activity is now not seen
        #
        # however mark_all will not update

        # verify that we have zero unseen after mark all
        feed.mark_all(seen=True)
        self.assertEqual(feed.count_unseen(), 0)

        # an update to an activity should kick the count back to one
        activity = activities[0]
        # check if an updated activity still gets marked
        import time
        time.sleep(1)
        activity.time = datetime.datetime.now()
        # hack to make sure its not duplicate
        activity.extra_context['foo'] = 'bar'
        feed.add(activity)

        self.assertEqual(feed.count_unseen(), 1)
        # mark as read again
        feed.mark_all(seen=True)
        self.assertEqual(feed.count_unseen(), 0)
Esempio n. 30
0
    def test_notification_feed(self):
        loves = Love.objects.all()[:10]
        feed = NotificationFeed(13)
        # slow version
        activities = []
        feed.delete()
        for love in loves:
            activity = Activity(love.user,
                                LoveVerb,
                                love,
                                love.user,
                                time=love.created_at,
                                extra_context=dict(hello='world'))
            activities.append(activity)
            feed.add(activity)
            assert feed.contains(activity)

        # so we have something to compare to
        aggregator = RecentVerbAggregator()
        aggregated_activities = aggregator.aggregate(activities)
        # check the feed
        feed_loves = feed[:20]
        self.assertEqual(len(aggregated_activities), len(feed_loves))

        # now the fast version
        feed.delete()
        self.assertEqual(int(feed.count()), 0)
        feed.add_many(activities)
        for activity in activities:
            assert feed.contains(activity)

        # test if we aggregated correctly
        self.assertEqual(feed.count_unseen(), len(aggregated_activities))
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())
        # sanity check
        self.assertNotEqual(feed.count_unseen(), 0)
        # test marking as seen or read
        feed.mark_all(seen=True)
        # verify that the new count is 0
        self.assertEqual(feed.count_unseen(), 0)
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())
Esempio n. 31
0
    def test_serialization(self):
        '''
        Test if serialization doesnt take up too much memory
        '''
        notification_feed = NotificationFeed(self.bogus_user.id)
        notification_feed.delete()

        love = Love.objects.all()[:10][0]
        follow = Follow.objects.all()[:10][0]
        list_item = ListItem.objects.all()[:1][0]
        notification_feed.add(love.create_activity())
        notification_feed.add(follow.create_activity())
        notification_feed.add(list_item.create_activity())
        size = notification_feed.size()
        self.assertLess(size, 500)
Esempio n. 32
0
    def test_mark_all(self):
        loves = Love.objects.all()[:3]
        feed = NotificationFeed(13)
        feed.delete()
        activities = [l.create_activity() for l in loves]

        # so we have something to compare to
        aggregator = RecentVerbAggregator()
        aggregated_activities = aggregator.aggregate(activities)

        # insert into the feed
        feed.add_many(activities)

        self.assertEqual(feed.count_unseen(), len(aggregated_activities))
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())
        # sanity check
        self.assertNotEqual(feed.count_unseen(), 0)

        # Activity gets inserted and marked read
        # a new activity is appended which updates the last_seen field
        # the activity is now not seen
        #
        # however mark_all will not update

        # first insert
        activity = activities[0]
        activity.time = datetime.datetime.now()
        feed.add(activity)
        self.assertNotEqual(feed.count_unseen(), 0)
        feed.mark_all(seen=True)
        self.assertEqual(feed.count_unseen(), 0)

        # check if an updated activity still gets marked
        import time
        time.sleep(1)
        activity.time = datetime.datetime.now()
        # hack to make sure its duplicate
        activity.extra_context['foo'] = 'bar'
        feed.add(activity)

        self.assertEqual(feed.count_unseen(), 1)
        # mark as read again
        feed.mark_all(seen=True)
        self.assertEqual(feed.count_unseen(), 0)
Esempio n. 33
0
    def test_notification_feed(self):
        loves = Love.objects.all()[:10]
        feed = NotificationFeed(13)
        # slow version
        activities = []
        feed.delete()
        for love in loves:
            activity = Activity(love.user, LoveVerb, love, love.user, time=love.created_at, extra_context=dict(hello='world'))
            activities.append(activity)
            feed.add(activity)
            assert feed.contains(activity)

        # so we have something to compare to
        aggregator = RecentVerbAggregator()
        aggregated_activities = aggregator.aggregate(activities)
        # check the feed
        feed_loves = feed[:20]
        self.assertEqual(len(aggregated_activities), len(feed_loves))

        # now the fast version
        feed.delete()
        self.assertEqual(int(feed.count()), 0)
        feed.add_many(activities)
        for activity in activities:
            assert feed.contains(activity)

        # test if we aggregated correctly
        self.assertEqual(feed.count_unseen(), len(aggregated_activities))
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())
        # sanity check
        self.assertNotEqual(feed.count_unseen(), 0)
        # test marking as seen or read
        feed.mark_all(seen=True)
        # verify that the new count is 0
        self.assertEqual(feed.count_unseen(), 0)
        # verify if we denormalize correctly
        self.assertEqual(feed.count_unseen(), feed.get_denormalized_count())