From 62d0aa159fc046a27bed47e337d787a08f4687d0 Mon Sep 17 00:00:00 2001 From: Sunaina Pai Date: Sat, 17 Mar 2018 14:45:21 +0530 Subject: Add makesite: A simple static site generator --- test/__init__.py | 0 test/path.py | 16 ++++++++ test/test_content.py | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test_file_io.py | 39 ++++++++++++++++++ test/test_headers.py | 43 +++++++++++++++++++ test/test_list.py | 46 +++++++++++++++++++++ test/test_main.py | 73 +++++++++++++++++++++++++++++++++ test/test_pages.py | 63 ++++++++++++++++++++++++++++ test/test_path.py | 78 +++++++++++++++++++++++++++++++++++ test/test_render.py | 25 +++++++++++ 10 files changed, 497 insertions(+) create mode 100644 test/__init__.py create mode 100644 test/path.py create mode 100644 test/test_content.py create mode 100644 test/test_file_io.py create mode 100644 test/test_headers.py create mode 100644 test/test_list.py create mode 100644 test/test_main.py create mode 100644 test/test_pages.py create mode 100644 test/test_path.py create mode 100644 test/test_render.py (limited to 'test') diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/path.py b/test/path.py new file mode 100644 index 0000000..38c0991 --- /dev/null +++ b/test/path.py @@ -0,0 +1,16 @@ +import os +import tempfile +import shutil + + +def temppath(*paths): + return os.path.join(tempfile.gettempdir(), *paths) + + +def move(src, dst): + if os.path.isfile(dst): + os.remove(dst) + elif os.path.isdir(dst): + shutil.rmtree(dst) + if os.path.exists(src): + os.rename(src, dst) diff --git a/test/test_content.py b/test/test_content.py new file mode 100644 index 0000000..06ec97d --- /dev/null +++ b/test/test_content.py @@ -0,0 +1,114 @@ +import unittest +import shutil +import os + +import makesite +from test import path + + +class ContentTest(unittest.TestCase): + def setUp(self): + self.blog_path = path.temppath('blog') + self.undated_path = os.path.join(self.blog_path, 'foo.txt') + self.dated_path = os.path.join(self.blog_path, '2018-01-01-foo.txt') + self.long_post_path = os.path.join(self.blog_path, 'bar.txt') + self.normal_post_path = os.path.join(self.blog_path, 'baz.txt') + self.md_post_path = os.path.join(self.blog_path, 'qux.md') + self.no_md_post_path = os.path.join(self.blog_path, 'qux.txt') + + os.makedirs(self.blog_path) + + with open(self.undated_path, 'w') as f: + f.write('hello world') + + with open(self.dated_path, 'w') as f: + f.write('hello world') + + with open(self.long_post_path, 'w') as f: + self.long_text = ' \n'.join('word' + str(i) for i in range(50)) + f.write(self.long_text) + + with open(self.normal_post_path, 'w') as f: + f.write('\n\nFoo') + + with open(self.md_post_path, 'w') as f: + f.write('*Foo*') + + with open(self.no_md_post_path, 'w') as f: + f.write('*Foo*') + + def tearDown(self): + shutil.rmtree(self.blog_path) + + # Rudimentary mock because unittest.mock is unavailable in Python 2.7. + def mock(self, *args): + self.mock_args = args + + def test_content_content(self): + content = makesite.read_content(self.long_post_path) + self.assertEqual(content['content'], self.long_text) + + def test_content_summary(self): + content = makesite.read_content(self.long_post_path) + expected_text = ' '.join('word' + str(i) for i in range(25)) + self.assertEqual(content['summary'], expected_text) + + def test_content_date(self): + content = makesite.read_content(self.dated_path) + self.assertEqual(content['date'], '2018-01-01') + + def test_content_date_missing(self): + content = makesite.read_content(self.undated_path) + self.assertEqual(content['date'], '1970-01-01') + + def test_content_slug_dated(self): + content = makesite.read_content(self.dated_path) + self.assertEqual(content['slug'], 'foo') + + def test_content_slug_undated(self): + content = makesite.read_content(self.undated_path) + self.assertEqual(content['slug'], 'foo') + + def test_content_headers(self): + content = makesite.read_content(self.normal_post_path) + self.assertEqual(content['a'], '1') + self.assertEqual(content['b'], '2') + self.assertEqual(content['content'], 'Foo') + + def test_markdown_rendering(self): + content = makesite.read_content(self.md_post_path) + self.assertEqual(content['content'], '

