コード例 #1
0
    def test_get_all_threads(self):
        # Create an anonymous feedback thread
        expected_thread_dict = {
            'status': u'open',
            'state_name': u'a_state_name',
            'summary': None,
            'original_author_username': None,
            'subject': u'a subject'
        }
        feedback_services.create_thread(
            self.EXP_ID, expected_thread_dict['state_name'], None,
            expected_thread_dict['subject'], 'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID, False)
        self.assertEqual(1, len(threads))
        self.assertDictContainsSubset(expected_thread_dict,
                                      threads[0].to_dict())

        # Viewer creates feedback thread
        expected_thread_dict = {
            'status': u'open',
            'state_name': u'a_state_name_second',
            'summary': None,
            'original_author_username': self.VIEWER_USERNAME,
            'subject': u'a subject second'
        }
        feedback_services.create_thread(
            self.EXP_ID, expected_thread_dict['state_name'], self.viewer_id,
            expected_thread_dict['subject'], 'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID, False)
        self.assertEqual(2, len(threads))
        self.assertDictContainsSubset(expected_thread_dict,
                                      threads[1].to_dict())
コード例 #2
0
    def test_get_total_open_threads_for_multiple_explorations(self):
        feedback_services.create_thread(
            self.EXP_ID_1, self.EXPECTED_THREAD_DICT['state_name'], None,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')
        feedback_services.create_thread(
            self.EXP_ID_2, self.EXPECTED_THREAD_DICT['state_name'], None,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')

        threads_exp_1 = feedback_services.get_all_threads(self.EXP_ID_1, False)
        self.assertEqual(1, len(threads_exp_1))
        threads_exp_2 = feedback_services.get_all_threads(self.EXP_ID_2, False)
        self.assertEqual(1, len(threads_exp_2))

        def _close_thread(exp_id, thread_id):
            thread = (feedback_models.FeedbackThreadModel.
                      get_by_exp_and_thread_id(exp_id, thread_id))
            thread.status = feedback_models.STATUS_CHOICES_FIXED
            thread.put()

        _close_thread(self.EXP_ID_1, threads_exp_1[0].get_thread_id())
        self.assertEqual(
            len(feedback_services.get_closed_threads(self.EXP_ID_1, False)), 1)
        self._run_computation()

        self.assertEqual(feedback_services.get_total_open_threads(
            feedback_services.get_thread_analytics_multi(
                [self.EXP_ID_1, self.EXP_ID_2])), 1)
コード例 #3
0
    def test_send_feedback_message_email(self):
        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name', self.user_id_a,
                'a subject', 'some text')
            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            messagelist = feedback_services.get_messages(
                self.exploration.id, thread_id)
            self.assertEqual(len(messagelist), 1)

            expected_feedback_message_dict = {
                'exploration_id': self.exploration.id,
                'thread_id': thread_id,
                'message_id': messagelist[0].message_id
            }
            # There are two jobs in the taskqueue: one for the realtime event
            # associated with creating a thread, and one for sending the email.
            self.assertEqual(self.count_jobs_in_taskqueue(), 2)
            model = feedback_models.UnsentFeedbackEmailModel.get(self.editor_id)

            self.assertEqual(len(model.feedback_message_references), 1)
            self.assertDictEqual(
                model.feedback_message_references[0],
                expected_feedback_message_dict)
            self.assertEqual(model.retries, 0)
コード例 #4
0
    def test_that_correct_emails_are_sent_for_multiple_feedback(self):
        expected_email_html_body = (
            'Hi editor,<br>'
            '<br>'
            'You\'ve received 1 new message on your Oppia explorations:<br>'
            '<ul><li>Title: some text<br></li>'
            '<li>Title: more text<br></li></ul>'
            'You can view and reply to your messages from your '
            '<a href="https://www.oppia.org/dashboard">dashboard</a>.'
            '<br>'
            'Thanks, and happy teaching!<br>'
            '<br>'
            'Best wishes,<br>'
            'The Oppia Team<br>'
            '<br>'
            'You can change your email preferences via the '
            '<a href="https://www.example.com">Preferences</a> page.')

        expected_email_text_body = (
            'Hi editor,\n'
            '\n'
            'You\'ve received 1 new message on your Oppia explorations:\n'
            '- Title: some text\n'
            '- Title: more text\n'
            'You can view and reply to your messages from your dashboard.'
            '\n'
            'Thanks, and happy teaching!\n'
            '\n'
            'Best wishes,\n'
            'The Oppia Team\n'
            '\n'
            'You can change your email preferences via the Preferences page.')

        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name',
                self.new_user_id, 'a subject', 'some text')

            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            feedback_services.create_message(
                self.exploration.id, thread_id, self.new_user_id,
                feedback_models.STATUS_CHOICES_OPEN, 'subject', 'more text')

            messagelist = feedback_services.get_messages(
                self.exploration.id, thread_id)
            self.assertEqual(len(messagelist), 2)

            self.process_and_flush_pending_tasks()

            messages = self.mail_stub.get_sent_messages(to=self.EDITOR_EMAIL)
            self.assertEqual(len(messages), 1)
            self.assertEqual(
                messages[0].html.decode(),
                expected_email_html_body)
            self.assertEqual(
                messages[0].body.decode(),
                expected_email_text_body)
コード例 #5
0
    def test_feedback_ids(self):
        """Test various conventions for thread and message ids."""
        exp_id = '0'
        feedback_services.create_thread(
            exp_id, 'a_state_name', None, 'a subject', 'some text')
        threadlist = feedback_services.get_all_threads(exp_id, False)
        self.assertEqual(len(threadlist), 1)
        thread_id = threadlist[0].get_thread_id()
        # The thread id should not have any full stops.
        self.assertNotIn('.', thread_id)

        messages = feedback_services.get_messages(exp_id, thread_id)
        self.assertEqual(len(messages), 1)
        message_id = messages[0].message_id
        self.assertTrue(isinstance(message_id, int))

        # Retrieve the message instance from the storage layer.
        datastore_id = feedback_models.FeedbackMessageModel.get_messages(
            exp_id, thread_id)[0].id

        full_thread_id = (feedback_models.FeedbackThreadModel
                          .generate_full_thread_id(exp_id, thread_id))
        # The message id should be prefixed with the full thread id and a full
        # stop, followed by the message id.
        self.assertEqual(
            datastore_id, '%s.%s' % (full_thread_id, message_id))
コード例 #6
0
    def test_thread_closed_job_running(self):
        with self._get_swap_context():
            # Create test objects.
            exp_id = 'eid'
            self.save_new_valid_exploration(exp_id, 'owner')

            # Trigger thread creation events.
            self.process_and_flush_pending_tasks()
            feedback_services.create_thread(
                exp_id, 'a_state_name', None, 'a subject', 'some text')
            self._flush_tasks_and_check_analytics(exp_id, {
                'num_open_threads': 1,
                'num_total_threads': 1,
            })

            # Trigger close event.
            threadlist = feedback_services.get_all_threads(exp_id, False)
            thread_id = threadlist[0]['thread_id']
            feedback_services.create_message(
                exp_id, thread_id, 'author',
                feedback_models.STATUS_CHOICES_FIXED, None, 'some text')
            self._flush_tasks_and_check_analytics(exp_id, {
                'num_open_threads': 0,
                'num_total_threads': 1,
            })
コード例 #7
0
 def test_status_of_newly_created_thread_is_open(self):
     exp_id = '0'
     feedback_services.create_thread(
         exp_id, 'a_state_name', None, 'a subject', 'some text')
     threadlist = feedback_services.get_all_threads(exp_id, False)
     thread_status = threadlist[0].status
     self.assertEqual(thread_status, feedback_models.STATUS_CHOICES_OPEN)
コード例 #8
0
    def test_making_feedback_thread_does_not_subscribe_to_exploration(self):
        with self._get_test_context():
            self.signup(USER_A_EMAIL, USER_A_USERNAME)
            user_a_id = self.get_user_id_from_email(USER_A_EMAIL)
            self.signup(USER_B_EMAIL, USER_B_USERNAME)
            user_b_id = self.get_user_id_from_email(USER_B_EMAIL)

            # User A creates an exploration.
            self.save_new_valid_exploration(
                EXP_ID, user_a_id, title=EXP_TITLE, category='Category')
            exp_last_updated_ms = (
                self._get_most_recent_exp_snapshot_created_on_ms(EXP_ID))

            # User B starts a feedback thread.
            feedback_services.create_thread(
                EXP_ID, None, user_b_id, FEEDBACK_THREAD_SUBJECT, 'text')
            thread_id = feedback_services.get_all_threads(
                EXP_ID, False)[0].get_thread_id()

            message = feedback_services.get_messages(
                EXP_ID, thread_id)[0]

            ModifiedRecentUpdatesAggregator.start_computation()
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    queue_name=taskqueue_services.QUEUE_NAME_DEFAULT),
                1)
            self.process_and_flush_pending_tasks()

            recent_notifications_for_user_a = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    user_a_id)[1])
            recent_notifications_for_user_b = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    user_b_id)[1])
            expected_thread_notification = {
                'activity_id': EXP_ID,
                'activity_title': EXP_TITLE,
                'author_id': user_b_id,
                'last_updated_ms': utils.get_time_in_millisecs(
                    message.created_on),
                'subject': FEEDBACK_THREAD_SUBJECT,
                'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
            }
            expected_creation_notification = (
                self._get_expected_activity_created_dict(
                    user_a_id, EXP_ID, EXP_TITLE, 'exploration',
                    feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                    exp_last_updated_ms))

            # User A sees A's commit and B's feedback thread.
            self.assertEqual(recent_notifications_for_user_a, [
                expected_thread_notification,
                expected_creation_notification
            ])
            # User B sees only her feedback thread, but no commits.
            self.assertEqual(recent_notifications_for_user_b, [
                expected_thread_notification,
            ])
