def test_context_base_url_nested_page(self): nav_cfg = [ { 'Home': 'index.md' }, { 'Nested': 'foo/bar.md' }, ] cfg = load_config(nav=nav_cfg, use_directory_urls=False) files = Files([ File( 'index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), File( 'foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), ]) nav = get_navigation(files, cfg) context = build.get_context(nav, files, cfg, nav.pages[1]) self.assertEqual(context['base_url'], '..')
def test_context_extra_css_js_from_nested_page_use_directory_urls(self): nav_cfg = [ { 'Home': 'index.md' }, { 'Nested': 'foo/bar.md' }, ] cfg = load_config( nav=nav_cfg, extra_css=['style.css'], extra_javascript=['script.js'], ) files = Files([ File( 'index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), File( 'foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), ]) nav = get_navigation(files, cfg) context = build.get_context(nav, files, cfg, nav.pages[1]) self.assertEqual(context['extra_css'], ['../../style.css']) self.assertEqual(context['extra_javascript'], ['../../script.js'])
def test_copy_file_dirty_not_modified(self, src_dir, dest_dir): file = File('test.txt', src_dir, dest_dir, use_directory_urls=False) file.is_modified = mock.Mock(return_value=False) dest_path = os.path.join(dest_dir, 'test.txt') file.copy_file(dirty=True) self.assertPathIsFile(dest_path) with open(dest_path, 'r', encoding='utf-8') as f: self.assertEqual(f.read(), 'destination content')
def test_file_eq(self): file = File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False) self.assertTrue(file == File( 'a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False))
def test_create_media_urls_use_directory_urls(self): expected_results = { 'https://media.cdn.org/jq.js': [ 'https://media.cdn.org/jq.js', 'https://media.cdn.org/jq.js', 'https://media.cdn.org/jq.js' ], 'http://media.cdn.org/jquery.js': [ 'http://media.cdn.org/jquery.js', 'http://media.cdn.org/jquery.js', 'http://media.cdn.org/jquery.js' ], '//media.cdn.org/jquery.js': [ '//media.cdn.org/jquery.js', '//media.cdn.org/jquery.js', '//media.cdn.org/jquery.js' ], 'media.cdn.org/jquery.js': [ 'media.cdn.org/jquery.js', '../media.cdn.org/jquery.js', '../../media.cdn.org/jquery.js' ], 'local/file/jquery.js': [ 'local/file/jquery.js', '../local/file/jquery.js', '../../local/file/jquery.js' ], 'local\\windows\\file\\jquery.js': [ 'local/windows/file/jquery.js', '../local/windows/file/jquery.js', '../../local/windows/file/jquery.js' ], 'image.png': ['image.png', '../image.png', '../../image.png'], 'style.css?v=20180308c': [ 'style.css?v=20180308c', '../style.css?v=20180308c', '../../style.css?v=20180308c' ], '#some_id': ['#some_id', '#some_id', '#some_id'] } cfg = load_config(use_directory_urls=True) pages = [ Page( 'Home', File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg), Page( 'About', File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg), Page( 'FooBar', File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg) ] for i, page in enumerate(pages): urls = utils.create_media_urls(expected_results.keys(), page) self.assertEqual([v[i] for v in expected_results.values()], urls)
def test_page_ne(self): cfg = load_config() f1 = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) f2 = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', f1, cfg) # Different Title self.assertTrue(pg != Page('Bar', f1, cfg)) # Different File self.assertTrue(pg != Page('Foo', f2, cfg))
def test_build_page_error(self, site_dir, mock_write_file): cfg = load_config(site_dir=site_dir, nav=['index.md'], plugins=[]) files = Files([ File( 'index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), ]) nav = get_navigation(files, cfg) page = files.documentation_pages()[0].page # Fake populate page page.title = 'Title' page.source = 'page content' page.content = '<p>page content</p>' with self.assertLogs('mkdocs', level='ERROR') as cm: self.assertRaises( OSError, build._build_page, page, cfg, files, nav, cfg['theme'].get_env(), ) self.assertEqual( cm.output, [ "ERROR:mkdocs.commands.build:Error building page 'index.md': Error message." ], ) self.assert_mock_called_once(mock_write_file)
def test_build_page_dirty_not_modified(self, site_dir, mock_write_file): cfg = load_config(site_dir=site_dir, nav=['testing.md'], plugins=[]) files = Files([ File( 'testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), ]) nav = get_navigation(files, cfg) page = files.documentation_pages()[0].page # Fake populate page page.title = 'Title' page.source = 'page content' page.content = '<p>page content</p>' build._build_page( page, cfg, files, nav, cfg['theme'].get_env(), dirty=True, ) self.assert_mock_called_once(mock_write_file)
def test_homepage(self): cfg = load_config(docs_dir=self.DOCS_DIR) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) self.assertIsNone(fl.page) pg = Page('Foo', fl, cfg) self.assertEqual(fl.page, pg) self.assertEqual(pg.url, '') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertTrue(pg.is_homepage) self.assertTrue(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.source, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def test_nav_bad_links(self): nav_cfg = [{ 'Home': 'index.md' }, { 'Missing': 'missing.html' }, { 'Bad External': 'example.com' }] expected = dedent(""" Page(title='Home', url='/') Link(title='Missing', url='missing.html') Link(title='Bad External', url='example.com') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) with self.assertLogs('mkdocs', level='WARNING') as cm: site_navigation = get_navigation(files, cfg) self.assertEqual(cm.output, [ "WARNING:mkdocs.structure.nav:A relative path to 'missing.html' is included " "in the 'nav' configuration, which is not found in the documentation files", "WARNING:mkdocs.structure.nav:A relative path to 'example.com' is included " "in the 'nav' configuration, which is not found in the documentation files" ]) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 1)
def test_populate_page_read_error(self, docs_dir, mock_open): cfg = load_config(docs_dir=docs_dir) file = File( 'missing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ) page = Page('Foo', file, cfg) with self.assertLogs('mkdocs', level='ERROR') as cm: self.assertRaises( OSError, build._populate_page, page, cfg, Files([file]), ) self.assertEqual( cm.output, [ 'ERROR:mkdocs.structure.pages:File not found: missing.md', "ERROR:mkdocs.commands.build:Error reading page 'missing.md': Error message.", ], ) self.assert_mock_called_once(mock_open)
def test_nested_ungrouped_nav(self): nav_cfg = [ { 'Home': 'index.md' }, { 'Contact': 'about/contact.md' }, { 'License Title': 'about/sub/license.md' }, ] expected = dedent(""" Page(title='Home', url='/') Page(title='Contact', url='/about/contact/') Page(title='License Title', url='/about/sub/license/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File( list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 3)
def test_nav_external_links(self): nav_cfg = [{ 'Home': 'index.md' }, { 'Local': '/local.html' }, { 'External': 'http://example.com/external.html' }] expected = dedent(""" Page(title='Home', url='/') Link(title='Local', url='/local.html') Link(title='External', url='http://example.com/external.html') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) with self.assertLogs('mkdocs', level='DEBUG') as cm: site_navigation = get_navigation(files, cfg) self.assertEqual(cm.output, [ "DEBUG:mkdocs.structure.nav:An absolute path to '/local.html' is included in the " "'nav' configuration, which presumably points to an external resource.", "DEBUG:mkdocs.structure.nav:An external link to 'http://example.com/external.html' " "is included in the 'nav' configuration." ]) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 1)
def test_nav_no_title(self): nav_cfg = ['index.md', {'About': 'about.md'}] expected = dedent(""" Page(title=[blank], url='/') Page(title='About', url='/about/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File(nav_cfg[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File(nav_cfg[1]['About'], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2)
def test_file_ne(self): file = File('a.md', '/path/to/docs', '/path/to/site', use_directory_urls=False) # Different filename self.assertTrue(file != File( 'b.md', '/path/to/docs', '/path/to/site', use_directory_urls=False) ) # Different src_path self.assertTrue(file != File('a.md', '/path/to/other', '/path/to/site', use_directory_urls=False)) # Different URL self.assertTrue(file != File( 'a.md', '/path/to/docs', '/path/to/site', use_directory_urls=True))
def test_get_by_type_nested_sections(self): nav_cfg = [{'Section 1': [{'Section 2': [{'Page': 'page.md'}]}]}] cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('page.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(len(_get_by_type(site_navigation, Section)), 2)
def test_nav_from_files(self): expected = dedent(""" Page(title=[blank], url='/') Page(title=[blank], url='/about/') """) cfg = load_config(site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2) self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
def test_nav_missing_page(self): nav_cfg = [{'Home': 'index.md'}] expected = dedent(""" Page(title='Home', url='/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('page_not_in_nav.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 1) self.assertEqual(len(site_navigation.pages), 1) for file in files: self.assertIsInstance(file.page, Page)
def test_build_extra_template(self): cfg = load_config() files = Files([ File( 'foo.html', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ), ]) build._build_extra_template('foo.html', files, cfg, mock.Mock())
def test_populate_page(self, docs_dir): cfg = load_config(docs_dir=docs_dir) file = File( 'index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file])) self.assertEqual(page.content, '<p>page content</p>')
def test_file_name_with_space(self): f = File('foo bar.md', '/path/to/docs', '/path/to/site', use_directory_urls=False) self.assertPathsEqual(f.src_path, 'foo bar.md') self.assertPathsEqual(f.abs_src_path, '/path/to/docs/foo bar.md') self.assertPathsEqual(f.dest_path, 'foo bar.html') self.assertPathsEqual(f.abs_dest_path, '/path/to/site/foo bar.html') self.assertEqual(f.url, 'foo%20bar.html') self.assertEqual(f.name, 'foo bar')
def get_rendered_result(self, files): cfg = load_config(docs_dir=self.DOCS_DIR) fs = [] for f in files: fs.append( File(f.replace('/', os.sep), cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])) pg = Page('Foo', fs[0], cfg) pg.read_source(cfg) pg.render(cfg, Files(fs)) return pg.content
def test_populate_page_dirty_not_modified(self, site_dir, docs_dir): cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) file = File( 'index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file]), dirty=True) # Content is empty as file read was skipped self.assertEqual(page.source, None) self.assertEqual(page.content, None)
def test_populate_page_dirty_modified(self, site_dir): cfg = load_config(site_dir=site_dir) file = File( 'testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'], ) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file]), dirty=True) self.assertTrue(page.source.startswith('# Welcome to MkDocs')) self.assertTrue( page.content.startswith( '<h1 id="welcome-to-mkdocs">Welcome to MkDocs</h1>', ), )
def build_page(title, path, config, md_src=''): """ Helper which returns a Page object. """ files = Files([ File( path, config['docs_dir'], config['site_dir'], config['use_directory_urls'], ), ]) page = Page(title, list(files)[0], config) # Fake page.read_source() page.source, page.meta = meta.get_data(md_src) return page, files
def test_files(self): fs = [ File('index.md', '/path/to/docs', '/path/to/site', use_directory_urls=True), File('foo/bar.md', '/path/to/docs', '/path/to/site', use_directory_urls=True), File('foo/bar.html', '/path/to/docs', '/path/to/site', use_directory_urls=True), File('foo/bar.jpg', '/path/to/docs', '/path/to/site', use_directory_urls=True), File('foo/bar.js', '/path/to/docs', '/path/to/site', use_directory_urls=True), File('foo/bar.css', '/path/to/docs', '/path/to/site', use_directory_urls=True) ] files = Files(fs) self.assertEqual([f for f in files], fs) self.assertEqual(len(files), 6) self.assertEqual(files.documentation_pages(), [fs[0], fs[1]]) self.assertEqual(files.static_pages(), [fs[2]]) self.assertEqual(files.media_files(), [fs[3], fs[4], fs[5]]) self.assertEqual(files.javascript_files(), [fs[4]]) self.assertEqual(files.css_files(), [fs[5]]) self.assertEqual(files.get_file_from_path('foo/bar.jpg'), fs[3]) self.assertEqual(files.get_file_from_path('foo/bar.jpg'), fs[3]) self.assertEqual(files.get_file_from_path('missing.jpg'), None) self.assertTrue(fs[2].src_path in files) self.assertTrue(fs[2].src_path in files) extra_file = File('extra.md', '/path/to/docs', '/path/to/site', use_directory_urls=True) self.assertFalse(extra_file.src_path in files) files.append(extra_file) self.assertEqual(len(files), 7) self.assertTrue(extra_file.src_path in files) self.assertEqual(files.documentation_pages(), [fs[0], fs[1], extra_file])
def test_BOM(self): md_src = '# An UTF-8 encoded file with a BOM' with TemporaryDirectory() as docs_dir: # We don't use mkdocs.tests.base.tempdir decorator here due to uniqueness of this test. cfg = load_config(docs_dir=docs_dir) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) # Create an UTF-8 Encoded file with BOM (as Micorsoft editors do). See #1186 with open(fl.abs_src_path, 'w', encoding='utf-8-sig') as f: f.write(md_src) # Now read the file. pg.read_source(cfg) # Ensure the BOM (`\ufeff`) is removed self.assertNotIn('\ufeff', pg.source) self.assertEqual(pg.source, md_src) self.assertEqual(pg.meta, {})
def test_md_readme_index_file_use_directory_urls(self): f = File('README.md', '/path/to/docs', '/path/to/site', use_directory_urls=True) self.assertPathsEqual(f.src_path, 'README.md') self.assertPathsEqual(f.abs_src_path, '/path/to/docs/README.md') self.assertPathsEqual(f.dest_path, 'index.html') self.assertPathsEqual(f.abs_dest_path, '/path/to/site/index.html') self.assertEqual(f.url, '.') self.assertEqual(f.name, 'index') self.assertTrue(f.is_documentation_page()) self.assertFalse(f.is_static_page()) self.assertFalse(f.is_media_file()) self.assertFalse(f.is_javascript()) self.assertFalse(f.is_css())
def test_md_file_nested(self): f = File('foo/bar.md', '/path/to/docs', '/path/to/site', use_directory_urls=False) self.assertPathsEqual(f.src_path, 'foo/bar.md') self.assertPathsEqual(f.abs_src_path, '/path/to/docs/foo/bar.md') self.assertPathsEqual(f.dest_path, 'foo/bar.html') self.assertPathsEqual(f.abs_dest_path, '/path/to/site/foo/bar.html') self.assertEqual(f.url, 'foo/bar.html') self.assertEqual(f.name, 'bar') self.assertTrue(f.is_documentation_page()) self.assertFalse(f.is_static_page()) self.assertFalse(f.is_media_file()) self.assertFalse(f.is_javascript()) self.assertFalse(f.is_css())
def test_nav_no_directory_urls(self): nav_cfg = [{'Home': 'index.md'}, {'About': 'about.md'}] expected = dedent(""" Page(title='Home', url='/index.html') Page(title='About', url='/about.html') """) cfg = load_config(nav=nav_cfg, use_directory_urls=False, site_url='http://example.com/') files = Files([ File( list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2)