fast and simple flat wiki system from markdown
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1014 lines
41 KiB

import os
import shutil
from textwrap import dedent
import time
import unittest
import swiki
import modules.link_utilities as link
def touch(path, content: str = ''):
with open(path, 'a') as f:
f.write(content)
def empty(input_path: str):
for root, dirs, files in os.walk(input_path):
for f in files:
os.unlink(os.path.join(root, f))
for d in dirs:
shutil.rmtree(os.path.join(root, d))
def make_test_directory():
test_path = os.path.join(current_dir, '__delete_test')
if os.path.isdir(test_path):
shutil.rmtree(test_path)
os.makedirs(test_path)
return test_path
current_dir = os.path.dirname(os.path.realpath(__file__))
class LinkUtilitiesTestCase(unittest.TestCase):
""" These are used after markdown conversion """
def setUp(self):
self.test_backlinks = [
{
'title': 'yeah',
'filename': 'yeah'
},
{
'title': 'yeah 2',
'filename': 'yeah-2',
}
]
def test_kebabify_basic(self):
test_name = 'A local link'
expected_output = 'a-local-link'
actual_output = link.kebabify(test_name)
self.assertEqual(expected_output, actual_output)
def test_kebabify_special_chars(self):
test_name = 'A local/link, yeah. (it\'s "special"!)'
expected_output = 'a-locallink-yeah-its-special'
actual_output = link.kebabify(test_name)
self.assertEqual(expected_output, actual_output)
def test_kebabify_long(self):
test_name = 'lorem ipsum ' * 17
expected_output = ('lorem-ipsum' + '-lorem-ipsum' * 16)[:200]
actual_output = link.kebabify(test_name)
self.assertEqual(expected_output, actual_output)
def test_get_local(self):
test_content = """A {{local link}}, a {{local link|with another name}}, and an <a href="www.example.com">external link</a>."""
expected_local_links = ['local link', 'with another name']
actual_local_links = link.get_local(test_content)
self.assertListEqual(expected_local_links, actual_local_links)
def test_get_local_with_raw(self):
test_content = """A {{local link}}, a {{local link|with another name}}, a {{% raw %}}{{raw link}}{{% endraw %}}, and an <a href="www.example.com">external link</a>."""
expected_local_links = ['local link', 'with another name']
actual_local_links = link.get_local(test_content)
self.assertListEqual(expected_local_links, actual_local_links)
def test_add_local(self):
test_content = """A {{local link}}, a {{local link|with another name}}, and an <a href="www.example.com">external link</a>."""
expected_output = """A <a href="local-link.html">local link</a>, a <a href="with-another-name.html">local link</a>, and an <a href="www.example.com">external link</a>."""
actual_output = link.add_local(test_content)
self.assertEqual(expected_output, actual_output)
def test_add_local_with_raw(self):
test_content = """A {{local link}}, a {{local link|with another name}}, a {{% raw %}}{{raw link}}{{% endraw %}}, and an <a href="www.example.com">external link</a>."""
expected_output = """A <a href="local-link.html">local link</a>, a <a href="with-another-name.html">local link</a>, a {{raw link}}, and an <a href="www.example.com">external link</a>."""
actual_output = link.add_local(test_content)
self.assertEqual(expected_output, actual_output)
def test_add_external(self):
test_content = """A {{local link}}, a {{local link|with another name}}, and an <a href="www.example.com">external link</a>."""
expected_output = """A {{local link}}, a {{local link|with another name}}, and an <a href="www.example.com" target="_blank">external link</a>."""
actual_output = link.add_external(test_content)
self.assertEqual(expected_output, actual_output)
def test_add_backlinks_no_backlinks(self):
test_content = expected_content = "Test content"
actual_content = link.add_backlinks(test_content, [])
self.assertEqual(expected_content, actual_content)
def test_add_backlinks_basic(self):
test_content = "<p>Test content</p>"
expected_content = """<p>Test content</p><section id="backlinks"><details><summary>Backlinks</summary><ul><li><a href="yeah.html">yeah</a></li><li><a href="yeah-2.html">yeah 2</a></li></ul></details></section>"""
actual_content = link.add_backlinks(test_content, self.test_backlinks)
self.assertEqual(expected_content, actual_content)
def test_add_backlinks_duplicates(self):
test_backlinks = [*self.test_backlinks, self.test_backlinks[0]]
test_content = "<p>Test content</p>"
expected_content = """<p>Test content</p><section id="backlinks"><details><summary>Backlinks</summary><ul><li><a href="yeah.html">yeah</a></li><li><a href="yeah-2.html">yeah 2</a></li></ul></details></section>"""
actual_content = link.add_backlinks(test_content, test_backlinks)
self.assertEqual(expected_content, actual_content)
class InitTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_path = make_test_directory()
def tearDown(self):
empty(self.test_path)
def test_delete_current_html(self):
# SET UP
test_file = os.path.join(self.test_path, 'test.html')
touch(test_file)
another_test_file = os.path.join(self.test_path, 'another_test.html')
touch(another_test_file)
test_css = os.path.join(self.test_path, 'style.css')
touch(test_css)
test_folder = os.path.join(self.test_path, 'keep')
os.mkdir(test_folder)
# TEST
swiki.delete_current_html(self.test_path)
self.assertFalse(os.path.isfile(test_file))
self.assertFalse(os.path.isfile(another_test_file))
self.assertTrue(os.path.isfile(test_css))
self.assertTrue(os.path.isdir(test_folder))
def test_update_config_existing(self):
# SET UP
swiki_folder = os.path.join(self.test_path, '_swiki')
os.mkdir(swiki_folder)
test_config_fp = os.path.join(swiki_folder, 'config.ini')
touch(test_config_fp, 'tab_size = 4')
# TEST
test_config = {'tab_size': 2}
swiki.update_config(test_config, test_config_fp)
self.assertEqual(test_config.get('tab_size'), 4)
def test_update_config_new(self):
# SET UP
swiki_folder = os.path.join(self.test_path, '_swiki')
os.mkdir(swiki_folder)
test_config_fp = os.path.join(swiki_folder, 'config.ini')
touch(test_config_fp, 'new_item = 123abc\n\nanother_item = abc123')
# TEST
test_config = {'tab_size': 2}
swiki.update_config(test_config, test_config_fp)
self.assertEqual(test_config.get('tab_size'), 2)
self.assertEqual(test_config.get('new_item'), '123abc')
self.assertEqual(test_config.get('another_item'), 'abc123')
@classmethod
def tearDownClass(cls):
if os.path.isdir(cls.test_path):
shutil.rmtree(cls.test_path)
class BuildUtilitiesTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_path = make_test_directory()
def tearDown(self):
empty(self.test_path)
def test_copy_css_file_if_exists(self):
# SET UP
test_swiki = os.path.join(self.test_path, '_swiki')
os.mkdir(test_swiki)
test_css = os.path.join(test_swiki, 'test.css')
touch(test_css, 'test')
test_output = os.path.join(self.test_path, 'output')
os.mkdir(test_output)
# TEST
swiki.copy_css_file(self.test_path, test_output)
self.assertTrue(os.path.isfile(os.path.join(test_output, 'test.css')))
def test_copy_css_files_if_multiple_exist(self):
# SET UP
test_swiki = os.path.join(self.test_path, '_swiki')
os.mkdir(test_swiki)
test_css_1 = os.path.join(test_swiki, 'test1.css')
touch(test_css_1, 'test')
test_css_2 = os.path.join(test_swiki, 'test2.css')
touch(test_css_2, 'test')
test_output = os.path.join(self.test_path, 'output')
os.mkdir(test_output)
# TEST
swiki.copy_css_file(self.test_path, test_output)
self.assertTrue(os.path.isfile(os.path.join(test_output, 'test1.css')))
self.assertTrue(os.path.isfile(os.path.join(test_output, 'test2.css')))
def test_copy_css_file_if_not_exists(self):
# SET UP
test_swiki = os.path.join(self.test_path, '_swiki')
os.mkdir(test_swiki)
test_output = os.path.join(self.test_path, 'output')
os.mkdir(test_output)
# TEST
swiki.copy_css_file(self.test_path, test_output)
self.assertEqual(os.listdir(test_swiki), [])
self.assertEqual(os.listdir(test_output), [])
def test_copy_media_if_exists(self):
# SET UP
test_media_file_1 = os.path.join(self.test_path, 'file_1.txt')
touch(test_media_file_1, 'test')
test_media_file_2 = os.path.join(self.test_path, 'file_2.txt')
touch(test_media_file_2, 'test')
test_output = os.path.join(self.test_path, 'output')
os.mkdir(test_output)
# TEST
swiki.copy_media(self.test_path, test_media_file_1, test_output)
swiki.copy_media(self.test_path, test_media_file_2, test_output)
self.assertTrue(os.path.isfile(os.path.join(test_output, 'file_1.txt')))
self.assertTrue(os.path.isfile(os.path.join(test_output, 'file_2.txt')))
def test_copy_media_if_not_exists(self):
# SET UP
test_output = os.path.join(self.test_path, 'output')
os.mkdir(test_output)
# TEST
with self.assertRaises(FileNotFoundError):
swiki.copy_media(self.test_path, 'nonexistent_file.txt', test_output)
self.assertEqual(os.listdir(test_output), [])
@classmethod
def tearDownClass(cls):
if os.path.isdir(cls.test_path):
shutil.rmtree(cls.test_path)
class WikiHelpersTestCase(unittest.TestCase):
def test_place_in_container(self):
element = swiki.place_in_container('p', 'test', 'Inner text!')
self.assertEqual(element, '<p id="test">Inner text!</p>')
def test_place_in_container_if_no_id(self):
element = swiki.place_in_container('p', None, 'No ID :O')
self.assertEqual(element, '<p>No ID :O</p>')
def test_add_last_modified(self):
current_time = time.gmtime()
formatted_time = time.strftime(swiki.DATE_FORMAT, current_time)
html = swiki.add_last_modified('preceding content', time.gmtime())
self.assertEqual(html, f'preceding content<p class="last-modified">Last modified: {formatted_time}</p>')
class MakePageDictTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_path = make_test_directory()
cls.test_input_path = os.path.join(cls.test_path, 'input')
cls.test_input_rel_path = 'sub'
cls.test_page_filename = 'test-page.md'
os.makedirs(os.path.join(cls.test_input_path, cls.test_input_rel_path))
cls.test_page_fp = os.path.join(cls.test_input_path, cls.test_input_rel_path, cls.test_page_filename)
cls.test_page_lm = time.gmtime()
def test_basic(self):
# SET UP
test_page = dedent("""\
---
title: yeah
description: uh huh
---
The content""")
with open(self.test_page_fp, 'w') as f:
f.write(test_page)
# TEST
page_dict = swiki.make_page_dict(self.test_input_path, self.test_input_rel_path, self.test_page_filename)
self.assertDictEqual(page_dict, {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': 'uh huh',
'last_modified': self.test_page_lm,
},
'content': 'The content',
'links': [],
})
def test_no_desc(self):
# SET UP
test_page = dedent("""\
---
title: yeah
---
The content""")
with open(self.test_page_fp, 'w') as f:
f.write(test_page)
# TEST
page_dict = swiki.make_page_dict(self.test_input_path, self.test_input_rel_path, self.test_page_filename)
self.assertDictEqual(page_dict, {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': '',
'last_modified': self.test_page_lm,
},
'content': 'The content',
'links': [],
})
def test_link(self):
# SET UP
test_page = dedent("""\
---
title: yeah
description: uh huh
---
The {{content}}""")
with open(self.test_page_fp, 'w') as f:
f.write(test_page)
# TEST
page_dict = swiki.make_page_dict(self.test_input_path, self.test_input_rel_path, self.test_page_filename)
self.assertDictEqual(page_dict, {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': 'uh huh',
'last_modified': self.test_page_lm,
},
'content': 'The {{content}}',
'links': ['content'],
})
def test_multiple_links(self):
# SET UP
test_page = dedent("""\
---
title: yeah
description: uh huh
---
The {{content}} and then...
{{another}}!""")
with open(self.test_page_fp, 'w') as f:
f.write(test_page)
# TEST
page_dict = swiki.make_page_dict(self.test_input_path, self.test_input_rel_path, self.test_page_filename)
self.assertDictEqual(page_dict, {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': 'uh huh',
'last_modified': self.test_page_lm,
},
'content': 'The {{content}} and then...\n\n{{another}}!',
'links': ['content', 'another'],
})
def test_index(self):
# SET UP
test_page = dedent("""\
---
title: yeah
description: uh huh
---
The content""")
with open(self.test_page_fp, 'w') as f:
f.write(test_page)
# TEST
page_dict = swiki.make_page_dict(self.test_input_path, self.test_input_rel_path, self.test_page_filename)
self.assertDictEqual(page_dict, {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': 'uh huh',
'last_modified': self.test_page_lm,
},
'content': 'The content',
'links': [],
})
@classmethod
def tearDownClass(cls):
if os.path.isdir(cls.test_path):
shutil.rmtree(cls.test_path)
class SitemapTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.first_test_page_dict = {
'folder': 'sub',
'metadata': {
'title': 'First Test',
'description': 'First Test',
'last_modified': '202001010000',
},
'content': 'The content',
'links': [],
'index': True
}
cls.second_test_page_dict = {
'folder': 'sub',
'metadata': {
'title': 'Second Test',
'description': 'Second Test',
'last_modified': '202001010000',
},
'content': 'The content',
'links': [],
'index': True
}
def test_empty_folder(self):
test_sitemap = dict()
test_sitemap = swiki.add_page_to_sitemap(self.first_test_page_dict, 'missing', test_sitemap)
result_sitemap = dict()
result_sitemap['missing'] = [self.first_test_page_dict]
self.assertDictEqual(test_sitemap, result_sitemap)
def test_existing_folder(self):
test_sitemap = dict()
test_sitemap['existing'] = [self.first_test_page_dict]
test_sitemap = swiki.add_page_to_sitemap(self.second_test_page_dict, 'existing', test_sitemap)
result_sitemap = dict()
result_sitemap['existing'] = [self.first_test_page_dict, self.second_test_page_dict]
self.assertDictEqual(test_sitemap, result_sitemap)
class LoadFrameTestCase(unittest.TestCase):
test_path: str
test_input_folder: str
test_swiki_folder: str
@classmethod
def setUpClass(cls):
cls.test_path = make_test_directory()
cls.test_input_folder = os.path.join(cls.test_path, 'input')
os.mkdir(cls.test_input_folder)
cls.test_swiki_folder = os.path.join(cls.test_input_folder, '_swiki')
os.mkdir(cls.test_swiki_folder)
test_frame_path = os.path.join(cls.test_swiki_folder, 'frame.html')
test_frame_content = dedent("""\
<html>
<head>
<title>{{title}}</title>
<meta name="description" content="{{description}}">
</head>
<body>{{content}}</body>
</html>""")
touch(test_frame_path, test_frame_content)
def test_basic(self):
expected_output = """<html><head><title>{{title}}</title><meta name="description" content="{{description}}"></head><body>{{content}}</body></html>"""
actual_output = swiki.load_frame(self.test_swiki_folder)
self.assertEqual(expected_output, actual_output)
@classmethod
def tearDownClass(cls):
if os.path.isdir(cls.test_path):
shutil.rmtree(cls.test_path)
class FillFrameTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_page_dict = {
'folder': 'sub',
'metadata': {
'title': 'yeah',
'description': 'uh huh',
'last_modified': '202001010000',
},
'content': 'The content',
'links': [],
'index': True
}
cls.test_frame = dedent("""\
<html>
<head>
<title>{{title}}</title>
<meta name="description" content="{{description}}">
</head>
<body>
{{content}}
</body>
</html>""")
cls.test_content = 'Test content'
def test_empty_metadata(self):
test_metadata = dict()
filled = swiki.fill_frame(self.test_frame, self.test_content, test_metadata)
self.assertEqual(filled, dedent("""\
<html>
<head>
<title></title>
<meta name="description" content="">
</head>
<body>
Test content
</body>
</html>"""))
def test_with_metadata(self):
test_metadata = {
'title': 'The title',
'description': 'The description'
}
filled = swiki.fill_frame(self.test_frame, self.test_content, test_metadata)
self.assertEqual(filled, dedent("""\
<html>
<head>
<title>The title</title>
<meta name="description" content="The description">
</head>
<body>
Test content
</body>
</html>"""))
class FormatRecentListTestCase(unittest.TestCase):
test_pages: dict
@classmethod
def setUpClass(cls) -> None:
cls.test_pages = {
'filename_first': {
'folder': 'sub',
'metadata': {
'title': 'first',
'description': 'uh huh',
'last_modified': time.gmtime(200),
},
'content': 'The content',
'links': [],
},
'filename_third': {
'folder': 'sub',
'metadata': {
'title': 'third',
'description': 'uh huh',
'last_modified': time.gmtime(0),
},
'content': 'The content',
'links': [],
},
'filename_second': {
'folder': 'sub',
'metadata': {
'title': 'second',
'description': 'uh huh',
'last_modified': time.gmtime(100),
},
'content': 'The content',
'links': [],
},
}
cls.times = [
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_first']['metadata'].get('last_modified')),
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_second']['metadata'].get('last_modified')),
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_third']['metadata'].get('last_modified')),
]
def test_basic(self):
expected_output = dedent(f"""\
<section class="recent-list"><h2>Recent Changes:</h2><ul><li>{self.times[0]}: <a href="filename_first.html">first</a></li><li>{self.times[1]}: <a href="filename_second.html">second</a></li><li>{self.times[2]}: <a href="filename_third.html">third</a></li></ul></section>""")
actual_output = swiki.format_recent_list(self.test_pages, 3)
self.assertEqual(expected_output, actual_output)
def test_max(self):
expected_output = dedent(f"""\
<section class="recent-list"><h2>Recent Changes:</h2><ul><li>{self.times[0]}: <a href="filename_first.html">first</a></li><li>{self.times[1]}: <a href="filename_second.html">second</a></li></ul></section>""")
actual_output = swiki.format_recent_list(self.test_pages, 2)
self.assertEqual(expected_output, actual_output)
class PreparePageForFileTestCase(unittest.TestCase):
test_page_info: dict
@classmethod
def setUpClass(cls) -> None:
cls.test_page_info = {
'folder': 'sub',
'metadata': {
'title': 'test',
'description': 'uh huh',
'last_modified': time.gmtime(100),
},
'content': 'The content here is normal.\tTab test.',
'links': [],
}
cls.test_page_filename = 'test_filename'
cls.test_tab_size = 2
cls.formatted_time = time.strftime(swiki.DATE_FORMAT, cls.test_page_info['metadata']['last_modified'])
def test_basic(self):
# Newline in this output is from Marko
expected_output = f'<main id="main"><article id="content"><h1 id="title">test</h1><p>The content here is normal. Tab test.</p>\n<p class="last-modified">Last modified: {self.formatted_time}</p></article></main>'
actual_output = swiki.prepare_page_for_file(self.test_page_info, self.test_page_filename, self.test_tab_size)
self.assertEqual(expected_output, actual_output)
def test_no_metadata(self):
test_page_info_no_metadata = {
**self.test_page_info,
'metadata': {}, # To 'remove' the metadata attribute
}
# Newline in this output is from Marko
expected_output = f'<main id="main"><article id="content"><h1 id="title">test_filename</h1><p>The content here is normal. Tab test.</p>\n</article></main>'
actual_output = swiki.prepare_page_for_file(test_page_info_no_metadata, self.test_page_filename, self.test_tab_size)
self.assertEqual(expected_output, actual_output)
class MakeSitemapHeaderTestCase(unittest.TestCase):
test_pages: dict
@classmethod
def setUpClass(cls) -> None:
cls.test_index_info = {
'metadata': {
'title': 'Index Title'
},
'content': 'Here is the content of an index file.'
}
cls.test_pages = {
'filename_first': {
'folder': 'sub',
'metadata': {
'title': 'first',
'description': 'uh huh',
'last_modified': time.gmtime(200),
},
'content': 'The content',
'links': [],
},
'filename_third': {
'folder': 'sub',
'metadata': {
'title': 'third',
'description': 'uh huh',
'last_modified': time.gmtime(0),
},
'content': 'The content',
'links': [],
},
'filename_second': {
'folder': 'sub',
'metadata': {
'title': 'second',
'description': 'uh huh',
'last_modified': time.gmtime(100),
},
'content': 'The content',
'links': [],
},
}
cls.test_config = {'tab_size': 2, 'recent_list': True, 'recent_list_length': 2}
cls.times = [
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_first']['metadata'].get('last_modified')),
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_second']['metadata'].get('last_modified')),
time.strftime(swiki.DATE_FORMAT, cls.test_pages['filename_third']['metadata'].get('last_modified')),
]
def test_basic(self):
expected_output = f'<h1 id="title">{self.test_index_info["metadata"].get("title", "Sitemap")}</h1><p>{self.test_index_info.get("content")}</p>\n<section class="recent-list"><h2>Recent Changes:</h2><ul><li>{self.times[0]}: <a href="filename_first.html">first</a></li><li>{self.times[1]}: <a href="filename_second.html">second</a></li></ul></section>'
actual_output = swiki.make_sitemap_header(self.test_index_info, self.test_pages, self.test_config)
self.assertEqual(expected_output, actual_output)
class MakeWikiIndexTestCase(unittest.TestCase):
# def make_wiki_index(sitemap: dict, pages: dict) -> str:
@classmethod
def setUpClass(cls) -> None:
cls.test_sitemap = {
'sub': ['filename_first'],
'sub/subsub': ['filename_second'],
'folder_two': ['filename_fourth', 'filename_fifth'],
# [root]
'': ['filename_third'],
}
cls.test_pages = {
'filename_first': {
'folder': 'sub',
'metadata': {
'title': 'first',
'description': 'uh huh',
'last_modified': time.gmtime(200),
},
'content': 'The content',
'links': [],
},
'filename_third': {
'folder': '',
'metadata': {
'title': 'third',
'description': 'uh huh',
'last_modified': time.gmtime(10),
},
'content': 'The content',
'links': [],
},
'filename_second': {
'folder': 'sub/subsub',
'metadata': {
'title': 'second',
'description': 'uh huh',
'last_modified': time.gmtime(100),
},
'content': 'The content',
'links': [],
},
'filename_fourth': {
'folder': 'folder_two',
'metadata': {
'title': 'fourth',
'description': '',
'last_modified': time.gmtime(100),
},
'content': 'The content',
'links': [],
},
'filename_fifth': {
'folder': 'folder_two',
'metadata': {
'title': 'fifth',
'description': 'uh huh',
'last_modified': time.gmtime(100),
},
'content': 'The content',
'links': [],
},
}
def test_basic(self):
expected_output = '<div><details><summary>[root]</summary><ul><li><a href="filename_third.html">third</a> - uh huh</li></ul></details></div><div><details><summary>folder_two</summary><ul><li><a href="filename_fifth.html">fifth</a> - uh huh</li><li><a href="filename_fourth.html">fourth</a></li></ul></details></div><div><details><summary>sub</summary><ul><li><a href="filename_first.html">first</a> - uh huh</li></ul></details></div><div><details><summary>sub/<wbr/>subsub</summary><ul><li><a href="filename_second.html">second</a> - uh huh</li></ul></details></div>'
actual_output = swiki.make_wiki_index(self.test_sitemap, self.test_pages)
self.assertEqual(expected_output, actual_output)
class MakeSitemapTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
sitemap_header = """<h1 id="title">Index Title</h1><p>Here is the content of an index file.</p>
<section class="recent-list"><h2>Recent Changes:</h2><ul><li>197001010003: <a href="filename_first.html">first</a></li><li>197001010001: <a href="filename_second.html">second</a></li></ul></section>"""
wiki_index = '<div><details><summary>[root]</summary><ul><li><a href="filename_third.html">third</a> - uh huh</li></ul></details></div>'
cls.test_sitemap_html = sitemap_header + wiki_index
cls.test_frame = dedent("""\
<html>
<head>
<title>{{title}}</title>
<meta name="description" content="{{description}}">
</head>
<body>
{{content}}
</body>
</html>""")
cls.test_index_metadata = {
'title': 'Index Title',
'description': 'Index description'
}
def test_basic(self):
expected_output = f"""\
<html>
<head>
<title>{self.test_index_metadata.get('title')}</title>
<meta name="description" content="{self.test_index_metadata.get('description')}">
</head>
<body>
<main id="main">{self.test_sitemap_html}</main>
</body>
</html>"""
actual_output = swiki.make_sitemap(self.test_sitemap_html, self.test_frame, self.test_index_metadata)
self.assertEqual(expected_output, actual_output)
class MakeWikiTestCase(unittest.TestCase):
@classmethod
def setUp(cls):
cls.test_path = make_test_directory()
cls.test_input_folder = os.path.join(cls.test_path, 'input')
os.mkdir(cls.test_input_folder)
cls.test_output_folder = os.path.join(cls.test_path, 'output')
os.mkdir(cls.test_output_folder)
test_file_path = os.path.join(cls.test_input_folder, 'test.md')
test_file_content = dedent("""\
---
title: Example File
description: Example description.
---
Some content.""")
touch(test_file_path, test_file_content)
cls.test_file_lm = time.strftime("%Y%m%d%H%M", time.gmtime(os.path.getmtime(test_file_path)))
another_test_file_path = os.path.join(cls.test_input_folder, 'another_test.md')
another_test_file_content = dedent("""\
---
title: Another File
description: Another description.
---
Another set of content, with *italics*!""")
touch(another_test_file_path, another_test_file_content)
cls.another_test_file_lm = time.strftime("%Y%m%d%H%M", time.gmtime(os.path.getmtime(another_test_file_path)))
test_swiki_folder = os.path.join(cls.test_input_folder, '_swiki')
os.mkdir(test_swiki_folder)
test_frame_path = os.path.join(test_swiki_folder, 'frame.html')
test_frame_content = dedent("""\
<html>
<head>
<title>{{title}}</title>
<meta name="description" content="{{description}}">
</head>
<body>{{content}}</body>
</html>""")
touch(test_frame_path, test_frame_content)
test_css_path = os.path.join(test_swiki_folder, 'style.css')
touch(test_css_path, 'body { font-size: 40rem; color: blue; }')
cls.test_config = {'tab_size': 2, 'recent_list': False, 'recent_list_length': 10}
def tearDown(self):
empty(self.test_output_folder)
def test_multiple_pages(self):
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
self.test_config)
test_example_file_path = os.path.join(self.test_output_folder, 'example-file.html')
self.assertTrue(os.path.isfile(test_example_file_path))
expected_example_file_content = dedent(f"""\
<html><head><title>Example File</title><meta name="description" content="Example description."></head><body><main id="main"><article id="content"><h1 id="title">Example File</h1><p>Some content.</p>
<p class="last-modified">Last modified: {self.test_file_lm}</p></article></main></body></html>""")
with open(test_example_file_path, 'r') as f:
actual_example_file_content = f.read()
self.assertEqual(expected_example_file_content, actual_example_file_content)
test_another_file_path = os.path.join(self.test_output_folder, 'another-file.html')
self.assertTrue(os.path.isfile(test_another_file_path))
expected_another_file_content = dedent(f"""\
<html><head><title>Another File</title><meta name="description" content="Another description."></head><body><main id="main"><article id="content"><h1 id="title">Another File</h1><p>Another set of content, with <em>italics</em>!</p>
<p class="last-modified">Last modified: {self.another_test_file_lm}</p></article></main></body></html>""")
with open(test_another_file_path, 'r') as f:
actual_another_file_content = f.read()
self.assertEqual(expected_another_file_content, actual_another_file_content)
test_css_path = os.path.join(self.test_output_folder, 'style.css')
self.assertTrue(os.path.isfile(test_css_path))
def test_same_title(self):
# SET UP
duplicate_test_file_path = os.path.join(self.test_input_folder, 'test_duplicate.md')
duplicate_test_file_content = dedent("""\
---
title: Example File
description: Example description.
---
Some content.""")
touch(duplicate_test_file_path, duplicate_test_file_content)
# TESTS
with self.assertRaises(RuntimeError) as e:
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
self.test_config)
actual_exception_message = str(e.exception)
expected_exception_message = f'''Page "Example File" with filename "example-file" conflicts with page "Example File" with filename "example-file".'''
self.assertEqual(expected_exception_message, actual_exception_message)
def test_same_filename_for_non_pages(self):
# SET UP
test_media_file_1 = os.path.join(self.test_input_folder, 'file_1.txt')
touch(test_media_file_1, 'test')
test_media_folder = os.path.join(self.test_input_folder, 'another_folder')
os.mkdir(test_media_folder)
test_media_file_2 = os.path.join(test_media_folder, 'file_1.txt')
touch(test_media_file_2, 'test')
# TEST
with self.assertRaises(RuntimeError):
swiki.make_wiki(self.test_input_folder, self.test_output_folder, self.test_config)
def test_index(self):
# SET UP
test_index_file_path = os.path.join(self.test_input_folder, '_swiki', 'index.md')
test_index_file_content = dedent("""\
---
title: Website Index
description: Index description.
---
This is the index, wow.""")
touch(test_index_file_path, test_index_file_content)
# TESTS
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
self.test_config)
output_index_file_path = os.path.join(self.test_output_folder, 'index.html')
self.assertTrue(os.path.isfile(output_index_file_path))
# Should alphabetize pages in input folder by title metadata
expected_index_file_content = dedent(f"""\
<html><head><title>Website Index</title><meta name="description" content="Index description."></head><body><main id="main"><h1 id="title">Website Index</h1><p>This is the index, wow.</p>
<div><details><summary>[root]</summary><ul><li><a href="another-file.html">Another File</a> - Another description.</li><li><a href="example-file.html">Example File</a> - Example description.</li></ul></details></div></main></body></html>""")
with open(output_index_file_path, 'r') as f:
actual_index_file_content = f.read()
self.assertEqual(expected_index_file_content, actual_index_file_content)
def test_recent(self):
test_recent_config = {'tab_size': 2, 'recent_list': True, 'recent_list_length': 10}
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
test_recent_config)
# should show both pages added in order of creation
output_index_file_path = os.path.join(self.test_output_folder, 'index.html')
self.assertTrue(os.path.isfile(output_index_file_path))
expected_index_file_content = f"""\
<html><head><title></title><meta name="description" content=""></head><body>\
<main id="main"><h1 id="title">Sitemap</h1><section class="recent-list"><h2>Recent Changes:</h2><ul>\
<li>{self.another_test_file_lm}: <a href="another-file.html">Another File</a></li>\
<li>{self.test_file_lm}: <a href="example-file.html">Example File</a></li></ul></section>\
<div><details><summary>[root]</summary><ul><li><a href="another-file.html">Another File</a> - Another description.</li>\
<li><a href="example-file.html">Example File</a> - Example description.</li></ul></details></div></main></body></html>"""
with open(output_index_file_path, 'r') as f:
actual_index_file_content = f.read()
self.assertEqual(expected_index_file_content, actual_index_file_content)
def test_recent_list_length(self):
test_recent_config = {'tab_size': 2, 'recent_list': True, 'recent_list_length': 1}
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
test_recent_config)
# should show both pages added in order of creation
output_index_file_path = os.path.join(self.test_output_folder, 'index.html')
self.assertTrue(os.path.isfile(output_index_file_path))
expected_index_file_content = f"""\
<html><head><title></title><meta name="description" content=""></head><body>\
<main id="main"><h1 id="title">Sitemap</h1><section class="recent-list"><h2>Recent Changes:</h2><ul>\
<li>{self.another_test_file_lm}: <a href="another-file.html">Another File</a></li></ul></section>\
<div><details><summary>[root]</summary><ul><li><a href="another-file.html">Another File</a> - Another description.</li>\
<li><a href="example-file.html">Example File</a> - Example description.</li></ul></details></div></main></body></html>"""
with open(output_index_file_path, 'r') as f:
actual_index_file_content = f.read()
self.assertEqual(expected_index_file_content, actual_index_file_content)
def test_ignore(self):
# SET UP
test_ignore_file_path = os.path.join(self.test_input_folder, '_ignore.md')
test_ignore_file_content = dedent("""\
---
title: Ignore
description: Ignored description.
---
We won't see this.""")
touch(test_ignore_file_path, test_ignore_file_content)
# TESTS
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
self.test_config)
output_file_path = os.path.join(self.test_output_folder, 'ignore.html')
self.assertFalse(os.path.isfile(output_file_path))
def test_reserved(self):
# SET UP
test_reserved_file_path = os.path.join(self.test_input_folder, 'reserved.md')
test_reserved_file_content = dedent("""\
---
title: Index
description: Reserved description.
---
Index is a reserved filename.""")
touch(test_reserved_file_path, test_reserved_file_content)
# TESTS
swiki.make_wiki(self.test_input_folder, self.test_output_folder,
self.test_config)
output_file_path = os.path.join(self.test_output_folder, 'index_.html')
reserved_output_file_path = os.path.join(self.test_output_folder, 'index.html')
self.assertTrue(os.path.isfile(output_file_path))
self.assertTrue(os.path.isfile(reserved_output_file_path))
@classmethod
def tearDownClass(cls):
if os.path.isdir(cls.test_path):
shutil.rmtree(cls.test_path)
if __name__ == '__main__':
unittest.main()