コード例 #9
0
    def test_multiple_exploration_commits_and_feedback_messages(self):
        with self._get_test_context():
            self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
            editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)

            # User creates an exploration.
            self.save_new_valid_exploration(
                EXP_1_ID, editor_id, title=EXP_1_TITLE,
                category='Category')

            exp1_last_updated_ms = (
                self._get_most_recent_exp_snapshot_created_on_ms(EXP_1_ID))

            # User gives feedback on it.
            feedback_services.create_thread(
                EXP_1_ID, None, editor_id, FEEDBACK_THREAD_SUBJECT,
                'text')
            thread_id = feedback_services.get_all_threads(
                EXP_1_ID, False)[0].get_thread_id()
            message = feedback_services.get_messages(EXP_1_ID, thread_id)[0]

            # User creates another exploration.
            self.save_new_valid_exploration(
                EXP_2_ID, editor_id, title=EXP_2_TITLE,
                category='Category')
            exp2_last_updated_ms = (
                self._get_most_recent_exp_snapshot_created_on_ms(EXP_2_ID))

            ModifiedRecentUpdatesAggregator.start_computation()
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    queue_name=taskqueue_services.QUEUE_NAME_DEFAULT),
                1)
            self.process_and_flush_pending_tasks()

            recent_notifications = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    editor_id)[1])
            self.assertEqual([(
                self._get_expected_activity_created_dict(
                    editor_id, EXP_2_ID, EXP_2_TITLE, 'exploration',
                    feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                    exp2_last_updated_ms)
            ), {
                'activity_id': EXP_1_ID,
                'activity_title': EXP_1_TITLE,
                'author_id': editor_id,
                'last_updated_ms': utils.get_time_in_millisecs(
                    message.created_on),
                'subject': FEEDBACK_THREAD_SUBJECT,
                'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
            }, (
                self._get_expected_activity_created_dict(
                    editor_id, EXP_1_ID, EXP_1_TITLE, 'exploration',
                    feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                    exp1_last_updated_ms)
            )], recent_notifications)
コード例 #10
0
    def test_get_total_open_threads_for_single_exploration(self):
        feedback_services.create_thread(
            self.EXP_ID_1, self.EXPECTED_THREAD_DICT['state_name'], None,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID_1, False)
        self.assertEqual(1, len(threads))

        self._run_computation()
        self.assertEqual(feedback_services.get_total_open_threads(
            feedback_services.get_thread_analytics_multi([self.EXP_ID_1])), 1)
