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))
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))
def test_news_notification(self): assessment = self.course.add_assessment() assessment.title = 'Assessment' assessment.html_content = 'assessment content' assessment.availability = courses.AVAILABILITY_AVAILABLE self.course.save() self.certificate_criteria.append( {'assessment_id': assessment.unit_id, 'pass_percent': 70.0}) actions.submit_assessment( self, assessment.unit_id, {'answers': '', 'score': 70, 'assessment_type': assessment.unit_id}, presubmit_checks=False) news_items = news.StudentNewsDao.get_news_items() self.assertEquals(1, len(news_items)) item = news_items[0] now_ts = utc.now_as_timestamp() self.assertEquals(certificate.CERTIFICATE_HANDLER_PATH, item.url) self.assertEquals(certificate.RESOURCE_KEY, item.resource_key) self.assertAlmostEqual( now_ts, utc.datetime_to_timestamp(item.when), delta=10) response = self.get('course') soup = self.parse_html_string_to_soup(response.body) self.assertEquals( [news_tests_lib.NewsItem( 'Course completion certificate earned!', certificate.CERTIFICATE_HANDLER_PATH, True)], news_tests_lib.extract_news_items_from_soup(soup))
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))
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))
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))
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
def test_announcement_news(self): actions.login('*****@*****.**') actions.register(self, 'John Doe') time.sleep(1) locale = 'de' announcement = self._add_announcement_and_translation(locale, is_draft=True) sent_data = { 'key': str(announcement.key()), 'title': 'Test Announcement', 'date': utc.to_text(seconds=utc.now_as_timestamp()), 'is_draft': False, } actions.login(self.ADMIN_EMAIL) response = self._put_announcement(sent_data) actions.login('*****@*****.**') # Verify announcement news item using news API directly news_items = news.CourseNewsDao.get_news_items() self.assertEquals(1, len(news_items)) item = news_items[0] now_timestamp = utc.now_as_timestamp() self.assertEquals( announcements.AnnouncementsStudentHandler.URL.lstrip('/'), item.url) self.assertEquals( str( announcements.TranslatableResourceAnnouncement.key_for_entity( announcement)), item.resource_key) self.assertAlmostEqual(now_timestamp, utc.datetime_to_timestamp(item.when), delta=10) # Verify announcement news item looking at HTTP response to /course response = self.get('course') soup = self.parse_html_string_to_soup(response.body) self.assertEquals([ news_tests_lib.NewsItem( 'Test Announcement', announcements.AnnouncementsStudentHandler.URL.lstrip('/'), True) ], news_tests_lib.extract_news_items_from_soup(soup)) # Verify announcement news item translated title. self._set_prefs_locale(locale) response = self.get('course') soup = self.parse_html_string_to_soup(response.body) self.assertEquals([ news_tests_lib.NewsItem( 'TEST ANNOUNCEMENT', announcements.AnnouncementsStudentHandler.URL.lstrip('/'), True) ], news_tests_lib.extract_news_items_from_soup(soup)) # Delete the announcement; news item should also go away. actions.login(self.ADMIN_EMAIL) self._delete_announcement(str(announcement.key())) actions.login('*****@*****.**') response = self.get('course') soup = self.parse_html_string_to_soup(response.body) self.assertEquals([], news_tests_lib.extract_news_items_from_soup(soup))