def test_get_inbox_omits_thread_if_all_constituent_messages_deleted(self):
        """
        inbox should not contain a thread if all its constituent messages are deleted
        """

        # get message items for Cersei
        message_items = MessageItem.objects.filter(
            user=self.users['Cersei'],
            message__tree_id=self.thread.tree_id,
            deleted__isnull=True).order_by('-message__sent')
        self.assertEqual(4, message_items.count())

        # delete message items within the thread one at a time
        for i in range(3, 0, -1):
            mi = MessageItem.objects.get(pk=message_items[i].id)
            mi.deleted = timezone.now()
            mi.save()
            (inbox, count) = MessageItem.get_inbox(self.users['Cersei'])
            self.assertEqual(1, count)

        # delete the final message
        mi = MessageItem.objects.get(pk=message_items[0].id)
        mi.deleted = timezone.now()
        mi.save()

        # get the deleted message items, of which there should now be four
        message_items = MessageItem.objects.filter(
            user=self.users['Cersei'],
            message__tree_id=self.thread.tree_id,
            deleted__isnull=False).order_by('-message__sent')
        self.assertEqual(4, message_items.count())

        # check there's now no items in the inbox
        (inbox, count) = MessageItem.get_inbox(self.users['Cersei'])
        self.assertEqual(0, count)
 def test_mark_all_deleted(self):
     """
     tests that marking all given messages as deleted only marks those that aren't already deleted
     """
     now = timezone.now()
     subjects = ['foo', 'bar', 'woo']
     messages = list(
         map(lambda subject: Message.objects.create(subject=subject),
             subjects))
     m1 = MessageItem.objects.create(user=self.users['Cersei'],
                                     message=messages[0])
     m2 = MessageItem.objects.create(user=self.users['Cersei'],
                                     message=messages[1],
                                     deleted=now)
     m3 = MessageItem.objects.create(user=self.users['Cersei'],
                                     message=messages[2])
     self.assertIsNone(m1.deleted)
     self.assertEqual(now, m2.deleted)
     self.assertIsNone(m3.deleted)
     MessageItem.mark_all_deleted([m1, m2, m3])
     self.assertIsNotNone(m1.deleted)
     self.assertGreaterEqual(m1.deleted, now)
     self.assertEqual(now, m2.deleted)
     self.assertIsNotNone(m3.deleted)
     self.assertGreaterEqual(m3.deleted, now)
    def test_create_message_items(self):
        m = Message.objects.create(subject='foo')

        # put Cersei in the course and the group
        CourseMember.objects.create(vle_course_id='001',
                                    user=self.users['Cersei'])
        GroupMember.objects.create(vle_course_id='001',
                                   vle_group_id='001',
                                   user=self.users['Cersei'])

        # put Lancel in the course but not the group
        CourseMember.objects.create(vle_course_id='001',
                                    user=self.users['Lancel'])

        # put Jaime in the course and the group
        CourseMember.objects.create(vle_course_id='001',
                                    user=self.users['Jaime'])
        GroupMember.objects.create(vle_course_id='001',
                                   vle_group_id='001',
                                   user=self.users['Jaime'])

        # send to Cersei, everyone in the course, everyone in the group
        user_ids = [self.users['Cersei'].id]
        group_ids = [delimiter.join(['001', '001'])]
        course_ids = ['001']
        all_user_ids = expand_user_group_course_ids_to_user_ids(
            delimiter, user_ids, group_ids, course_ids)
        MessageItem.create_message_items(m, all_user_ids)
        self.assertEqual(3, MessageItem.objects.count())

        # test that the three recipients are as expected
        messages = MessageItem.objects.all().order_by('user__first_name')
        self.assertEqual('Cersei', messages[0].user.first_name)
        self.assertEqual('Jaime', messages[1].user.first_name)
        self.assertEqual('Lancel', messages[2].user.first_name)
    def test_get_unread_message_item_count_for_message_trees(self):
        # create another thread
        recipients = [{'id': self.users['Cersei'].id, 'type': u'u'}]
        thread2 = Message.send_message(sender=self.users['Tywin'],
                                       recipients=recipients,
                                       subject='Loras Tyrell',
                                       body='Marry him!')

        # get a list of tree ids
        tree_ids = [self.thread.tree_id, thread2.tree_id]

        # read a message
        mi = MessageItem.objects.get(user=self.users['Cersei'],
                                     message=self.thread)
        mi.read = timezone.now()
        mi.save()

        # get counts of unread message items and unread message items in each thread in the inbox page
        undeleted_dict = MessageItem.get_unread_message_item_count_for_message_trees(
            self.users['Cersei'], tree_ids)
        self.assertEqual(2, len(undeleted_dict))
        self.assertDictEqual({
            self.thread.tree_id: 3,
            thread2.tree_id: 1,
        }, undeleted_dict)
    def test_get_inbox_has_threads(self):
        """
        inbox consists of threads (i.e. groups of messages with the same tree_id)
        """

        # for each user
        for k, v in iteritems(self.users):
            # check there is only one thread in the inbox
            (inbox, count) = MessageItem.get_inbox(v)
            self.assertEqual(1, count)
    def test_sorting(self):
        self.thread.delete()

        # create more threads
        recipients = [{'id': self.users['Cersei'].id, 'type': u'u'}]
        senders = ['Tywin', 'Tyrion', 'Jaime', 'Lancel']
        threads = list(
            map(
                lambda first_name: Message.send_message(
                    sender=self.users[first_name],
                    recipients=recipients,
                    subject='Irrelevant',
                    body='Irrelevant'), senders))

        # check sorted by sender asc
        (inbox, total) = MessageItem.get_inbox(self.users['Cersei'],
                                               sort_field='sender',
                                               sort_dir='asc')
        self.assertEqual(len(threads), total)
        self.assertListEqual(
            list(
                map(lambda t: t.id,
                    [threads[2], threads[3], threads[1], threads[0]])),
            list(map(lambda m: m.message.id, inbox)))

        # check sorted by sender desc
        (inbox, total) = MessageItem.get_inbox(self.users['Cersei'],
                                               sort_field='sender',
                                               sort_dir='desc')
        self.assertListEqual(
            list(
                map(lambda t: t.id,
                    [threads[0], threads[1], threads[3], threads[2]])),
            list(map(lambda m: m.message.id, inbox)))

        # give the threads different sent datetimes
        l = [
            (threads[0], 25, 16),
            (threads[1], 25, 9),
            (threads[2], 24, 13),
            (threads[3], 24, 10),
        ]
        for triple in l:
            thread = triple[0]
            thread.sent = datetime(year=2014,
                                   month=7,
                                   day=triple[1],
                                   hour=triple[2],
                                   minute=0,
                                   second=0).replace(tzinfo=utc)
            thread.save()

        # check sorted by date asc (i.e. oldest first)
        (inbox, total) = MessageItem.get_inbox(self.users['Cersei'],
                                               sort_field='date',
                                               sort_dir='asc')
        self.assertListEqual(list(map(lambda t: t.id, reversed(threads))),
                             list(map(lambda m: m.message.id, inbox)))

        # check sorted by date desc (i.e. newest first)
        (inbox, total) = MessageItem.get_inbox(self.users['Cersei'],
                                               sort_field='date',
                                               sort_dir='desc')
        self.assertListEqual(list(map(lambda t: t.id, threads)),
                             list(map(lambda m: m.message.id, inbox)))