Example #1
0
    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)
Example #2
0
 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))
Example #3
0
 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, [])
Example #4
0
 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)
Example #5
0
def _data_to_navigation(data, files, config):
    if isinstance(data, dict):
        return [
            _data_to_navigation(
                (key,
                 value), files, config) if isinstance(value, str) else Section(
                     title=key,
                     children=_data_to_navigation(
                         value,
                         files,
                         config,
                     ),
                 ) for key, value in data.items()
        ]
    elif isinstance(data, list):
        return [
            _data_to_navigation(item, files, config)[0] if
            isinstance(item, dict) and len(item) == 1 else _data_to_navigation(
                item, files, config) for item in data
        ]
    title, path = data if isinstance(data, tuple) else (None, data)
    file = files.get_file_from_path(path)
    if file:
        return Page(title, file, config)
    return Link(title, path)
Example #6
0
 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>')
Example #7
0
 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
Example #8
0
 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)
Example #9
0
 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>', ), )
Example #10
0
def get_navigation(files, config):
    """ Build site navigation from config and files."""
    nav_config = config['nav'] or nest_paths(
        f.src_path for f in files.documentation_pages())
    items = _data_to_navigation(nav_config, files, config)
    if not isinstance(items, list):
        items = [items]

    # Get only the pages from the navigation, ignoring any sections and links.
    pages = _get_by_type(items, Page)

    # Include next, previous and parent links.
    _add_previous_and_next_links(pages)
    _add_parent_links(items)

    missing_from_config = [
        file for file in files.documentation_pages() if file.page is None
    ]
    if missing_from_config:
        log.info(
            'The following pages exist in the docs directory, but are not '
            'included in the "nav" configuration:\n  - {}'.format(
                '\n  - '.join([file.src_path
                               for file in missing_from_config]), ), )
        # Any documentation files not found in the nav should still have an associated page, so we
        # create them here. The Page object will automatically be assigned to `file.page` during
        # its creation (and this is the only way in which these page objects are accessable).
        for file in missing_from_config:
            Page(None, file, config)

    links = _get_by_type(items, Link)
    for link in links:
        scheme, netloc, path, params, query, fragment = urlparse(link.url)
        if scheme or netloc:
            log.debug(
                "An external link to '{}' is included in "
                "the 'nav' configuration.".format(link.url), )
        elif link.url.startswith('/'):
            log.debug(
                "An absolute path to '{}' is included in the 'nav' configuration, "
                "which presumably points to an external resource.".format(
                    link.url, ), )
        else:
            msg = (
                "A relative path to '{}' is included in the 'nav' configuration, "
                "which is not found in the documentation files".format(
                    link.url, ))
            log.warning(msg)
    return Navigation(items, pages)
Example #11
0
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
Example #12
0
 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, {})
Example #13
0
 def test_page_render(self):
     cfg = load_config()
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     pg.read_source(cfg)
     self.assertEqual(pg.content, None)
     self.assertEqual(pg.toc, [])
     pg.render(cfg, [fl])
     self.assertTrue(
         pg.content.startswith(
             '<h1 id="welcome-to-mkdocs">Welcome to MkDocs</h1>\n'))
     self.assertEqual(
         str(pg.toc).strip(),
         dedent("""
         Welcome to MkDocs - #welcome-to-mkdocs
             Commands - #commands
             Project layout - #project-layout
     """))
Example #14
0
 def test_page_no_directory_url(self):
     cfg = load_config(use_directory_urls=False)
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     self.assertEqual(pg.url, 'testing.html')
     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.assertFalse(pg.is_homepage)
     self.assertFalse(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, [])
Example #15
0
 def test_page_canonical_url_nested_no_slash(self):
     cfg = load_config(site_url='http://example.com/foo')
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     self.assertEqual(pg.url, 'testing/')
     self.assertEqual(pg.abs_url, '/foo/testing/')
     self.assertEqual(pg.canonical_url, 'http://example.com/foo/testing/')
     self.assertEqual(pg.edit_url, None)
     self.assertEqual(pg.file, fl)
     self.assertEqual(pg.content, None)
     self.assertFalse(pg.is_homepage)
     self.assertFalse(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, [])
