Commit fd4164de by Ned Batchelder

Merge pull request #11737 from edx/release

Release ⇒ master
parents ad5cec10 00b270c3
......@@ -233,7 +233,7 @@ class TestCourseIndex(CourseTestCase):
# delete nofications that are dismissed
CourseRerunState.objects.get(id=rerun_state.id)
self.assertTrue(has_course_author_access(user2, rerun_course_key))
self.assertFalse(has_course_author_access(user2, rerun_course_key))
def assert_correct_json_response(self, json_response):
"""
......
......@@ -54,10 +54,6 @@ class RoleCache(object):
for access_role in self._roles
)
def add_role(self, role):
"""Adds a role to the cache."""
self._roles.add(role)
class AccessRole(object):
"""
......@@ -66,7 +62,7 @@ class AccessRole(object):
__metaclass__ = ABCMeta
@abstractmethod
def has_user(self, user, refresh=True):
def has_user(self, user):
"""
Return whether the supplied django user has access to this role.
"""
......@@ -134,7 +130,7 @@ class RoleBase(AccessRole):
self.course_key = course_key
self._role_name = role_name
def has_user(self, user, refresh=False):
def has_user(self, user):
"""
Return whether the supplied django user has access to this role.
"""
......@@ -142,7 +138,7 @@ class RoleBase(AccessRole):
return False
# pylint: disable=protected-access
if not hasattr(user, '_roles') or refresh:
if not hasattr(user, '_roles'):
# Cache a list of tuples identifying the particular roles that a user has
# Stored as tuples, rather than django models, to make it cheaper to construct objects for comparison
user._roles = RoleCache(user)
......@@ -161,8 +157,7 @@ class RoleBase(AccessRole):
entry = CourseAccessRole(user=user, role=self._role_name, course_id=self.course_key, org=self.org)
entry.save()
if hasattr(user, '_roles'):
# pylint: disable=protected-access
user._roles.add_role(entry)
del user._roles
def remove_users(self, *users):
"""
......
......@@ -40,6 +40,7 @@ from student.tests.factories import (
from xmodule.x_module import XModuleMixin
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import (
ModuleStoreTestCase,
SharedModuleStoreTestCase,
......@@ -297,7 +298,7 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
# assert ccx creator has role=ccx_coach
role = CourseCcxCoachRole(course_key)
self.assertTrue(role.has_user(self.coach, refresh=True))
self.assertTrue(role.has_user(self.coach))
@ddt.data("CCX demo 1", "CCX demo 2", "CCX demo 3")
def test_create_multiple_ccx(self, ccx_name):
......@@ -790,28 +791,25 @@ def patched_get_children(self, usage_key_filter=None):
@override_settings(FIELD_OVERRIDE_PROVIDERS=(
'ccx.overrides.CustomCoursesForEdxOverrideProvider',))
@patch('xmodule.x_module.XModuleMixin.get_children', patched_get_children, spec=True)
class TestCCXGrades(ModuleStoreTestCase, LoginEnrollmentTestCase):
class TestCCXGrades(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Tests for Custom Courses views.
"""
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
def setUp(self):
"""
Set up tests
"""
super(TestCCXGrades, self).setUp()
self._course = CourseFactory.create(enable_ccx=True)
@classmethod
def setUpClass(cls):
super(TestCCXGrades, cls).setUpClass()
cls._course = course = CourseFactory.create(enable_ccx=True)
# Create a course outline
self.start = datetime.datetime(
cls.mooc_start = start = datetime.datetime(
2010, 5, 12, 2, 42, tzinfo=pytz.UTC
)
chapter = ItemFactory.create(
start=self.start, parent=self._course, category='sequential'
start=start, parent=course, category='sequential'
)
self.sections = [
cls.sections = sections = [
ItemFactory.create(
parent=chapter,
category="sequential",
......@@ -819,7 +817,7 @@ class TestCCXGrades(ModuleStoreTestCase, LoginEnrollmentTestCase):
for _ in xrange(4)
]
# making problems available at class level for possible future use in tests
self.problems = [
cls.problems = [
[
ItemFactory.create(
parent=section,
......@@ -827,9 +825,15 @@ class TestCCXGrades(ModuleStoreTestCase, LoginEnrollmentTestCase):
data=StringResponseXMLFactory().build_xml(answer='foo'),
metadata={'rerandomize': 'always'}
) for _ in xrange(4)
] for section in self.sections
] for section in sections
]
def setUp(self):
"""
Set up tests
"""
super(TestCCXGrades, self).setUp()
# Create instructor account
self.coach = coach = AdminFactory.create()
self.client.login(username=coach.username, password="test")
......@@ -902,18 +906,13 @@ class TestCCXGrades(ModuleStoreTestCase, LoginEnrollmentTestCase):
rows = response.content.strip().split('\r')
headers = rows[0]
records = dict()
for i in range(1, len(rows)):
data = dict(zip(headers.strip().split(','), rows[i].strip().split(',')))
records[data['username']] = data
student_data = records[self.student.username] # pylint: disable=no-member
self.assertNotIn('HW 04', student_data)
self.assertEqual(student_data['HW 01'], '0.75')
self.assertEqual(student_data['HW 02'], '0.5')
self.assertEqual(student_data['HW 03'], '0.25')
self.assertEqual(student_data['HW Avg'], '0.5')
# picking first student records
data = dict(zip(headers.strip().split(','), rows[1].strip().split(',')))
self.assertNotIn('HW 04', data)
self.assertEqual(data['HW 01'], '0.75')
self.assertEqual(data['HW 02'], '0.5')
self.assertEqual(data['HW 03'], '0.25')
self.assertEqual(data['HW Avg'], '0.5')
@patch('courseware.views.render_to_response', intercept_renderer)
def test_student_progress(self):
......
......@@ -11,8 +11,6 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RemoveField(
model_name='courseoverview',
name='facebook_url',
),
# Removed because we accidentally removed this column without first
# removing the code that refers to this. This can cause errors in production.
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.db import migrations, models, OperationalError, connection
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
class Migration(migrations.Migration):
......@@ -10,10 +11,17 @@ class Migration(migrations.Migration):
('course_overviews', '0008_remove_courseoverview_facebook_url'),
]
operations = [
migrations.AddField(
# An original version of 0008 removed the facebook_url field
# We need to handle the case where our noop 0008 ran AND the case
# where the original 0008 ran. We do that by using Django's introspection
# API to query INFORMATION_SCHEMA. _meta is unavailable as the
# column has already been removed from the model.
fields = connection.introspection.get_table_description(connection.cursor(),'course_overviews_courseoverview')
operations = []
if not any(f.name == 'facebook_url' for f in fields):
operations += migrations.AddField(
model_name='courseoverview',
name='facebook_url',
field=models.TextField(null=True),
),
]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment