diff --git a/Makefile b/Makefile index 157ab43..4e0ca38 100644 --- a/Makefile +++ b/Makefile @@ -50,11 +50,13 @@ node_modules: test: lint spellcheck lint: + $(ENV)/nose2 --verbose $(NODE_BIN)/eslint 'theme/static/src/js/' $(NODE_BIN)/sass-lint -vqc .sass-lint.yml $(ENV)/flake8 $(BASEDIR)/plugins/ $(FLAKE8_IGNORE) $(ENV)/flake8 $(BASEDIR)/scripts/ $(FLAKE8_IGNORE) $(ENV)/flake8 $(BASEDIR)/config/ $(FLAKE8_IGNORE) + $(ENV)/flake8 $(BASEDIR)/tests/ $(FLAKE8_IGNORE) spellcheck: $(NODE_BIN)/mdspell --en-gb -ranx theme/templates/**/*.* theme/templates/*.* diff --git a/plugins/links.py b/plugins/links.py index b207577..9a57055 100644 --- a/plugins/links.py +++ b/plugins/links.py @@ -10,6 +10,7 @@ def accounts(): links = {} for key, (site, user, url, icon) in settings.accounts.items(): links[key] = DotDictionary({ + 'key': key, 'site': site, 'username': user, 'url': url.format(user), diff --git a/requirements.txt b/requirements.txt index 2fad8f6..4008c60 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,12 @@ flake8==2.5.0 fontawesome_markdown==0.2.5 +git+https://github.com/ryneeverett/python-markdown-comments.git gitpython==2.0.7 iso8601==0.1.11 markdown==2.6.6 -git+https://github.com/ryneeverett/python-markdown-comments.git -pelican==3.6.3 +nose2==0.6.5 pelican-minify==0.9 +pelican==3.6.3 pyembed-markdown==1.1.0 python-resize-image==1.1.3 pyyaml==3.12 diff --git a/tests/TestWrapper.py b/tests/TestWrapper.py new file mode 100644 index 0000000..59854d9 --- /dev/null +++ b/tests/TestWrapper.py @@ -0,0 +1,33 @@ +import unittest +import os.path +from bs4 import BeautifulSoup + + +class TestClient: + output_path = os.path.realpath('./output') + + def get(self, path): + file_path = self.build_path(path) + content = "".join(open(file_path).readlines()) + if path.endswith('html'): + content = BeautifulSoup(content, 'html.parser') + return content + + def build_path(self, path): + if path.startswith('/'): + path = path[1:] + return os.path.join(self.output_path, path) + + def exists(self, path): + try: + open(self.build_path(path)).close() + return True + except FileNotFoundError: + return False + + +class TestCase(unittest.TestCase): + client = TestClient() + + def assertTitle(self, content, title): + self.assertIn(title, content.title.string) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 0000000..718be4d --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,18 @@ +from tests.TestWrapper import TestCase +from bs4 import BeautifulSoup + + +class TestClientTestCase(TestCase): + def test_client_fails(self): + with self.assertRaises(FileNotFoundError): + self.client.get('foo.bar') + + def test_client_gets_data(self): + content = self.client.get('index.html') + self.assertIsInstance(content, BeautifulSoup) + + def test_file_exists(self): + self.assertTrue(self.client.exists('index.html')) + + def test_file_doesnt_exist(self): + self.assertFalse(self.client.exists('foo.bar')) diff --git a/tests/tests_core.py b/tests/tests_core.py new file mode 100644 index 0000000..c607ea5 --- /dev/null +++ b/tests/tests_core.py @@ -0,0 +1,48 @@ +from tests.TestWrapper import TestCase +from config import settings + + +class CorePagesTestCase(TestCase): + def test_has_index(self): + content = self.client.get('index.html') + self.assertTitle(content, 'Homepage') + + def test_has_robots(self): + content = self.client.get('robots.txt') + self.assertIn('Allow: /', content) + + def test_has_sitemap(self): + content = self.client.get('sitemap.xml') + self.assertIn(settings.url, content) + + def test_has_atom_feed(self): + content = self.client.get('feed.atom') + self.assertIn(settings.url, content) + + def test_has_404_page(self): + content = self.client.get('.404.html') + self.assertTitle(content, '404') + + def test_has_scripts(self): + content = self.client.get('index.html') + for script in content.find_all('script'): + self.client.exists(script.attrs['src']) + + def test_has_stylesheet(self): + content = self.client.get('index.html') + for script in content.find_all('link', rel='stylesheet'): + self.assertTrue(self.client.exists(script.attrs['href'])) + + def test_has_link_icons(self): + content = self.client.get('index.html') + for script in content.find_all('link', rel='icon'): + self.assertTrue(self.client.exists(script.attrs['href'])) + for script in content.find_all('link', rel='apple-touch-icon-precomposed'): + self.assertTrue(self.client.exists(script.attrs['href'])) + + def test_footer_links(self): + content = self.client.get('index.html') + footer = content.footer + for link in footer.find('p', class_="social").find_all('a'): + self.assertIn(link.attrs['alt'], settings.footer_accounts) + self.assertIn("fa fa-", str(list(link.children)[0])) diff --git a/tests/tests_homepage.py b/tests/tests_homepage.py new file mode 100644 index 0000000..174de86 --- /dev/null +++ b/tests/tests_homepage.py @@ -0,0 +1,12 @@ +from tests.TestWrapper import TestCase +import os.path + + +class HomepageTestCase(TestCase): + def test_blog_links(self): + content = self.client.get('index.html') + blogs = content.find('section', id='blog').find_all('div', class_="col-xs-12") + self.assertTrue(len(blogs) <= 4) + for post in content.find('section', id='blog').find_all('div', class_="col-xs-12"): + url = os.path.join(post.find('a').attrs['href'], 'index.html') + self.assertTrue(self.client.exists(url)) diff --git a/theme/templates/extras/footer.html b/theme/templates/extras/footer.html index b6e5b21..7bbdfa1 100644 --- a/theme/templates/extras/footer.html +++ b/theme/templates/extras/footer.html @@ -4,7 +4,7 @@