Example #16
0
 def test_nested_index_page_no_parent_no_directory_urls(self):
     cfg = load_config(docs_dir=self.DOCS_DIR, use_directory_urls=False)
     fl = File('sub1/index.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     pg.parent = None  # non-homepage at nav root level; see #1919.
     self.assertEqual(pg.url, 'sub1/index.html')
     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.assertFalse(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, [])
Example #17
0
 def test_page_title_from_homepage_filename(self):
     cfg = load_config(docs_dir=self.DOCS_DIR)
     fl = File('index.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page(None, fl, cfg)
     pg.read_source(cfg)
     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.assertTrue(pg.source.startswith('## Test'))
     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, 'Home')
     self.assertEqual(pg.toc, [])
Example #18
0
 def test_page_title_from_markdown(self):
     cfg = load_config()
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page(None, fl, cfg)
     pg.read_source(cfg)
     self.assertEqual(pg.url, 'testing/')
     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.assertFalse(pg.is_homepage)
     self.assertFalse(pg.is_index)
     self.assertTrue(pg.is_page)
     self.assertFalse(pg.is_section)
     self.assertTrue(pg.is_top_level)
     self.assertTrue(pg.source.startswith('# Welcome to MkDocs\n'))
     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, 'Welcome to MkDocs')
     self.assertEqual(pg.toc, [])
Example #19
0
 def test_page_eq(self):
     cfg = load_config()
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     self.assertTrue(pg == Page('Foo', fl, cfg))
Example #20
0
    def test_create_search_index(self):

        html_content = """
        <h1 id="heading-1">Heading 1</h1>
        <p>Content 1</p>
        <h2 id="heading-2">Heading 2</h1>
        <p>Content 2</p>
        <h3 id="heading-3">Heading 3</h1>
        <p>Content 3</p>
        """

        cfg = load_config()
        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,
            ),
        ]

        md = dedent("""
        # Heading 1
        ## Heading 2
        ### Heading 3
        """)
        toc = get_toc(get_markdown_toc(md))

        full_content = ''.join("""Heading{0}Content{0}""".format(i)
                               for i in range(1, 4))

        for page in pages:
            # Fake page.read_source() and page.render()
            page.source = md
            page.toc = toc
            page.content = html_content

            index = search_index.SearchIndex()
            index.add_entry_from_context(page)

            self.assertEqual(len(index._entries), 4)

            loc = page.url

            self.assertEqual(index._entries[0]['title'], page.title)
            self.assertEqual(
                strip_whitespace(index._entries[0]['text'], ),
                full_content,
            )
            self.assertEqual(index._entries[0]['location'], loc)

            self.assertEqual(index._entries[1]['title'], "Heading 1")
            self.assertEqual(index._entries[1]['text'], "Content 1")
            self.assertEqual(
                index._entries[1]['location'],
                "{}#heading-1".format(loc),
            )

            self.assertEqual(index._entries[2]['title'], "Heading 2")
            self.assertEqual(
                strip_whitespace(index._entries[2]['text'], ),
                "Content2",
            )
            self.assertEqual(
                index._entries[2]['location'],
                "{}#heading-2".format(loc),
            )

            self.assertEqual(index._entries[3]['title'], "Heading 3")
            self.assertEqual(
                strip_whitespace(index._entries[3]['text'], ),
                "Content3",
            )
            self.assertEqual(
                index._entries[3]['location'],
                "{}#heading-3".format(loc),
            )
Example #21
0
 def test_source_date_epoch(self):
     cfg = load_config()
     fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     self.assertEqual(pg.update_date, '1970-01-01')
Example #22
0
 def test_missing_page(self):
     cfg = load_config()
     fl = File('missing.md', cfg['docs_dir'], cfg['site_dir'],
               cfg['use_directory_urls'])
     pg = Page('Foo', fl, cfg)
     self.assertRaises(OSError, pg.read_source, cfg)