Foo

\n') + + def test_markdown_import_error(self): + makesite._test = 'ImportError' + original_log = makesite.log + + makesite.log = self.mock + self.mock_args = None + content = makesite.read_content(self.md_post_path) + + makesite._test = None + makesite.log = original_log + + self.assertEqual(content['content'], '*Foo*') + self.assertEqual(self.mock_args, + ('WARNING: Cannot render Markdown in {}: {}', + self.md_post_path, 'Error forced by test')) + + def test_no_markdown_rendering(self): + content = makesite.read_content(self.no_md_post_path) + self.assertEqual(content['content'], '*Foo*') + + def test_no_markdown_import_error(self): + makesite._test = 'ImportError' + original_log = makesite.log + + makesite.log = self.mock + self.mock_args = None + content = makesite.read_content(self.no_md_post_path) + + makesite._test = None + makesite.log = original_log + + self.assertEqual(content['content'], '*Foo*') + self.assertIsNone(self.mock_args) diff --git a/test/test_file_io.py b/test/test_file_io.py new file mode 100644 index 0000000..3760956 --- /dev/null +++ b/test/test_file_io.py @@ -0,0 +1,39 @@ +import unittest +import os +import shutil + +import makesite +from test import path + + +class FileIOTest(unittest.TestCase): + """Tests for file I/O functions.""" + + def test_fread(self): + text = 'foo\nbar\n' + filepath = path.temppath('foo.txt') + with open(filepath, 'w') as f: + f.write(text) + text_read = makesite.fread(filepath) + os.remove(filepath) + self.assertEqual(text_read, text) + + def test_fwrite(self): + text = 'baz\nqux\n' + filepath = path.temppath('foo.txt') + makesite.fwrite(filepath, text) + with open(filepath) as f: + text_read = f.read() + os.remove(filepath) + self.assertEqual(text_read, text) + + def test_fwrite_makedir(self): + text = 'baz\nqux\n' + dirpath = path.temppath('foo', 'bar') + filepath = os.path.join(dirpath, 'foo.txt') + makesite.fwrite(filepath, text) + with open(filepath) as f: + text_read = f.read() + self.assertTrue(os.path.isdir(dirpath)) + shutil.rmtree(path.temppath('foo')) + self.assertEqual(text_read, text) diff --git a/test/test_headers.py b/test/test_headers.py new file mode 100644 index 0000000..56eeb4a --- /dev/null +++ b/test/test_headers.py @@ -0,0 +1,43 @@ +import unittest +import makesite + + +class HeaderTest(unittest.TestCase): + """Tests for read_headers() function.""" + + def test_single_header(self): + text = '' + headers = list(makesite.read_headers(text)) + self.assertEqual(headers, [('key1', 'val1', 19)]) + + def test_multiple_headers(self): + text = '\n' + headers = list(makesite.read_headers(text)) + self.assertEqual(headers, [('key1', 'val1', 20), ('key2', 'val2', 38)]) + + def test_headers_and_text(self): + text = '\n\nFoo\n' + headers = list(makesite.read_headers(text)) + self.assertEqual(headers, [('a', '1', 14), ('b', '2', 28)]) + + def test_headers_and_blank_line(self): + text = '\n\n\n\n' + headers = list(makesite.read_headers(text)) + self.assertEqual(headers, [('a', '1', 14), + ('b', '2', 29), + ('c', '3', 43)]) + + def test_multiline_header(self): + text = '\n' + headers = list(makesite.read_headers(text)) + self.assertEqual(headers, [('a', '1', 13), + ('b', '2', 27), + ('c', '3', 40)]) + + def test_no_header(self): + headers = list(makesite.read_headers('Foo')) + self.assertEqual(headers, []) + + def test_empty_string(self): + headers = list(makesite.read_headers('')) + self.assertEqual(headers, []) diff --git a/test/test_list.py b/test/test_list.py new file mode 100644 index 0000000..8acb2ef --- /dev/null +++ b/test/test_list.py @@ -0,0 +1,46 @@ +import unittest +import shutil +import os +import makesite +from test import path + +class PagesTest(unittest.TestCase): + def setUp(self): + self.site_path = path.temppath('site') + + def tearDown(self): + shutil.rmtree(self.site_path) + + def test_list(self): + posts = [{'content': 'Foo'}, {'content': 'Bar'}] + dst = os.path.join(self.site_path, 'list.txt') + list_layout = '
{{ content }}
' + item_layout = '

