def test_multi_replace(): course_source = '"/course/file.png"' assert replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY) == \ replace_static_urls(replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY), DATA_DIRECTORY) assert replace_course_urls(course_source, COURSE_KEY) == \ replace_course_urls(replace_course_urls(course_source, COURSE_KEY), COURSE_KEY)
def test_data_dir_fallback(mock_storage, mock_modulestore, mock_settings): mock_modulestore.return_value = Mock(XMLModuleStore) mock_storage.url.side_effect = Exception mock_storage.exists.return_value = True assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) mock_storage.exists.return_value = False assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY))
def test_raw_static_check(): """ Make sure replace_static_urls leaves alone things that end in '.raw' """ path = '"/static/foo.png?raw"' assert_equals(path, replace_static_urls(path, DATA_DIRECTORY)) text = 'text <tag a="/static/js/capa/protex/protex.nocache.js?raw"/><div class="' assert_equals(path, replace_static_urls(path, text))
def test_multi_replace(): course_source = '"/course/file.png"' assert_equals( replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY), replace_static_urls(replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY), DATA_DIRECTORY) ) assert_equals( replace_course_urls(course_source, course_id), replace_course_urls(replace_course_urls(course_source, course_id), course_id) )
def test_mongo_filestore(mock_get_excluded_extensions, mock_get_base_url, mock_modulestore, mock_static_content): mock_modulestore.return_value = Mock(MongoModuleStore) mock_static_content.get_canonicalized_asset_path.return_value = "c4x://mock_url" mock_get_base_url.return_value = u'' mock_get_excluded_extensions.return_value = ['foobar'] # No namespace => no change to path assert replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY) == '"/static/data_dir/file.png"' # Namespace => content url assert '"' + mock_static_content.get_canonicalized_asset_path.return_value + '"' == \ replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY, course_id=COURSE_KEY) mock_static_content.get_canonicalized_asset_path.assert_called_once_with(COURSE_KEY, 'file.png', u'', ['foobar'])
def test_mongo_filestore(mock_modulestore, mock_static_content): mock_modulestore.return_value = Mock(MongoModuleStore) mock_static_content.convert_legacy_static_url_with_course_id.return_value = "c4x://mock_url" # No namespace => no change to path assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) # Namespace => content url assert_equals( '"' + mock_static_content.convert_legacy_static_url_with_course_id.return_value + '"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY, course_id=COURSE_KEY) ) mock_static_content.convert_legacy_static_url_with_course_id.assert_called_once_with('file.png', COURSE_KEY)
def test_storage_url_exists(mock_storage): mock_storage.exists.return_value = True mock_storage.url.return_value = '/static/file.png' assert replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY) == '"/static/file.png"' mock_storage.exists.assert_called_once_with('file.png') mock_storage.url.assert_called_once_with('file.png')
def test_storage_url_not_exists(mock_storage): mock_storage.exists.return_value = False mock_storage.url.return_value = '/static/data_dir/file.png' assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) mock_storage.exists.assert_called_once_with('file.png') mock_storage.url.assert_called_once_with('data_dir/file.png')
def get_module_info(store, location, rewrite_static_links=False): try: module = store.get_item(location) except ItemNotFoundError: # create a new one store.create_and_save_xmodule(location) module = store.get_item(location) data = module.data if rewrite_static_links: data = replace_static_urls( module.data, None, course_namespace=Location([ module.location.tag, module.location.org, module.location.course, None, None ]) ) return { 'id': module.location.url(), 'data': data, # TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata # what's the intent here? all metadata incl inherited & namespaced? 'metadata': module.xblock_kvs._metadata }
def test_storage_url_exists(mock_storage): mock_storage.exists.return_value = True mock_storage.url.return_value = "/static/file.png" assert_equals('"/static/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) mock_storage.exists.called_once_with("file.png") mock_storage.url.called_once_with("data_dir/file.png")
def get_course_syllabus_section(course, section_key): """ This returns the snippet of html to be rendered on the syllabus page, given the key for the section. Valid keys: - syllabus - guest_syllabus """ # Many of these are stored as html files instead of some semantic # markup. This can change without effecting this interface when we find a # good format for defining so many snippets of text/html. if section_key in ['syllabus', 'guest_syllabus']: try: filesys = course.system.resources_fs # first look for a run-specific version dirs = [path("syllabus") / course.url_name, path("syllabus")] filepath = find_file(filesys, dirs, section_key + ".html") with filesys.open(filepath) as html_file: return replace_static_urls( html_file.read().decode('utf-8'), getattr(course, 'data_dir', None), course_id=course.id, static_asset_path=course.static_asset_path, ) except ResourceNotFoundError: log.exception( u"Missing syllabus section %s in course %s", section_key, course.location.to_deprecated_string() ) return "! Syllabus missing !" raise KeyError("Invalid about key " + str(section_key))
def get_module_info(store, location, parent_location=None, rewrite_static_links=False): try: if location.revision is None: module = store.get_item(location) else: module = store.get_item(location) except ItemNotFoundError: # create a new one template_location = Location( ['i4x', 'edx', 'templates', location.category, 'Empty']) module = store.clone_item(template_location, location) data = module.data if rewrite_static_links: data = replace_static_urls( module.data, None, course_namespace=Location([ module.location.tag, module.location.org, module.location.course, None, None ]) ) return { 'id': module.location.url(), 'data': data, # TODO (cpennington): This really shouldn't have to do this much # reaching in to get the metadata 'metadata': module._model_data._kvs._metadata }
def _get_module_info(usage_loc, rewrite_static_links=False): """ metadata, data, id representation of a leaf module fetcher. :param usage_loc: A BlockUsageLocator """ old_location = loc_mapper().translate_locator_to_location(usage_loc) store = get_modulestore(old_location) try: module = store.get_item(old_location) except ItemNotFoundError: if old_location.category in ['course_info']: # create a new one store.create_and_save_xmodule(old_location) module = store.get_item(old_location) else: raise data = module.data if rewrite_static_links: # we pass a partially bogus course_id as we don't have the RUN information passed yet # through the CMS. Also the contentstore is also not RUN-aware at this point in time. data = replace_static_urls( module.data, None, course_id=module.location.org + '/' + module.location.course + '/BOGUS_RUN_REPLACE_WHEN_AVAILABLE' ) return { 'id': unicode(usage_loc), 'data': data, 'metadata': module.get_explicitly_set_fields_by_scope(Scope.settings) }
def get_module_info(store, location, rewrite_static_links=False): try: module = store.get_item(location) except ItemNotFoundError: # create a new one store.create_and_save_xmodule(location) module = store.get_item(location) data = module.data if rewrite_static_links: # we pass a partially bogus course_id as we don't have the RUN information passed yet # through the CMS. Also the contentstore is also not RUN-aware at this point in time. data = replace_static_urls( module.data, None, course_id=module.location.org + '/' + module.location.course + '/BOGUS_RUN_REPLACE_WHEN_AVAILABLE' ) return { 'id': module.location.url(), 'data': data, # TODO (cpennington): This really shouldn't have to do this much reaching in to get the metadata # what's the intent here? all metadata incl inherited & namespaced? 'metadata': module.xblock_kvs._metadata }
def _get_module_info(usage_loc, rewrite_static_links=True): """ metadata, data, id representation of a leaf module fetcher. :param usage_loc: A BlockUsageLocator """ old_location = loc_mapper().translate_locator_to_location(usage_loc) store = get_modulestore(old_location) try: module = store.get_item(old_location) except ItemNotFoundError: if old_location.category in CREATE_IF_NOT_FOUND: # Create a new one for certain categories only. Used for course info handouts. store.create_and_save_xmodule(old_location) module = store.get_item(old_location) else: raise data = getattr(module, 'data', '') if rewrite_static_links: # we pass a partially bogus course_id as we don't have the RUN information passed yet # through the CMS. Also the contentstore is also not RUN-aware at this point in time. data = replace_static_urls( data, None, course_id=module.location.org + '/' + module.location.course + '/BOGUS_RUN_REPLACE_WHEN_AVAILABLE' ) # Note that children aren't being returned until we have a use case. return { 'id': unicode(usage_loc), 'data': data, 'metadata': own_metadata(module) }
def _get_module_info(usage_key, user, rewrite_static_links=True): """ metadata, data, id representation of a leaf module fetcher. :param usage_key: A UsageKey """ store = modulestore() try: module = store.get_item(usage_key) except ItemNotFoundError: if usage_key.category in CREATE_IF_NOT_FOUND: # Create a new one for certain categories only. Used for course info handouts. module = store.create_and_save_xmodule(usage_key, user.id) else: raise data = getattr(module, 'data', '') if rewrite_static_links: data = replace_static_urls( data, None, course_id=module.location.course_key ) # Note that children aren't being returned until we have a use case. return { 'id': unicode(module.location), 'data': data, 'metadata': own_metadata(module) }
def _get_module_info(xblock, rewrite_static_links=True, include_ancestor_info=False, include_publishing_info=False): """ metadata, data, id representation of a leaf module fetcher. :param usage_key: A UsageKey """ with modulestore().bulk_operations(xblock.location.course_key): data = getattr(xblock, 'data', '') if rewrite_static_links: data = replace_static_urls( data, None, course_id=xblock.location.course_key ) # Pre-cache has changes for the entire course because we'll need it for the ancestor info # Except library blocks which don't [yet] use draft/publish if not isinstance(xblock.location, LibraryUsageLocator): modulestore().has_changes(modulestore().get_course(xblock.location.course_key, depth=None)) # Note that children aren't being returned until we have a use case. xblock_info = create_xblock_info( xblock, data=data, metadata=own_metadata(xblock), include_ancestor_info=include_ancestor_info ) if include_publishing_info: add_container_page_publishing_info(xblock, xblock_info) return xblock_info
def get_course_syllabus_section(course, section_key): """ This returns the snippet of html to be rendered on the syllabus page, given the key for the section. Valid keys: - syllabus - guest_syllabus """ # Many of these are stored as html files instead of some semantic # markup. This can change without effecting this interface when we find a # good format for defining so many snippets of text/html. if section_key in ["syllabus", "guest_syllabus"]: try: fs = course.system.resources_fs # first look for a run-specific version dirs = [path("syllabus") / course.url_name, path("syllabus")] filepath = find_file(fs, dirs, section_key + ".html") with fs.open(filepath) as htmlFile: return replace_static_urls( htmlFile.read().decode("utf-8"), getattr(course, "data_dir", None), course_namespace=course.location ) except ResourceNotFoundError: log.exception( "Missing syllabus section {key} in course {url}".format(key=section_key, url=course.location.url()) ) return "! Syllabus missing !" raise KeyError("Invalid about key " + str(section_key))
def remap_static_url(original_url, course): input_url = "'" + original_url + "'" output_url = replace_static_urls( input_url, getattr(course, 'data_dir', None), course_namespace=course.location ) # strip off the quotes again... return output_url[1:-1]
def remap_static_url(original_url, course): """Remap a URL in the ways the course requires.""" # Ick: this should be possible without having to quote and unquote the URL... input_url = "'" + original_url + "'" output_url = replace_static_urls( input_url, getattr(course, "data_dir", None), course_id=course.id, static_asset_path=course.static_asset_path ) # strip off the quotes again... return output_url[1:-1]
def test_static_url_with_query(mock_modulestore, mock_storage): """ Make sure urls with query have the parameter section unaltered """ mock_storage.exists.return_value = False mock_modulestore.return_value = Mock(MongoModuleStore) pre_text = 'EMBED src ="/static/LAlec04_controller.swf?csConfigFile=/c4x/org/course/asset/LAlec04_config.xml"' post_text = 'EMBED src ="/c4x/org/course/asset/LAlec04_controller.swf?csConfigFile=/c4x/org/course/asset/LAlec04_config.xml"' assert_equals(post_text, replace_static_urls(pre_text, DATA_DIRECTORY, COURSE_KEY))
def test_static_url_with_xblock_resource(mock_modulestore, mock_storage): """ Make sure that for URLs with XBlock resource URL, which start with /static/, we don't rewrite them. """ mock_storage.exists.return_value = False mock_modulestore.return_value = Mock(MongoModuleStore) pre_text = 'EMBED src ="/static/xblock/resources/babys_first.lil_xblock/public/images/pacifier.png"' post_text = pre_text assert_equals(post_text, replace_static_urls(pre_text, DATA_DIRECTORY, COURSE_KEY))
def test_static_url_with_xblock_resource_on_cdn(mock_modulestore, mock_storage): """ Make sure that for URLs with XBlock resource URL, which start with /static/, we don't rewrite them, even if these are served from an absolute URL like a CDN. """ mock_storage.exists.return_value = False mock_modulestore.return_value = Mock(MongoModuleStore) pre_text = 'EMBED src ="https://example.com/static/xblock/resources/tehehe.xblock/public/images/woo.png"' post_text = pre_text assert_equals(post_text, replace_static_urls(pre_text, DATA_DIRECTORY, COURSE_KEY))
def remap_static_url(original_url, course): """Remap a URL in the ways the course requires.""" # Ick: this should be possible without having to quote and unquote the URL... input_url = "'" + original_url + "'" output_url = replace_static_urls( input_url, getattr(course, 'data_dir', None), course_namespace=course.location, ) # strip off the quotes again... return output_url[1:-1]
def replace_static_urls( data_dir, block, view, frag, context, course_id=None, static_asset_path="" ): # pylint: disable=unused-argument """ Updates the supplied module with a new get_html function that wraps the old get_html function and substitutes urls of the form /static/... with urls that are /static/<prefix>/... """ return wrap_fragment( frag, static_replace.replace_static_urls(frag.content, data_dir, course_id, static_asset_path=static_asset_path) )
def remap_static_url(original_url, course): """Remap a URL in the ways the course requires.""" # Ick: this should be possible without having to quote and unquote the URL... input_url = "'" + original_url + "'" output_url = replace_static_urls( input_url, getattr(course, 'data_dir', None), course_id=course.id, static_asset_path=course.static_asset_path) # strip off the quotes again... return output_url[1:-1]
def replace_static_urls(data_dir, block, view, frag, context, course_id=None, static_asset_path=''): # pylint: disable=unused-argument """ Updates the supplied module with a new get_html function that wraps the old get_html function and substitutes urls of the form /static/... with urls that are /static/<prefix>/... """ return wrap_fragment(frag, static_replace.replace_static_urls( frag.content, data_dir, course_id, static_asset_path=static_asset_path ))
def test_mongo_filestore(mock_get_base_url, mock_modulestore, mock_static_content): mock_modulestore.return_value = Mock(MongoModuleStore) mock_static_content.get_canonicalized_asset_path.return_value = "c4x://mock_url" mock_get_base_url.return_value = u'' # No namespace => no change to path assert_equals('"/static/data_dir/file.png"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY)) # Namespace => content url assert_equals( '"' + mock_static_content.get_canonicalized_asset_path.return_value + '"', replace_static_urls(STATIC_SOURCE, DATA_DIRECTORY, course_id=COURSE_KEY)) mock_static_content.get_canonicalized_asset_path.assert_called_once_with( COURSE_KEY, 'file.png', u'')
def _replace_static_from_url(self, url): if not url: return url try: from static_replace import replace_static_urls except ImportError: return url url = '"{}"'.format(url) lms_relative_url = replace_static_urls(url, course_id=self.course_id) # pylint: disable=no-member lms_relative_url = lms_relative_url.strip('"') return self._make_url_absolute(lms_relative_url)
def list(self, request, course, *args, **kwargs): course_updates_module = get_course_info_section_module(request, request.user, course, "updates") update_items = get_course_update_items(course_updates_module) updates_to_show = [update for update in update_items if update.get("status") != "deleted"] for item in updates_to_show: content = item["content"] content = replace_static_urls(content, course_id=course.id, static_asset_path=course.static_asset_path) item["content"] = make_static_urls_absolute(request, content) return Response(updates_to_show)
def test_static_url_with_query(mock_modulestore, mock_storage): """ Make sure that for urls with query params: query params that contain "^/static/" are converted to full location urls query params that do not contain "^/static/" are left unchanged """ mock_storage.exists.return_value = False mock_modulestore.return_value = Mock(MongoModuleStore) pre_text = 'EMBED src ="/static/LAlec04_controller.swf?csConfigFile=/static/LAlec04_config.xml&name1=value1&name2=value2"' post_text = 'EMBED src ="/c4x/org/course/asset/LAlec04_controller.swf?csConfigFile=%2Fc4x%2Forg%2Fcourse%2Fasset%2FLAlec04_config.xml&name1=value1&name2=value2"' assert_equals(post_text, replace_static_urls(pre_text, DATA_DIRECTORY, COURSE_KEY))
def list(self, request, course, *args, **kwargs): course_handouts_module = get_course_info_section_module(request, request.user, course, "handouts") if course_handouts_module: handouts_html = course_handouts_module.data handouts_html = replace_static_urls( handouts_html, course_id=course.id, static_asset_path=course.static_asset_path ) handouts_html = make_static_urls_absolute(self.request, handouts_html) return Response({"handouts_html": handouts_html}) else: # course_handouts_module could be None if there are no handouts raise Http404(u"No handouts for {}".format(unicode(course.id)))
def list(self, request, course, *args, **kwargs): course_handouts_module = get_course_info_section_module(request, course, 'handouts') if course_handouts_module: handouts_html = course_handouts_module.data handouts_html = replace_static_urls( handouts_html, course_id=course.id, static_asset_path=course.static_asset_path) handouts_html = make_static_urls_absolute(self.request, handouts_html) return Response({'handouts_html': handouts_html}) else: # course_handouts_module could be None if there are no handouts raise Http404(u"No handouts for {}".format(unicode(course.id)))
def collect_assets_from_text(text, course_id, include_content=False): """ Yield dicts of asset content and path from static asset paths found in the given text. Make sure to have replaced the URLs with rewrite_absolute_static_urls first. If include_content is True, the result will include a contentstore StaticContent file object which wraps the actual binary content of the file. """ try: from static_replace import replace_static_urls except ImportError as exc: raise EdXPlatformImportError(exc) # Replace static urls like '/static/foo.png' static_paths = [] # Drag-and-drop-v2 has # "/static/blah.png" # which must be changed to "/static/blah.png" for replace_static_urls to work: text2 = text.replace(""", '"') replace_static_urls(text=text2, course_id=course_id, static_paths_out=static_paths) for (path, uri) in static_paths: if path.startswith('/static/'): path = path[8:] info = { 'path': path, 'url': '/' + six.text_type(course_id.make_asset_key("asset", path)), } if include_content: content = get_asset_content_from_path(course_id, path) if content is None: LOG.error("Static asset not found: (%s, %s)", path, uri) else: info['content'] = content yield info
def _get_module_info(xblock, rewrite_static_links=True): """ metadata, data, id representation of a leaf module fetcher. :param usage_key: A UsageKey """ data = getattr(xblock, 'data', '') if rewrite_static_links: data = replace_static_urls( data, None, course_id=xblock.location.course_key ) # Note that children aren't being returned until we have a use case. return create_xblock_info(xblock, data=data, metadata=own_metadata(xblock), include_ancestor_info=True)
def replace_static_from_url(url, course_id): """ Converts /static assets links to absolute links """ if not url: return url try: from static_replace import replace_static_urls except ImportError: return url url = '"{}"'.format(url) lms_relative_url = replace_static_urls(url, course_id=CourseKey.from_string(course_id)) lms_relative_url = lms_relative_url.strip('"') return prefix_with_lms_base(lms_relative_url)
def list(self, request, course, *args, **kwargs): course_handouts_module = get_course_info_section_module(request, request.user, course, 'handouts') if course_handouts_module: if course_handouts_module.data == "<ol></ol>": handouts_html = None else: handouts_html = course_handouts_module.data handouts_html = replace_static_urls( handouts_html, course_id=course.id, static_asset_path=course.static_asset_path ) handouts_html = make_static_urls_absolute(self.request, handouts_html) return Response({'handouts_html': handouts_html}) else: # course_handouts_module could be None if there are no handouts return Response({'handouts_html': None})
def _expand_static_url(self, url): """ This is required to make URLs like '/static/dnd-test-image.png' work (note: that is the only portable URL format for static files that works across export/import and reruns). This method is unfortunately a bit hackish since XBlock does not provide a low-level API for this. """ if hasattr(self.runtime, 'replace_urls'): url = self.runtime.replace_urls('"{}"'.format(url))[1:-1] elif hasattr(self.runtime, 'course_id'): # edX Studio uses a different runtime for 'studio_view' than 'student_view', # and the 'studio_view' runtime doesn't provide the replace_urls API. try: from static_replace import replace_static_urls # pylint: disable=import-error url = replace_static_urls('"{}"'.format(url), None, course_id=self.runtime.course_id)[1:-1] except ImportError: pass return url
def list(self, request, *args, **kwargs): course_id = CourseKey.from_string(kwargs['course_id']) course = modulestore().get_course(course_id) course_handouts_module = get_course_info_section_module( request, course, 'handouts') if course_handouts_module: handouts_html = course_handouts_module.data handouts_html = replace_static_urls( handouts_html, course_id=course_id, static_asset_path=course.static_asset_path) handouts_html = make_static_urls_absolute(self.request, handouts_html) return Response({'handouts_html': handouts_html}) else: # course_handouts_module could be None if there are no handouts # (such as while running tests) raise Http404(u"No handouts for {}".format(unicode(course_id)))
def list(self, request, course, *args, **kwargs): course_updates_module = get_course_info_section_module(request, course, 'updates') update_items = get_course_update_items(course_updates_module) updates_to_show = [ update for update in update_items if update.get("status") != "deleted" ] for item in updates_to_show: content = item['content'] content = replace_static_urls( content, course_id=course.id, static_asset_path=course.static_asset_path) item['content'] = make_static_urls_absolute(request, content) return Response(updates_to_show)
def _get_module_info(xblock, rewrite_static_links=True): """ metadata, data, id representation of a leaf module fetcher. :param usage_key: A UsageKey """ data = getattr(xblock, 'data', '') if rewrite_static_links: data = replace_static_urls(data, None, course_id=xblock.location.course_key) # Pre-cache has changes for the entire course because we'll need it for the ancestor info modulestore().has_changes(modulestore().get_course( xblock.location.course_key, depth=None)) # Note that children aren't being returned until we have a use case. return create_xblock_info(xblock, data=data, metadata=own_metadata(xblock), include_ancestor_info=True)
def list(self, request, *args, **kwargs): course_id = CourseKey.from_string(kwargs['course_id']) course = modulestore().get_course(course_id) course_updates_module = get_course_info_section_module( request, course, 'updates') update_items = reversed(getattr(course_updates_module, 'items', [])) updates_to_show = [ update for update in update_items if update.get("status") != "deleted" ] for item in updates_to_show: content = item['content'] content = replace_static_urls( content, course_id=course_id, static_asset_path=course.static_asset_path) item['content'] = make_static_urls_absolute(request, content) return Response(updates_to_show)
def test_relative_url_for_split_course(self): """ Test relative path for split courses assets """ with modulestore().default_store(ModuleStoreEnum.Type.split): module_store = modulestore() course_id = module_store.make_course_key('edX', 'toy', '2012_Fall') import_course_from_xml( module_store, self.user.id, TEST_DATA_DIR, ['toy'], static_content_store=contentstore(), target_id=course_id, create_if_not_present=True ) course = module_store.get_course(course_id) filename = 'sample_static.html' html_src_attribute = '"/static/{}"'.format(filename) asset_url = replace_static_urls(html_src_attribute, course_id=course.id) url = asset_url.replace('"', '') base_url = url.replace(filename, '') self.assertIn("/{}".format(filename), url) resp = self.client.get(url) self.assertEquals(resp.status_code, 200) # simulation of html page where base_url is up-to asset's main directory # and relative_path is dom element with its src relative_path = 'just_a_test.jpg' # browser append relative_path with base_url absolute_path = base_url + relative_path self.assertIn("/{}".format(relative_path), absolute_path) resp = self.client.get(absolute_path) self.assertEquals(resp.status_code, 200)
def _get_html(): return static_replace.replace_static_urls( get_html(), data_dir, course_id, static_asset_path=static_asset_path)
def wrapper(self, request_json, suffix=''): response = json.dumps(func(self, request_json, suffix)) response = replace_static_urls(response, course_id=self.runtime.course_id) return Response(response, content_type='application/json')
def _get_html(): return static_replace.replace_static_urls(get_html(), data_dir, course_namespace)