コード例 #11
0
    def map(item):
        user_id = item.id
        job_queued_msec = RecentUpdatesMRJobManager._get_job_queued_msec()
        reducer_key = '%s@%s' % (user_id, job_queued_msec)

        exploration_ids_list = item.activity_ids
        collection_ids_list = item.collection_ids
        feedback_thread_ids_list = item.feedback_thread_ids

        (most_recent_activity_commits, tracked_exp_models_for_feedback) = (
            RecentUpdatesMRJobManager._get_most_recent_activity_commits(
                exp_models.ExplorationModel, exploration_ids_list,
                'exploration', feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                feconf.COMMIT_MESSAGE_EXPLORATION_DELETED))

        for exp_model in tracked_exp_models_for_feedback:
            threads = feedback_services.get_all_threads(exp_model.id, False)
            for thread in threads:
                full_thread_id = (
                    feedback_models.FeedbackThreadModel.generate_full_thread_id(
                        exp_model.id, thread['thread_id']))
                if full_thread_id not in feedback_thread_ids_list:
                    feedback_thread_ids_list.append(full_thread_id)

        # TODO(bhenning): Implement a solution to having feedback threads for
        # collections.
        most_recent_activity_commits += (
            RecentUpdatesMRJobManager._get_most_recent_activity_commits(
                collection_models.CollectionModel, collection_ids_list,
                'collection', feconf.UPDATE_TYPE_COLLECTION_COMMIT,
                feconf.COMMIT_MESSAGE_COLLECTION_DELETED))[0]

        for recent_activity_commit_dict in most_recent_activity_commits:
            yield (reducer_key, recent_activity_commit_dict)

        for feedback_thread_id in feedback_thread_ids_list:
            exp_id = feedback_services.get_exp_id_from_full_thread_id(
                feedback_thread_id)
            thread_id = feedback_services.get_thread_id_from_full_thread_id(
                feedback_thread_id)
            last_message = (
                feedback_models.FeedbackMessageModel.get_most_recent_message(
                    exp_id, thread_id))

            yield (reducer_key, {
                'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
                'activity_id': last_message.exploration_id,
                'activity_title': exp_models.ExplorationModel.get_by_id(
                    last_message.exploration_id).title,
                'author_id': last_message.author_id,
                'last_updated_ms': utils.get_time_in_millisecs(
                    last_message.created_on),
                'subject': last_message.get_thread_subject(),
            })
コード例 #12
0
 def test_get_all_threads_without_suggestion(self):
     with self.swap(
         feedback_models.FeedbackThreadModel, 'get_threads',
         self._get_threads):
         with self.swap(utils, 'get_time_in_millisecs',
                        self._get_milliseconds):
             threads = feedback_services.get_all_threads(
                 self.EXP_ID2, False)
     self.assertEqual(len(threads), 2)
     self.assertEqual(threads[0]['thread_id'], self.THREAD_ID4)
     self.assertEqual(threads[1]['thread_id'], self.THREAD_ID5)
コード例 #13
0
    def test_get_total_open_threads_before_job_run(self):
        self.assertEqual(feedback_services.get_total_open_threads(
            feedback_services.get_thread_analytics_multi([self.EXP_ID_1])), 0)

        feedback_services.create_thread(
            self.EXP_ID_1, self.EXPECTED_THREAD_DICT['state_name'], None,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID_1, False)
        self.assertEqual(1, len(threads))

        self.assertEqual(feedback_services.get_total_open_threads(
            feedback_services.get_thread_analytics_multi([self.EXP_ID_1])), 0)
コード例 #14
0
    def test_that_emails_are_sent_for_feedback_message(self):
        expected_email_html_body = (
            'Hi newuser,<br><br>'
            'New update to thread "a subject" on '
            '<a href="https://www.oppia.org/A">Title</a>:<br>'
            '<ul><li>editor: editor message<br></li></ul>'
            '(You received this message because you are a '
            'participant in this thread.)<br><br>'
            'Best wishes,<br>'
            'The Oppia team<br>'
            '<br>'
            'You can change your email preferences via the '
            '<a href="https://www.example.com">Preferences</a> page.')

        expected_email_text_body = (
            'Hi newuser,\n'
            '\n'
            'New update to thread "a subject" on Title:\n'
            '- editor: editor message\n'
            '(You received this message because you are a'
            ' participant in this thread.)\n'
            '\n'
            'Best wishes,\n'
            'The Oppia team\n'
            '\n'
            'You can change your email preferences via the Preferences page.')

        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name',
                self.new_user_id, 'a subject', 'some text')
            self.process_and_flush_pending_tasks()

            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            feedback_services.create_message(
                self.exploration.id, thread_id, self.editor_id, None, None,
                'editor message')
            self.process_and_flush_pending_tasks()

            messages = self.mail_stub.get_sent_messages(to=self.NEW_USER_EMAIL)
            self.assertEqual(len(messages), 1)
            self.assertEqual(
                messages[0].html.decode(),
                expected_email_html_body)
            self.assertEqual(
                messages[0].body.decode(),
                expected_email_text_body)
コード例 #15
0
    def test_get_all_threads(self):
        # Create an anonymous feedback thread
        feedback_services.create_thread(
            self.EXP_ID_1, self.EXPECTED_THREAD_DICT['state_name'], None,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID_1, False)
        self.assertEqual(1, len(threads))
        self.assertDictContainsSubset(self.EXPECTED_THREAD_DICT,
                                      threads[0].to_dict())

        self.EXPECTED_THREAD_DICT_VIEWER['original_author_username'] = (
            self.VIEWER_USERNAME)

        # Viewer creates feedback thread
        feedback_services.create_thread(
            self.EXP_ID_1, self.EXPECTED_THREAD_DICT_VIEWER['state_name'],
            self.viewer_id, self.EXPECTED_THREAD_DICT_VIEWER['subject'],
            'not used here')

        threads = feedback_services.get_all_threads(self.EXP_ID_1, False)
        self.assertEqual(2, len(threads))
        self.assertDictContainsSubset(self.EXPECTED_THREAD_DICT_VIEWER,
                                      threads[1].to_dict())
コード例 #16
0
    def test_that_emails_are_not_sent_to_anonymous_user(self):
        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            # Create thread as anonoymous user.
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name',
                None, 'a subject', 'some text')
            self.process_and_flush_pending_tasks()

            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            feedback_services.create_message(
                self.exploration.id, thread_id, self.editor_id,
                feedback_models.STATUS_CHOICES_FIXED, None, 'editor message')
            self.process_and_flush_pending_tasks()

            messages = self.mail_stub.get_sent_messages()
            self.assertEqual(len(messages), 0)
コード例 #17
0
    def test_that_email_is_sent_for_reply_on_feedback(self):
        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name', self.user_id_a,
                'a subject', 'A message')
            # There are two jobs in the taskqueue: one for the realtime event
            # associated with creating a thread, and one for sending the email.
            self.assertEqual(self.count_jobs_in_taskqueue(), 2)
            self.process_and_flush_pending_tasks()

            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            feedback_services.create_message(
                self.exploration.id, thread_id, self.editor_id, None, None,
                'editor message')
            self.assertEqual(self.count_jobs_in_taskqueue(), 1)
            self.process_and_flush_pending_tasks()
コード例 #18
0
    def test_that_emails_are_not_sent_if_already_seen(self):
        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                self.exploration.id, 'a_state_name',
                self.new_user_id, 'a subject', 'some text')

            threadlist = feedback_services.get_all_threads(
                self.exploration.id, False)
            thread_id = threadlist[0].get_thread_id()

            self.login(self.EDITOR_EMAIL)
            csrf_token = self.get_csrf_token_from_response(
                self.testapp.get('/create/%s' % self.exploration.id))
            self.post_json('%s' % feconf.FEEDBACK_THREAD_VIEW_EVENT_URL, {
                'exploration_id': self.exploration.id,
                'thread_id': thread_id}, csrf_token)

            self.process_and_flush_pending_tasks()
            messages = self.mail_stub.get_sent_messages(to=self.EDITOR_EMAIL)
            self.assertEqual(len(messages), 0)
コード例 #19
0
    def test_feedback_thread_subscription(self):
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id, strict=False)
        user_c_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_c_id, strict=False)

        self.assertEqual(user_b_subscriptions_model, None)
        self.assertEqual(user_c_subscriptions_model, None)

        with self.swap(
            subscription_services, 'subscribe_to_thread', self._null_fn
            ), self.swap(
                subscription_services, 'subscribe_to_exploration', self._null_fn
            ):
            # User B starts a feedback thread.
            feedback_services.create_thread(
                self.EXP_ID_1, None, self.user_b_id, 'subject', 'text')
            # User C adds to that thread.
            thread_id = feedback_services.get_all_threads(
                self.EXP_ID_1, False)[0].get_thread_id()
            feedback_services.create_message(
                self.EXP_ID_1, thread_id, self.user_c_id, None, None,
                'more text')

        self._run_one_off_job()

        # Both users are subscribed to the feedback thread.
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id)
        user_c_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_c_id)

        self.assertEqual(user_b_subscriptions_model.activity_ids, [])
        self.assertEqual(user_c_subscriptions_model.activity_ids, [])
        full_thread_id = (
            feedback_models.FeedbackThreadModel.generate_full_thread_id(
                self.EXP_ID_1, thread_id))
        self.assertEqual(
            user_b_subscriptions_model.feedback_thread_ids, [full_thread_id])
        self.assertEqual(
            user_c_subscriptions_model.feedback_thread_ids, [full_thread_id])
コード例 #20
0
ファイル: feedback.py プロジェクト: alexgower/oppia
    def get(self, exploration_id):
        threads = None
        list_type = self.request.get('list_type')
        has_suggestion = self._string_to_bool(
            self.request.get('has_suggestion'))
        if has_suggestion is None:
            raise self.InvalidInputException(
                'Invalid value for has_suggestion.')
        if list_type == self._LIST_TYPE_OPEN:
            threads = feedback_services.get_open_threads(
                exploration_id, has_suggestion)
        elif list_type == self._LIST_TYPE_CLOSED:
            threads = feedback_services.get_closed_threads(
                exploration_id, has_suggestion)
        elif list_type == self._LIST_TYPE_ALL:
            threads = feedback_services.get_all_threads(
                exploration_id, has_suggestion)
        else:
            raise self.InvalidInputException('Invalid list type.')

        self.values.update({'threads': [t.to_dict() for t in threads]})
        self.render_json(self.values)
コード例 #21
0
 def test_get_all_threads_with_suggestion(self):
     threads = feedback_services.get_all_threads(self.EXP_ID1, True)
     self.assertEqual(len(threads), 3)
     self.assertEqual(threads[0].id, self.EXP_ID1 + '.' + self.THREAD_ID1)
     self.assertEqual(threads[1].id, self.EXP_ID1 + '.' + self.THREAD_ID2)
     self.assertEqual(threads[2].id, self.EXP_ID1 + '.' + self.THREAD_ID3)
コード例 #22
0
    def test_subscribing_to_exploration_subscribes_to_its_feedback_threads(
            self):
        with self._get_test_context():
            self.signup(USER_A_EMAIL, USER_A_USERNAME)
            user_a_id = self.get_user_id_from_email(USER_A_EMAIL)
            self.signup(USER_B_EMAIL, USER_B_USERNAME)
            user_b_id = self.get_user_id_from_email(USER_B_EMAIL)
            user_a = user_services.UserActionsInfo(user_a_id)

            # User A creates an exploration.
            self.save_new_valid_exploration(EXP_ID,
                                            user_a_id,
                                            title=EXP_TITLE,
                                            category='Category')
            exp_last_updated_ms = (
                self._get_most_recent_exp_snapshot_created_on_ms(EXP_ID))

            # User B starts a feedback thread.
            feedback_services.create_thread(EXP_ID, None, user_b_id,
                                            FEEDBACK_THREAD_SUBJECT, 'text')
            thread_id = feedback_services.get_all_threads(
                EXP_ID, False)[0].get_thread_id()
            message = feedback_services.get_messages(EXP_ID, thread_id)[0]

            # User A adds user B as an editor of the exploration.
            rights_manager.assign_role_for_exploration(
                user_a, EXP_ID, user_b_id, rights_manager.ROLE_EDITOR)

            ModifiedRecentUpdatesAggregator.start_computation()
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    taskqueue_services.QUEUE_NAME_CONTINUOUS_JOBS), 1)
            self.process_and_flush_pending_tasks()

            recent_notifications_for_user_a = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    user_a_id)[1])
            recent_notifications_for_user_b = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    user_b_id)[1])
            expected_thread_notification = {
                'activity_id': EXP_ID,
                'activity_title': EXP_TITLE,
                'author_id': user_b_id,
                'last_updated_ms':
                utils.get_time_in_millisecs(message.created_on),
                'subject': FEEDBACK_THREAD_SUBJECT,
                'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
            }
            expected_creation_notification = (
                self._get_expected_activity_created_dict(
                    user_a_id, EXP_ID, EXP_TITLE, 'exploration',
                    feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                    exp_last_updated_ms))

            # User A sees A's commit and B's feedback thread.
            self.assertEqual(
                recent_notifications_for_user_a,
                [expected_thread_notification, expected_creation_notification])
            # User B sees A's commit and B's feedback thread.
            self.assertEqual(recent_notifications_for_user_b, [
                expected_thread_notification,
                expected_creation_notification,
            ])