{{ content }}

' + makesite.make_list(posts, dst, list_layout, item_layout) + with open(os.path.join(self.site_path, 'list.txt')) as f: + self.assertEqual(f.read(), '

Foo

Bar

') + + def test_list_params(self): + posts = [{'content': 'Foo', 'title': 'foo'}, + {'content': 'Bar', 'title': 'bar'}] + dst = os.path.join(self.site_path, 'list.txt') + list_layout = '
{{ key }}:{{ title }}:{{ content }}
' + item_layout = '

{{ key }}:{{ title }}:{{ content }}

' + makesite.make_list(posts, dst, list_layout, item_layout, + key='val', title='lorem') + with open(os.path.join(self.site_path, 'list.txt')) as f: + text = f.read() + self.assertEqual(text, + '
val:lorem:

val:foo:Foo

val:bar:Bar

') + + def test_dst_params(self): + posts = [{'content': 'Foo'}, {'content': 'Bar'}] + dst = os.path.join(self.site_path, '{{ key }}.txt') + list_layout = '
{{ content }}
' + item_layout = '

{{ content }}

' + makesite.make_list(posts, dst, list_layout, item_layout, key='val') + + expected_path = os.path.join(self.site_path, 'val.txt') + self.assertTrue(os.path.isfile(expected_path)) + with open(expected_path) as f: + self.assertEqual(f.read(), '

Foo

Bar

