diff --git a/.gitignore b/.gitignore index 8af1aeb09..d45f260f7 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,7 @@ quokka/project_template/static_build/* quokka/project_template/modules/* !quokka/project_template/modules/README.md +.venv venv old_* .envrc @@ -89,3 +90,4 @@ docs/book .eggs README.rst +/nbproject/private/ diff --git a/.travis.yml b/.travis.yml index 2055c7377..bae1aa88d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ install: - make install script: make test after_success: + - codecov - coveralls notifications: slack: quokkaproject:pjF8y81mqwXxQRtf5sGz5zqr diff --git a/Makefile b/Makefile index 57aa9b1ba..5c6529f5c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: docs test pep8 clean install build publish tree create_env devserver pandoc adduser test: pep8 - QUOKKA_MODE=test py.test --cov=quokka -l --tb=short --maxfail=1 tests/ + QUOKKA_MODE=test pytest -vvv --cov=quokka -l --tb=short --maxfail=1 tests/ pep8: @flake8 quokka --ignore=F403 --exclude=migrations diff --git a/quokka/admin/widgets.py b/quokka/admin/widgets.py index b03e2bddc..7cafb3e89 100644 --- a/quokka/admin/widgets.py +++ b/quokka/admin/widgets.py @@ -1,7 +1,7 @@ from flask import current_app -from quokka.core.template import render_template from wtforms.widgets import TextArea, TextInput +from quokka.core.content.views import render_template class TextEditor(TextArea): diff --git a/quokka/admin/wtforms_html5.py b/quokka/admin/wtforms_html5.py index ccc3a1c09..85e01933f 100644 --- a/quokka/admin/wtforms_html5.py +++ b/quokka/admin/wtforms_html5.py @@ -195,7 +195,7 @@ def set_title(field, render_kw=None): """ if render_kw is None: render_kw = {} - if 'title' not in render_kw and getattr(field, 'description'): + if 'title' not in render_kw and getattr(field, 'description', None): render_kw['title'] = '{}'.format(field.description) return render_kw diff --git a/quokka/core/content/models.py b/quokka/core/content/models.py index 6d2fcc4d9..d3bf4e692 100644 --- a/quokka/core/content/models.py +++ b/quokka/core/content/models.py @@ -230,13 +230,13 @@ def metadata(self): # TODO: get metadata from database # TODO: implement libratar/gravatar # return { - # 'cover': 'foo', - # 'author_gravatar': 'http://i.pravatar.cc/300', - # 'about_author': 'About Author', - # 'translations': ['en'], - # 'og_image': 'foo', - # 'series': 'aa', - # 'asides': 'aaa' + # 'cover': 'foo', + # 'author_gravatar': 'http://i.pravatar.cc/300', + # 'about_author': 'About Author', + # 'translations': ['en'], + # 'og_image': 'foo', + # 'series': 'aa', + # 'asides': 'aaa' # } data = {} data.update(custom_var_dict(self.data.get('custom_vars'))) diff --git a/quokka/core/content/utils.py b/quokka/core/content/utils.py index 57aaef312..237c720ff 100644 --- a/quokka/core/content/utils.py +++ b/quokka/core/content/utils.py @@ -10,9 +10,10 @@ def url_for_content(content, include_ext=True): else: data = content + data_category_slug = data.get('category_slug') + data_slugify_category = slugify_category(data.get('category') or '') category_slug = ( - data.get('category_slug') or - slugify_category(data.get('category') or '') + data_category_slug or data_slugify_category ) slug = data.get('slug') or slugify(data.get('title')) diff --git a/quokka/core/content/views.py b/quokka/core/content/views.py index 74c72d288..479bdb378 100644 --- a/quokka/core/content/views.py +++ b/quokka/core/content/views.py @@ -259,6 +259,9 @@ def render_rss(self, content_type, templates, **context): if content.date > rss_pubdate: rss_pubdate = content.date + content_title = content.title.encode('utf-8') + content_url = content.url.encode('utf-8') + rss.items.append( pyrss.RSSItem( title=content.title, @@ -267,8 +270,7 @@ def render_rss(self, content_type, templates, **context): author=str(content.author), categories=[str(content.tags)], guid=hashlib.sha1( - content.title.encode('utf-8') + - content.url.encode('utf-8') + content_title + content_url ).hexdigest(), pubDate=content.date, ) diff --git a/quokka/core/db.py b/quokka/core/db.py index 431c55aea..afc09ad77 100644 --- a/quokka/core/db.py +++ b/quokka/core/db.py @@ -183,17 +183,14 @@ def page_set(self, *args, **kwargs): return self.content_set(*args, **kwargs) def block_set(self, *args, **kwargs): - kwargs.setdefault( - 'sort', - self.app.theme_context.get( - 'BLOCK_ORDER_BY', [('title', -1)] - ) - ) - if not args: - args = [{'content_type': 'block'}] - elif isinstance(args[0], dict): - args[0]['content_type'] = 'block' - return self.content_set(*args, **kwargs) + kwargs.setdefault('sort', self.app.theme_context.get( + 'BLOCK_ORDER_BY', [('title', -1)] + )) + if not args: + args = [{'content_type': 'block'}] + elif isinstance(args[0], dict): + args[0]['content_type'] = 'block' + return self.content_set(*args, **kwargs) def select(self, colname, *args, **kwargs): return self.get_collection(colname).find(*args, **kwargs) diff --git a/quokka/core/views/sitemap.py b/quokka/core/views/sitemap.py index 871372817..e890a0d32 100644 --- a/quokka/core/views/sitemap.py +++ b/quokka/core/views/sitemap.py @@ -11,12 +11,13 @@ def get_contents(self): TODO: Should include extra paths, fixed paths config based paths, static paths """ + index = self.get_index() + cat = self.get_categories() + tags = self.get_tags() + authors = self.get_authors() + articles = self.get_articles_and_pages() return ( - self.get_index() + - self.get_categories() + - self.get_tags() + - self.get_authors() + - self.get_articles_and_pages() + index + cat + tags + authors + articles ) def get_index(self): diff --git a/quokka/utils/upload.py b/quokka/utils/upload.py index 251e1c50f..bc8042679 100644 --- a/quokka/utils/upload.py +++ b/quokka/utils/upload.py @@ -9,7 +9,7 @@ def dated_path(obj, file_data): try: - prefix = getattr(obj, 'model_name') + prefix = getattr(obj, 'model_name', None) except BaseException: prefix = "undefined" diff --git a/requirements-dev.txt b/requirements-dev.txt index ba32aa2f0..b3d737954 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,3 +12,7 @@ twine>=1.9.1 wheel>=0.30.0 flask>=1.0 logzero +pytest_mock +mock +pytest_django +pyyaml \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/admin/__init__.py b/tests/admin/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/admin/test__init__.py b/tests/admin/test__init__.py new file mode 100644 index 000000000..b26dd3bf9 --- /dev/null +++ b/tests/admin/test__init__.py @@ -0,0 +1,308 @@ +import import_string +import pytest +import mock +import quokka +from flask_admin import Admin +from quokka.admin.views import FileAdmin, IndexView, ModelView +from quokka.admin import create_admin, QuokkaAdmin, configure_admin +from quokka.core.app import QuokkaApp +from quokka.core.flask_dynaconf import configure_dynaconf + +################################################### +# pytest - Quokka - quokka/admin/test__init__.py # +################################################### +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_failed_param_app_none_err(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.create_admin(app=None) + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_failed_param_app_string_empty_err(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.create_admin(app="") + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_called_indexview_false(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + quokka.admin.create_admin(app=mock_Admin) + assert mock_IndexView.called is False + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_called_quokkaadmin_false(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + quokka.admin.create_admin(app=mock_Admin) + assert mock_QuokkaAdmin(app=mock_Admin).called is False + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_called_quokkaapp_is_instance_of(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + assert isinstance(appQk, QuokkaApp) == True + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_create_admin_called_quokkaadmin_is_not_none(mock_Admin, + mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + resp = quokka.admin.create_admin(app=appQk) + assert resp is not None + + +def test_create_admin_called_quokkaadmin_is_instance_resp_name_admin(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + resp = quokka.admin.create_admin(app=appQk) + assert resp.name == 'Admin' + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_admin_called_param_app_none_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_admin(app=None, admin=None) + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_admin_called_param_app_string_empty_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_admin(app="", admin=None) + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_admin_called_param_admin_none_assert_true(mock_Admin, + mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + quokka.admin.configure_admin(app=appQk, admin=None) + assert mock_create_admin.called is True + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_admin_called_param_admin_mock_quokka_admin_assert_false(mock_Admin, + mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + quokka.admin.configure_admin(app=appQk, admin=mock_QuokkaAdmin) + assert mock_create_admin.called is False + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_admin_called_param_admin_none_assert_is_not_none(mock_Admin, + mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + resp = quokka.admin.configure_admin(app=appQk, admin=None) + assert resp != None + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_admin_called_param_admin_none_assert_is_quokka_admin_instance( + mock_Admin, mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQkk = QuokkaApp('quokka') + configure_dynaconf(appQkk) + resp = quokka.admin.configure_admin(app=appQkk, admin=None) + assert resp.name == 'Quokka Admin' + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_file_admin_called_param_app_none_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_file_admin(app=None) + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_file_admin_called_param_app_string_empty_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_file_admin(app="") + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_file_admin_called_param_admin_none_assert_none(mock_Admin, + mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + assert quokka.admin.configure_file_admin(app=appQk) is None + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_extra_views_called_param_app_none_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_extra_views(app=None) + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +@mock.patch("quokka.admin.create_admin") +def test_configure_extra_views_called_param_app_string_empty_err(mock_create_admin, + mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + quokka.admin.configure_extra_views(app="") + assert "object has no attribute" in str(err.value) + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("quokka.admin.create_admin") +@mock.patch("flask_admin.Admin") +def test_configure_extra_views_called_param_admin_none_assert_none(mock_Admin, + mock_create_admin, mock_QuokkaAdmin, mock_IndexView): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + assert quokka.admin.configure_extra_views(app=appQk) is None + + +@mock.patch("quokka.admin.views.IndexView") +@mock.patch("quokka.admin.QuokkaAdmin") +@mock.patch("flask_admin.Admin") +def test_quokkaadmin_class_instance_error(mock_Admin, mock_QuokkaAdmin, mock_IndexView): + with pytest.raises(AttributeError) as err: + qa = QuokkaAdmin(Admin) + assert "type object 'Admin' has no attribute" in str(err.value) + + +def test_quokkaadmin_class_is_instance_of(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + assert isinstance(qa, QuokkaAdmin) == True + + +def test_quokkaadmin_class_instance_register_method(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + assert qa.name == "Admin" + + +def test_quokkaadmin_class_instance_add_icon_method_assert_endpoint(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + + qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest") + assert 'http://endpoint.pytest' in appQk.config.get('ADMIN_ICONS')[0] + + +def test_quokkaadmin_class_instance_add_icon_method_assert_icon(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + + qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest") + assert 'icon.png' in appQk.config.get('ADMIN_ICONS')[0] + + +def test_quokkaadmin_class_instance_add_icon_method_assert_text_pytest(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + + qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest") + assert 'text.pytest' in appQk.config.get('ADMIN_ICONS')[0] + + +def test_QuokkaAdmin_class_instance_add_icon_method_assert_add_content_format(): + appQk = QuokkaApp('quokka') + configure_dynaconf(appQk) + + with pytest.raises(TypeError) as err: + qa = QuokkaAdmin( + appQk, + index_view=IndexView(), + template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'), + base_template='admin/quokka/master.html' + ) + qa.add_content_format() + assert "takes 0 positional arguments but 1 was given" in str(err.value) + diff --git a/tests/admin/test_actions.py b/tests/admin/test_actions.py new file mode 100644 index 000000000..f0c51b130 --- /dev/null +++ b/tests/admin/test_actions.py @@ -0,0 +1,62 @@ +import pytest +import mock +import json +import random +from copy import deepcopy +from datetime import datetime +from flask import Response, current_app, flash, redirect, url_for, Markup +from flask_admin.actions import action +from quokka.utils.text import slugify +from quokka.admin.actions import PublishAction, CloneAction, UserProfileBlockAction, ExportAction +from quokka.core.app import QuokkaApp +from quokka.core.flask_dynaconf import configure_dynaconf + +################################################## +#pytest - Quokka - quokka/admin/test_actions.py # +################################################## +def test_publishaction_class_instance_of(): + pa = PublishAction() + assert isinstance(pa, PublishAction) == True + +def test_cloneaction_class_instance_of(): + ca = CloneAction() + assert isinstance(ca, CloneAction) == True + +def test_userprofileblockaction_class_instance_of(): + upba = UserProfileBlockAction() + assert isinstance(upba, UserProfileBlockAction) == True + +def test_exportaction_class_instance_of(): + ea = ExportAction() + assert isinstance(ea, ExportAction) == True + +def test_publishaction_class_def_action_toggle_publish_method_instance_error_outside_context(): + with pytest.raises(RuntimeError) as err: + pa = PublishAction() + pa.action_toggle_publish('12345') + assert "Working outside of application context." in str(err.value) + +def test_cloneaction_class_def_action_clone_item_method_instance_error_outside_context(): + with pytest.raises(RuntimeError) as err: + ca = CloneAction() + ca.action_clone_item('12345') + assert "Working outside of application context." in str(err.value) + +def test_userprofileblockaction_class_def_action_create_userprofile_method_instance_error_outside_context(): + with pytest.raises(RuntimeError) as err: + upba = UserProfileBlockAction() + upba.action_create_userprofile('12345') + assert "Working outside of application context." in str(err.value) + +def test_exportaction_class_def_export_to_json_method_instance_error_outside_context(): + with pytest.raises(AttributeError) as err: + ea = ExportAction() + ea.export_to_json('12345') + assert "object has no attribute" in str(err.value) + +def test_exportaction_class_def_export_to_csv_method_instance_error_outside_context(): + with pytest.raises(AttributeError) as err: + ea = ExportAction() + ea.export_to_csv('12345') + assert "object has no attribute" in str(err.value) + diff --git a/tests/admin/test_ajax.py b/tests/admin/test_ajax.py new file mode 100644 index 000000000..168c9a92b --- /dev/null +++ b/tests/admin/test_ajax.py @@ -0,0 +1,3 @@ +#module unused +def test_quokka_admin_ajax_unused(): + pass diff --git a/tests/admin/test_fields.py b/tests/admin/test_fields.py new file mode 100644 index 000000000..eeafd53ca --- /dev/null +++ b/tests/admin/test_fields.py @@ -0,0 +1,91 @@ +import pytest +import mock +from flask_admin import form +from flask_admin.form.upload import ImageUploadInput +from quokka.admin.fields import SmartSelect2Field, ThumbWidget, ThumbField, ContentImageField + +################################ +#pytest - fixtures - setUp(); # +################################ +ss2f = SmartSelect2Field() +tw = ThumbWidget() +tf = ThumbField() +cif = ContentImageField() + +################################################## +#pytest - Quokka - quokka/admin/test_fields.py # +################################################## +def test_smartselect2field_isinstance_of_false(): + assert isinstance(ss2f, SmartSelect2Field) == False + +def test_thumbwidget_isinstance_of(): + assert isinstance(tw, ThumbWidget) == True + +def test_thumbfield_isinstance_of_false(): + assert isinstance(tf, ThumbField) == False + +def test_contentimagefield_isinstance_of_false(): + assert isinstance(cif, ContentImageField) == False + +def test_smartselect2field_class_assert_creation_counter_property(): + assert ss2f.creation_counter == 7 + +def test_smartselect2field_class_assert_iter_choices_method(): + with pytest.raises(AttributeError) as err: + ss2f = SmartSelect2Field() + ss2f.iter_choices() + assert "object has no attribute" in str(err.value) + +def test_smartselect2field_class_assert_concrete_choices_method(): + with pytest.raises(AttributeError) as err: + ss2f = SmartSelect2Field() + ss2f.concrete_choices() + assert "object has no attribute" in str(err.value) + +def test_smartselect2field_class_assert_concrete_choices_property(): + with pytest.raises(AttributeError) as err: + ss2f = SmartSelect2Field() + ss2f.concrete_choices + assert "object has no attribute" in str(err.value) + +def test_smartselect2field_class_assert_choice_values_method(): + with pytest.raises(AttributeError) as err: + ss2f = SmartSelect2Field() + ss2f.choice_values() + assert "object has no attribute" in str(err.value) + +def test_smartselect2field_class_assert_choice_values_property(): + with pytest.raises(AttributeError) as err: + ss2f = SmartSelect2Field() + ss2f.choice_values + assert "object has no attribute" in str(err.value) + +def test_smartselect2field_class_assert_pre_validate_method(): + with pytest.raises(AttributeError) as err: + ss2f.pre_validate() + assert "object has no attribute" in str(err.value) + +def test_thumbwidget_data_template_property(): + assert tw.data_template == '
java-debugger-code
\n'
+
+def test_class_highlightmixin():
+ with pytest.raises(AttributeError) as err:
+ high = HighlightMixin()
+ block = high.block_code(text="java-debugger-code", lang="pt")
+ assert "HighlightMixin object has no attribute options" in str(err.value)
+
diff --git a/tests/core/content/test_utils.py b/tests/core/content/test_utils.py
new file mode 100644
index 000000000..a9368fb66
--- /dev/null
+++ b/tests/core/content/test_utils.py
@@ -0,0 +1,41 @@
+import time
+import pytest
+import mock
+import click
+import datetime
+
+from quokka.utils.text import (
+ slugify_category, slugify
+)
+from flask import current_app as app
+from quokka.core.content.utils import (
+ url_for_content,
+ url_for_category,
+ strftime
+)
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+param_dict = {"java":"debugger", "slug":"slug-mock", "title":"title-mock"}
+
+def get_year_format():
+ date_timestamp = datetime.datetime.now()
+ return date_timestamp.year.__str__()
+
+
+#######################################################
+#pytest - Quokka - tests/core/content/test_utils.py #
+#######################################################
+def test_url_for_content():
+ with pytest.raises(RuntimeError) as err:
+ url = url_for_content(content=param_dict)
+ assert "Working outside of application context." in str(err.value)
+
+def test_url_for_category():
+ url = url_for_category("java-categoty-mock")
+ assert url == "java-categoty-mock"
+
+def test_strftime():
+ assert strftime(time, "%Y") == get_year_format()
+
diff --git a/tests/core/content/test_views.py b/tests/core/content/test_views.py
new file mode 100644
index 000000000..4685afcba
--- /dev/null
+++ b/tests/core/content/test_views.py
@@ -0,0 +1,156 @@
+import pytest
+import mock
+import click
+import hashlib
+import PyRSS2Gen as pyrss
+from datetime import (
+ datetime, timedelta
+)
+from flask import (
+ current_app as app, render_template,
+ abort, request
+)
+from flask.views import MethodView
+from flask_simplelogin import is_logged_in
+from quokka.utils.atom import AtomFeed
+from quokka.core.content.models import (
+ make_model, make_paginator,
+ Category, Tag, Author
+)
+from quokka.utils.text import (
+ slugify_category, normalize_var,
+ slugify, cdata, make_external_url
+)
+from quokka.core.content.views import (
+ BaseView, ArticleListView,
+ CategoryListView, TagListView,
+ AuthorListView, DetailView,
+ PreviewView
+)
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+baseview = BaseView()
+articlelistview = ArticleListView()
+categorylistview = CategoryListView()
+taglistview = TagListView()
+authorlistview = AuthorListView()
+detailview = DetailView()
+previewview = PreviewView()
+
+
+#######################################################
+#pytest - Quokka - tests/core/content/test_views.py #
+#######################################################
+def test_class_baseview_is_subclass():
+ assert issubclass(BaseView, MethodView) == True
+
+def test_class_baseview_is_instance():
+ assert isinstance(baseview, BaseView) == True
+
+def test_class_baseview_decorators():
+ assert baseview.decorators == ()
+
+def test_class_baseview_methods():
+ assert baseview.methods is None
+
+def test_class_baseview_provide_automatic_options_property():
+ assert baseview.provide_automatic_options is None
+
+def test_class_articlelistview_is_subclass():
+ assert issubclass(ArticleListView, BaseView) == True
+
+def test_class_articlelistview_is_instance():
+ assert isinstance(articlelistview, ArticleListView) == True
+
+def test_class_articlelistview_decorators_property():
+ assert articlelistview.decorators == ()
+
+def test_class_articlelistview_methods_property():
+ assert articlelistview.methods == {'GET'}
+
+def test_class_articlelistview_provide_automatic_options_property():
+ assert articlelistview.provide_automatic_options is None
+
+def test_class_categorylistview_is_subclass():
+ assert issubclass(CategoryListView, BaseView) == True
+
+def test_class_categorylistview_is_instance():
+ assert isinstance(categorylistview, CategoryListView) == True
+
+def test_class_categorylistview_is_instance():
+ assert categorylistview.decorators == ()
+
+def test_class_categorylistview_methods_property():
+ assert categorylistview.methods == {'GET'}
+
+def test_class_categorylistview_provide_automatic_options():
+ assert categorylistview.provide_automatic_options is None
+
+def test_class_taglistview_is_subclass():
+ assert issubclass(TagListView, BaseView) == True
+
+def test_isinstance_TagListView_is_instance():
+ assert isinstance(taglistview, TagListView) == True
+
+def test_class_taglistview_decorators():
+ assert taglistview.decorators == ()
+
+def test_class_taglistview_methods_property():
+ assert taglistview.methods == {'GET'}
+
+def test_class_taglistview_provide_automatic_options():
+ assert taglistview.provide_automatic_options is None
+
+def test_class_authorlistview_is_subclass():
+ assert issubclass(AuthorListView, BaseView) == True
+
+def test_class_authorlistview_is_instance():
+ assert isinstance(authorlistview, AuthorListView) == True
+
+def test_class_authorlistview_decorators():
+ assert authorlistview.decorators == ()
+
+def test_class_authorlistview_methods_property():
+ assert authorlistview.methods == {'GET'}
+
+def test_class_authorlistview_provide_automatic_options():
+ assert authorlistview.provide_automatic_options is None
+
+def test_class_detailview_is_subclass():
+ assert issubclass(DetailView, BaseView) == True
+
+def test_class_detailview_is_instance():
+ assert isinstance(detailview, DetailView) == True
+
+def test_class_detailview_decorators():
+ assert detailview.decorators == ()
+
+def test_class_detailview_methods_property():
+ assert detailview.methods == {'GET'}
+
+def test_class_detailview_provide_automatic_options():
+ assert detailview.provide_automatic_options is None
+
+def test_class_detailview_is_preview():
+ assert detailview.is_preview is False
+
+def test_class_previewview_is_subclass():
+ assert issubclass(PreviewView, DetailView) == True
+
+def test_class_previewview_is_instance():
+ assert isinstance(previewview, PreviewView) == True
+
+def test_class_previewview_decorators():
+ assert previewview.decorators == ()
+
+def test_class_previewview_methods_property():
+ assert previewview.methods == {'GET'}
+
+def test_class_previewview_provide_automatic_options():
+ assert previewview.provide_automatic_options is None
+
+def test_class_previewview_is_preview():
+ assert previewview.is_preview is True
diff --git a/tests/core/test__init__.py b/tests/core/test__init__.py
new file mode 100644
index 000000000..c9c8979af
--- /dev/null
+++ b/tests/core/test__init__.py
@@ -0,0 +1,253 @@
+import mock
+import pytest
+from inspect import getargspec
+import sys
+import import_string
+from quokka import create_app
+from quokka.core.app import QuokkaModule
+from quokka.core.content.admin import AdminArticlesView, AdminPagesView, AdminBlocksView
+from quokka.core.content.views import (
+ DetailView, PreviewView, ArticleListView, CategoryListView, TagListView,
+ AuthorListView
+)
+from quokka.core.content.utils import url_for_content, strftime
+from quokka.core.content import configure
+from quokka import create_app
+from quokka.core.content import configure
+from quokka.core import configure_extension, configure_extensions
+
+################################################################################
+#pytest - fixtures #
+################################################################################
+app = create_app(test=True)
+ce = configure_extensions(app)
+
+#################################################################################
+#pytest - Quokka - test_core__init__.py #
+#################################################################################
+def test_app_equals_ce_instance():
+ assert app == ce
+
+def test_ce_equals_app_instance():
+ assert ce == app
+
+def test_ce_admin():
+ with pytest.raises(KeyError) as err:
+ ce.admin
+ assert "admin" in str(err.value)
+
+def test_ce_before_requests_funcs():
+ assert ce.before_request_funcs == {}
+
+def test_ce_blueprints():
+ assert ce.blueprints == {}
+
+def test_ce_db():
+ with pytest.raises(KeyError) as err:
+ ce.db
+ assert "db" in str(err.value)
+
+def test_ce_debug():
+ assert ce.debug == False
+
+def test_ce_default_config():
+ assert ce.default_config['TEMPLATES_AUTO_RELOAD'] == None
+ assert ce.default_config['JSONIFY_MIMETYPE'] == 'application/json'
+ assert ce.default_config['PROPAGATE_EXCEPTIONS'] == None
+ assert ce.default_config['TESTING'] == False
+ assert ce.default_config['DEBUG'] == None
+ assert ce.default_config['ENV'] == None
+ assert ce.default_config['MAX_COOKIE_SIZE'] == 4093
+
+def test_ce_env():
+ assert ce.env == "production"
+
+def test_ce_error_handler_spec():
+ assert ce.error_handler_spec == {}
+
+def test_ce_extensions():
+ assert ce.extensions == {}
+
+def test_ce_got_first_request():
+ assert ce.got_first_request == False
+
+def test_ce_has_static_folder():
+ assert ce.has_static_folder == True
+
+def test_ce_import_name():
+ assert ce.import_name == "quokka"
+
+def test_ce_jinja_properties_env():
+ assert ce.jinja_env.auto_reload == False
+ assert ce.jinja_env.block_end_string == "%}"
+ assert ce.jinja_env.block_start_string == "{%"
+ assert ce.jinja_env.bytecode_cache == None
+ assert ce.jinja_env.comment_end_string == "#}"
+ assert ce.jinja_env.comment_start_string == "{#"
+ assert ce.jinja_env.enable_async == False
+ assert ce.jinja_env.exception_formatter == None
+ assert ce.jinja_env.exception_handler == None
+
+def test_ce_jinja_env_extensions():
+ assert ce.jinja_env.extensions['jinja2.ext.AutoEscapeExtension'] != ""
+ assert ce.jinja_env.extensions['jinja2.ext.WithExtension'] != ""
+
+def test_ce_jinja_env_filters_not_empty():
+ assert ce.jinja_env.filters['abs'] != ""
+ assert ce.jinja_env.filters['attr'] != ""
+ assert ce.jinja_env.filters['batch'] != ""
+ assert ce.jinja_env.filters['capitalize'] != ""
+ assert ce.jinja_env.filters['center'] != ""
+ assert ce.jinja_env.filters['count'] != ""
+ assert ce.jinja_env.filters['d'] != ""
+ assert ce.jinja_env.filters['default'] != ""
+ assert ce.jinja_env.filters['dictsort'] != ""
+ assert ce.jinja_env.filters['e'] != ""
+ assert ce.jinja_env.filters['escape'] != ""
+ assert ce.jinja_env.filters['filesizeformat'] != ""
+ assert ce.jinja_env.filters['first'] != ""
+ assert ce.jinja_env.filters['float'] != ""
+ assert ce.jinja_env.filters['forceescape'] != ""
+ assert ce.jinja_env.filters['format'] != ""
+ assert ce.jinja_env.filters['groupby'] != ""
+ assert ce.jinja_env.filters['indent'] != ""
+ assert ce.jinja_env.filters['int'] != ""
+ assert ce.jinja_env.filters['lower'] != ""
+ assert ce.jinja_env.filters['map'] != ""
+ assert ce.jinja_env.filters['min'] != ""
+ assert ce.jinja_env.filters['max'] != ""
+ assert ce.jinja_env.filters['pprint'] != ""
+ assert ce.jinja_env.filters['random'] != ""
+ assert ce.jinja_env.filters['reject'] != ""
+ assert ce.jinja_env.filters['rejectattr'] != ""
+ assert ce.jinja_env.filters['replace'] != ""
+ assert ce.jinja_env.filters['reverse'] != ""
+ assert ce.jinja_env.filters['round'] != ""
+ assert ce.jinja_env.filters['safe'] != ""
+ assert ce.jinja_env.filters['select'] != ""
+ assert ce.jinja_env.filters['selectattr'] != ""
+ assert ce.jinja_env.filters['slice'] != ""
+ assert ce.jinja_env.filters['sort'] != ""
+ assert ce.jinja_env.filters['string'] != ""
+ assert ce.jinja_env.filters['striptags'] != ""
+ assert ce.jinja_env.filters['sum'] != ""
+ assert ce.jinja_env.filters['title'] != ""
+ assert ce.jinja_env.filters['trim'] != ""
+ assert ce.jinja_env.filters['abs'] != ""
+ assert ce.jinja_env.filters['wordwrap'] != ""
+
+def test_ce_jinja_loader():
+ assert ce.jinja_loader.encoding == 'utf-8'
+ assert ce.jinja_loader.followlinks == False
+ assert ce.jinja_loader.has_source_access == True
+ assert ce.jinja_loader.searchpath != ""
+
+def test_ce_jinja_options():
+ assert ce.jinja_options['extensions'][0] == 'jinja2.ext.autoescape'
+ assert ce.jinja_options['extensions'][1] == 'jinja2.ext.with_'
+
+def test_ce_logger():
+ assert ce.logger.disabled == False
+ assert ce.logger.level == 0
+ assert ce.logger.manager.disable == 0
+ assert ce.logger.manager.emittedNoHandlerWarning == False
+ assert ce.logger.manager.loggerClass == None
+ assert ce.logger.manager.root.name == 'root'
+
+def test_ce_name():
+ assert ce.name == "quokka"
+
+def test_ce_permanent_session_lifetime():
+ assert ce.permanent_session_lifetime.days == 31
+ assert ce.permanent_session_lifetime.max.days == 999999999
+ assert ce.permanent_session_lifetime.microseconds == 0
+ assert ce.permanent_session_lifetime.min.days == -999999999
+ assert ce.permanent_session_lifetime.seconds == 0
+
+def test_ce_preserve_context_on_exception():
+ assert ce.preserve_context_on_exception == False
+
+def test_ce_propagate_exceptions():
+ assert ce.propagate_exceptions == True
+
+def test_ce_root_path():
+ assert ce.root_path != ""
+
+def test_ce_secret_key():
+ assert ce.secret_key == None
+
+def test_ce_send_file_max_age_default():
+ assert ce.send_file_max_age_default.days == 0
+ assert ce.send_file_max_age_default.microseconds == 0
+ assert ce.send_file_max_age_default.seconds == 43200
+
+def test_ce_session_cookie_name():
+ assert ce.session_cookie_name == "session"
+
+def test_ce_session_interface():
+ assert ce.session_interface.key_derivation == "hmac"
+ assert ce.session_interface.pickle_based == False
+ assert ce.session_interface.salt == "cookie-session"
+
+def test_ce_shell_context_processors():
+ assert ce.shell_context_processors == []
+
+def test_ce_static_folder():
+ assert ce.static_folder != ""
+
+def test_ce_static_url_path():
+ assert ce.static_url_path == "/static"
+
+def test_ce_subdomain_matching():
+ assert ce.subdomain_matching == False
+
+def test_ce_teardown_appcontext_funcs():
+ assert ce.teardown_appcontext_funcs == []
+
+def test_ce_teardown_request_funcs():
+ assert ce.teardown_request_funcs == {}
+
+def test_ce_template_folder():
+ assert ce.template_folder == "templates"
+
+def test_ce_templates_auto_reload():
+ assert ce.templates_auto_reload == False
+
+def test_ce_test_cli_runner_class():
+ assert ce.test_cli_runner_class == None
+
+def test_ce_test_client_class():
+ assert ce.test_client_class == None
+
+def test_ce_testing():
+ assert ce.testing == True
+
+def test_ce_theme_context():
+ assert ce.theme_context['DEFAULT_LANG'] == None
+ assert ce.theme_context['PAGES'] == []
+ assert ce.theme_context['tags'] == []
+ assert ce.theme_context['articles'] == []
+ assert ce.theme_context['categories'] == []
+ assert ce.theme_context['tag_cloud'] == []
+ assert ce.theme_context['USE_LESS'] == False
+
+def test_ce_url_build_error_handlers():
+ assert ce.url_build_error_handlers == []
+
+def test_ce_url_default_functions():
+ assert ce.url_default_functions == {}
+
+def test_ce_url_map():
+ assert ce.url_map.charset == 'utf-8'
+ assert ce.url_map.default_subdomain == ''
+ assert ce.url_map.encoding_errors == 'replace'
+ assert ce.url_map.host_matching == False
+ assert ce.url_map.redirect_defaults == True
+ assert ce.url_map.sort_key == None
+ assert ce.url_map.sort_parameters == False
+ assert ce.url_map.strict_slashes == True
+
+def test_ce_use_x_sendfile():
+ assert ce.use_x_sendfile == False
+
+
diff --git a/tests/core/test_app.py b/tests/core/test_app.py
new file mode 100644
index 000000000..f533535fc
--- /dev/null
+++ b/tests/core/test_app.py
@@ -0,0 +1,165 @@
+import mock
+import click
+import pytest
+import quokka
+from flask_admin import Admin
+from quokka.admin.views import FileAdmin, IndexView, ModelView
+from quokka.admin import create_admin, QuokkaAdmin, configure_admin
+from quokka.core.app import QuokkaApp
+from quokka.core.flask_dynaconf import configure_dynaconf
+from flask import Blueprint, Flask
+from flask.helpers import _endpoint_from_view_func
+from quokka.core.app import QuokkaApp, QuokkaModule
+
+
+################################################################################
+#pytest - fixtures #
+################################################################################
+appQk = QuokkaApp('quokka')
+configure_dynaconf(appQk)
+module = QuokkaModule(__name__)
+
+
+#################################################################################
+#pytest - Quokka - tests/core/test_app.py #
+#################################################################################
+def test_class_quokkamodule_deferred_functions_property():
+ assert module.deferred_functions == []
+
+def test_class_quokkamodule_has_static_folder_is_False():
+ assert module.has_static_folder == False
+
+def test_class_quokkamodule_json_decoder():
+ assert module.json_decoder == None
+
+def test_class_quokkamodule_root_path_property():
+ assert module.root_path != ""
+
+def test_class_quokkamodule_has_static_folder():
+ assert module.static_folder == None
+
+def test_class_quokkamodule_url_path_property():
+ assert module.static_url_path == None
+
+def test_class_quokkamodule_subdomain_property():
+ assert module.subdomain == None
+
+def test_class_quokkamodule_template_folder_property():
+ assert module.template_folder == 'templates'
+
+def test_class_quokkamodule_url_fix_property():
+ assert module.url_prefix == None
+
+def test_class_quokkamodule_url_values_defaults_property():
+ assert module.url_values_defaults == {}
+
+def test_class_quokkamodule_warn_on_modifications_property():
+ assert module.warn_on_modifications == False
+
+def test_quokkaapp_class_is_instance_of():
+ configure_dynaconf(appQk)
+
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+ assert isinstance(qa, QuokkaAdmin) == True
+
+
+def test_quokkaapp_class_instance_register_method():
+ appQk = QuokkaApp('quokka')
+ configure_dynaconf(appQk)
+
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+ assert qa.name == "Admin"
+
+
+def test_quokkaapp_class_instance_add_icon_method_assert_endpoint():
+ appQk = QuokkaApp('quokka')
+ configure_dynaconf(appQk)
+
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+
+ qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest")
+ assert 'http://endpoint.pytest' in appQk.config.get('ADMIN_ICONS')[0]
+
+
+def test_quokkaapp_class_instance_add_icon_method_assert_icon():
+ appQk = QuokkaApp('quokka')
+ configure_dynaconf(appQk)
+
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+
+ qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest")
+ assert 'icon.png' in appQk.config.get('ADMIN_ICONS')[0]
+
+
+def test_quokkaapp_class_instance_add_icon_method_assert_text_pytest():
+ appQk = QuokkaApp('quokka')
+ configure_dynaconf(appQk)
+
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+
+ qa.add_icon("http://endpoint.pytest", "icon.png", "text.pytest")
+ assert 'text.pytest' in appQk.config.get('ADMIN_ICONS')[0]
+
+
+def test_quokkaapp_class_instance_add_icon_method_assert_add_content_format():
+ appQk = QuokkaApp('quokka')
+ configure_dynaconf(appQk)
+
+ with pytest.raises(TypeError) as err:
+ qa = QuokkaAdmin(
+ appQk,
+ index_view=IndexView(),
+ template_mode=appQk.config.get('FLASK_ADMIN_TEMPLATE_MODE'),
+ base_template='admin/quokka/master.html'
+ )
+ qa.add_content_format()
+ assert "takes 0 positional arguments but 1 was given" in str(err.value)
+
+def test_quokkaapp_class_blueprint_property():
+ assert appQk.blueprints != {}
+
+def test_quokkaapp_class_debug_property():
+ assert appQk.debug == False
+
+def test_quokkaapp_class_env_property():
+ assert appQk.env == 'production'
+
+def test_quokkaapp_class_extensions_property():
+ assert appQk.extensions != {}
+
+def test_quokkaapp_class_got_first_request():
+ assert appQk.got_first_request == False
+
+def test_quokkaapp_class_get_name_property():
+ assert appQk.name == 'quokka'
+
+def test_quokkaapp_class_has_static_folder_property():
+ assert appQk.has_static_folder == True
+
+
+
diff --git a/tests/core/test_auth.py b/tests/core/test_auth.py
new file mode 100644
index 000000000..0934f1e33
--- /dev/null
+++ b/tests/core/test_auth.py
@@ -0,0 +1,54 @@
+import pytest
+import mock
+import click
+import getpass
+from flask import (
+ current_app, url_for, Markup
+)
+from flask_htmlbuilder.htmlbuilder import html
+from quokka.admin.actions import (
+ UserProfileBlockAction
+)
+from quokka.admin.views import (
+ ModelView
+)
+from quokka.admin.forms import (
+ Form, fields,
+ ValidationError, validators
+)
+from quokka.utils.text import (
+ slugify
+)
+from werkzeug.security import (
+ check_password_hash,
+ generate_password_hash
+)
+from flask_simplelogin import (
+ SimpleLogin, get_username
+)
+from quokka.core.auth import (
+ create_user, UserForm,
+ format_profile, UserView,
+ validate_login, configure,
+ configure_user_admin, get_current_user
+)
+
+################################################################################
+#pytest - fixtures #
+################################################################################
+param_data = {'username': 'mock-user', 'password':'mock-pass'}
+
+
+#################################################################################
+#pytest - Quokka - tests/core/test_app.py #
+#################################################################################
+def test_create_user():
+ with pytest.raises(ValueError) as err:
+ debugger = create_user(data=param_data)
+ assert "username and password are required." in str(err.value)
+
+def test_class_UserForm():
+ with pytest.raises(RuntimeError) as err:
+ userform = UserForm()
+ assert "Working outside of application context." in str(err.value)
+
diff --git a/tests/core/test_blueprints.py b/tests/core/test_blueprints.py
new file mode 100644
index 000000000..f44efb174
--- /dev/null
+++ b/tests/core/test_blueprints.py
@@ -0,0 +1,23 @@
+import pytest
+import mock
+import click
+import importlib
+import os
+from quokka.core.commands_collector import (
+ CommandsCollector
+)
+from quokka.core.blueprints import (
+ load_from_folder,
+ get_blueprint_commands,
+ blueprint_commands
+)
+
+def test_load_from_folder():
+ pass
+
+def test_get_blueprint_commands():
+ pass
+
+def test_blueprint_commands():
+ pass
+
diff --git a/tests/core/test_commands_collector.py b/tests/core/test_commands_collector.py
new file mode 100644
index 000000000..edc8fadef
--- /dev/null
+++ b/tests/core/test_commands_collector.py
@@ -0,0 +1,71 @@
+import mock
+import click
+import importlib
+import os
+import sys
+import click
+from quokka.core.commands_collector import CommandsCollector
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+command_collector = CommandsCollector(modules_path="quokka/", base_module_name="quokka")
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_class_commandscollector_add_help_option():
+ assert command_collector.add_help_option == True
+
+def test_class_commandscollector_allow_extra_args():
+ assert command_collector.allow_extra_args == True
+
+def test_class_commandscollector_allow_interspersed_args():
+ assert command_collector.allow_interspersed_args == False
+
+def test_class_commandscollector_base_module_name():
+ assert command_collector.base_module_name == 'quokka'
+
+def test_class_commandscollector_callback():
+ assert command_collector.callback is None
+
+def test_class_commandscollector_chain():
+ assert command_collector.chain == False
+
+def test_class_commandscollector_context_settings():
+ assert command_collector.context_settings == {}
+
+def test_class_commandscollector_epilog():
+ assert command_collector.epilog is None
+
+def test_class_commandscollector_help():
+ assert command_collector.help is None
+
+def test_class_commandscollector_ignore_unknow_options():
+ assert command_collector.ignore_unknown_options == False
+
+def test_class_commandscollector_invoke_without_command():
+ assert command_collector.invoke_without_command == False
+
+def test_class_commandscollector_modules_path():
+ assert command_collector.modules_path == 'quokka/'
+
+def test_class_commandscollector_name():
+ assert command_collector.name is None
+
+def test_class_commandscollector_no_args_is_help():
+ assert command_collector.no_args_is_help == True
+
+def test_class_commandscollector_options_metavar():
+ assert command_collector.options_metavar == '[OPTIONS]'
+
+def test_class_commandscollector_params():
+ assert command_collector.params == []
+
+def test_class_commandscollector_short_help():
+ assert command_collector.short_help is None
+
+def test_class_commandscollector_subcommand_metavar():
+ assert command_collector.subcommand_metavar == 'COMMAND [ARGS]...'
diff --git a/tests/core/test_context_processors.py b/tests/core/test_context_processors.py
new file mode 100644
index 000000000..148faad00
--- /dev/null
+++ b/tests/core/test_context_processors.py
@@ -0,0 +1,22 @@
+import pytest
+import mock
+import click
+from quokka.core.content.models import make_model, Category
+from quokka.utils.blocks import build_menu, get_text_block, get_quokka_home
+from quokka.core.context_processors import configure
+from quokka import create_app
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure():
+ assert configure(app) is None
+
+
diff --git a/tests/core/test_db.py b/tests/core/test_db.py
new file mode 100644
index 000000000..15ac8c219
--- /dev/null
+++ b/tests/core/test_db.py
@@ -0,0 +1,45 @@
+import mock
+import click
+import itertools
+from contextlib import suppress
+from copy import deepcopy
+from pymongo import MongoClient
+from tinydb_serialization import SerializationMiddleware
+from tinymongo import TinyMongoClient
+from tinymongo.serializers import DateTimeSerializer
+from tinymongo.tinymongo import generate_id
+from quokka.utils.text import split_all_category_roots
+from quokka.core.db import QuokkaTinyMongoClient, QuokkaDB
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+quokka_mongo = QuokkaTinyMongoClient()
+quokka_db = QuokkaDB()
+mock_collections = {'index': 'index', 'contents': 'contents', 'uploads': 'uploads', 'users': 'users'}
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_class_quokkatinymongoclient_isinstance():
+ assert isinstance(quokka_mongo, QuokkaTinyMongoClient) == True
+
+def test_class_quokkadb_isinstance():
+ assert isinstance(quokka_db, QuokkaDB) == True
+
+def test_class_quokkadb_collections():
+ assert quokka_db.collections == mock_collections
+
+def test_class_quokkadb_config():
+ assert quokka_db.config == {}
+
+def test_class_quokkadb_folder():
+ assert quokka_db.folder == 'databases'
+
+def test_class_quokkadb_host():
+ assert quokka_db.host == 'localhost'
+
+def test_class_quokkadb_name():
+ assert quokka_db.name == 'quokka_db'
+
diff --git a/tests/core/test_error_handlers.py b/tests/core/test_error_handlers.py
new file mode 100644
index 000000000..da1e67d60
--- /dev/null
+++ b/tests/core/test_error_handlers.py
@@ -0,0 +1,20 @@
+import mock
+import click
+from flask import render_template
+from quokka import create_app
+from quokka.core.error_handlers import configure
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure():
+ assert configure(app) is None
+
+
+
diff --git a/tests/core/test_errors.py b/tests/core/test_errors.py
new file mode 100644
index 000000000..ac240ecef
--- /dev/null
+++ b/tests/core/test_errors.py
@@ -0,0 +1,5 @@
+from tinymongo.errors import DuplicateKeyError
+
+def test_module_unused():
+ pass
+
diff --git a/tests/core/test_flask_dynaconf.py b/tests/core/test_flask_dynaconf.py
new file mode 100644
index 000000000..26ab68367
--- /dev/null
+++ b/tests/core/test_flask_dynaconf.py
@@ -0,0 +1,24 @@
+import mock
+import pytest
+from flask import Markup
+from dynaconf.contrib import FlaskDynaconf
+from dynaconf.utils import DynaconfDict
+from dynaconf.loaders import yaml_loader, env_loader, default_loader
+from quokka import create_app
+from quokka.core.flask_dynaconf import configure_dynaconf
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure_dynaconf():
+ conf = configure_dynaconf(app)
+ assert conf is None
+
+
diff --git a/tests/core/test_logger.py b/tests/core/test_logger.py
new file mode 100644
index 000000000..1cf2ad273
--- /dev/null
+++ b/tests/core/test_logger.py
@@ -0,0 +1,21 @@
+import pytest
+import mock
+import logging
+from quokka.core.logger import configure
+from quokka import create_app
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure():
+ conf = configure(app)
+ assert conf is None
+
+
diff --git a/tests/core/test_monitoring.py b/tests/core/test_monitoring.py
new file mode 100644
index 000000000..965e653a1
--- /dev/null
+++ b/tests/core/test_monitoring.py
@@ -0,0 +1,20 @@
+import pytest
+import mock
+from quokka.core.monitoring import configure
+from quokka import create_app
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure():
+ conf = configure(app)
+ assert conf is None
+
+
diff --git a/tests/core/test_regex_url_support.py b/tests/core/test_regex_url_support.py
new file mode 100644
index 000000000..cc70a4631
--- /dev/null
+++ b/tests/core/test_regex_url_support.py
@@ -0,0 +1,36 @@
+import pytest
+import mock
+from werkzeug.routing import BaseConverter
+from quokka.core.regex_url_support import RegexConverter, Regex
+from quokka import create_app
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+regex_converter = RegexConverter("quokka/mock/url", ("mock", list))
+regex = Regex(app)
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_class_regexconverter_is_subclass():
+ assert issubclass(RegexConverter, BaseConverter) == True
+
+def test_class_regexconverter_isinstance():
+ assert isinstance(regex_converter, RegexConverter) == True
+
+def test_class_regexconverter_map_property():
+ assert regex_converter.map == 'quokka/mock/url'
+
+def test_class_regexconverter_weight_property():
+ assert regex_converter.weight == 100
+
+def test_class_regex_isinstance():
+ assert isinstance(regex, Regex) == True
+
+def test_class_regex_name():
+ assert regex.app.name == 'quokka'
+
+
diff --git a/tests/core/test_template_filters.py b/tests/core/test_template_filters.py
new file mode 100644
index 000000000..c62b25b68
--- /dev/null
+++ b/tests/core/test_template_filters.py
@@ -0,0 +1,24 @@
+import pytest
+from quokka.utils.blocks import (
+ get_block,
+ get_blocks,
+ get_block_by_id
+)
+from quokka.core.template_filters import (
+ is_list, configure
+)
+from quokka import create_app
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+app = create_app(test=True)
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_configure():
+ assert configure(app) is None
+
diff --git a/tests/core/views/__init__.py b/tests/core/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/core/views/test_sitemap.py b/tests/core/views/test_sitemap.py
new file mode 100644
index 000000000..c86e5a1fa
--- /dev/null
+++ b/tests/core/views/test_sitemap.py
@@ -0,0 +1,31 @@
+import mock
+import click
+from flask import render_template
+from flask import current_app as app
+from flask.views import MethodView
+from quokka.core.content.models import make_model
+from quokka.core.views.sitemap import SiteMapView
+
+
+#######################################################
+#pytest - fixtures #
+#######################################################
+sitemapview = SiteMapView()
+
+
+#######################################################
+#pytest - Quokka - tests/core/views/test_sitemap.py #
+#######################################################
+def test_class_sitemapview_isinstance():
+ assert isinstance(sitemapview, SiteMapView) is True
+
+def test_class_sitemap_decorators_empty_tuple():
+ assert sitemapview.decorators == ()
+
+def test_class_sitemap_mehots_dicionary_GET():
+ assert sitemapview.methods == {'GET'}
+
+def test_class_sitemap_provide_automatic_options_property_is_None():
+ assert sitemapview.provide_automatic_options is None
+
+
diff --git a/tests/module_template/__init_.py b/tests/module_template/__init_.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/module_template/quokka_module_template/test_admin.py b/tests/module_template/quokka_module_template/test_admin.py
new file mode 100644
index 000000000..ee327da33
--- /dev/null
+++ b/tests/module_template/quokka_module_template/test_admin.py
@@ -0,0 +1,166 @@
+import pytest
+import mock
+from flask import current_app
+from flask_admin.contrib.pymongo import filters
+from flask_admin.form import Select2Widget
+from flask_admin.model.fields import (
+ InlineFieldList, InlineFormField
+)
+from quokka.admin.forms import Form, fields
+from quokka.admin.views import ModelView
+from quokka.module_template.quokka_module_template.admin import (
+ InnerForm, UserForm,
+ UserView, TweetForm,
+ TweetView
+)
+
+
+################################
+#pytest - fixtures #
+################################
+class MockClassColl():
+ name=None
+ def __init__(self):
+ self.name = "mock-coll"
+
+mock_class_coll = MockClassColl()
+user_form = UserView(coll=mock_class_coll)
+tweet_view = TweetView(coll=mock_class_coll)
+
+
+#####################################
+#pytest - Quokka - test__init__.py #
+#####################################
+def test_class_InnerForm():
+ with pytest.raises(RuntimeError) as err:
+ inner_form = InnerForm()
+ assert "Working outside of application context." in str(err.value)
+
+def test_class_UserForm():
+ with pytest.raises(RuntimeError) as err:
+ user_form = UserForm()
+ assert "Working outside of application context." in str(err.value)
+
+def test_class_UserView_action_disallowed_list():
+ assert user_form.action_disallowed_list == []
+
+def test_class_UserView_admin_property():
+ assert user_form.admin is None
+
+def test_class_UserView_blueprint_property():
+ assert user_form.blueprint is None
+
+def test_class_UserView_category_property():
+ assert user_form.category is None
+
+def test_class_UserView_details_modal_property():
+ assert user_form.details_modal == False
+
+def test_class_UserView_edit_modal_property():
+ assert user_form.edit_modal == False
+
+def test_class_UserView_endpoint_property():
+ assert user_form.endpoint == 'quokka.module_template.quokka_module_template.admin.mock-collview'
+
+def test_class_UserView_ajax_refs_property():
+ assert user_form.form_ajax_refs is None
+
+def test_class_UserView_form_columns_property():
+ assert user_form.form_columns is None
+
+def test_class_UserView_form_create_rules_property():
+ assert user_form.form_create_rules is None
+
+def test_class_UserView_url_property():
+ assert user_form.url is None
+
+def test_class_UserView_static_folder_property():
+ assert user_form.static_folder is None
+
+def test_class_UserView_simple_list_pager_property():
+ assert user_form.simple_list_pager == False
+
+def test_class_UserView_model_property():
+ assert user_form.model is None
+
+def test_class_UserView_name_property():
+ assert user_form.name == 'Mock-Coll'
+
+def test_class_UserView_page_size_property():
+ assert user_form.page_size == 20
+
+def test_class_UserView_static_url_path_property():
+ assert user_form.static_url_path is None
+
+def test_class_UserView_list_template_property():
+ assert user_form.list_template == 'admin/model/list.html'
+
+def test_class_UserView_form_rules_property():
+ assert user_form.form_rules is None
+
+def test_class_TweetForm():
+ with pytest.raises(RuntimeError) as err:
+ user_form = TweetForm()
+ assert "Working outside of application context." in str(err.value)
+
+def test_class_TweetView_is_instance():
+ assert isinstance(tweet_view, TweetView) == True
+
+def test_class_TweetView_action_disallowed_list():
+ assert tweet_view.action_disallowed_list == []
+
+def test_class_TweetView_admin_property():
+ assert tweet_view.admin is None
+
+def test_class_TweetView_blueprint_property():
+ assert tweet_view.blueprint is None
+
+def test_class_TweetView_category_property():
+ assert tweet_view.category is None
+
+def test_class_TweetView_details_modal_property():
+ assert tweet_view.details_modal == False
+
+def test_class_TweetView_edit_modal_property():
+ assert tweet_view.edit_modal == False
+
+def test_class_TweetView_endpoint_property():
+ assert tweet_view.endpoint == 'quokka.module_template.quokka_module_template.admin.mock-collview'
+
+def test_class_TweetView_ajax_refs_property():
+ assert tweet_view.form_ajax_refs is None
+
+def test_class_TweetView_form_columns_property():
+ assert tweet_view.form_columns is None
+
+def test_class_TweetView_form_create_rules_property():
+ assert tweet_view.form_create_rules is None
+
+def test_class_TweetView_url_property():
+ assert tweet_view.url is None
+
+def test_class_TweetView_static_folder_property():
+ assert tweet_view.static_folder is None
+
+def test_class_TweetView_simple_list_pager_property():
+ assert tweet_view.simple_list_pager == False
+
+def test_class_TweetView_model_property():
+ assert tweet_view.model is None
+
+def test_class_TweetView_name_property():
+ assert tweet_view.name == 'Mock-Coll'
+
+def test_class_TweetView_page_size_property():
+ assert tweet_view.page_size == 20
+
+def test_class_TweetView_static_url_path_property():
+ assert tweet_view.static_url_path is None
+
+def test_class_TweetView_list_template_property():
+ assert tweet_view.list_template == 'admin/model/list.html'
+
+def test_class_TweetView_form_rules_property():
+ assert tweet_view.form_rules is None
+
+
diff --git a/tests/module_template/test_setup.py b/tests/module_template/test_setup.py
new file mode 100644
index 000000000..30cd334ba
--- /dev/null
+++ b/tests/module_template/test_setup.py
@@ -0,0 +1,8 @@
+############################################
+#pytest - quokka/module_template/setup.py #
+############################################
+
+def test_quokka_module_template_setup_call_umplement():
+ pass
+
+
diff --git a/tests/project_template/__init__.py b/tests/project_template/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/templates/__init__.py b/tests/templates/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/test__init__.py b/tests/test__init__.py
new file mode 100644
index 000000000..3e4a737aa
--- /dev/null
+++ b/tests/test__init__.py
@@ -0,0 +1,141 @@
+import mock
+import quokka
+from quokka import create_app, create_app_base
+from pytest_mock import mocker
+from quokka.core.app import QuokkaApp
+from quokka.core.flask_dynaconf import configure_dynaconf
+
+################################
+#pytest - fixtures - setUp(); #
+################################
+class MockTestApp(object):
+
+ def __init__(self, config):
+ self.config = config
+ return self.config
+
+
+#####################################
+#pytest - Quokka - test__init__.py #
+#####################################
+def test_create_app_called_params_default(mocker):
+ mocker.patch("quokka.create_app_base")
+ mocker.patch("quokka.core.configure_extensions")
+ quokka.create_app()
+ quokka.create_app_base.assert_called_once_with(test=False)
+
+def test_create_app_called_test_false(mocker):
+ mocker.patch("quokka.create_app_base")
+ mocker.patch("quokka.core.configure_extensions")
+ quokka.create_app(test=False)
+ quokka.create_app_base.assert_called_once_with(test=False)
+
+def test_create_app_called_test_true(mocker):
+ mocker.patch("quokka.create_app_base")
+ mocker.patch("quokka.core.configure_extensions")
+ quokka.create_app(test=True)
+ quokka.create_app_base.assert_called_once_with(test=True)
+
+def test_create_app_called_test_true_and_settings_dict(mocker):
+ mocker.patch("quokka.create_app_base")
+ mocker.patch("quokka.core.configure_extensions")
+ quokka.create_app(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'})
+ quokka.create_app_base.assert_called_once_with(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'})
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_quokkaapp_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ quokka.create_app_base(test=False, ext_list=None)
+ assert mock_QuokkaApp.called is False
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_dynaconf_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ quokka.create_app_base(test=False, ext_list=None)
+ assert mock_configure_dynaconf.called is False
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_configure_extension_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ quokka.create_app_base(test=False, ext_list=None)
+ assert mock_configure_extension.called is False
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_quokkaapp_called_is_false_and_test_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ quokka.create_app_base(test=True, ext_list=[])
+ assert mock_QuokkaApp.called is False
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_dynaconf_called_is_false_test_true_and_ext_list(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ quokka.create_app_base(test=True, ext_list=['quokka.core.configure_extension'])
+ assert mock_configure_dynaconf.called is False
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_configure_dynaconf_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext)
+ assert mock_configure_dynaconf.called is True
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_quokkaapp_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext)
+ assert mock_QuokkaApp.called is True
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_configure_extension_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext)
+ assert mock_configure_extension.called is True
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_configure_extension_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'})
+ assert mock_configure_extension.called is True
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_configure_dynaconf_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'})
+ assert mock_configure_dynaconf.called is True
+
+@mock.patch("quokka.core.app.QuokkaApp")
+@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf")
+@mock.patch("quokka.core.configure_extension")
+def test_create_app_base_function_quokkaapp_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp):
+ list_ext = ['quokka.core.app.QuokkaApp',
+ 'quokka.core.flask_dynaconf.configure_dynaconf',
+ 'quokka.core.configure_extension']
+ quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'})
+ assert mock_QuokkaApp.called is True
+
+
+
diff --git a/tests/test_basic.py b/tests/test_basic.py
deleted file mode 100644
index 1f9418114..000000000
--- a/tests/test_basic.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-def test_basic(app):
- assert app.name == 'quokka'
diff --git a/tests/test_cli.py b/tests/test_cli.py
new file mode 100644
index 000000000..2ba345573
--- /dev/null
+++ b/tests/test_cli.py
@@ -0,0 +1,76 @@
+import mock
+import click
+import quokka
+import pytest_django
+from yaml import load
+from quokka import create_app
+from pytest_mock import mocker
+from manage.cli import cli, init_cli
+import pytest, os, errno, pathlib, os.path, pytest_mock
+from quokka.cli import copyfolder, with_app, check, main, init, runserver
+from click.testing import CliRunner
+from pathlib import Path
+
+################################
+#pytest - fixtures - setUp(); #
+################################
+directory_pwd = os.getcwd()+"/tests/"
+directory_test = "copy-directory-test/"
+file_test = "cli-test-file"
+
+class AppMock():
+
+ def __init__(param):
+ return None
+
+ def extensions():
+ pass
+
+ def blueprints():
+ pass
+
+#pytest - fixture click.testing
+@pytest.fixture(scope='function')
+def runner(request):
+ return CliRunner()
+
+
+#################################
+#pytest - Quokka - test_cli.py #
+#################################
+def test_copy_folder_error_first_param():
+ with pytest.raises(FileNotFoundError) as error:
+ copyfolder("", directory_pwd+directory_test+file_test)
+ assert "No such file or directory" in str(error.value)
+
+def test_copy_folder_error_second_param():
+ with pytest.raises(FileNotFoundError) as error:
+ copyfolder(directory_pwd+file_test, "")
+ assert "No such file or directory" in str(error.value)
+
+def test_copy_folder_file_exists():
+ copyfolder(directory_pwd+file_test, directory_pwd+directory_test+file_test)
+ assert os.path.isfile(directory_pwd+directory_test+file_test) is True
+ os.unlink(directory_pwd+directory_test+file_test)
+
+@mock.patch("functools.wraps")
+@mock.patch("quokka.create_app")
+def test_with_app(mock_create_app, mock_wraps):
+ with_app('f')
+ assert mock_wraps.called is False
+
+@mock.patch("click.command")
+@mock.patch("click.argument")
+@mock.patch("click.option")
+@mock.patch("pathlib.Path")
+@mock.patch("quokka.cli.copyfolder")
+def test_init(mocker_copyfolder, mocker_Path, mocker_option, mocker_argument, mocker_command, runner):
+ @click.command()
+ @click.argument('name', nargs=-1)
+ def run_init_test():
+ init('name-mock', '.', '../', 'theme-mock', 'modules-mock')
+ result = runner.invoke(run_init_test)
+
+ assert not result.exception
+ assert mocker_copyfolder.called is False
+
diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/utils/test_atom.py b/tests/utils/test_atom.py
new file mode 100644
index 000000000..e9ed0e5b3
--- /dev/null
+++ b/tests/utils/test_atom.py
@@ -0,0 +1,47 @@
+import pytest
+import mock
+import time
+from datetime import datetime
+from werkzeug._compat import (
+ implements_to_string, string_types
+)
+from werkzeug.wrappers import BaseResponse
+from quokka.utils.atom import (
+ escape, _make_text_block,
+ AtomFeed, FeedEntry,
+ format_iso8601
+)
+
+
+################################
+#pytest - fixtures - setUp(); #
+################################
+XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'
+make = _make_text_block(name="name-param-mock", content="content-param-mock")
+param_mock = {"title_type":"", "text":"", "url":"", "feed_url":"", "id":"", "updated":"",
+"author":"", "icon":"", "logo":"", "rights":"", "rights_type":"", "subtitle":"", "subtitle_type":"", "generator":"", "links":""}
+
+
+##################################
+#pytest - Quokka - test_atom.py #
+##################################
+def test_escape():
+ assert escape("mock-pytest-param") == "mock-pytest-param"
+
+def test_make_text_block():
+ assert make == '