コード例 #23
0
    def test_making_feedback_thread_does_not_subscribe_to_exploration(self):
        with self.swap(
            user_jobs_continuous, 'DashboardRecentUpdatesAggregator',
            MockRecentUpdatesAggregator):
            self.signup(USER_A_EMAIL, USER_A_USERNAME)
            user_a_id = self.get_user_id_from_email(USER_A_EMAIL)
            self.signup(USER_B_EMAIL, USER_B_USERNAME)
            user_b_id = self.get_user_id_from_email(USER_B_EMAIL)

            # User A creates an exploration.
            self.save_new_valid_exploration(
                EXP_ID, user_a_id, title=EXP_TITLE, category='Category')
            exp_last_updated_ms = (
                self._get_most_recent_exp_snapshot_created_on_ms(EXP_ID))

            # User B starts a feedback thread.
            feedback_services.create_thread(
                'exploration', EXP_ID, user_b_id, FEEDBACK_THREAD_SUBJECT,
                'text')
            thread_id = feedback_services.get_all_threads(
                'exploration', EXP_ID, False)[0].id

            message = feedback_services.get_messages(thread_id)[0]

            (
                user_jobs_continuous.DashboardRecentUpdatesAggregator
                .start_computation())
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    taskqueue_services.QUEUE_NAME_CONTINUOUS_JOBS), 1)
            self.process_and_flush_pending_tasks()

            recent_notifications_for_user_a = (
                user_jobs_continuous.DashboardRecentUpdatesAggregator
                .get_recent_user_changes(user_a_id)[1])
            recent_notifications_for_user_b = (
                user_jobs_continuous.DashboardRecentUpdatesAggregator
                .get_recent_user_changes(user_b_id)[1])
            expected_thread_notification = {
                'activity_id': EXP_ID,
                'activity_title': EXP_TITLE,
                'author_id': user_b_id,
                'last_updated_ms': utils.get_time_in_millisecs(
                    message.created_on),
                'subject': FEEDBACK_THREAD_SUBJECT,
                'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
            }
            expected_creation_notification = (
                self._get_expected_activity_created_dict(
                    user_a_id, EXP_ID, EXP_TITLE, 'exploration',
                    feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                    exp_last_updated_ms))

            # User A sees A's commit and B's feedback thread.
            self.assertEqual(
                recent_notifications_for_user_a, [
                    expected_thread_notification,
                    expected_creation_notification
                ])
            # User B sees only her feedback thread, but no commits.
            self.assertEqual(
                recent_notifications_for_user_b, [
                    expected_thread_notification,
                ])
コード例 #24
0
    def test_email_is_sent_when_suggestion_created(self):
        """Tests SuggestionEmailHandler functionality."""

        user_id_b = self.user_id_b

        class MockActivityRights:
            def __init__(self,
                         exploration_id,
                         owner_ids,
                         editor_ids,
                         voice_artist_ids,
                         viewer_ids,
                         community_owned=False,
                         cloned_from=None,
                         status=True,
                         viewable_if_private=False,
                         first_published_msec=None):
                # User B ID hardcoded into owner_ids to get email_manager
                # to send email to user B to test functionality.
                self.id = exploration_id
                self.getLintToShutUp = owner_ids
                self.editor_ids = editor_ids
                self.voice_artist_ids = voice_artist_ids
                self.viewer_ids = viewer_ids
                self.community_owned = community_owned
                self.cloned_from = cloned_from
                self.status = status
                self.viewable_if_private = viewable_if_private
                self.first_published_msec = first_published_msec
                self.owner_ids = [user_id_b]

        email_user_b = self.swap(rights_domain, 'ActivityRights',
                                 MockActivityRights)
        with email_user_b, self.can_send_feedback_email_ctx:
            with self.can_send_emails_ctx:
                change = {
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'property_name': exp_domain.STATE_PROPERTY_CONTENT,
                    'state_name': 'state_1',
                    'new_value': 'new suggestion content'
                }

                # Create suggestion from user A to user B.
                suggestion_services.create_suggestion(
                    feconf.SUGGESTION_TYPE_EDIT_STATE_CONTENT,
                    feconf.ENTITY_TYPE_EXPLORATION, self.exploration.id, 1,
                    self.user_id_a, change, 'test description')
                threadlist = feedback_services.get_all_threads(
                    feconf.ENTITY_TYPE_EXPLORATION, self.exploration.id, True)
                thread_id = threadlist[0].id

                # Enqueue and send suggestion email task.
                payload = {
                    'exploration_id': self.exploration.id,
                    'thread_id': thread_id
                }
                messages = self._get_all_sent_email_messages()
                self.assertEqual(len(messages), 0)
                taskqueue_services.enqueue_task(
                    feconf.TASK_URL_SUGGESTION_EMAILS, payload, 0)
                self.process_and_flush_pending_tasks()

                # Check that user B received message.
                messages = self._get_sent_email_messages(self.USER_B_EMAIL)
                self.assertEqual(len(messages), 1)

                # Check that user B received correct message.
                expected_message = (
                    'Hi userB,\nuserA has submitted a new suggestion'
                    ' for your Oppia exploration, "Title".\nYou can'
                    ' accept or reject this suggestion by visiting'
                    ' the feedback page for your exploration.\n\nTha'
                    'nks!\n- The Oppia Team\n\nYou can change your'
                    ' email preferences via the Preferences page.')
                self.assertEqual(messages[0].body, expected_message)