') diff --git a/test/test_main.py b/test/test_main.py new file mode 100644 index 0000000..50f1cc5 --- /dev/null +++ b/test/test_main.py @@ -0,0 +1,73 @@ +import unittest +import makesite +import os +import shutil +import json + +from test import path + + +class MainTest(unittest.TestCase): + def setUp(self): + path.move('_site', '_site.backup') + path.move('params.json', 'params.json.backup') + + def tearDown(self): + path.move('_site.backup', '_site') + path.move('params.json.backup', 'params') + + def test_site_missing(self): + makesite.main() + + def test_site_exists(self): + os.mkdir('_site') + with open('_site/foo.txt', 'w') as f: + f.write('foo') + + self.assertTrue(os.path.isfile('_site/foo.txt')) + makesite.main() + self.assertFalse(os.path.isfile('_site/foo.txt')) + + def test_default_params(self): + makesite.main() + + with open('_site/blog/proin-quam/index.html') as f: + s1 = f.read() + + with open('_site/blog/rss.xml') as f: + s2 = f.read() + + shutil.rmtree('_site') + + self.assertIn('Home', s1) + self.assertIn('Proin Quam - Lorem Ipsum', s1) + self.assertIn('Published on 2018-01-01 by Admin', s1) + + self.assertIn('http://localhost:8000/', s2) + self.assertIn('http://localhost:8000/blog/proin-quam/', s2) + + def test_json_params(self): + params = { + 'base_path': '/base', + 'subtitle': 'Foo', + 'author': 'Bar', + 'site_url': 'http://localhost/base' + } + with open('params.json', 'w') as f: + json.dump(params, f) + makesite.main() + + with open('_site/blog/proin-quam/index.html') as f: + s1 = f.read() + + with open('_site/blog/rss.xml') as f: + s2 = f.read() + + shutil.rmtree('_site') + + self.assertIn('Home', s1) + self.assertIn('Proin Quam - Foo', s1) + self.assertIn('Published on 2018-01-01 by Bar', s1) + + self.assertIn('http://localhost/base/', s2) + self.assertIn('http://localhost/base/blog/proin-quam/', s2) diff --git a/test/test_pages.py b/test/test_pages.py new file mode 100644 index 0000000..5fe7a4d --- /dev/null +++ b/test/test_pages.py @@ -0,0 +1,63 @@ +import unittest +import os +import shutil +import makesite +from test import path + +class PagesTest(unittest.TestCase): + def setUp(self): + self.blog_path = path.temppath('blog') + self.site_path = path.temppath('site') + os.makedirs(self.blog_path) + + with open(os.path.join(self.blog_path, 'foo.txt'), 'w') as f: + f.write('Foo') + with open(os.path.join(self.blog_path, 'bar.txt'), 'w') as f: + f.write('Bar') + with open(os.path.join(self.blog_path, '2018-01-01-foo.txt'), 'w') as f: + f.write('Foo') + with open(os.path.join(self.blog_path, '2018-01-02-bar.txt'), 'w') as f: + f.write('Bar') + + def tearDown(self): + shutil.rmtree(self.blog_path) + shutil.rmtree(self.site_path) + + def test_pages_undated(self): + src = os.path.join(self.blog_path, '[fb]*.txt') + dst = os.path.join(self.site_path, '{{ slug }}.txt') + tpl = '
{{ content }}
' + makesite.make_pages(src, dst, tpl) + with open(os.path.join(self.site_path, 'foo.txt')) as f: + self.assertEqual(f.read(), '
Foo
') + with open(os.path.join(self.site_path, 'bar.txt')) as f: + self.assertEqual(f.read(), '
Bar
') + + def test_pages_dated(self): + src = os.path.join(self.blog_path, '2*.txt') + dst = os.path.join(self.site_path, '{{ slug }}.txt') + tpl = '
{{ content }}
' + makesite.make_pages(src, dst, tpl) + with open(os.path.join(self.site_path, 'foo.txt')) as f: + self.assertEqual(f.read(), '
Foo
') + with open(os.path.join(self.site_path, 'bar.txt')) as f: + self.assertEqual(f.read(), '
Bar
') + + def test_pages_layout_params(self): + src = os.path.join(self.blog_path, '2*.txt') + dst = os.path.join(self.site_path, '{{ slug }}.txt') + tpl = '
{{ slug }}:{{ title }}:{{ date }}:{{ content }}
' + makesite.make_pages(src, dst, tpl, title='Lorem') + with open(os.path.join(self.site_path, 'foo.txt')) as f: + self.assertEqual(f.read(), '
foo:Lorem:2018-01-01:Foo
') + with open(os.path.join(self.site_path, 'bar.txt')) as f: + self.assertEqual(f.read(), '
bar:Lorem:2018-01-02:Bar
') + + def test_pages_return_value(self): + src = os.path.join(self.blog_path, '2*.txt') + dst = os.path.join(self.site_path, '{{ slug }}.txt') + tpl = '
{{ content }}
' + posts = makesite.make_pages(src, dst, tpl) + self.assertEqual(len(posts), 2) + self.assertEqual(posts[0]['date'], '2018-01-02') + self.assertEqual(posts[1]['date'], '2018-01-01') diff --git a/test/test_path.py b/test/test_path.py new file mode 100644 index 0000000..91e76e8 --- /dev/null +++ b/test/test_path.py @@ -0,0 +1,78 @@ +import unittest +import os +import shutil + +from test import path + +class PathTest(unittest.TestCase): + def test_temppath(self): + self.assertTrue(path.temppath()) + + def test_move_existing_file(self): + src = os.path.join(path.temppath(), 'foo.txt') + dst = os.path.join(path.temppath(), 'bar.txt') + with open(src, 'w') as f: + f.write('foo') + + path.move(src, dst) + self.assertFalse(os.path.isfile(src)) + self.assertTrue(os.path.isfile(dst)) + + with open(dst) as f: + text = f.read() + + os.remove(dst) + + self.assertEqual(text, 'foo') + + def test_move_missing_file(self): + src = os.path.join(path.temppath(), 'foo.txt') + dst = os.path.join(path.temppath(), 'bar.txt') + path.move(src, dst) + self.assertFalse(os.path.isfile(src)) + self.assertFalse(os.path.isfile(dst)) + + def test_move_file_cleanup(self): + src = os.path.join(path.temppath(), 'foo.txt') + dst = os.path.join(path.temppath(), 'bar.txt') + with open(dst, 'w') as f: + f.write('foo') + path.move(src, dst) + self.assertFalse(os.path.isfile(src)) + self.assertFalse(os.path.isfile(dst)) + + def test_move_existing_dir(self): + src = os.path.join(path.temppath(), 'foo') + srcf = os.path.join(src, 'foo.txt') + dst = os.path.join(path.temppath(), 'bar') + dstf = os.path.join(dst, 'foo.txt') + + os.makedirs(src) + with open(srcf, 'w') as f: + f.write('foo') + + path.move(src, dst) + self.assertFalse(os.path.isdir(src)) + self.assertTrue(os.path.isdir(dst)) + + with open(dstf) as f: + text = f.read() + + shutil.rmtree(dst) + + self.assertEqual(text, 'foo') + + def test_move_missing_dir(self): + src = os.path.join(path.temppath(), 'foo') + dst = os.path.join(path.temppath(), 'bar') + path.move(src, dst) + self.assertFalse(os.path.isdir(src)) + self.assertFalse(os.path.isdir(dst)) + + def test_move_dir_cleanup(self): + src = os.path.join(path.temppath(), 'foo') + dst = os.path.join(path.temppath(), 'bar') + os.makedirs(dst) + path.move(src, dst) + self.assertFalse(os.path.isdir(src)) + self.assertFalse(os.path.isdir(dst)) diff --git a/test/test_render.py b/test/test_render.py new file mode 100644 index 0000000..e036b70 --- /dev/null +++ b/test/test_render.py @@ -0,0 +1,25 @@ +import unittest +import makesite + +class RenderTest(unittest.TestCase): + """Tests for render() function.""" + + def test_oneline_template(self): + tpl = 'foo {{ key1 }} baz {{ key2 }}' + out = makesite.render(tpl, key1='bar', key2='qux') + self.assertEqual(out, 'foo bar baz qux') + + def test_multiline_template(self): + tpl = 'foo {{ key1 }}\nbaz {{ key1 }}' + out = makesite.render(tpl, key1='bar') + self.assertEqual(out, 'foo bar\nbaz bar') + + def test_repeated_key(self): + tpl = 'foo {{ key1 }} baz {{ key1 }}' + out = makesite.render(tpl, key1='bar') + self.assertEqual(out, 'foo bar baz bar') + + def test_multiline_placeholder(self): + tpl = 'foo {{\nkey1\n}} baz {{\nkey2\n}}' + out = makesite.render(tpl, key1='bar', key2='qux') + self.assertEqual(out, 'foo bar baz qux') -- cgit v1.2.3