test_field_overrides.py 5.36 KB
Newer Older
1 2 3
"""
Tests for `field_overrides` module.
"""
4
# pylint: disable=missing-docstring
5 6 7
import unittest

from django.test.utils import override_settings
8
from nose.plugins.attrib import attr
9
from xblock.field_data import DictFieldData
10

11
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
12
from xmodule.modulestore.tests.factories import CourseFactory
13 14 15 16

from ..field_overrides import (
    FieldOverrideProvider,
    OverrideFieldData,
17
    OverrideModulestoreFieldData,
18 19
    disable_overrides,
    resolve_dotted
20
)
21
from ..testutils import FieldOverrideTestMixin
22

23
TESTUSER = "testuser"
24 25


26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
class TestOverrideProvider(FieldOverrideProvider):
    """
    A concrete implementation of `FieldOverrideProvider` for testing.
    """
    def get(self, block, name, default):
        if self.user:
            assert self.user is TESTUSER

        assert block == 'block'

        if name == 'foo':
            return 'fu'
        elif name == 'oh':
            return 'man'

        return default

    @classmethod
    def enabled_for(cls, course):
        return True


48
@attr(shard=1)
49 50
@override_settings(FIELD_OVERRIDE_PROVIDERS=(
    'courseware.tests.test_field_overrides.TestOverrideProvider',))
51
class OverrideFieldDataTests(SharedModuleStoreTestCase):
52 53 54 55
    """
    Tests for `OverrideFieldData`.
    """

56 57 58 59 60 61 62 63
    @classmethod
    def setUpClass(cls):
        """
        Course is created here and shared by all the class's tests.
        """
        super(OverrideFieldDataTests, cls).setUpClass()
        cls.course = CourseFactory.create(enable_ccx=True)

64
    def setUp(self):
65
        super(OverrideFieldDataTests, self).setUp()
66 67 68
        OverrideFieldData.provider_classes = None

    def tearDown(self):
69
        super(OverrideFieldDataTests, self).tearDown()
70 71 72 73 74 75
        OverrideFieldData.provider_classes = None

    def make_one(self):
        """
        Factory method.
        """
76
        return OverrideFieldData.wrap(TESTUSER, self.course, DictFieldData({
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
            'foo': 'bar',
            'bees': 'knees',
        }))

    def test_get(self):
        data = self.make_one()
        self.assertEqual(data.get('block', 'foo'), 'fu')
        self.assertEqual(data.get('block', 'bees'), 'knees')
        with disable_overrides():
            self.assertEqual(data.get('block', 'foo'), 'bar')

    def test_set(self):
        data = self.make_one()
        data.set('block', 'foo', 'yowza')
        self.assertEqual(data.get('block', 'foo'), 'fu')
        with disable_overrides():
            self.assertEqual(data.get('block', 'foo'), 'yowza')

    def test_delete(self):
        data = self.make_one()
        data.delete('block', 'foo')
        self.assertEqual(data.get('block', 'foo'), 'fu')
        with disable_overrides():
            # Since field_data is responsible for attribute access, you'd
            # expect it to raise AttributeError. In fact, it raises KeyError,
            # so we check for that.
            with self.assertRaises(KeyError):
                data.get('block', 'foo')

    def test_has(self):
        data = self.make_one()
        self.assertTrue(data.has('block', 'foo'))
        self.assertTrue(data.has('block', 'bees'))
        self.assertTrue(data.has('block', 'oh'))
        with disable_overrides():
            self.assertFalse(data.has('block', 'oh'))

    def test_many(self):
        data = self.make_one()
        data.set_many('block', {'foo': 'baz', 'ah': 'ic'})
        self.assertEqual(data.get('block', 'foo'), 'fu')
        self.assertEqual(data.get('block', 'ah'), 'ic')
        with disable_overrides():
            self.assertEqual(data.get('block', 'foo'), 'baz')

    @override_settings(FIELD_OVERRIDE_PROVIDERS=())
    def test_no_overrides_configured(self):
        data = self.make_one()
        self.assertIsInstance(data, DictFieldData)


128
@attr(shard=1)
129 130 131
@override_settings(
    MODULESTORE_FIELD_OVERRIDE_PROVIDERS=['courseware.tests.test_field_overrides.TestOverrideProvider']
)
132
class OverrideModulestoreFieldDataTests(FieldOverrideTestMixin, OverrideFieldDataTests):
133 134 135 136 137 138 139 140 141 142 143 144
    def make_one(self):
        return OverrideModulestoreFieldData.wrap(self.course, DictFieldData({
            'foo': 'bar',
            'bees': 'knees',
        }))

    @override_settings(MODULESTORE_FIELD_OVERRIDE_PROVIDERS=[])
    def test_no_overrides_configured(self):
        data = self.make_one()
        self.assertIsInstance(data, DictFieldData)


145
@attr(shard=1)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
class ResolveDottedTests(unittest.TestCase):
    """
    Tests for `resolve_dotted`.
    """

    def test_bad_sub_import(self):
        with self.assertRaises(ImportError):
            resolve_dotted('courseware.tests.test_foo')

    def test_bad_import(self):
        with self.assertRaises(ImportError):
            resolve_dotted('nosuchpackage')

    def test_import_something_that_isnt_already_loaded(self):
        self.assertEqual(
            resolve_dotted('courseware.tests.animport.SOMENAME'),
            'bar'
        )


166 167 168 169 170 171 172 173 174 175 176
def inject_field_overrides(blocks, course, user):
    """
    Apparently the test harness doesn't use LmsFieldStorage, and I'm
    not sure if there's a way to poke the test harness to do so.  So,
    we'll just inject the override field storage in this brute force
    manner.
    """
    OverrideFieldData.provider_classes = None
    for block in blocks:
        block._field_data = OverrideFieldData.wrap(   # pylint: disable=protected-access
            user, course, block._field_data)   # pylint: disable=protected-access