コード例 #25
0
    def test_that_correct_emails_are_sent_for_multiple_feedback(self):
        expected_email_html_body = (
            'Hi editor,<br>'
            '<br>'
            'You\'ve received 2 new messages on your Oppia explorations:<br>'
            '<ul>'
            '<li><a href="https://www.oppia.org/create/A#/feedback">Title</a>:'
            '<br>'
            '<ul><li>some text<br></li>'
            '<li>more text<br></li>'
            '</ul></li></ul>'
            'You can view and reply to your messages from your '
            '<a href="https://www.oppia.org/creator_dashboard">dashboard</a>.'
            '<br>'
            '<br>Thanks, and happy teaching!<br>'
            '<br>'
            'Best wishes,<br>'
            'The Oppia Team<br>'
            '<br>'
            'You can change your email preferences via the '
            '<a href="https://www.example.com">Preferences</a> page.')

        expected_email_text_body = (
            'Hi editor,\n'
            '\n'
            'You\'ve received 2 new messages on your Oppia explorations:\n'
            '- Title:\n'
            '- some text\n'
            '- more text\n'
            'You can view and reply to your messages from your dashboard.\n'
            '\n'
            'Thanks, and happy teaching!\n'
            '\n'
            'Best wishes,\n'
            'The Oppia Team\n'
            '\n'
            'You can change your email preferences via the Preferences page.')

        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                'exploration', self.exploration.id,
                self.new_user_id, 'a subject', 'some text')

            threadlist = feedback_services.get_all_threads(
                'exploration', self.exploration.id, False)
            thread_id = threadlist[0].id

            feedback_services.create_message(
                thread_id, self.new_user_id,
                feedback_models.STATUS_CHOICES_OPEN, 'subject', 'more text')

            messagelist = feedback_services.get_messages(thread_id)
            self.assertEqual(len(messagelist), 2)

            self.process_and_flush_pending_tasks()

            messages = self.mail_stub.get_sent_messages(
                to=self.EDITOR_EMAIL)
            self.assertEqual(len(messages), 1)
            self.assertEqual(
                messages[0].html.decode(), expected_email_html_body)
            self.assertEqual(
                messages[0].body.decode(), expected_email_text_body)
コード例 #26
0
ファイル: feedback.py プロジェクト: vabs22/oppia
 def get(self, exploration_id):
     self.values.update({
         'threads': feedback_services.get_all_threads(
             exploration_id, False)})
     self.render_json(self.values)
コード例 #27
0
 def test_get_all_threads_with_suggestion(self):
     threads = feedback_services.get_all_threads(self.EXP_ID1, True)
     self.assertEqual(len(threads), 3)
     self.assertEqual(threads[0].id, self.EXP_ID1 + '.' + self.THREAD_ID1)
     self.assertEqual(threads[1].id, self.EXP_ID1 + '.' + self.THREAD_ID2)
     self.assertEqual(threads[2].id, self.EXP_ID1 + '.' + self.THREAD_ID3)
コード例 #28
0
    def test_that_emails_are_sent_for_both_status_change_and_message(self):
        expected_email_html_body_message = (
            'Hi newuser,<br><br>'
            'New update to thread "a subject" on '
            '<a href="https://www.oppia.org/create/A#/feedback">Title</a>:<br>'
            '<ul><li>editor: editor message<br></li></ul>'
            '(You received this message because you are a '
            'participant in this thread.)<br><br>'
            'Best wishes,<br>'
            'The Oppia team<br>'
            '<br>'
            'You can change your email preferences via the '
            '<a href="https://www.example.com">Preferences</a> page.')

        expected_email_text_body_message = (
            'Hi newuser,\n'
            '\n'
            'New update to thread "a subject" on Title:\n'
            '- editor: editor message\n'
            '(You received this message because you are a'
            ' participant in this thread.)\n'
            '\n'
            'Best wishes,\n'
            'The Oppia team\n'
            '\n'
            'You can change your email preferences via the Preferences page.')

        expected_email_html_body_status = (
            'Hi newuser,<br><br>'
            'New update to thread "a subject" on '
            '<a href="https://www.oppia.org/create/A#/feedback">Title</a>:<br>'
            '<ul><li>editor: changed status from open to fixed<br></li></ul>'
            '(You received this message because you are a '
            'participant in this thread.)<br><br>'
            'Best wishes,<br>'
            'The Oppia team<br>'
            '<br>'
            'You can change your email preferences via the '
            '<a href="https://www.example.com">Preferences</a> page.')

        expected_email_text_body_status = (
            'Hi newuser,\n'
            '\n'
            'New update to thread "a subject" on Title:\n'
            '- editor: changed status from open to fixed\n'
            '(You received this message because you are a'
            ' participant in this thread.)\n'
            '\n'
            'Best wishes,\n'
            'The Oppia team\n'
            '\n'
            'You can change your email preferences via the Preferences page.')
        with self.can_send_emails_ctx, self.can_send_feedback_email_ctx:
            feedback_services.create_thread(
                'exploration', self.exploration.id,
                self.new_user_id, 'a subject', 'some text')
            self.process_and_flush_pending_tasks()

            threadlist = feedback_services.get_all_threads(
                'exploration', self.exploration.id, False)
            thread_id = threadlist[0].id

            feedback_services.create_message(
                thread_id, self.editor_id,
                feedback_models.STATUS_CHOICES_FIXED, None,
                'editor message')
            self.process_and_flush_pending_tasks()

            messages = self.mail_stub.get_sent_messages(to=self.NEW_USER_EMAIL)
            self.assertEqual(len(messages), 2)
            self.assertEqual(
                messages[0].html.decode(), expected_email_html_body_status)
            self.assertEqual(
                messages[0].body.decode(), expected_email_text_body_status)
            self.assertEqual(
                messages[1].html.decode(), expected_email_html_body_message)
            self.assertEqual(
                messages[1].body.decode(), expected_email_text_body_message)
コード例 #29
0
 def test_get_all_threads_without_suggestion(self):
     threads = feedback_services.get_all_threads(self.EXP_ID1, False)
     self.assertEqual(len(threads), 2)
     self.assertEqual(threads[0].id, self.EXP_ID1 + '.' + self.THREAD_ID4)
     self.assertEqual(threads[1].id, self.EXP_ID1 + '.' + self.THREAD_ID5)
