コード例 #1
0
    def test_get_news_some_old_some_new(self):
        user = actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')

        # Newsworthy thing happened beyond newsworthy time limit,
        then_ts = utc.now_as_timestamp() - news.NEWSWORTHINESS_SECONDS - 1
        then = utc.timestamp_to_datetime(then_ts)
        self._set_student_enroll_date(user, then)
        news_item = news.NewsItem('test:one', 'url_one', then)
        news.CourseNewsDao.add_news_item(news_item)
        news_item = news.NewsItem('test:two', 'url_two', then)
        news.CourseNewsDao.add_news_item(news_item)
        # But student has seen the thing, so it's marked as non-new.
        news.StudentNewsDao.mark_item_seen('test:one')

        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(['has_new_news'],
                          self._get_news_title_styles(soup))
        self.assertEquals(
            [
                news_tests_lib.NewsItem('Test Item two', 'url_two', True),
                news_tests_lib.NewsItem('Test Item one', 'url_one', False),
            ],
            news_tests_lib.extract_news_items_from_soup(soup))
コード例 #2
0
    def test_news_label_filtering(self):
        actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')

        label_foo = models.LabelDAO.save(models.LabelDTO(
            None, {'title': 'Foo',
                   'descripton': 'foo',
                   'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK}))
        label_bar = models.LabelDAO.save(models.LabelDTO(
            None, {'title': 'Bar',
                   'descripton': 'bar',
                   'type': models.LabelDTO.LABEL_TYPE_COURSE_TRACK}))

        now_ts = utc.now_as_timestamp() + 3  # Avoid filtering in-past items
        news.CourseNewsDao.add_news_item(news.NewsItem(
            'test:no_labels', 'url_no_labels',
            when=utc.timestamp_to_datetime(now_ts)))
        news.CourseNewsDao.add_news_item(news.NewsItem(
            'test:with_labels', 'url_with_labels',
            labels=common_utils.list_to_text([label_foo]),
            when=utc.timestamp_to_datetime(now_ts - 1)))

        # Student starts life with no labels, so should match both items.
        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(
            [news_tests_lib.NewsItem(
                'Test Item no_labels', 'url_no_labels', True),
             news_tests_lib.NewsItem(
                 'Test Item with_labels', 'url_with_labels', True)],
            news_tests_lib.extract_news_items_from_soup(soup))

        # Apply non-matching label to Student; should not see labeled news.
        models.Student.set_labels_for_current(
            common_utils.list_to_text([label_bar]))
        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(
            [news_tests_lib.NewsItem(
                'Test Item no_labels', 'url_no_labels', True)],
            news_tests_lib.extract_news_items_from_soup(soup))

        # Apply matching label to Student; should again see labeled news.
        models.Student.set_labels_for_current(
            common_utils.list_to_text([label_foo, label_bar]))
        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(
            [news_tests_lib.NewsItem(
                'Test Item no_labels', 'url_no_labels', True),
             news_tests_lib.NewsItem(
                 'Test Item with_labels', 'url_with_labels', True)],
            news_tests_lib.extract_news_items_from_soup(soup))
コード例 #3
0
 def _test_add_duplicate_news_item(self, dao_class):
     now = utc.now_as_datetime()
     news_item = news.NewsItem('test:key', 'test:url', when=now)
     dao_class.add_news_item(news_item)
     dao_class.add_news_item(news_item)
     dao_class.add_news_item(news_item)
     dao_class.add_news_item(news_item)
     self.assertEquals([news_item], dao_class.get_news_items())
コード例 #4
0
 def _test_add_multiple_news_items(self, dao_class):
     NUM_ITEMS = 10
     expected_items = []
     for x in xrange(NUM_ITEMS):
         news_item = news.NewsItem('test:key_%d' % x, 'test:url')
         expected_items.append(news_item)
         dao_class.add_news_item(news_item)
     actual_items = dao_class.get_news_items()
     self.assertEquals(expected_items, actual_items)
コード例 #5
0
    def test_old_student_news_removed_when_seen_far_in_the_past(self):
        actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')
        now = utc.now_as_datetime()
        item_one = news.NewsItem('key_one', 'test:url', when=now)
        item_two = news.NewsItem('key_two', 'test:url', when=now)
        news.StudentNewsDao.add_news_item(item_one)
        news.StudentNewsDao.add_news_item(item_two)

        # Nothing seen; should have both news items still.
        news_items = news.StudentNewsDao.get_news_items()
        self.assertEquals(2, len(news_items))
        self.assertIn(item_one, news_items)
        self.assertIn(item_two, news_items)

        # Now we mark item_one as visited.  Still should retain both items,
        # since we're within the newsworthiness time limit.
        news.StudentNewsDao.mark_item_seen(item_one.resource_key)
        seen_one = news.SeenItem(item_one.resource_key, now)
        self.assertEquals([seen_one], news.StudentNewsDao.get_seen_items())
        news_items = news.StudentNewsDao.get_news_items()
        self.assertEquals(2, len(news_items))
        self.assertIn(item_one, news_items)
        self.assertIn(item_two, news_items)

        # Set the newsworthiness timeout to one second so we can get this
        # done in a sane amount of time.
        try:
            save_newsworthiness_seconds = news.NEWSWORTHINESS_SECONDS
            news.NEWSWORTHINESS_SECONDS = 1
            time.sleep(2)
            now = utc.now_as_datetime()

            # Marking item two as seen should have the side effect of
            # removing the seen and news items for 'key_one'.
            news.StudentNewsDao.mark_item_seen(item_two.resource_key)
            self.assertEquals([item_two], news.StudentNewsDao.get_news_items())
            seen_two = news.SeenItem(item_two.resource_key, now)
            self.assertEquals([seen_two], news.StudentNewsDao.get_seen_items())

        finally:
            news.NEWSWORTHINESS_SECONDS = save_newsworthiness_seconds
コード例 #6
0
    def post_set_draft_status(cls, handler):
        """Sets the draft status of a course component.

        Only works with CourseModel13 courses, but the REST handler
        is only called with this type of courses.

        XSRF is checked in the dashboard.
        """
        key = handler.request.get('key')

        if not AnnouncementsRights.can_edit(handler):
            transforms.send_json_response(
                handler, 401, 'Access denied.', {'key': key})
            return

        entity = AnnouncementEntity.get(key)
        if not entity:
            transforms.send_json_response(
                handler, 404, 'Object not found.', {'key': key})
            return

        set_draft = handler.request.get('set_draft')
        if set_draft == '1':
            set_draft = True
        elif set_draft == '0':
            set_draft = False
        else:
            transforms.send_json_response(
                handler, 401, 'Invalid set_draft value, expected 0 or 1.',
                {'set_draft': set_draft}
            )
            return

        if entity.is_draft and not set_draft:
            item = news.NewsItem(
                str(TranslatableResourceAnnouncement.key_for_entity(entity)),
                AnnouncementsStudentHandler.URL.lstrip('/'))
            news.CourseNewsDao.add_news_item(item)

        entity.is_draft = set_draft
        entity.put()

        transforms.send_json_response(
            handler,
            200,
            'Draft status set to %s.' % (
                resources_display.DRAFT_TEXT if set_draft else
                resources_display.PUBLISHED_TEXT
            ), {
                'is_draft': set_draft
            }
        )
        return
コード例 #7
0
    def test_student_and_course_news(self):
        user = actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')

        then_ts = utc.now_as_timestamp() - news.NEWSWORTHINESS_SECONDS - 1
        then = utc.timestamp_to_datetime(then_ts)
        self._set_student_enroll_date(user, then)
        news_item = news.NewsItem('test:one', 'url_one', then)
        news.CourseNewsDao.add_news_item(news_item)
        news_item = news.NewsItem('test:two', 'url_two', then)
        news.StudentNewsDao.add_news_item(news_item)

        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(['has_new_news'],
                          self._get_news_title_styles(soup))
        self.assertEquals(
            [
                news_tests_lib.NewsItem('Test Item two', 'url_two', True),
                news_tests_lib.NewsItem('Test Item one', 'url_one', True),
            ],
            news_tests_lib.extract_news_items_from_soup(soup))
コード例 #8
0
    def _test_add_newer_and_older_news_item(self, dao_class):
        now_ts = utc.now_as_timestamp()

        older = news.NewsItem('test:key', 'test:url',
                              when=utc.timestamp_to_datetime(now_ts))
        newer = news.NewsItem('test:key', 'test:url',
                              when=utc.timestamp_to_datetime(now_ts + 1))

        dao_class.add_news_item(older)
        self.assertEquals([older], dao_class.get_news_items())

        # Newer items added with no-overwrite flag do not displace older item.
        dao_class.add_news_item(newer, overwrite_existing=False)
        self.assertEquals([older], dao_class.get_news_items())

        # Newer items displace older items with the same key.
        dao_class.add_news_item(newer)
        self.assertEquals([newer], dao_class.get_news_items())

        # But older items w/ same key do not displace newer ones.
        dao_class.add_news_item(older)
        self.assertEquals([newer], dao_class.get_news_items())
コード例 #9
0
    def test_news_before_user_registration_is_not_news(self):
        news_item = news.NewsItem(
            'test:before', 'before_url', utc.now_as_datetime())
        news.CourseNewsDao.add_news_item(news_item)
        time.sleep(1)
        user = actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')
        now = utc.now_as_datetime()
        news_item = news.NewsItem('test:at', 'at_url', now)
        self._set_student_enroll_date(user, now)
        news.CourseNewsDao.add_news_item(news_item)
        time.sleep(1)
        news_item = news.NewsItem(
            'test:after', 'after_url', utc.now_as_datetime())
        news.CourseNewsDao.add_news_item(news_item)

        # Expect to not see news item from before student registration.
        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(
            [news_tests_lib.NewsItem('Test Item after', 'after_url', True),
             news_tests_lib.NewsItem('Test Item at', 'at_url', True)],
            news_tests_lib.extract_news_items_from_soup(soup))
コード例 #10
0
    def _test_remove_news_item(self, dao_class):
        # Just need to see no explosions.
        dao_class.remove_news_item('no_such_item_key')

        # Add an item so that we can remove it next.
        now = utc.now_as_datetime()
        news_item = news.NewsItem('test:key', 'test:url', when=now)
        dao_class.add_news_item(news_item)
        self.assertEquals([news_item], dao_class.get_news_items())

        # Remove the item; verify empty set of items.
        dao_class.remove_news_item(news_item.resource_key)
        self.assertEquals([], dao_class.get_news_items())

        # Remove again an item that had existed; just want no explosions.
        dao_class.remove_news_item(news_item.resource_key)
        self.assertEquals([], dao_class.get_news_items())
コード例 #11
0
    def test_get_news_unseen(self):
        user = actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')

        # Added item is older than newsworthiness cutoff, but student has
        # not been marked as having seen it, so it's new news.
        then_ts = utc.now_as_timestamp() - news.NEWSWORTHINESS_SECONDS - 1
        then = utc.timestamp_to_datetime(then_ts)
        self._set_student_enroll_date(user, then)
        news_item = news.NewsItem('test:key', 'test:url', then)
        news.CourseNewsDao.add_news_item(news_item)

        response = self.get('course')
        soup = self.parse_html_string_to_soup(response.body)
        self.assertEquals(['has_new_news'],
                          self._get_news_title_styles(soup))
        self.assertEquals(
            [news_tests_lib.NewsItem('Test Item key', 'test:url', True)],
            news_tests_lib.extract_news_items_from_soup(soup))
コード例 #12
0
    def _test_mark_item_seen(self, dao_class):
        actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')

        now = utc.now_as_datetime()
        news_item = news.NewsItem('test:key', 'test:url', when=now)
        dao_class.add_news_item(news_item)
        self.assertEquals([news_item], dao_class.get_news_items())
        news.StudentNewsDao.mark_item_seen(news_item.resource_key)

        seen_item = news.SeenItem(news_item.resource_key, now)
        self.assertEquals([seen_item], news.StudentNewsDao.get_seen_items())

        # Move time forward one tick, and verify that the timestamp *does*
        # move forward on the 'seen' record.
        time.sleep(1)
        seen_item.when = utc.now_as_datetime()
        news.StudentNewsDao.mark_item_seen(news_item.resource_key)
        self.assertEquals([seen_item], news.StudentNewsDao.get_seen_items())
コード例 #13
0
    def put(self):
        """Handles REST PUT verb with JSON payload."""
        request = transforms.loads(self.request.get('request'))
        key = request.get('key')

        if not self.assert_xsrf_token_or_fail(
                request, self.ACTION, {'key': key}):
            return

        if not AnnouncementsRights.can_edit(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        entity = AnnouncementEntity.get(key)
        if not entity:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        schema = AnnouncementsItemRESTHandler.SCHEMA()

        payload = request.get('payload')
        update_dict = transforms.json_to_dict(
            transforms.loads(payload), schema.get_json_schema_dict())
        if entity.is_draft and not update_dict.get('set_draft'):
            item = news.NewsItem(
                str(TranslatableResourceAnnouncement.key_for_entity(entity)),
                AnnouncementsStudentHandler.URL.lstrip('/'))
            news.CourseNewsDao.add_news_item(item)

        # The datetime widget returns a datetime object and we need a UTC date.
        update_dict['date'] = update_dict['date'].date()
        del update_dict['key']  # Don't overwrite key member method in entity.
        transforms.dict_to_entity(entity, update_dict)

        entity.put()

        transforms.send_json_response(self, 200, 'Saved.')
コード例 #14
0
    def test_old_news_excluded_by_new_news(self):
        NUM_OLD_ITEMS = news.MIN_NEWS_ITEMS_TO_DISPLAY * 2
        NUM_NEW_ITEMS = news.MIN_NEWS_ITEMS_TO_DISPLAY * 2

        user = actions.login(self.STUDENT_EMAIL)
        actions.register(self, 'John Smith')
        then_ts = (
            utc.now_as_timestamp() - news.NEWSWORTHINESS_SECONDS -
            NUM_OLD_ITEMS - 1)
        self._set_student_enroll_date(user, utc.timestamp_to_datetime(then_ts))

        # Add many old items - twice as many as we're willing to show.
        expected_old_items = []
        for i in xrange(NUM_OLD_ITEMS):
            expected_old_items.append(news_tests_lib.NewsItem(
                'Test Item %i' % i, 'u%i' % i, False))

            then = utc.timestamp_to_datetime(then_ts + i)
            item = news.NewsItem('test:%d' % i, 'u%d' % i, then)
            news.CourseNewsDao.add_news_item(item)
            news.StudentNewsDao.mark_item_seen('test:%d' % i)

        # Force everything we just did to be old news.
        try:
            save_newsworthiness_seconds = news.NEWSWORTHINESS_SECONDS
            news.NEWSWORTHINESS_SECONDS = 1
            time.sleep(2)

            # Expect that we see old items in newest-first order.
            expected_old_items.reverse()

            # Verify that we are only shown half of the old-news items before
            # we add any new ones.
            response = self.get('course')
            soup = self.parse_html_string_to_soup(response.body)
            self.assertEquals(
                expected_old_items[0:NUM_OLD_ITEMS / 2],
                news_tests_lib.extract_news_items_from_soup(soup))

            # Start adding new news items, one at a time.
            expected_new_items = []
            for i in xrange(NUM_NEW_ITEMS):
                j = NUM_OLD_ITEMS + i
                expected_new_items.append(news_tests_lib.NewsItem(
                    'Test Item %i' % j, 'u%i' % j, True))
                then = utc.timestamp_to_datetime(then_ts + j)
                item = news.NewsItem('test:%d' % j, 'u%d' % j, then)
                news.CourseNewsDao.add_news_item(item)

                # Expect to see all new items, and maybe some old items,
                # as long as the new ones are not crowding them out.
                # New items should appear strictly first.
                expected_items = list(reversed(expected_new_items))
                if i < news.MIN_NEWS_ITEMS_TO_DISPLAY:
                    expected_items += expected_old_items[
                        :news.MIN_NEWS_ITEMS_TO_DISPLAY - i - 1]

                response = self.get('course')
                soup = self.parse_html_string_to_soup(response.body)
                actual_items = news_tests_lib.extract_news_items_from_soup(soup)
                self.assertEquals(expected_items, actual_items)

        finally:
            news.NEWSWORTHINESS_SECONDS = save_newsworthiness_seconds
コード例 #15
0
def _post_update_progress(course, student, progress_, event_entity, event_key):
    """Called back when student has progress event recorded."""

    if student_is_qualified(student, course):
        item = news.NewsItem(RESOURCE_KEY, CERTIFICATE_HANDLER_PATH)
        news.StudentNewsDao.add_news_item(item, overwrite_existing=False)