fix expired message on dashboard and some of the tests
This commit is contained in:
@@ -235,18 +235,18 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
|
||||
# # of sql queries to default,
|
||||
# # of mongo queries,
|
||||
# )
|
||||
('no_overrides', 1, True, False): (18, 1),
|
||||
('no_overrides', 2, True, False): (18, 1),
|
||||
('no_overrides', 3, True, False): (18, 1),
|
||||
('ccx', 1, True, False): (18, 1),
|
||||
('ccx', 2, True, False): (18, 1),
|
||||
('ccx', 3, True, False): (18, 1),
|
||||
('no_overrides', 1, False, False): (18, 1),
|
||||
('no_overrides', 2, False, False): (18, 1),
|
||||
('no_overrides', 3, False, False): (18, 1),
|
||||
('ccx', 1, False, False): (18, 1),
|
||||
('ccx', 2, False, False): (18, 1),
|
||||
('ccx', 3, False, False): (18, 1),
|
||||
('no_overrides', 1, True, False): (20, 1),
|
||||
('no_overrides', 2, True, False): (20, 1),
|
||||
('no_overrides', 3, True, False): (20, 1),
|
||||
('ccx', 1, True, False): (20, 1),
|
||||
('ccx', 2, True, False): (20, 1),
|
||||
('ccx', 3, True, False): (20, 1),
|
||||
('no_overrides', 1, False, False): (20, 1),
|
||||
('no_overrides', 2, False, False): (20, 1),
|
||||
('no_overrides', 3, False, False): (20, 1),
|
||||
('ccx', 1, False, False): (20, 1),
|
||||
('ccx', 2, False, False): (20, 1),
|
||||
('ccx', 3, False, False): (20, 1),
|
||||
}
|
||||
|
||||
|
||||
@@ -258,19 +258,19 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
|
||||
__test__ = True
|
||||
|
||||
TEST_DATA = {
|
||||
('no_overrides', 1, True, False): (18, 3),
|
||||
('no_overrides', 2, True, False): (18, 3),
|
||||
('no_overrides', 3, True, False): (18, 3),
|
||||
('ccx', 1, True, False): (18, 3),
|
||||
('ccx', 2, True, False): (18, 3),
|
||||
('ccx', 3, True, False): (18, 3),
|
||||
('ccx', 1, True, True): (19, 3),
|
||||
('ccx', 2, True, True): (19, 3),
|
||||
('ccx', 3, True, True): (19, 3),
|
||||
('no_overrides', 1, False, False): (18, 3),
|
||||
('no_overrides', 2, False, False): (18, 3),
|
||||
('no_overrides', 3, False, False): (18, 3),
|
||||
('ccx', 1, False, False): (18, 3),
|
||||
('ccx', 2, False, False): (18, 3),
|
||||
('ccx', 3, False, False): (18, 3),
|
||||
('no_overrides', 1, True, False): (20, 3),
|
||||
('no_overrides', 2, True, False): (20, 3),
|
||||
('no_overrides', 3, True, False): (20, 3),
|
||||
('ccx', 1, True, False): (20, 3),
|
||||
('ccx', 2, True, False): (20, 3),
|
||||
('ccx', 3, True, False): (20, 3),
|
||||
('ccx', 1, True, True): (21, 3),
|
||||
('ccx', 2, True, True): (21, 3),
|
||||
('ccx', 3, True, True): (21, 3),
|
||||
('no_overrides', 1, False, False): (20, 3),
|
||||
('no_overrides', 2, False, False): (20, 3),
|
||||
('no_overrides', 3, False, False): (20, 3),
|
||||
('ccx', 1, False, False): (20, 3),
|
||||
('ccx', 2, False, False): (20, 3),
|
||||
('ccx', 3, False, False): (20, 3),
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Note: The access control logic in this file does NOT check for enrollment in
|
||||
It is a wrapper around has_access that additionally checks for enrollment.
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
@@ -836,15 +836,15 @@ class CourseOverviewAccessTestCase(ModuleStoreTestCase):
|
||||
user = getattr(self, user_attr_name)
|
||||
user = User.objects.get(id=user.id)
|
||||
|
||||
if (user_attr_name == 'user_staff' and
|
||||
action == 'see_exists' and
|
||||
course_attr_name in
|
||||
['course_default', 'course_not_started']):
|
||||
if user_attr_name == 'user_staff' and action == 'see_exists':
|
||||
# checks staff role
|
||||
num_queries = 1
|
||||
elif user_attr_name == 'user_normal' and action == 'see_exists' and course_attr_name != 'course_started':
|
||||
# checks staff role and enrollment data
|
||||
num_queries = 2
|
||||
elif user_attr_name == 'user_normal' and action == 'see_exists':
|
||||
if course_attr_name == 'course_started':
|
||||
num_queries = 1
|
||||
else:
|
||||
# checks staff role and enrollment data
|
||||
num_queries = 2
|
||||
else:
|
||||
num_queries = 0
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_num_queries_instructor_paced(self):
|
||||
self.fetch_course_info_with_queries(self.instructor_paced_course, 28, 3)
|
||||
self.fetch_course_info_with_queries(self.instructor_paced_course, 29, 3)
|
||||
|
||||
def test_num_queries_self_paced(self):
|
||||
self.fetch_course_info_with_queries(self.self_paced_course, 28, 3)
|
||||
self.fetch_course_info_with_queries(self.self_paced_course, 29, 3)
|
||||
|
||||
@@ -205,8 +205,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
|
||||
NUM_PROBLEMS = 20
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 10, 147),
|
||||
(ModuleStoreEnum.Type.split, 4, 147),
|
||||
(ModuleStoreEnum.Type.mongo, 10, 157),
|
||||
(ModuleStoreEnum.Type.split, 4, 153),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count):
|
||||
@@ -1430,8 +1430,8 @@ class ProgressPageTests(ProgressPageBaseTests):
|
||||
self.assertContains(resp, u"Download Your Certificate")
|
||||
|
||||
@ddt.data(
|
||||
(True, 38),
|
||||
(False, 37)
|
||||
(True, 40),
|
||||
(False, 39)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_progress_queries_paced_courses(self, self_paced, query_count):
|
||||
@@ -1442,8 +1442,8 @@ class ProgressPageTests(ProgressPageBaseTests):
|
||||
|
||||
@patch.dict(settings.FEATURES, {'ASSUME_ZERO_GRADE_IF_ABSENT_FOR_ALL_TESTS': False})
|
||||
@ddt.data(
|
||||
(False, 45, 28),
|
||||
(True, 37, 24)
|
||||
(False, 47, 30),
|
||||
(True, 39, 26)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_progress_queries(self, enable_waffle, initial, subsequent):
|
||||
|
||||
@@ -430,18 +430,18 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
# course is outside the context manager that is verifying the number of queries,
|
||||
# and with split mongo, that method ends up querying disabled_xblocks (which is then
|
||||
# cached and hence not queried as part of call_single_thread).
|
||||
(ModuleStoreEnum.Type.mongo, False, 1, 5, 2, 17, 5),
|
||||
(ModuleStoreEnum.Type.mongo, False, 50, 5, 2, 17, 5),
|
||||
(ModuleStoreEnum.Type.mongo, False, 1, 5, 2, 19, 7),
|
||||
(ModuleStoreEnum.Type.mongo, False, 50, 5, 2, 19, 7),
|
||||
# split mongo: 3 queries, regardless of thread response size.
|
||||
(ModuleStoreEnum.Type.split, False, 1, 3, 3, 17, 5),
|
||||
(ModuleStoreEnum.Type.split, False, 50, 3, 3, 17, 5),
|
||||
(ModuleStoreEnum.Type.split, False, 1, 3, 3, 19, 7),
|
||||
(ModuleStoreEnum.Type.split, False, 50, 3, 3, 19, 7),
|
||||
|
||||
# Enabling Enterprise integration should have no effect on the number of mongo queries made.
|
||||
(ModuleStoreEnum.Type.mongo, True, 1, 5, 2, 17, 5),
|
||||
(ModuleStoreEnum.Type.mongo, True, 50, 5, 2, 17, 5),
|
||||
(ModuleStoreEnum.Type.mongo, True, 1, 5, 2, 19, 7),
|
||||
(ModuleStoreEnum.Type.mongo, True, 50, 5, 2, 19, 7),
|
||||
# split mongo: 3 queries, regardless of thread response size.
|
||||
(ModuleStoreEnum.Type.split, True, 1, 3, 3, 17, 5),
|
||||
(ModuleStoreEnum.Type.split, True, 50, 3, 3, 17, 5),
|
||||
(ModuleStoreEnum.Type.split, True, 1, 3, 3, 19, 7),
|
||||
(ModuleStoreEnum.Type.split, True, 50, 3, 3, 19, 7),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_number_of_mongo_queries(
|
||||
|
||||
@@ -403,8 +403,8 @@ class ViewsQueryCountTestCase(
|
||||
return inner
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 3, 4, 35),
|
||||
(ModuleStoreEnum.Type.split, 3, 13, 35),
|
||||
(ModuleStoreEnum.Type.mongo, 3, 4, 37),
|
||||
(ModuleStoreEnum.Type.split, 3, 13, 37),
|
||||
)
|
||||
@ddt.unpack
|
||||
@count_queries
|
||||
@@ -412,8 +412,8 @@ class ViewsQueryCountTestCase(
|
||||
self.create_thread_helper(mock_request)
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 3, 3, 31),
|
||||
(ModuleStoreEnum.Type.split, 3, 10, 31),
|
||||
(ModuleStoreEnum.Type.mongo, 3, 3, 33),
|
||||
(ModuleStoreEnum.Type.split, 3, 10, 33),
|
||||
)
|
||||
@ddt.unpack
|
||||
@count_queries
|
||||
|
||||
@@ -33,6 +33,8 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
if cert_name_long == "":
|
||||
cert_name_long = settings.CERT_NAME_LONG
|
||||
billing_email = settings.PAYMENT_SUPPORT_EMAIL
|
||||
|
||||
is_course_expired = getattr(show_courseware_link, 'error_code') == 'audit_expired'
|
||||
%>
|
||||
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
@@ -65,7 +67,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
<h2 class="hd hd-2 sr" id="details-heading-${enrollment.course_id}">${_('Course details')}</h2>
|
||||
<div class="wrapper-course-image" aria-hidden="true">
|
||||
% if show_courseware_link and not is_unfulfilled_entitlement:
|
||||
% if not is_course_blocked:
|
||||
% if not is_course_blocked and not is_course_expired:
|
||||
<a href="${course_target}" data-course-key="${enrollment.course_id}" class="cover" tabindex="-1">
|
||||
<img src="${course_overview.image_urls['small']}" class="course-image" alt="${_('{course_number} {course_name} Home Page').format(course_number=course_overview.number, course_name=course_overview.display_name_with_default)}" />
|
||||
</a>
|
||||
@@ -92,7 +94,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
<div class="wrapper-course-details">
|
||||
<h3 class="course-title" id="course-title-${enrollment.course_id}">
|
||||
% if show_courseware_link and not is_unfulfilled_entitlement:
|
||||
% if not is_course_blocked:
|
||||
% if not is_course_blocked and not is_course_expired:
|
||||
<a data-course-key="${enrollment.course_id}" href="${course_target}">${course_overview.display_name_with_default}</a>
|
||||
% else:
|
||||
<a class="disable-look" data-course-key="${enrollment.course_id}">${course_overview.display_name_with_default}</a>
|
||||
@@ -128,7 +130,14 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
%>
|
||||
|
||||
<span class="info-date-block-container">
|
||||
% if is_unfulfilled_entitlement:
|
||||
% if is_course_expired:
|
||||
<span class="info-date-block" data-course-key="${enrollment.course_id}">
|
||||
${show_courseware_link.user_message}
|
||||
<span class="sr">
|
||||
${_('for {course_display_name}').format(course_display_name=course_overview.display_name_with_default)}
|
||||
</span>
|
||||
</span>
|
||||
% elif is_unfulfilled_entitlement:
|
||||
<span class="info-date-block" aria-live="polite">
|
||||
<span class="icon fa fa-warning" aria-hidden="true"></span>
|
||||
% if not entitlement_expired_at:
|
||||
@@ -167,7 +176,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
<div class="course-actions">
|
||||
% if show_courseware_link or is_unfulfilled_entitlement:
|
||||
% if course_overview.has_ended():
|
||||
% if not is_course_blocked:
|
||||
% if not is_course_blocked and not is_course_expired:
|
||||
<a href="${course_target}" class="enter-course archived" data-course-key="${enrollment.course_id}">${_('View Archived Course')}<span class="sr"> ${course_overview.display_name_with_default}</span></a>
|
||||
% else:
|
||||
<a class="enter-course-blocked archived" data-course-key="${enrollment.course_id}">${_('View Archived Course')}<span class="sr"> ${course_overview.display_name_with_default}</span></a>
|
||||
@@ -183,7 +192,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
${course_overview.display_name_with_default}
|
||||
</span>
|
||||
</a>
|
||||
% elif not is_course_blocked:
|
||||
% elif not is_course_blocked and not is_course_expired:
|
||||
<a href="${course_target}"
|
||||
class="enter-course ${'hidden' if is_unfulfilled_entitlement else ''}"
|
||||
data-course-key="${enrollment.course_id}">
|
||||
@@ -202,14 +211,6 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
|
||||
</a>
|
||||
% endif
|
||||
% endif
|
||||
% elif hasattr(show_courseware_link, 'user_message'):
|
||||
<span class="enter-course-blocked"
|
||||
data-course-key="${enrollment.course_id}">
|
||||
${show_courseware_link.user_message}
|
||||
<span class="sr">
|
||||
${_('for {course_display_name}').format(course_display_name=course_overview.display_name_with_default)}
|
||||
</span>
|
||||
</span>
|
||||
% endif
|
||||
|
||||
% if show_courseware_link or course_overview.has_social_sharing_url() or course_overview.has_marketing_url():
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Contains code related to computing content gating course duration limits
|
||||
and course access based on these limits.
|
||||
"""
|
||||
from datetime import timedelta
|
||||
|
||||
from django.apps import apps
|
||||
@@ -16,11 +21,15 @@ class AuditExpiredError(AccessError):
|
||||
def __init__(self, user, course, end_date):
|
||||
error_code = "audit_expired"
|
||||
developer_message = "User {} had access to {} until {}".format(user, course, end_date)
|
||||
user_message = _("Your audit access period has expired.")
|
||||
# TODO: Translate the end_date
|
||||
user_message = _("Course access expired on ") + end_date.strftime("%B %d, %Y")
|
||||
super(AuditExpiredError, self).__init__(error_code, developer_message, user_message)
|
||||
|
||||
|
||||
def check_course_expired(user, course):
|
||||
"""
|
||||
Check if the course expired for the user.
|
||||
"""
|
||||
# TODO: Only limit audit users
|
||||
# TODO: Limit access to instructor paced courses based on end-date, rather than content availability date
|
||||
CourseEnrollment = apps.get_model('student.CourseEnrollment')
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -1,3 +1,6 @@
|
||||
"""
|
||||
Course duration limits application configuration
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
@@ -1,6 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,6 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -173,7 +173,7 @@ class TestCourseHomePage(CourseHomePageTestCase):
|
||||
course_home_url(self.course)
|
||||
|
||||
# Fetch the view and verify the query counts
|
||||
with self.assertNumQueries(54, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with self.assertNumQueries(66, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with check_mongo_calls(4):
|
||||
url = course_home_url(self.course)
|
||||
self.client.get(url)
|
||||
|
||||
@@ -124,7 +124,7 @@ class TestCourseUpdatesPage(SharedModuleStoreTestCase):
|
||||
course_updates_url(self.course)
|
||||
|
||||
# Fetch the view and verify that the query counts haven't changed
|
||||
with self.assertNumQueries(34, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with self.assertNumQueries(38, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with check_mongo_calls(4):
|
||||
url = course_updates_url(self.course)
|
||||
self.client.get(url)
|
||||
|
||||
Reference in New Issue
Block a user