コード例 #30
0
    def test_multiple_exploration_commits_and_feedback_messages(self):
        with self._get_test_context():
            with self.swap(constants, 'ENABLE_GENERALIZED_FEEDBACK_THREADS',
                           True):
                self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
                editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)

                # User creates an exploration.
                self.save_new_valid_exploration(EXP_1_ID,
                                                editor_id,
                                                title=EXP_1_TITLE,
                                                category='Category')

                exp1_last_updated_ms = (
                    self._get_most_recent_exp_snapshot_created_on_ms(EXP_1_ID))

                # User gives feedback on it.
                feedback_services.create_thread('exploration', EXP_1_ID, None,
                                                editor_id,
                                                FEEDBACK_THREAD_SUBJECT,
                                                'text')
                thread_id = feedback_services.get_all_threads(
                    'exploration', EXP_1_ID, False)[0].id
                message = feedback_services.get_messages(thread_id)[0]

                # User creates another exploration.
                self.save_new_valid_exploration(EXP_2_ID,
                                                editor_id,
                                                title=EXP_2_TITLE,
                                                category='Category')
                exp2_last_updated_ms = (
                    self._get_most_recent_exp_snapshot_created_on_ms(EXP_2_ID))

                ModifiedRecentUpdatesAggregator.start_computation()
                self.assertEqual(
                    self.count_jobs_in_taskqueue(
                        taskqueue_services.QUEUE_NAME_CONTINUOUS_JOBS), 1)
                self.process_and_flush_pending_tasks()

                recent_notifications = (ModifiedRecentUpdatesAggregator.
                                        get_recent_notifications(editor_id)[1])
                self.assertEqual(
                    [(self._get_expected_activity_created_dict(
                        editor_id, EXP_2_ID, EXP_2_TITLE, 'exploration',
                        feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                        exp2_last_updated_ms)), {
                            'activity_id':
                            EXP_1_ID,
                            'activity_title':
                            EXP_1_TITLE,
                            'author_id':
                            editor_id,
                            'last_updated_ms':
                            utils.get_time_in_millisecs(message.created_on),
                            'subject':
                            FEEDBACK_THREAD_SUBJECT,
                            'type':
                            feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
                        },
                     (self._get_expected_activity_created_dict(
                         editor_id, EXP_1_ID, EXP_1_TITLE, 'exploration',
                         feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                         exp1_last_updated_ms))], recent_notifications)
コード例 #31
0
 def test_get_all_threads_without_suggestion(self):
     threads = feedback_services.get_all_threads(self.EXP_ID1, False)
     self.assertEqual(len(threads), 2)
     self.assertEqual(threads[0].id, self.EXP_ID1 + '.' + self.THREAD_ID4)
     self.assertEqual(threads[1].id, self.EXP_ID1 + '.' + self.THREAD_ID5)
コード例 #32
0
    def map(item):
        """Implements the map function (generator).
        Computes most recent activity commits and feedbacks of a specific user.

        Args:
            item: UserSubscriptionsModel. An instance of UserSubscriptionsModel.

        Yields:
            This function may yield as many times as appropriate (including
            zero) 2-tuples in the format (str, dict), where
                - str: A key of the form 'user_id@job_queued_msec'.
                - dict: A dictionary with the following keys:
                    - 'type': str. Either feconf.UPDATE_TYPE_EXPLORATION_COMMIT
                        or feconf.UPDATE_TYPE_FEEDBACK_MESSAGE.
                    - 'activity_id': str. The ID of the exploration being
                        committed to or to which the feedback thread belongs.
                    - 'activity_title': str. The title of the activity.
                    - 'last_updated_ms': float. The time when the update was
                        made, in milliseconds since the Epoch.
                    - 'author_id': str. The ID of the author who made the
                        update.
                    - 'subject': str. A brief description of the recent updates.
        """
        user_id = item.id
        job_queued_msec = RecentUpdatesMRJobManager._get_job_queued_msec()
        reducer_key = '%s@%s' % (user_id, job_queued_msec)

        exploration_ids_list = item.activity_ids
        collection_ids_list = item.collection_ids
        feedback_thread_ids_list = item.general_feedback_thread_ids

        (most_recent_activity_commits, tracked_exp_models_for_feedback) = (
            RecentUpdatesMRJobManager._get_most_recent_activity_commits(
                exp_models.ExplorationModel, exploration_ids_list,
                'exploration', feconf.UPDATE_TYPE_EXPLORATION_COMMIT,
                feconf.COMMIT_MESSAGE_EXPLORATION_DELETED))

        for exp_model in tracked_exp_models_for_feedback:
            threads = feedback_services.get_all_threads(
                feconf.ENTITY_TYPE_EXPLORATION, exp_model.id, False)
            for thread in threads:
                if thread.id not in feedback_thread_ids_list:
                    feedback_thread_ids_list.append(thread.id)

        # TODO(bhenning): Implement a solution to having feedback threads for
        # collections.
        most_recent_activity_commits += (
            RecentUpdatesMRJobManager._get_most_recent_activity_commits(
                collection_models.CollectionModel, collection_ids_list,
                'collection', feconf.UPDATE_TYPE_COLLECTION_COMMIT,
                feconf.COMMIT_MESSAGE_COLLECTION_DELETED))[0]

        for recent_activity_commit_dict in most_recent_activity_commits:
            yield (reducer_key, recent_activity_commit_dict)

        for feedback_thread_id in feedback_thread_ids_list:
            last_message = (feedback_models.GeneralFeedbackMessageModel.
                            get_most_recent_message(feedback_thread_id))
            exploration_id = last_message.entity_id

            yield (reducer_key, {
                'type':
                feconf.UPDATE_TYPE_FEEDBACK_MESSAGE,
                'activity_id':
                exploration_id,
                'activity_title':
                exp_models.ExplorationModel.get_by_id(exploration_id).title,
                'author_id':
                last_message.author_id,
                'last_updated_ms':
                utils.get_time_in_millisecs(last_message.created_on),
                'subject':
                feedback_services.get_thread_subject(last_message.thread_id),
            })