Example #23
0
    def test_nested_page_edit_url_windows(self):
        configs = [{
            'repo_url': 'http://github.com/mkdocs/mkdocs'
        }, {
            'repo_url': 'https://github.com/mkdocs/mkdocs/'
        }, {
            'repo_url': 'http://example.com'
        }, {
            'repo_url': 'http://example.com',
            'edit_uri': 'edit/master'
        }, {
            'repo_url': 'http://example.com',
            'edit_uri': '/edit/master'
        }, {
            'repo_url': 'http://example.com/foo/',
            'edit_uri': '/edit/master/'
        }, {
            'repo_url': 'http://example.com/foo',
            'edit_uri': '/edit/master/'
        }, {
            'repo_url': 'http://example.com/foo/',
            'edit_uri': '/edit/master'
        }, {
            'repo_url': 'http://example.com/foo/',
            'edit_uri': 'edit/master/'
        }, {
            'repo_url': 'http://example.com/foo',
            'edit_uri': 'edit/master/'
        }, {
            'repo_url': 'http://example.com',
            'edit_uri': '?query=edit/master'
        }, {
            'repo_url': 'http://example.com/',
            'edit_uri': '?query=edit/master/'
        }, {
            'repo_url': 'http://example.com',
            'edit_uri': '#edit/master'
        }, {
            'repo_url': 'http://example.com/',
            'edit_uri': '#edit/master/'
        }]

        expected = [
            'http://github.com/mkdocs/mkdocs/edit/master/docs/sub1/non-index.md',
            'https://github.com/mkdocs/mkdocs/edit/master/docs/sub1/non-index.md',
            None, 'http://example.com/edit/master/sub1/non-index.md',
            'http://example.com/edit/master/sub1/non-index.md',
            'http://example.com/edit/master/sub1/non-index.md',
            'http://example.com/edit/master/sub1/non-index.md',
            'http://example.com/edit/master/sub1/non-index.md',
            'http://example.com/foo/edit/master/sub1/non-index.md',
            'http://example.com/foo/edit/master/sub1/non-index.md',
            'http://example.com?query=edit/master/sub1/non-index.md',
            'http://example.com/?query=edit/master/sub1/non-index.md',
            'http://example.com#edit/master/sub1/non-index.md',
            'http://example.com/#edit/master/sub1/non-index.md'
        ]

        for i, c in enumerate(configs):
            c['docs_dir'] = self.DOCS_DIR
            cfg = load_config(**c)
            fl = File('sub1\\non-index.md', cfg['docs_dir'], cfg['site_dir'],
                      cfg['use_directory_urls'])
            pg = Page('Foo', fl, cfg)
            self.assertEqual(pg.url, 'sub1/non-index/')
            self.assertEqual(pg.edit_url, expected[i])
Example #24
0
    def test_page_edit_url(self):
        configs = [
            {
                'repo_url': 'http://github.com/mkdocs/mkdocs'
            },
            {
                'repo_url': 'https://github.com/mkdocs/mkdocs/'
            },
            {
                'repo_url': 'http://example.com'
            },
            {
                'repo_url': 'http://example.com',
                'edit_uri': 'edit/master'
            },
            {
                'repo_url': 'http://example.com',
                'edit_uri': '/edit/master'
            },
            {
                'repo_url': 'http://example.com/foo/',
                'edit_uri': '/edit/master/'
            },
            {
                'repo_url': 'http://example.com/foo',
                'edit_uri': '/edit/master/'
            },
            {
                'repo_url': 'http://example.com/foo/',
                'edit_uri': '/edit/master'
            },
            {
                'repo_url': 'http://example.com/foo/',
                'edit_uri': 'edit/master/'
            },
            {
                'repo_url': 'http://example.com/foo',
                'edit_uri': 'edit/master/'
            },
            {
                'repo_url': 'http://example.com',
                'edit_uri': '?query=edit/master'
            },
            {
                'repo_url': 'http://example.com/',
                'edit_uri': '?query=edit/master/'
            },
            {
                'repo_url': 'http://example.com',
                'edit_uri': '#edit/master'
            },
            {
                'repo_url': 'http://example.com/',
                'edit_uri': '#edit/master/'
            },
            {
                'repo_url': 'http://example.com',
                'edit_uri': ''  # Set to blank value
            },
            {
                # Nothing defined
            }
        ]

        expected = [
            'http://github.com/mkdocs/mkdocs/edit/master/docs/testing.md',
            'https://github.com/mkdocs/mkdocs/edit/master/docs/testing.md',
            None, 'http://example.com/edit/master/testing.md',
            'http://example.com/edit/master/testing.md',
            'http://example.com/edit/master/testing.md',
            'http://example.com/edit/master/testing.md',
            'http://example.com/edit/master/testing.md',
            'http://example.com/foo/edit/master/testing.md',
            'http://example.com/foo/edit/master/testing.md',
            'http://example.com?query=edit/master/testing.md',
            'http://example.com/?query=edit/master/testing.md',
            'http://example.com#edit/master/testing.md',
            'http://example.com/#edit/master/testing.md', None, None
        ]

        for i, c in enumerate(configs):
            cfg = load_config(**c)
            fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'],
                      cfg['use_directory_urls'])
            pg = Page('Foo', fl, cfg)
            self.assertEqual(pg.url, 'testing/')
            self.assertEqual(pg.edit_url, expected[i])