import datetime import locale import logging import os.path from posixpath import join as posix_join from sys import platform from jinja2.utils import generate_lorem_ipsum from pelican.contents import Article, Author, Category, Page, Static from pelican.plugins.signals import content_object_init from pelican.settings import DEFAULT_CONFIG from pelican.tests.support import (LoggedTestCase, get_context, get_settings, unittest) from pelican.utils import (path_to_url, posixize_path, truncate_html_words) # generate one paragraph, enclosed with
TEST_CONTENT = str(generate_lorem_ipsum(n=1)) TEST_SUMMARY = generate_lorem_ipsum(n=1, html=False) class TestBase(LoggedTestCase): def setUp(self): super().setUp() self.old_locale = locale.setlocale(locale.LC_ALL) locale.setlocale(locale.LC_ALL, 'C') self.page_kwargs = { 'content': TEST_CONTENT, 'context': { 'localsiteurl': '', 'generated_content': {}, 'static_content': {}, 'static_links': set() }, 'metadata': { 'summary': TEST_SUMMARY, 'title': 'foo bar', 'author': Author('Blogger', DEFAULT_CONFIG), }, 'source_path': '/path/to/file/foo.ext' } self._disable_limit_filter() def tearDown(self): locale.setlocale(locale.LC_ALL, self.old_locale) self._enable_limit_filter() def _disable_limit_filter(self): from pelican.contents import logger logger.disable_filter() def _enable_limit_filter(self): from pelican.contents import logger logger.enable_filter() def _copy_page_kwargs(self): # make a deep copy of page_kwargs page_kwargs = {key: self.page_kwargs[key] for key in self.page_kwargs} for key in page_kwargs: if not isinstance(page_kwargs[key], dict): break page_kwargs[key] = { subkey: page_kwargs[key][subkey] for subkey in page_kwargs[key] } return page_kwargs class TestPage(TestBase): def test_use_args(self): # Creating a page with arguments passed to the constructor should use # them to initialise object's attributes. metadata = {'foo': 'bar', 'foobar': 'baz', 'title': 'foobar', } page = Page(TEST_CONTENT, metadata=metadata, context={'localsiteurl': ''}) for key, value in metadata.items(): self.assertTrue(hasattr(page, key)) self.assertEqual(value, getattr(page, key)) self.assertEqual(page.content, TEST_CONTENT) def test_mandatory_properties(self): # If the title is not set, must throw an exception. page = Page('content') self.assertFalse(page._has_valid_mandatory_properties()) self.assertLogCountEqual( count=1, msg="Skipping .*: could not find information about 'title'", level=logging.ERROR) page = Page('content', metadata={'title': 'foobar'}) self.assertTrue(page._has_valid_mandatory_properties()) def test_summary_from_metadata(self): # If a :summary: metadata is given, it should be used page = Page(**self.page_kwargs) self.assertEqual(page.summary, TEST_SUMMARY) def test_summary_max_length(self): # If a :SUMMARY_MAX_LENGTH: is set, and there is no other summary, # generated summary should not exceed the given length. page_kwargs = self._copy_page_kwargs() settings = get_settings() page_kwargs['settings'] = settings del page_kwargs['metadata']['summary'] settings['SUMMARY_MAX_LENGTH'] = None page = Page(**page_kwargs) self.assertEqual(page.summary, TEST_CONTENT) settings['SUMMARY_MAX_LENGTH'] = 10 page = Page(**page_kwargs) self.assertEqual(page.summary, truncate_html_words(TEST_CONTENT, 10)) settings['SUMMARY_MAX_LENGTH'] = 0 page = Page(**page_kwargs) self.assertEqual(page.summary, '') def test_summary_end_suffix(self): # If a :SUMMARY_END_SUFFIX: is set, and there is no other summary, # generated summary should contain the specified marker at the end. page_kwargs = self._copy_page_kwargs() settings = get_settings() page_kwargs['settings'] = settings del page_kwargs['metadata']['summary'] settings['SUMMARY_END_SUFFIX'] = 'test_marker' settings['SUMMARY_MAX_LENGTH'] = 10 page = Page(**page_kwargs) self.assertEqual(page.summary, truncate_html_words(TEST_CONTENT, 10, 'test_marker')) self.assertIn('test_marker', page.summary) def test_summary_get_summary_warning(self): """calling ._get_summary() should issue a warning""" page_kwargs = self._copy_page_kwargs() page = Page(**page_kwargs) self.assertEqual(page.summary, TEST_SUMMARY) self.assertEqual(page._get_summary(), TEST_SUMMARY) self.assertLogCountEqual( count=1, msg=r"_get_summary\(\) has been deprecated since 3\.6\.4\. " "Use the summary decorator instead", level=logging.WARNING) def test_slug(self): page_kwargs = self._copy_page_kwargs() settings = get_settings() page_kwargs['settings'] = settings settings['SLUGIFY_SOURCE'] = "title" page = Page(**page_kwargs) self.assertEqual(page.slug, 'foo-bar') settings['SLUGIFY_SOURCE'] = "basename" page = Page(**page_kwargs) self.assertEqual(page.slug, 'foo') # test slug from title with unicode and case inputs = ( # (title, expected, preserve_case, use_unicode) ('指導書', 'zhi-dao-shu', False, False), ('指導書', 'Zhi-Dao-Shu', True, False), ('指導書', '指導書', False, True), ('指導書', '指導書', True, True), ('Çığ', 'cig', False, False), ('Çığ', 'Cig', True, False), ('Çığ', 'çığ', False, True), ('Çığ', 'Çığ', True, True), ) settings = get_settings() page_kwargs = self._copy_page_kwargs() page_kwargs['settings'] = settings for title, expected, preserve_case, use_unicode in inputs: settings['SLUGIFY_PRESERVE_CASE'] = preserve_case settings['SLUGIFY_USE_UNICODE'] = use_unicode page_kwargs['metadata']['title'] = title page = Page(**page_kwargs) self.assertEqual(page.slug, expected, (title, preserve_case, use_unicode)) def test_defaultlang(self): # If no lang is given, default to the default one. page = Page(**self.page_kwargs) self.assertEqual(page.lang, DEFAULT_CONFIG['DEFAULT_LANG']) # it is possible to specify the lang in the metadata infos self.page_kwargs['metadata'].update({'lang': 'fr', }) page = Page(**self.page_kwargs) self.assertEqual(page.lang, 'fr') def test_save_as(self): # If a lang is not the default lang, save_as should be set # accordingly. # if a title is defined, save_as should be set page = Page(**self.page_kwargs) self.assertEqual(page.save_as, "pages/foo-bar.html") # if a language is defined, save_as should include it accordingly self.page_kwargs['metadata'].update({'lang': 'fr', }) page = Page(**self.page_kwargs) self.assertEqual(page.save_as, "pages/foo-bar-fr.html") def test_relative_source_path(self): # 'relative_source_path' should be the relative path # from 'PATH' to 'source_path' page_kwargs = self._copy_page_kwargs() # If 'source_path' is None, 'relative_source_path' should # also return None page_kwargs['source_path'] = None page = Page(**page_kwargs) self.assertIsNone(page.relative_source_path) page_kwargs = self._copy_page_kwargs() settings = get_settings() full_path = page_kwargs['source_path'] settings['PATH'] = os.path.dirname(full_path) page_kwargs['settings'] = settings page = Page(**page_kwargs) # if 'source_path' is set, 'relative_source_path' should # return the relative path from 'PATH' to 'source_path' self.assertEqual( page.relative_source_path, os.path.relpath( full_path, os.path.dirname(full_path) )) def test_metadata_url_format(self): # Arbitrary metadata should be passed through url_format() page = Page(**self.page_kwargs) self.assertIn('summary', page.url_format.keys()) page.metadata['directory'] = 'test-dir' page.settings = get_settings(PAGE_SAVE_AS='{directory}/{slug}') self.assertEqual(page.save_as, 'test-dir/foo-bar') def test_datetime(self): # If DATETIME is set to a tuple, it should be used to override LOCALE dt = datetime.datetime(2015, 9, 13) page_kwargs = self._copy_page_kwargs() # set its date to dt page_kwargs['metadata']['date'] = dt page = Page(**page_kwargs) # page.locale_date is a unicode string in both python2 and python3 dt_date = dt.strftime(DEFAULT_CONFIG['DEFAULT_DATE_FORMAT']) self.assertEqual(page.locale_date, dt_date) page_kwargs['settings'] = get_settings() # I doubt this can work on all platforms ... if platform == "win32": locale = 'jpn' else: locale = 'ja_JP.utf8' page_kwargs['settings']['DATE_FORMATS'] = {'jp': (locale, '%Y-%m-%d(%a)')} page_kwargs['metadata']['lang'] = 'jp' import locale as locale_module try: page = Page(**page_kwargs) self.assertEqual(page.locale_date, '2015-09-13(\u65e5)') except locale_module.Error: # The constructor of ``Page`` will try to set the locale to # ``ja_JP.utf8``. But this attempt will failed when there is no # such locale in the system. You can see which locales there are # in your system with ``locale -a`` command. # # Until we find some other method to test this functionality, we # will simply skip this test. unittest.skip("There is no locale %s in this system." % locale) def test_template(self): # Pages default to page, metadata overwrites default_page = Page(**self.page_kwargs) self.assertEqual('page', default_page.template) page_kwargs = self._copy_page_kwargs() page_kwargs['metadata']['template'] = 'custom' custom_page = Page(**page_kwargs) self.assertEqual('custom', custom_page.template) def test_signal(self): def receiver_test_function(sender): receiver_test_function.has_been_called = True pass receiver_test_function.has_been_called = False content_object_init.connect(receiver_test_function) self.assertIn( receiver_test_function, content_object_init.receivers_for(Page)) self.assertFalse(receiver_test_function.has_been_called) Page(**self.page_kwargs) self.assertTrue(receiver_test_function.has_been_called) def test_get_content(self): # Test that the content is updated with the relative links to # filenames, tags and categories. settings = get_settings() args = self.page_kwargs.copy() args['settings'] = settings # Tag args['content'] = ('A simple test, with a ' 'link') page = Page(**args) content = page.get_content('http://notmyidea.org') self.assertEqual( content, ('A simple test, with a ' 'link')) # Category args['content'] = ('A simple test, with a ' 'link') page = Page(**args) content = page.get_content('http://notmyidea.org') self.assertEqual( content, ('A simple test, with a ' 'link')) def test_intrasite_link(self): cls_name = '_DummyArticle' article = type(cls_name, (object,), {'url': 'article.html'}) args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['generated_content'] = {'article.rst': article} # Classic intrasite link via filename args['content'] = ( 'A simple test, with a ' 'link' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a ' 'link' ) # fragment args['content'] = ( 'A simple test, with a ' 'link' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a ' 'link' ) # query args['content'] = ( 'A simple test, with a ' 'link' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a ' 'link' ) # combination args['content'] = ( 'A simple test, with a ' 'link' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a ' 'link' ) # also test for summary in metadata parsed = ( 'A simple summary test, with a ' 'link' ) linked = ( 'A simple summary test, with a ' 'link' ) args['settings']['FORMATTED_FIELDS'] = ['summary', 'custom'] args['metadata']['summary'] = parsed args['metadata']['custom'] = parsed args['context']['localsiteurl'] = 'http://notmyidea.org' p = Page(**args) # This is called implicitly from all generators and Pelican.run() once # all files are processed. Here we process just one page so it needs # to be called explicitly. p.refresh_metadata_intersite_links() self.assertEqual(p.summary, linked) self.assertEqual(p.custom, linked) def test_intrasite_link_more(self): cls_name = '_DummyAsset' args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['static_content'] = { 'images/poster.jpg': type(cls_name, (object,), {'url': 'images/poster.jpg'}), 'assets/video.mp4': type(cls_name, (object,), {'url': 'assets/video.mp4'}), 'images/graph.svg': type(cls_name, (object,), {'url': 'images/graph.svg'}), } args['context']['generated_content'] = { 'reference.rst': type(cls_name, (object,), {'url': 'reference.html'}), } # video.poster args['content'] = ( 'There is a video with poster ' '' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'There is a video with poster ' '' ) # object.data args['content'] = ( 'There is a svg object ' '' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'There is a svg object ' '' ) # blockquote.cite args['content'] = ( 'There is a blockquote with cite attribute ' '
blah blah' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'There is a blockquote with cite attribute ' '
' 'blah blah' '' ) def test_intrasite_link_absolute(self): """Test that absolute URLs are merged properly.""" args = self.page_kwargs.copy() args['settings'] = get_settings( STATIC_URL='http://static.cool.site/{path}', ARTICLE_URL='http://blog.cool.site/{slug}.html') args['source_path'] = 'content' args['context']['static_content'] = { 'images/poster.jpg': Static('', settings=args['settings'], source_path='images/poster.jpg'), } args['context']['generated_content'] = { 'article.rst': Article('', settings=args['settings'], metadata={ 'slug': 'article', 'title': 'Article'}) } # Article link will go to blog args['content'] = ( 'Article' ) content = Page(**args).get_content('http://cool.site') self.assertEqual( content, 'Article' ) # Page link will go to the main site args['content'] = ( 'Index' ) content = Page(**args).get_content('http://cool.site') self.assertEqual( content, 'Index' ) # Image link will go to static args['content'] = ( '' ) content = Page(**args).get_content('http://cool.site') self.assertEqual( content, '' ) def test_intrasite_link_escape(self): article = type( '_DummyArticle', (object,), {'url': 'article-spaces.html'}) asset = type( '_DummyAsset', (object,), {'url': 'name@example.com'}) args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['generated_content'] = {'article spaces.rst': article} args['context']['static_content'] = {'name@example.com': asset} expected_output = ( 'A simple test with a ' 'link ' 'file' ) # not escaped args['content'] = ( 'A simple test with a ' 'link ' 'file' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual(content, expected_output) # html escaped args['content'] = ( 'A simple test with a ' 'link ' 'file' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual(content, expected_output) # url escaped args['content'] = ( 'A simple test with a ' 'link ' 'file' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual(content, expected_output) # html and url escaped args['content'] = ( 'A simple test with a ' 'link ' 'file' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual(content, expected_output) def test_intrasite_link_markdown_spaces(self): cls_name = '_DummyArticle' article = type(cls_name, (object,), {'url': 'article-spaces.html'}) args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['generated_content'] = {'article spaces.rst': article} # An intrasite link via filename with %20 as a space args['content'] = ( 'A simple test, with a ' 'link' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a ' 'link' ) def test_intrasite_link_source_and_generated(self): """Test linking both to the source and the generated article """ cls_name = '_DummyAsset' args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['generated_content'] = { 'article.rst': type(cls_name, (object,), {'url': 'article.html'})} args['context']['static_content'] = { 'article.rst': type(cls_name, (object,), {'url': 'article.rst'})} args['content'] = ( 'A simple test, with a link to an' 'article and its' 'source' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a link to an' 'article and its' 'source' ) def test_intrasite_link_to_static_content_with_filename(self): """Test linking to a static resource with deprecated {filename} """ cls_name = '_DummyAsset' args = self.page_kwargs.copy() args['settings'] = get_settings() args['source_path'] = 'content' args['context']['static_content'] = { 'poster.jpg': type(cls_name, (object,), {'url': 'images/poster.jpg'})} args['content'] = ( 'A simple test, with a link to a' 'poster' ) content = Page(**args).get_content('http://notmyidea.org') self.assertEqual( content, 'A simple test, with a link to a' 'poster' ) def test_multiple_authors(self): """Test article with multiple authors.""" args = self.page_kwargs.copy() content = Page(**args) assert content.authors == [content.author] args['metadata'].pop('author') args['metadata']['authors'] = [Author('First Author', DEFAULT_CONFIG), Author('Second Author', DEFAULT_CONFIG)] content = Page(**args) assert content.authors assert content.author == content.authors[0] class TestArticle(TestBase): def test_template(self): # Articles default to article, metadata overwrites default_article = Article(**self.page_kwargs) self.assertEqual('article', default_article.template) article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['template'] = 'custom' custom_article = Article(**article_kwargs) self.assertEqual('custom', custom_article.template) def test_slugify_category_author(self): settings = get_settings() settings['SLUG_REGEX_SUBSTITUTIONS'] = [ (r'C#', 'csharp'), (r'[^\w\s-]', ''), (r'(?u)\A\s*', ''), (r'(?u)\s*\Z', ''), (r'[-\s]+', '-'), ] settings['ARTICLE_URL'] = '{author}/{category}/{slug}/' settings['ARTICLE_SAVE_AS'] = '{author}/{category}/{slug}/index.html' article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['author'] = Author("O'Brien", settings) article_kwargs['metadata']['category'] = Category( 'C# & stuff', settings) article_kwargs['metadata']['title'] = 'fnord' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertEqual(article.url, 'obrien/csharp-stuff/fnord/') self.assertEqual( article.save_as, 'obrien/csharp-stuff/fnord/index.html') def test_slugify_with_author_substitutions(self): settings = get_settings() settings['AUTHOR_REGEX_SUBSTITUTIONS'] = [ ('Alexander Todorov', 'atodorov'), ('Krasimir Tsonev', 'krasimir'), (r'[^\w\s-]', ''), (r'(?u)\A\s*', ''), (r'(?u)\s*\Z', ''), (r'[-\s]+', '-'), ] settings['ARTICLE_URL'] = 'blog/{author}/{slug}/' settings['ARTICLE_SAVE_AS'] = 'blog/{author}/{slug}/index.html' article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['author'] = Author('Alexander Todorov', settings) article_kwargs['metadata']['title'] = 'fnord' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertEqual(article.url, 'blog/atodorov/fnord/') self.assertEqual(article.save_as, 'blog/atodorov/fnord/index.html') def test_slugify_category_with_dots(self): settings = get_settings() settings['CATEGORY_REGEX_SUBSTITUTIONS'] = [ ('Fedora QA', 'fedora.qa'), ] settings['ARTICLE_URL'] = '{category}/{slug}/' article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['category'] = Category('Fedora QA', settings) article_kwargs['metadata']['title'] = 'This Week in Fedora QA' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertEqual(article.url, 'fedora.qa/this-week-in-fedora-qa/') def test_valid_save_as_detects_breakout(self): settings = get_settings() article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['slug'] = '../foo' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertFalse(article._has_valid_save_as()) def test_valid_save_as_detects_breakout_to_root(self): settings = get_settings() article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['slug'] = '/foo' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertFalse(article._has_valid_save_as()) def test_valid_save_as_passes_valid(self): settings = get_settings() article_kwargs = self._copy_page_kwargs() article_kwargs['metadata']['slug'] = 'foo' article_kwargs['settings'] = settings article = Article(**article_kwargs) self.assertTrue(article._has_valid_save_as()) class TestStatic(LoggedTestCase): def setUp(self): super().setUp() self.settings = get_settings( STATIC_SAVE_AS='{path}', STATIC_URL='{path}', PAGE_SAVE_AS=os.path.join('outpages', '{slug}.html'), PAGE_URL='outpages/{slug}.html') self.context = get_context(self.settings) self.static = Static(content=None, metadata={}, settings=self.settings, source_path=posix_join('dir', 'foo.jpg'), context=self.context) self.context['static_content'][self.static.source_path] = self.static def tearDown(self): pass def test_attach_to_same_dir(self): """attach_to() overrides a static file's save_as and url. """ page = Page( content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'fakepage.md')) self.static.attach_to(page) expected_save_as = os.path.join('outpages', 'foo.jpg') self.assertEqual(self.static.save_as, expected_save_as) self.assertEqual(self.static.url, path_to_url(expected_save_as)) def test_attach_to_parent_dir(self): """attach_to() preserves dirs inside the linking document dir. """ page = Page(content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path='fakepage.md') self.static.attach_to(page) expected_save_as = os.path.join('outpages', 'dir', 'foo.jpg') self.assertEqual(self.static.save_as, expected_save_as) self.assertEqual(self.static.url, path_to_url(expected_save_as)) def test_attach_to_other_dir(self): """attach_to() ignores dirs outside the linking document dir. """ page = Page(content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md')) self.static.attach_to(page) expected_save_as = os.path.join('outpages', 'foo.jpg') self.assertEqual(self.static.save_as, expected_save_as) self.assertEqual(self.static.url, path_to_url(expected_save_as)) def test_attach_to_ignores_subsequent_calls(self): """attach_to() does nothing when called a second time. """ page = Page(content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'fakepage.md')) self.static.attach_to(page) otherdir_settings = self.settings.copy() otherdir_settings.update(dict( PAGE_SAVE_AS=os.path.join('otherpages', '{slug}.html'), PAGE_URL='otherpages/{slug}.html')) otherdir_page = Page( content="other page", metadata={'title': 'otherpage'}, settings=otherdir_settings, source_path=os.path.join('dir', 'otherpage.md')) self.static.attach_to(otherdir_page) otherdir_save_as = os.path.join('otherpages', 'foo.jpg') self.assertNotEqual(self.static.save_as, otherdir_save_as) self.assertNotEqual(self.static.url, path_to_url(otherdir_save_as)) def test_attach_to_does_nothing_after_save_as_referenced(self): """attach_to() does nothing if the save_as was already referenced. (For example, by a {static} link an a document processed earlier.) """ original_save_as = self.static.save_as page = Page( content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'fakepage.md')) self.static.attach_to(page) self.assertEqual(self.static.save_as, original_save_as) self.assertEqual(self.static.url, path_to_url(original_save_as)) def test_attach_to_does_nothing_after_url_referenced(self): """attach_to() does nothing if the url was already referenced. (For example, by a {static} link an a document processed earlier.) """ original_url = self.static.url page = Page( content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'fakepage.md')) self.static.attach_to(page) self.assertEqual(self.static.save_as, self.static.source_path) self.assertEqual(self.static.url, original_url) def test_attach_to_does_not_override_an_override(self): """attach_to() does not override paths that were overridden elsewhere. (For example, by the user with EXTRA_PATH_METADATA) """ customstatic = Static( content=None, metadata=dict(save_as='customfoo.jpg', url='customfoo.jpg'), settings=self.settings, source_path=os.path.join('dir', 'foo.jpg'), context=self.settings.copy()) page = Page( content="fake page", metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'fakepage.md')) customstatic.attach_to(page) self.assertEqual(customstatic.save_as, 'customfoo.jpg') self.assertEqual(customstatic.url, 'customfoo.jpg') def test_attach_link_syntax(self): """{attach} link syntax triggers output path override & url replacement. """ html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual( content, html, "{attach} link syntax did not trigger URL replacement.") expected_save_as = os.path.join('outpages', 'foo.jpg') self.assertEqual(self.static.save_as, expected_save_as) self.assertEqual(self.static.url, path_to_url(expected_save_as)) def test_tag_link_syntax(self): "{tag} link syntax triggers url replacement." html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual(content, html) def test_category_link_syntax(self): "{category} link syntax triggers url replacement." html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual(content, html) def test_author_link_syntax(self): "{author} link syntax triggers url replacement." html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual(content, html) def test_index_link_syntax(self): "{index} link syntax triggers url replacement." html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual(content, html) expected_html = ('link') self.assertEqual(content, expected_html) def test_unknown_link_syntax(self): "{unknown} link syntax should trigger warning." html = 'link' page = Page(content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertEqual(content, html) self.assertLogCountEqual( count=1, msg="Replacement Indicator 'unknown' not recognized, " "skipping replacement", level=logging.WARNING) def test_link_to_unknown_file(self): "{filename} link to unknown file should trigger warning." html = 'link' page = Page(content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertEqual(content, html) self.assertLogCountEqual( count=1, msg="Unable to find 'foo', skipping url replacement.", level=logging.WARNING) def test_index_link_syntax_with_spaces(self): """{index} link syntax triggers url replacement with spaces around the equal sign.""" html = 'link' page = Page( content=html, metadata={'title': 'fakepage'}, settings=self.settings, source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), context=self.context) content = page.get_content('') self.assertNotEqual(content, html) expected_html = ('link') self.assertEqual(content, expected_html) def test_not_save_as_draft(self): """Static.save_as is not affected by draft status.""" static = Static( content=None, metadata=dict(status='draft',), settings=self.settings, source_path=os.path.join('dir', 'foo.jpg'), context=self.settings.copy()) expected_save_as = posixize_path(os.path.join('dir', 'foo.jpg')) self.assertEqual(static.status, 'draft') self.assertEqual(static.save_as, expected_save_as) self.assertEqual(static.url, path_to_url(expected_save_as))