コード例 #33
0
    def test_email_sent_when_feedback_in_thread(self):
        # Create feedback thread.
        with self.can_send_feedback_email_ctx, self.can_send_emails_ctx:
            feedback_services.create_thread(feconf.ENTITY_TYPE_EXPLORATION,
                                            self.exploration.id,
                                            self.user_id_a, 'a subject',
                                            'some text')
            threadlist = feedback_services.get_all_threads(
                feconf.ENTITY_TYPE_EXPLORATION, self.exploration.id, False)
            thread_id = threadlist[0].id

            # Create another message.
            feedback_services.create_message(thread_id, self.user_id_b, None,
                                             None, 'user b message')

            # Check that there are two messages in thread.
            messages = feedback_services.get_messages(thread_id)
            self.assertEqual(len(messages), 2)

            # Check that there are no feedback emails sent to Editor.
            messages = self._get_sent_email_messages(self.EDITOR_EMAIL)
            self.assertEqual(len(messages), 0)

            # Send task and subsequent email to Editor.
            self.process_and_flush_pending_tasks()
            messages = self._get_sent_email_messages(self.EDITOR_EMAIL)
            expected_message = (
                'Hi editor,\n\nYou\'ve received 2 new messages on your'
                ' Oppia explorations:\n- Title:\n- some text\n- user b message'
                '\nYou can view and reply to your messages from your dashboard.'
                '\n\nThanks, and happy teaching!\n\nBest wishes,\nThe Oppia'
                ' Team\n\nYou can change your email preferences via the '
                'Preferences page.')

            # Assert that the message is correct.
            self.assertEqual(len(messages), 1)
            self.assertEqual(messages[0].body, expected_message)

            # Create another message that is len = 201.
            user_b_message = 'B' * 201
            feedback_services.create_message(thread_id, self.user_id_b, None,
                                             None, user_b_message)

            # Check that there are three messages in thread.
            messages = feedback_services.get_messages(thread_id)
            self.assertEqual(len(messages), 3)

            # Send task and subsequent email to Editor.
            self.process_and_flush_pending_tasks()
            messages = self._get_sent_email_messages(self.EDITOR_EMAIL)

            # What is expected in the email body.
            expected_message = (
                'Hi editor,\n\nYou\'ve received a new message on your Oppia'
                ' explorations:\n- Title:\n- ' + 'B' * 200 + '...' +
                '\nYou can'
                ' view and reply to your messages from your dashboard.\n\nThank'
                's, and happy teaching!\n\nBest wishes,\nThe Oppia Team\n\nYou'
                ' can change your email preferences via the Preferences page.')

            # Check that greater than 200 word message is sent
            # and has correct message.

            self.assertEqual(len(messages), 2)
            self.assertEqual(messages[1].body, expected_message)

            # Create another message.
            feedback_services.create_message(thread_id, self.user_id_b, None,
                                             None, 'user b another message')

            # Pops feedback message references.
            feedback_services.pop_feedback_message_references_transactional(
                self.editor_id, 0)

            # Send task and subsequent email to Editor.
            self.process_and_flush_pending_tasks()
            messages = self._get_sent_email_messages(self.EDITOR_EMAIL)

            # Check that there are three messages.
            self.assertEqual(len(messages), 3)
コード例 #34
0
 def get(self, exploration_id):
     self.values.update({
         'threads': [t.to_dict() for t in feedback_services.get_all_threads(
             exploration_id, False)]})
     self.render_json(self.values)
コード例 #35
0
ファイル: feedback.py プロジェクト: alexgower/oppia
 def get(self, exploration_id):
     self.values.update({
         'threads': [t.to_dict() for t in feedback_services.get_all_threads(
             exploration_id, False)]})
     self.render_json(self.values)
コード例 #36
0
ファイル: tasks_test.py プロジェクト: tirthbal/oppia
    def test_email_sent_when_feedback_in_thread(self):
        # Create feedback thread.
        with self.can_send_feedback_email_ctx, self.can_send_emails_ctx:
            feedback_services.create_thread(feconf.ENTITY_TYPE_EXPLORATION,
                                            self.exploration.id,
                                            self.user_id_a, 'a subject',
                                            'some text')
            threadlist = feedback_services.get_all_threads(
                feconf.ENTITY_TYPE_EXPLORATION, self.exploration.id, False)
            thread_id = threadlist[0].id

            # Create another message.
            feedback_services.create_message(thread_id, self.user_id_b, None,
                                             None, 'user b message')

            # Check that there are two messages in thread.
            messages = feedback_services.get_messages(thread_id)
            self.assertEqual(len(messages), 2)

            # Telling tasks.py to send email to User 'A'.
            payload = {'user_id': self.user_id_a}
            taskqueue_services.enqueue_email_task(
                feconf.TASK_URL_FEEDBACK_MESSAGE_EMAILS, payload, 0)

            # Check that there are no feedback emails sent to User 'A'.
            messages = self.mail_stub.get_sent_messages(to=self.USER_A_EMAIL)
            self.assertEqual(len(messages), 0)

            # Send task and subsequent email to User 'A'.
            self.process_and_flush_pending_tasks()
            messages = self.mail_stub.get_sent_messages(to=self.USER_A_EMAIL)
            expected_message = (
                'Hi userA,\n\nNew update to thread "a subject"'
                ' on Title:\n- userB: user b message\n(You received'
                ' this message because you are a participant in this thread.)'
                '\n\nBest wishes,\nThe Oppia team\n\nYou can change your email'
                ' preferences via the Preferences page.')

            # Assert that the message is correct.
            self.assertEqual(len(messages), 1)
            self.assertEqual(messages[0].body.decode(), expected_message)

            # Create another message that is len = 201.
            user_b_message = 'B' * 201
            feedback_services.create_message(thread_id, self.user_id_b, None,
                                             None, user_b_message)

            # Check that there are three messages in thread.
            messages = feedback_services.get_messages(thread_id)
            self.assertEqual(len(messages), 3)

            # Telling tasks.py to send email to User 'A'.
            payload = {'user_id': self.user_id_a}
            taskqueue_services.enqueue_email_task(
                feconf.TASK_URL_FEEDBACK_MESSAGE_EMAILS, payload, 0)

            # Check that there is one feedback email sent to User 'A'.
            messages = self.mail_stub.get_sent_messages(to=self.USER_A_EMAIL)
            self.assertEqual(len(messages), 1)

            # Send task and subsequent email to User 'A'.
            self.process_and_flush_pending_tasks()
            messages = self.mail_stub.get_sent_messages(to=self.USER_A_EMAIL)

            # What is expected in the email body.
            expected_message = (
                'Hi userA,\n\nNew update to thread "a subject"'
                ' on Title:\n- userB:' + 'B' * 200 + '...' +
                ' e\n(You received'
                ' this message because you are a participant in this thread.)'
                '\n\nBest wishes,\nThe Oppia team\n\nYou can change your email'
                ' preferences via the Preferences page.')

            # Check that greater than 200 word message is sent.
            self.assertEqual(len(messages), 2)