markdown-xblock 2.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- markdown_xblock/__init__.py +2 -0
- markdown_xblock/html.py +335 -0
- markdown_xblock/public/plugins/codemirror/LICENSE +21 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/dialog/dialog.css +32 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/dialog/dialog.js +155 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/display/fullscreen.css +6 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/display/fullscreen.js +41 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/edit/matchbrackets.js +120 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/search/search.js +159 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/search/searchcursor.js +189 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/selection/active-line.js +71 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/lib/codemirror.css +319 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/lib/codemirror.js +7923 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/css/css.js +717 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/htmlmixed/htmlmixed.js +121 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/javascript/javascript.js +684 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/markdown/markdown.js +883 -0
- markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/xml/xml.js +384 -0
- markdown_xblock/public/plugins/codemirror/langs/en.js +8 -0
- markdown_xblock/public/plugins/codemirror/plugin.min.js +1 -0
- markdown_xblock/public/plugins/codemirror/source.html +270 -0
- markdown_xblock/public/plugins/codesample/css/prism.css +141 -0
- markdown_xblock/public/plugins/codesample/js/prism.js +15 -0
- markdown_xblock/public/plugins/codesample/plugin.min.js +1 -0
- markdown_xblock/public/plugins/image/plugin.min.js +1 -0
- markdown_xblock/public/plugins/link/plugin.min.js +1 -0
- markdown_xblock/public/plugins/lists/plugin.min.js +1 -0
- markdown_xblock/public/plugins/textcolor/plugin.min.js +1 -0
- markdown_xblock/public/skin/content.inline.min.css +1 -0
- markdown_xblock/public/skin/content.min.css +2 -0
- markdown_xblock/public/skin/fonts/icomoon-small.eot +0 -0
- markdown_xblock/public/skin/fonts/icomoon-small.svg +175 -0
- markdown_xblock/public/skin/fonts/icomoon-small.ttf +0 -0
- markdown_xblock/public/skin/fonts/icomoon-small.woff +0 -0
- markdown_xblock/public/skin/fonts/icomoon.eot +0 -0
- markdown_xblock/public/skin/fonts/icomoon.svg +153 -0
- markdown_xblock/public/skin/fonts/icomoon.ttf +0 -0
- markdown_xblock/public/skin/fonts/icomoon.woff +0 -0
- markdown_xblock/public/skin/fonts/readme.md +1 -0
- markdown_xblock/public/skin/img/anchor.gif +0 -0
- markdown_xblock/public/skin/img/loader.gif +0 -0
- markdown_xblock/public/skin/img/object.gif +0 -0
- markdown_xblock/public/skin/img/trans.gif +0 -0
- markdown_xblock/public/skin/img/wline.gif +0 -0
- markdown_xblock/public/skin/skin.ie7.min.css +1 -0
- markdown_xblock/public/skin/skin.json +51 -0
- markdown_xblock/public/skin/skin.min.css +1 -0
- markdown_xblock/static/css/html.css +15 -0
- markdown_xblock/static/css/pygments.css +61 -0
- markdown_xblock/static/html/lms.html +1 -0
- markdown_xblock/static/html/studio.html +29 -0
- markdown_xblock/static/js/html.js +233 -0
- markdown_xblock/static/js/tinymce/themes/modern/theme.min.js +1 -0
- markdown_xblock/static/js/tinymce/tinymce.js +26801 -0
- markdown_xblock/static/js/tinymce/tinymce.min.js +2 -0
- markdown_xblock/translations/README.txt +4 -0
- markdown_xblock/utils.py +11 -0
- markdown_xblock-2.4.0.dist-info/METADATA +158 -0
- markdown_xblock-2.4.0.dist-info/RECORD +83 -0
- markdown_xblock-2.4.0.dist-info/WHEEL +5 -0
- markdown_xblock-2.4.0.dist-info/entry_points.txt +2 -0
- markdown_xblock-2.4.0.dist-info/licenses/LICENSE +671 -0
- markdown_xblock-2.4.0.dist-info/top_level.txt +5 -0
- releasenotes/notes/add-default-css-for-tables-3a53e02e8a350253.yaml +5 -0
- releasenotes/notes/add_public_view-d24763b7941dc2b0.yaml +4 -0
- releasenotes/notes/custom-css-classes-7984a9c95147d39c.yaml +5 -0
- releasenotes/notes/export-md-to-file-ab1528b4c28cb2f0.yaml +5 -0
- releasenotes/notes/fix-course-export-b35c78a22be0c6b5.yaml +6 -0
- releasenotes/notes/missing-codemirror-files-d64ccb15d0faf640.yaml +6 -0
- releasenotes/notes/pypi-release-3e4d5ceb7b6e252a.yaml +7 -0
- releasenotes/notes/python-3.12-support-dac839f8d01ac6b9.yaml +4 -0
- releasenotes/notes/refactor-ci-36abda8c15250d06.yaml +6 -0
- releasenotes/notes/refactor-export-import-49bbf0e8a364f139.yaml +8 -0
- releasenotes/notes/remove_py35-0b265861449b1753.yaml +9 -0
- releasenotes/notes/safe_mode_replace_escape-40fdb78ec8aa5eff.yaml +7 -0
- releasenotes/notes/show_in_read_only_mode-3af39459d5d56b33.yaml +7 -0
- requirements/base.txt +9 -0
- requirements/dev.txt +2 -0
- requirements/reno.txt +1 -0
- requirements/test.txt +9 -0
- tests/__init__.py +1 -0
- tests/test_basics.py +280 -0
- var/.placeholder +2 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
upgrade:
|
|
3
|
+
- |
|
|
4
|
+
This release removes support for Python 3.5. Do not upgrade to
|
|
5
|
+
this release on platforms still using Python 3.5.
|
|
6
|
+
deprecations:
|
|
7
|
+
- |
|
|
8
|
+
With this release, all automated testing on Python 3.5 has been
|
|
9
|
+
removed, and Python 3.8 is the recommended Python release.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
features:
|
|
3
|
+
- |
|
|
4
|
+
The XBlock settings now support the string values "replace" and "escape"
|
|
5
|
+
for safe_mode, just like the upstream Markdown2 library does. A Boolean
|
|
6
|
+
value of True is considered to be equivalent to "replace". A value of
|
|
7
|
+
False, None, or the empty string disables safe mode.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
fixes:
|
|
3
|
+
- |
|
|
4
|
+
The XBlock now renders normally in "read-only" ("masquerading")
|
|
5
|
+
mode, which applies when a course instructor (a user with either
|
|
6
|
+
per-course or platform-wide Staff permissions) selects the "View
|
|
7
|
+
this course as" → "Specific learner" option in the Open edX LMS.
|
requirements/base.txt
ADDED
requirements/dev.txt
ADDED
requirements/reno.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
reno
|
requirements/test.txt
ADDED
tests/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tests module."""
|
tests/test_basics.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Markdown XBlock tests
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import print_function
|
|
5
|
+
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
from mock import Mock, patch
|
|
9
|
+
from workbench.runtime import WorkbenchRuntime
|
|
10
|
+
from xblock.field_data import DictFieldData
|
|
11
|
+
from xblock.fields import ScopeIds
|
|
12
|
+
|
|
13
|
+
from markdown2 import MarkdownError
|
|
14
|
+
|
|
15
|
+
import markdown_xblock
|
|
16
|
+
from markdown_xblock.html import DEFAULT_EXTRAS
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestMarkdownXBlock(unittest.TestCase):
|
|
20
|
+
"""
|
|
21
|
+
Unit tests for `markdown_xblock`
|
|
22
|
+
"""
|
|
23
|
+
def setUp(self):
|
|
24
|
+
block_type = 'markdown'
|
|
25
|
+
self.runtime = WorkbenchRuntime()
|
|
26
|
+
def_id = self.runtime.id_generator.create_definition(block_type)
|
|
27
|
+
usage_id = self.runtime.id_generator.create_usage(def_id)
|
|
28
|
+
|
|
29
|
+
self.scope_ids = ScopeIds('user', block_type, def_id, usage_id)
|
|
30
|
+
|
|
31
|
+
def test_render(self):
|
|
32
|
+
"""
|
|
33
|
+
Test a basic rendering with default settings.
|
|
34
|
+
"""
|
|
35
|
+
field_data = DictFieldData({'data': '# This is h1'})
|
|
36
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
37
|
+
fragment = block.student_view()
|
|
38
|
+
self.assertIn('<div class="markdown_xblock"><h1>This is h1</h1>\n</div>\n', fragment.content)
|
|
39
|
+
|
|
40
|
+
def test_public_view(self):
|
|
41
|
+
"""
|
|
42
|
+
Test public view rendering.
|
|
43
|
+
"""
|
|
44
|
+
field_data = DictFieldData({'data': '# This is h1'})
|
|
45
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
46
|
+
student_view_fragment = block.student_view()
|
|
47
|
+
self.assertIn('<div class="markdown_xblock"><h1>This is h1</h1>\n</div>\n',
|
|
48
|
+
student_view_fragment.content)
|
|
49
|
+
public_view_fragment = block.public_view()
|
|
50
|
+
self.assertIn('<div class="markdown_xblock"><h1>This is h1</h1>\n</div>\n',
|
|
51
|
+
public_view_fragment.content)
|
|
52
|
+
|
|
53
|
+
def test_render_default_settings(self):
|
|
54
|
+
"""
|
|
55
|
+
Test a basic rendering with default settings.
|
|
56
|
+
|
|
57
|
+
Expects the content to be sanitized by injecting
|
|
58
|
+
[HTML_REMOVED] in place of the HTML tags, and the sentence
|
|
59
|
+
being wrapped in a <p> block (since the <h1> tags are no
|
|
60
|
+
longer interpreted as HTML).
|
|
61
|
+
"""
|
|
62
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
63
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
64
|
+
fragment = block.student_view()
|
|
65
|
+
self.assertIn(
|
|
66
|
+
'<div class="markdown_xblock"><p>[HTML_REMOVED]This is h1[HTML_REMOVED]</p>\n</div>\n',
|
|
67
|
+
fragment.content
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def test_render_invalid_safe_mode(self):
|
|
71
|
+
"""
|
|
72
|
+
Test a basic rendering with default settings.
|
|
73
|
+
|
|
74
|
+
Expects the rendering to fail since safe_mode is not set to
|
|
75
|
+
one of 'replace', 'escape', True or False.
|
|
76
|
+
"""
|
|
77
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
78
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
79
|
+
settings = {
|
|
80
|
+
"extras": DEFAULT_EXTRAS,
|
|
81
|
+
"safe_mode": 'this is an invalid safe mode'
|
|
82
|
+
}
|
|
83
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
84
|
+
get_settings_mock.return_value = settings
|
|
85
|
+
with self.assertRaises(MarkdownError):
|
|
86
|
+
_ = block.student_view()
|
|
87
|
+
|
|
88
|
+
def test_render_replace_inline_html(self):
|
|
89
|
+
"""
|
|
90
|
+
Test a basic rendering with safe_mode explicitly set to 'replace'.
|
|
91
|
+
|
|
92
|
+
Expects the content to be sanitized by injecting
|
|
93
|
+
[HTML_REMOVED] in place of the HTML tags, and the sentence
|
|
94
|
+
being wrapped in a <p> block (since the <h1> tags are no
|
|
95
|
+
longer interpreted as HTML).
|
|
96
|
+
"""
|
|
97
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
98
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
99
|
+
settings = {
|
|
100
|
+
"extras": DEFAULT_EXTRAS,
|
|
101
|
+
"safe_mode": 'replace'
|
|
102
|
+
}
|
|
103
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
104
|
+
get_settings_mock.return_value = settings
|
|
105
|
+
fragment = block.student_view()
|
|
106
|
+
self.assertIn(
|
|
107
|
+
'<div class="markdown_xblock"><p>[HTML_REMOVED]This is h1[HTML_REMOVED]</p>\n</div>\n',
|
|
108
|
+
fragment.content
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def test_render_replace_inline_html_boolean_setting(self):
|
|
112
|
+
"""
|
|
113
|
+
Test a basic rendering with safe_mode set to True (instead of 'replace').
|
|
114
|
+
|
|
115
|
+
Expects the content to be sanitized by injecting
|
|
116
|
+
[HTML_REMOVED] in place of the HTML tags, and the sentence
|
|
117
|
+
being wrapped in a <p> block (since the <h1> tags are no
|
|
118
|
+
longer interpreted as HTML).
|
|
119
|
+
"""
|
|
120
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
121
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
122
|
+
settings = {
|
|
123
|
+
"extras": DEFAULT_EXTRAS,
|
|
124
|
+
"safe_mode": True
|
|
125
|
+
}
|
|
126
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
127
|
+
get_settings_mock.return_value = settings
|
|
128
|
+
fragment = block.student_view()
|
|
129
|
+
self.assertIn(
|
|
130
|
+
'<div class="markdown_xblock"><p>[HTML_REMOVED]This is h1[HTML_REMOVED]</p>\n</div>\n',
|
|
131
|
+
fragment.content
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def test_render_escape_inline_html(self):
|
|
135
|
+
"""
|
|
136
|
+
Test a basic rendering with safe_mode set to 'escape'
|
|
137
|
+
|
|
138
|
+
Expects the content to be sanitized by escaping < and > with < and >
|
|
139
|
+
and the sentence being wrapped in a <p> block (since the <h1> tags are
|
|
140
|
+
no longer interpreted as HTML).
|
|
141
|
+
"""
|
|
142
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
143
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
144
|
+
settings = {
|
|
145
|
+
"extras": DEFAULT_EXTRAS,
|
|
146
|
+
"safe_mode": 'escape'
|
|
147
|
+
}
|
|
148
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
149
|
+
get_settings_mock.return_value = settings
|
|
150
|
+
fragment = block.student_view()
|
|
151
|
+
self.assertIn(
|
|
152
|
+
'<div class="markdown_xblock"><p><h1>This is h1</h1></p>\n</div>\n',
|
|
153
|
+
fragment.content
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def test_render_allow_inline_html(self):
|
|
157
|
+
"""
|
|
158
|
+
Test a basic rendering with javascript enabled.
|
|
159
|
+
Expects the content *not* to be sanitized.
|
|
160
|
+
"""
|
|
161
|
+
field_data = DictFieldData({'data': '<h1>This is h1</h1>'})
|
|
162
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
163
|
+
settings = {
|
|
164
|
+
"extras": DEFAULT_EXTRAS,
|
|
165
|
+
"safe_mode": False
|
|
166
|
+
}
|
|
167
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
168
|
+
get_settings_mock.return_value = settings
|
|
169
|
+
fragment = block.student_view()
|
|
170
|
+
self.assertIn('<div class="markdown_xblock"><h1>This is h1</h1>\n</div>\n',
|
|
171
|
+
fragment.content)
|
|
172
|
+
|
|
173
|
+
def test_render_url_safe_mode_replace(self):
|
|
174
|
+
"""
|
|
175
|
+
Test rendering a URL with safe_mode set to 'replace'.
|
|
176
|
+
"""
|
|
177
|
+
field_data = DictFieldData(
|
|
178
|
+
{'data': '[test1](https://test.com/courses/course-v1:Org+Class+Version/about) [test2](https://test.com/courses/course-v1%3AOrg%2BClass%2BVersion/about)'} # noqa: E501
|
|
179
|
+
)
|
|
180
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
181
|
+
settings = {
|
|
182
|
+
"extras": DEFAULT_EXTRAS,
|
|
183
|
+
"safe_mode": 'replace'
|
|
184
|
+
}
|
|
185
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
186
|
+
get_settings_mock.return_value = settings
|
|
187
|
+
fragment = block.student_view()
|
|
188
|
+
self.assertIn(
|
|
189
|
+
'<a href="https://test.com/courses/course-v1:Org+Class+Version/about">test1</a>',
|
|
190
|
+
fragment.content
|
|
191
|
+
)
|
|
192
|
+
self.assertIn(
|
|
193
|
+
'<a href="https://test.com/courses/course-v1%3AOrg%2BClass%2BVersion/about">test2</a>',
|
|
194
|
+
fragment.content
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
def test_render_url_safe_mode_escape(self):
|
|
198
|
+
"""
|
|
199
|
+
Test rendering a URL with safe_mode set to 'replace'.
|
|
200
|
+
"""
|
|
201
|
+
field_data = DictFieldData(
|
|
202
|
+
{'data': '[test1](https://test.com/courses/course-v1:Org+Class+Version/about) [test2](https://test.com/courses/course-v1%3AOrg%2BClass%2BVersion/about)'} # noqa: E501
|
|
203
|
+
)
|
|
204
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
205
|
+
settings = {
|
|
206
|
+
"extras": DEFAULT_EXTRAS,
|
|
207
|
+
"safe_mode": 'escape'
|
|
208
|
+
}
|
|
209
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
210
|
+
get_settings_mock.return_value = settings
|
|
211
|
+
fragment = block.student_view()
|
|
212
|
+
self.assertIn(
|
|
213
|
+
'<a href="https://test.com/courses/course-v1:Org+Class+Version/about">test1</a>',
|
|
214
|
+
fragment.content
|
|
215
|
+
)
|
|
216
|
+
self.assertIn(
|
|
217
|
+
'<a href="https://test.com/courses/course-v1%3AOrg%2BClass%2BVersion/about">test2</a>',
|
|
218
|
+
fragment.content
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
def test_render_url_no_safe_mode(self):
|
|
222
|
+
"""
|
|
223
|
+
Test rendering a URL with safe_mode disabled.
|
|
224
|
+
"""
|
|
225
|
+
field_data = DictFieldData(
|
|
226
|
+
{'data': '[test](https://test.com/courses/course-v1:Org+Class+Version/about)'}
|
|
227
|
+
)
|
|
228
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
229
|
+
settings = {
|
|
230
|
+
"extras": DEFAULT_EXTRAS,
|
|
231
|
+
"safe_mode": False
|
|
232
|
+
}
|
|
233
|
+
with patch('markdown_xblock.html.get_xblock_settings') as get_settings_mock:
|
|
234
|
+
get_settings_mock.return_value = settings
|
|
235
|
+
fragment = block.student_view()
|
|
236
|
+
self.assertIn(
|
|
237
|
+
'<a href="https://test.com/courses/course-v1:Org+Class+Version/about">test</a>',
|
|
238
|
+
fragment.content
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def test_substitution_no_system(self):
|
|
242
|
+
"""
|
|
243
|
+
Test that the substitution is not performed when `system` is not present inside XBlock.
|
|
244
|
+
"""
|
|
245
|
+
field_data = DictFieldData({'data': '%%USER_ID%% %%COURSE_ID%%'})
|
|
246
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
247
|
+
fragment = block.student_view()
|
|
248
|
+
self.assertIn('<div class="markdown_xblock"><p>%%USER_ID%% %%COURSE_ID%%</p>\n</div>\n', fragment.content)
|
|
249
|
+
|
|
250
|
+
def test_substitution_not_found(self):
|
|
251
|
+
"""
|
|
252
|
+
Test that the keywords are not replaced when they're not found.
|
|
253
|
+
"""
|
|
254
|
+
field_data = DictFieldData({'data': 'USER_ID%% %%COURSE_ID%%'})
|
|
255
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
256
|
+
block.system = Mock(anonymous_student_id=None)
|
|
257
|
+
fragment = block.student_view()
|
|
258
|
+
self.assertIn('<div class="markdown_xblock"><p>USER_ID%% %%COURSE_ID%%</p>\n</div>\n', fragment.content)
|
|
259
|
+
|
|
260
|
+
def test_user_id_substitution(self):
|
|
261
|
+
"""
|
|
262
|
+
Test replacing %%USER_ID%% with anonymous user ID.
|
|
263
|
+
"""
|
|
264
|
+
field_data = DictFieldData({'data': '%%USER_ID%%'})
|
|
265
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
266
|
+
block.system = Mock(anonymous_student_id='test_user')
|
|
267
|
+
fragment = block.student_view()
|
|
268
|
+
self.assertIn('<div class="markdown_xblock"><p>test_user</p>\n</div>\n', fragment.content)
|
|
269
|
+
|
|
270
|
+
def test_course_id_substitution(self):
|
|
271
|
+
"""
|
|
272
|
+
Test replacing %%COURSE_ID%% with HTML representation of course key.
|
|
273
|
+
"""
|
|
274
|
+
field_data = DictFieldData({'data': '%%COURSE_ID%%'})
|
|
275
|
+
block = markdown_xblock.MarkdownXBlock(self.runtime, field_data, scope_ids=self.scope_ids)
|
|
276
|
+
course_locator_mock = Mock()
|
|
277
|
+
course_locator_mock.html_id = Mock(return_value='test_course')
|
|
278
|
+
block.system = Mock(course_id=course_locator_mock)
|
|
279
|
+
fragment = block.student_view()
|
|
280
|
+
self.assertIn('<div class="markdown_xblock"><p>test_course</p>\n</div>\n', fragment.content)
|
var/.placeholder
ADDED