aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar kosayoda <[email protected]>2021-03-25 16:36:16 +0800
committerGravatar kosayoda <[email protected]>2021-03-25 16:36:16 +0800
commitacf7880e233faeb91ce2eeb59855f40b6e7db3e0 (patch)
tree6c4eff2c0249a1f9cec1832c55312da6016a3c40
parentReplace `markdown2` with `markdown` and `python-frontmatter`. (diff)
Refactor content app tests.
The tests uses pyfakefs to simulate a fake filesystem that is reused over the content app tests. Test coverage for the app is brought to 100%.
-rw-r--r--Pipfile1
-rw-r--r--Pipfile.lock10
-rw-r--r--pydis_site/apps/content/tests/helpers.py84
-rw-r--r--pydis_site/apps/content/tests/test_content/_info.yml2
-rw-r--r--pydis_site/apps/content/tests/test_content/category/_info.yml2
-rw-r--r--pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml2
-rw-r--r--pydis_site/apps/content/tests/test_content/category/subcategory/test4.md6
-rw-r--r--pydis_site/apps/content/tests/test_content/category/test3.md6
-rw-r--r--pydis_site/apps/content/tests/test_content/test.md10
-rw-r--r--pydis_site/apps/content/tests/test_content/test2.md6
-rw-r--r--pydis_site/apps/content/tests/test_utils.py185
-rw-r--r--pydis_site/apps/content/tests/test_views.py267
-rw-r--r--pydis_site/apps/content/utils.py2
-rw-r--r--pydis_site/apps/content/views/page_category.py2
14 files changed, 295 insertions, 290 deletions
diff --git a/Pipfile b/Pipfile
index c2b87ab4..c51215b6 100644
--- a/Pipfile
+++ b/Pipfile
@@ -36,6 +36,7 @@ mccabe = "~=0.6.1"
pep8-naming = "~=0.9"
pre-commit = "~=2.1"
unittest-xml-reporting = "~=3.0"
+pyfakefs = "~=4.4.0"
[requires]
python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
index 4f8bd0d3..6125e538 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "a338a377b64a5d25bf925646c97d932a2d1c783fc8f40d91b6a9ab8f30c2b14e"
+ "sha256": "dc85f4f1b6ef58c2832d79542d6e88729cd2464bdf9324fef4d0757561f07ca7"
},
"pipfile-spec": 6,
"requires": {
@@ -605,6 +605,14 @@
"markers": "python_version >= '3.6'",
"version": "==6.0.0"
},
+ "pyfakefs": {
+ "hashes": [
+ "sha256:082d863e0e2a74351f697da404e329a91e18e5055942e59d1b836e8459b2c94c",
+ "sha256:1ac3b2845dabe69af56c20691b9347914581195ccdde352535fb7d4ff0055c19"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
"pyflakes": {
"hashes": [
"sha256:910208209dcea632721cb58363d0f72913d9e8cf64dc6f8ae2e02a3609aba40d",
diff --git a/pydis_site/apps/content/tests/helpers.py b/pydis_site/apps/content/tests/helpers.py
new file mode 100644
index 00000000..4e0cca34
--- /dev/null
+++ b/pydis_site/apps/content/tests/helpers.py
@@ -0,0 +1,84 @@
+from pyfakefs.fake_filesystem_unittest import TestCase
+
+# Valid markdown content with YAML metadata
+MARKDOWN_WITH_METADATA = """
+---
+title: TestTitle
+description: TestDescription
+relevant_links:
+ Python Discord: https://pythondiscord.com
+ Discord: https://discord.com
+---
+# This is a header.
+"""
+
+MARKDOWN_WITHOUT_METADATA = """#This is a header."""
+
+# Valid YAML in a _info.yml file
+CATEGORY_INFO = """
+name: Category Name
+description: Description
+"""
+
+# The HTML generated from the above markdown data
+PARSED_HTML = (
+ '<h1 id="this-is-a-header">This is a header.'
+ '<a class="headerlink" href="#this-is-a-header" title="Permanent link">&para;</a></h1>'
+)
+
+# The YAML metadata parsed from the above markdown data
+PARSED_METADATA = {
+ "title": "TestTitle", "description": "TestDescription",
+ "relevant_links": {
+ "Python Discord": "https://pythondiscord.com",
+ "Discord": "https://discord.com"
+ }
+}
+
+# The YAML data parsed from the above _info.yml file
+PARSED_CATEGORY_INFO = {"name": "Category Name", "description": "Description"}
+
+
+class MockPagesTestCase(TestCase):
+ """
+ TestCase with a fake filesystem for testing.
+
+ Structure:
+ ├── _info.yml
+ ├── root.md
+ ├── root_without_metadata.md
+ ├── not_a_page.md
+ ├── tmp
+ |   ├── _info.yml
+ |   └── category_without_info
+ └── category
+    ├── _info.yml
+    ├── with_metadata.md
+    └── subcategory
+    ├── with_metadata.md
+       └── without_metadata.md
+ """
+
+ def setUp(self):
+ """Create the fake filesystem."""
+ self.setUpPyfakefs()
+
+ self.fs.create_file("_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("root.md", contents=MARKDOWN_WITH_METADATA)
+ self.fs.create_file("root_without_metadata.md", contents=MARKDOWN_WITHOUT_METADATA)
+ self.fs.create_file("not_a_page.md/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("category/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("category/with_metadata.md", contents=MARKDOWN_WITH_METADATA)
+ self.fs.create_file("category/subcategory/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file(
+ "category/subcategory/with_metadata.md", contents=MARKDOWN_WITH_METADATA
+ )
+ self.fs.create_file(
+ "category/subcategory/without_metadata.md", contents=MARKDOWN_WITHOUT_METADATA
+ )
+
+ # There is always a `tmp` directory in the filesystem, so make it a category
+ # for testing purposes.
+ # See: https://jmcgeheeiv.github.io/pyfakefs/release/usage.html#os-temporary-directories
+ self.fs.create_file("tmp/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_dir("tmp/category_without_info")
diff --git a/pydis_site/apps/content/tests/test_content/_info.yml b/pydis_site/apps/content/tests/test_content/_info.yml
deleted file mode 100644
index ad5fc113..00000000
--- a/pydis_site/apps/content/tests/test_content/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: Base Category
-description: Base Description
diff --git a/pydis_site/apps/content/tests/test_content/category/_info.yml b/pydis_site/apps/content/tests/test_content/category/_info.yml
deleted file mode 100644
index 8311509d..00000000
--- a/pydis_site/apps/content/tests/test_content/category/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: My Category
-description: My Description
diff --git a/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml b/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml
deleted file mode 100644
index f1c40264..00000000
--- a/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: My Category 1
-description: My Description 1
diff --git a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md b/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
deleted file mode 100644
index 1763a869..00000000
--- a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 4
-description: Testing 4
----
-
-This is also test content and in subcategory.
diff --git a/pydis_site/apps/content/tests/test_content/category/test3.md b/pydis_site/apps/content/tests/test_content/category/test3.md
deleted file mode 100644
index 9f294130..00000000
--- a/pydis_site/apps/content/tests/test_content/category/test3.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 3
-description: Testing 3
----
-
-This is too test content, but in category.
diff --git a/pydis_site/apps/content/tests/test_content/test.md b/pydis_site/apps/content/tests/test_content/test.md
deleted file mode 100644
index 709860d1..00000000
--- a/pydis_site/apps/content/tests/test_content/test.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: Test
-description: Testing
-relevant_links:
- Asking Good Questions: https://pythondiscord.com/pages/resources/guides/asking-good-questions/
- Help Channel Guide: https://pythondiscord.com/pages/resources/guides/help-channels/
- Code of Conduct: https://pythondiscord.com/pages/code-of-conduct/
----
-
-This is test content.
diff --git a/pydis_site/apps/content/tests/test_content/test2.md b/pydis_site/apps/content/tests/test_content/test2.md
deleted file mode 100644
index 0e57c3cd..00000000
--- a/pydis_site/apps/content/tests/test_content/test2.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 2
-description: Testing 2
----
-
-This is too test content.
diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index 3831ad33..58175d6f 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -1,150 +1,91 @@
from pathlib import Path
-from unittest.mock import patch
-from django.conf import settings
from django.http import Http404
-from django.test import TestCase, override_settings
-from markdown2 import markdown
from pydis_site.apps.content import utils
+from pydis_site.apps.content.tests.helpers import (
+ MockPagesTestCase, PARSED_CATEGORY_INFO, PARSED_HTML, PARSED_METADATA
+)
-BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
+class GetCategoryTests(MockPagesTestCase):
+ """Tests for the get_category function."""
-class TestGetCategory(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_successfully(self):
- """Check does this get right data from category data file."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_category(path)
+ def test_get_valid_category(self):
+ result = utils.get_category(Path("category"))
- self.assertEqual(result, {"name": "My Category", "description": "My Description"})
+ self.assertEqual(result, {"name": "Category Name", "description": "Description"})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_not_exists(self):
- """Check does this raise 404 error when category don't exists."""
+ def test_get_nonexistent_category(self):
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid")
- utils.get_category(path)
+ utils.get_category(Path("invalid"))
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_not_directory(self):
- """Check does this raise 404 error when category isn't directory."""
+ def test_get_category_with_path_to_file(self):
+ # Valid categories are directories, not files
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("test.md")
- utils.get_category(path)
+ utils.get_category(Path("root.md"))
+ def test_get_category_without_info_yml(self):
+ # Categories should provide an _info.yml file
+ with self.assertRaises(FileNotFoundError):
+ utils.get_category(Path("tmp/category_without_info"))
-class TestGetCategories(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- @patch("pydis_site.apps.content.utils.get_category")
- def test_get_categories(self, get_category_mock):
- """Check does this return test content categories."""
- get_category_mock.return_value = {"name": "My Category", "description": "My Description"}
- path = BASE_PATH.joinpath("category")
- result = utils.get_categories(path)
+class GetCategoriesTests(MockPagesTestCase):
+ """Tests for the get_categories function."""
- self.assertEqual(
- result, {"subcategory": {"name": "My Category", "description": "My Description"}}
- )
+ def test_get_root_categories(self):
+ result = utils.get_categories(Path("."))
+
+ info = PARSED_CATEGORY_INFO
+ self.assertEqual(result, {"category": info, "tmp": info, "not_a_page.md": info})
+
+ def test_get_categories_with_subcategories(self):
+ result = utils.get_categories(Path("category"))
+
+ self.assertEqual(result, {"subcategory": PARSED_CATEGORY_INFO})
+
+ def test_get_categories_without_subcategories(self):
+ result = utils.get_categories(Path("category/subcategory"))
+
+ self.assertEqual(result, {})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_categories_in_category(self):
- """Check does this call joinpath when getting subcategories."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_categories(path)
+
+class GetCategoryPagesTests(MockPagesTestCase):
+ """Tests for the get_category_pages function."""
+
+ def test_get_pages_in_root_category_successfully(self):
+ """The method should successfully retrieve page metadata."""
+ root_category_pages = utils.get_category_pages(Path("."))
self.assertEqual(
- result, {"subcategory": {"name": "My Category 1", "description": "My Description 1"}}
+ root_category_pages, {"root": PARSED_METADATA, "root_without_metadata": {}}
)
+ def test_get_pages_in_subcategories_successfully(self):
+ """The method should successfully retrieve page metadata."""
+ category_pages = utils.get_category_pages(Path("category"))
-class TestGetPages(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_all_root_pages(self):
- """Check does this return all root level testing content."""
- path = BASE_PATH
- result = utils.get_pages(path)
-
- for case in ["test", "test2"]:
- with self.subTest(guide=case):
- md = markdown(BASE_PATH.joinpath(f"{case}.md").read_text(), extras=["metadata"])
-
- self.assertIn(case, result)
- self.assertEqual(md.metadata, result[case])
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_all_category_pages(self):
- """Check does this return all category testing content."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_pages(path)
-
- md = markdown(BASE_PATH.joinpath("category", "test3.md").read_text(), extras=["metadata"])
-
- self.assertIn("test3", result)
- self.assertEqual(md.metadata, result["test3"])
-
-
-class TestGetPage(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_root_page_success(self):
- """Check does this return page HTML and metadata when root page exist."""
- path = BASE_PATH.joinpath("test.md")
- result = utils.get_page(path)
-
- md = markdown(
- BASE_PATH.joinpath("test.md").read_text(),
- extras=[
- "metadata",
- "fenced-code-blocks",
- "header-ids",
- "strike",
- "target-blank-links",
- "tables",
- "task_list"
- ]
- )
+ # Page metadata is properly retrieved
+ self.assertEqual(category_pages, {"with_metadata": PARSED_METADATA})
- self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_root_page_dont_exist(self):
- """Check does this raise Http404 when root page don't exist."""
- with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid")
- utils.get_page(path)
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_page_success(self):
- """Check does this return page HTML and metadata when category guide exist."""
- path = BASE_PATH.joinpath("category", "test3.md")
- result = utils.get_page(path)
-
- md = markdown(
- BASE_PATH.joinpath("category", "test3.md").read_text(),
- extras=[
- "metadata",
- "fenced-code-blocks",
- "header-ids",
- "strike",
- "target-blank-links",
- "tables",
- "task_list"
- ]
- )
+class GetPageTests(MockPagesTestCase):
+ """Tests for the get_page function."""
- self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
+ def test_get_page(self):
+ cases = [
+ ("Root page with metadata", "root.md", PARSED_HTML, PARSED_METADATA),
+ ("Root page without metadata", "root_without_metadata.md", PARSED_HTML, {}),
+ ("Page with metadata", "category/with_metadata.md", PARSED_HTML, PARSED_METADATA),
+ ("Page without metadata", "category/subcategory/without_metadata.md", PARSED_HTML, {}),
+ ]
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_page_dont_exist(self):
- """Check does this raise Http404 when category page don't exist."""
- with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("category", "invalid")
- utils.get_page(path)
+ for msg, page_path, expected_html, expected_metadata in cases:
+ with self.subTest(msg=msg):
+ html, metadata = utils.get_page(Path(page_path))
+ self.assertEqual(html, expected_html)
+ self.assertEqual(metadata, expected_metadata)
- @patch("pydis_site.settings.PAGES_PATH", new=BASE_PATH)
- def test_get_category_page_category_dont_exist(self):
- """Check does this raise Http404 when category don't exist."""
+ def test_get_nonexistent_page_returns_404(self):
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid", "some-guide")
- utils.get_page(path)
+ utils.get_page(Path("invalid"))
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index c61671a2..560378bc 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -1,140 +1,145 @@
from pathlib import Path
-from unittest.mock import patch
+from unittest import TestCase
-from django.conf import settings
from django.http import Http404
-from django.test import RequestFactory, TestCase, override_settings
-from django_hosts.resolvers import reverse
+from django.test import RequestFactory, SimpleTestCase, override_settings
+from pyfakefs import fake_filesystem_unittest
+from pydis_site.apps.content.tests.helpers import (
+ MockPagesTestCase, PARSED_CATEGORY_INFO, PARSED_HTML, PARSED_METADATA
+)
from pydis_site.apps.content.views import PageOrCategoryView
-BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
-
-
-class TestPageOrCategoryView(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- def test_page_return_code_200(self, get_category_mock, get_page_mock):
- get_page_mock.return_value = {"guide": "test", "metadata": {}}
-
- url = reverse("content:page_category", args=["test2"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- get_category_mock.assert_called_once()
- get_page_mock.assert_called_once()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_page_return_404(self, get_category_mock, get_page_mock):
- """Check that return code is 404 when invalid page provided."""
- get_page_mock.side_effect = Http404("Page not found.")
-
- url = reverse("content:page_category", args=["invalid-guide"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 404)
- get_page_mock.assert_not_called()
- get_category_mock.assert_not_called()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
- @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_valid_category_code_200(
- self,
- get_categories_mock,
- get_pages_mock,
- get_category_mock
- ):
- """Check that return code is 200 when visiting valid category."""
- get_category_mock.return_value = {"name": "test", "description": "test"}
- get_pages_mock.return_value = {}
-
- url = reverse("content:page_category", args=["category"])
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 200)
- get_pages_mock.assert_called_once()
- self.assertEqual(get_category_mock.call_count, 2)
- get_categories_mock.assert_called_once()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
- @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_invalid_category_code_404(
- self,
- get_categories_mock,
- get_pages_mock,
- get_category_mock
- ):
- """Check that return code is 404 when trying to visit invalid category."""
- get_category_mock.side_effect = Http404("Category not found.")
-
- url = reverse("content:page_category", args=["invalid-category"])
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 404)
- get_category_mock.assert_not_called()
- get_pages_mock.assert_not_called()
- get_categories_mock.assert_not_called()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_valid_category_page_code_200(
- self,
- get_category_mock,
- get_page_mock
- ):
- """Check that return code is 200 when visiting valid category page."""
- get_page_mock.return_value = {"guide": "test", "metadata": {}}
-
- url = reverse("content:page_category", args=["category/test3"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- get_page_mock.assert_called_once()
- self.assertEqual(get_category_mock.call_count, 2)
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_invalid_category_page_code_404(
- self,
- get_category_mock,
- get_page_mock
- ):
- """Check that return code is 200 when trying to visit invalid category page."""
- get_page_mock.side_effect = Http404("Page not found.")
-
- url = reverse("content:page_category", args=["category/invalid"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 404)
- get_page_mock.assert_not_called()
- get_category_mock.assert_not_called()
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_page_category_template_names(self):
- """Check that this return category, page template or raise Http404."""
- factory = RequestFactory()
+
+# Set the module constant within Patcher to use the fake filesystem
+# https://jmcgeheeiv.github.io/pyfakefs/master/usage.html#modules-to-reload
+with fake_filesystem_unittest.Patcher() as _:
+ BASE_PATH = Path(".")
+
+
+@override_settings(PAGES_PATH=BASE_PATH)
+class PageOrCategoryViewTests(MockPagesTestCase, SimpleTestCase, TestCase):
+ """Tests for the PageOrCategoryView class."""
+
+ def setUp(self):
+ """Set test helpers, then set up fake filesystem."""
+ self.factory = RequestFactory()
+ self.view = PageOrCategoryView.as_view()
+ self.ViewClass = PageOrCategoryView()
+ super().setUp()
+
+ # Integration tests
+ def test_valid_page_or_category_returns_200(self):
+ cases = [
+ ("Page at root", "root"),
+ ("Category page", "category"),
+ ("Page in category", "category/with_metadata"),
+ ("Subcategory page", "category/subcategory"),
+ ("Page in subcategory", "category/subcategory/with_metadata"),
+ ]
+ for msg, path in cases:
+ with self.subTest(msg=msg, path=path):
+ request = self.factory.get(f"/{path}")
+ response = self.view(request, location=path)
+ self.assertEqual(response.status_code, 200)
+
+ def test_nonexistent_page_returns_404(self):
+ with self.assertRaises(Http404):
+ request = self.factory.get("/invalid")
+ self.view(request, location="invalid")
+
+ # Unit tests
+ def test_get_template_names_returns_correct_templates(self):
+ category_template = "content/listing.html"
+ page_template = "content/page.html"
+ cases = [
+ ("root", page_template),
+ ("root_without_metadata", page_template),
+ ("category/with_metadata", page_template),
+ ("category/subcategory/with_metadata", page_template),
+ ("category", category_template),
+ ("category/subcategory", category_template),
+ ]
+
+ for path, expected_template in cases:
+ with self.subTest(path=path, expected_template=expected_template):
+ self.ViewClass.full_location = Path(path)
+ self.assertEqual(self.ViewClass.get_template_names(), [expected_template])
+
+ def test_get_template_names_with_nonexistent_paths_returns_404(self):
+ for path in ("invalid", "another_invalid", "nonexistent"):
+ with self.subTest(path=path):
+ self.ViewClass.full_location = Path(path)
+ with self.assertRaises(Http404):
+ self.ViewClass.get_template_names()
+
+ def test_get_context_data_with_valid_page(self):
+ """The method should return required fields in the template context."""
+ request = self.factory.get("/root")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="root")
+
+ cases = [
+ ("Context includes HTML page content", "page", PARSED_HTML),
+ ("Context includes page title", "page_title", PARSED_METADATA["title"]),
+ (
+ "Context includes page description",
+ "page_description",
+ PARSED_METADATA["description"]
+ ),
+ (
+ "Context includes relevant link names and URLs",
+ "relevant_links",
+ PARSED_METADATA["relevant_links"]
+ ),
+ ]
+ context = self.ViewClass.get_context_data()
+ for msg, key, expected_value in cases:
+ with self.subTest(msg=msg):
+ self.assertEqual(context[key], expected_value)
+
+ def test_get_context_data_with_valid_category(self):
+ """The method should return required fields in the template context."""
+ request = self.factory.get("/category")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="category")
+
cases = [
- {"location": "category", "output": ["content/listing.html"]},
- {"location": "test", "output": ["content/page.html"]},
- {"location": "invalid", "output": None, "raises": Http404}
+ (
+ "Context includes subcategory names and their information",
+ "categories",
+ {"subcategory": PARSED_CATEGORY_INFO}
+ ),
+ (
+ "Context includes page names and their metadata",
+ "pages",
+ {"with_metadata": PARSED_METADATA}
+ ),
+ (
+ "Context includes page description",
+ "page_description",
+ PARSED_CATEGORY_INFO["description"]
+ ),
+ ("Context includes page title", "page_title", PARSED_CATEGORY_INFO["name"]),
]
- for case in cases:
- with self.subTest(location=case["location"], output=case["output"]):
- request = factory.get(f"/pages/{case['location']}")
- instance = PageOrCategoryView()
- instance.request = request
- location = Path(case["location"])
- instance.location = location
- instance.full_location = BASE_PATH / location
-
- if "raises" in case:
- with self.assertRaises(case["raises"]):
- instance.get_template_names()
- else:
- self.assertEqual(case["output"], instance.get_template_names())
+ context = self.ViewClass.get_context_data()
+ for msg, key, expected_value in cases:
+ with self.subTest(msg=msg):
+ self.assertEqual(context[key], expected_value)
+
+ def test_get_context_data_breadcrumbs(self):
+ """The method should return correct breadcrumbs."""
+ request = self.factory.get("/category/subcategory/with_metadata")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="category/subcategory/with_metadata")
+
+ context = self.ViewClass.get_context_data()
+ self.assertEquals(
+ context["breadcrumb_items"],
+ [
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "."},
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "category"},
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "category/subcategory"},
+ ]
+ )
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 11d2b792..726c991f 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -33,7 +33,7 @@ def get_category_pages(path: Path) -> Dict[str, Dict]:
for item in path.glob("*.md"):
if item.is_file():
- pages[item.stem] = frontmatter.load(item)
+ pages[item.stem] = frontmatter.load(item).metadata
return pages
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 4a2ed2d6..eec4e7e5 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -13,7 +13,7 @@ class PageOrCategoryView(TemplateView):
def dispatch(self, request: t.Any, *args, **kwargs) -> t.Any:
"""Conform URL path location to the filesystem path."""
- self.location = Path(self.kwargs.get("location", ""))
+ self.location = Path(kwargs.get("location", ""))
self.full_location = settings.PAGES_PATH / self.location
return super().dispatch(request, *args, **kwargs)