diff options
author | 2019-04-19 15:29:27 +0200 | |
---|---|---|
committer | 2019-04-19 15:29:27 +0200 | |
commit | 5d9d6eec3159a9c87ca45dc5b294534daf8495fa (patch) | |
tree | 281274633fe8a9cc5c79d5f66409cf1fd87702dc | |
parent | Merge branch 'django_front_page' of github.com:python-discord/site into djang... (diff) |
Addressing all comments in volcyy's second review. The tests now mock the API calls so we don't have to actually call the API every time we run tests.
-rw-r--r-- | Pipfile | 2 | ||||
-rw-r--r-- | pydis_site/apps/home/__init__.py (renamed from pydis_site/apps/main/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/apps.py (renamed from pydis_site/apps/main/apps.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/migrations/0001_initial.py (renamed from pydis_site/apps/main/migrations/0001_initial.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/migrations/__init__.py (renamed from pydis_site/apps/main/migrations/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/models/__init__.py (renamed from pydis_site/apps/main/models/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/models/repo_data.py (renamed from pydis_site/apps/main/models/repo_data.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/templatetags/__init__.py (renamed from pydis_site/apps/main/templatetags/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/templatetags/extra_filters.py (renamed from pydis_site/apps/main/templatetags/extra_filters.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/tests/__init__.py (renamed from pydis_site/apps/main/tests/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/tests/mock_github_api_response.json | 44 | ||||
-rw-r--r-- | pydis_site/apps/home/tests/test_repodata_helpers.py | 92 | ||||
-rw-r--r-- | pydis_site/apps/home/tests/test_templatetags.py (renamed from pydis_site/apps/main/tests/test_templatetags.py) | 2 | ||||
-rw-r--r-- | pydis_site/apps/home/tests/test_views.py (renamed from pydis_site/apps/main/tests/test_views.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/urls.py (renamed from pydis_site/apps/main/urls.py) | 3 | ||||
-rw-r--r-- | pydis_site/apps/home/views/__init__.py (renamed from pydis_site/apps/main/views/__init__.py) | 0 | ||||
-rw-r--r-- | pydis_site/apps/home/views/home.py (renamed from pydis_site/apps/main/views/home.py) | 49 | ||||
-rw-r--r-- | pydis_site/apps/main/tests/test_repodata_helpers.py | 66 | ||||
-rw-r--r-- | pydis_site/hosts.py | 2 | ||||
-rw-r--r-- | pydis_site/settings.py | 12 | ||||
-rw-r--r-- | pydis_site/static/css/base/base.css | 32 | ||||
-rw-r--r-- | pydis_site/static/css/home/index.css | 12 | ||||
-rw-r--r-- | pydis_site/templates/base/navbar.html | 2 | ||||
-rw-r--r-- | pydis_site/templates/home/index.html | 16 | ||||
-rw-r--r-- | pydis_site/urls.py | 2 |
25 files changed, 204 insertions, 132 deletions
@@ -34,4 +34,4 @@ python_version = "3.7" [scripts] makemigrations = "python manage.py makemigrations" django_shell = "python manage.py shell" -test = "python manage.py test -v 2" +test = "python manage.py test" diff --git a/pydis_site/apps/main/__init__.py b/pydis_site/apps/home/__init__.py index e69de29b..e69de29b 100644 --- a/pydis_site/apps/main/__init__.py +++ b/pydis_site/apps/home/__init__.py diff --git a/pydis_site/apps/main/apps.py b/pydis_site/apps/home/apps.py index 90dc7137..90dc7137 100644 --- a/pydis_site/apps/main/apps.py +++ b/pydis_site/apps/home/apps.py diff --git a/pydis_site/apps/main/migrations/0001_initial.py b/pydis_site/apps/home/migrations/0001_initial.py index a2bf9f3e..a2bf9f3e 100644 --- a/pydis_site/apps/main/migrations/0001_initial.py +++ b/pydis_site/apps/home/migrations/0001_initial.py diff --git a/pydis_site/apps/main/migrations/__init__.py b/pydis_site/apps/home/migrations/__init__.py index e69de29b..e69de29b 100644 --- a/pydis_site/apps/main/migrations/__init__.py +++ b/pydis_site/apps/home/migrations/__init__.py diff --git a/pydis_site/apps/main/models/__init__.py b/pydis_site/apps/home/models/__init__.py index f327795a..f327795a 100644 --- a/pydis_site/apps/main/models/__init__.py +++ b/pydis_site/apps/home/models/__init__.py diff --git a/pydis_site/apps/main/models/repo_data.py b/pydis_site/apps/home/models/repo_data.py index c975c904..c975c904 100644 --- a/pydis_site/apps/main/models/repo_data.py +++ b/pydis_site/apps/home/models/repo_data.py diff --git a/pydis_site/apps/main/templatetags/__init__.py b/pydis_site/apps/home/templatetags/__init__.py index 70aca169..70aca169 100644 --- a/pydis_site/apps/main/templatetags/__init__.py +++ b/pydis_site/apps/home/templatetags/__init__.py diff --git a/pydis_site/apps/main/templatetags/extra_filters.py b/pydis_site/apps/home/templatetags/extra_filters.py index edffe9ac..edffe9ac 100644 --- a/pydis_site/apps/main/templatetags/extra_filters.py +++ b/pydis_site/apps/home/templatetags/extra_filters.py diff --git a/pydis_site/apps/main/tests/__init__.py b/pydis_site/apps/home/tests/__init__.py index e69de29b..e69de29b 100644 --- a/pydis_site/apps/main/tests/__init__.py +++ b/pydis_site/apps/home/tests/__init__.py diff --git a/pydis_site/apps/home/tests/mock_github_api_response.json b/pydis_site/apps/home/tests/mock_github_api_response.json new file mode 100644 index 00000000..37dc672e --- /dev/null +++ b/pydis_site/apps/home/tests/mock_github_api_response.json @@ -0,0 +1,44 @@ +[ + { + "full_name": "python-discord/bot", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/site", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/snekbox", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/django-simple-bulma", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/django-crispy-bulma", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/seasonalbot", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + } +] diff --git a/pydis_site/apps/home/tests/test_repodata_helpers.py b/pydis_site/apps/home/tests/test_repodata_helpers.py new file mode 100644 index 00000000..8ab2a467 --- /dev/null +++ b/pydis_site/apps/home/tests/test_repodata_helpers.py @@ -0,0 +1,92 @@ +import json +from datetime import timedelta +from pathlib import Path +from unittest import mock + +from django.test import TestCase +from django.utils import timezone + +from pydis_site.apps.home.models import RepositoryMetadata +from pydis_site.apps.home.views import HomeView + + +def mocked_requests_get(*args, **kwargs): + """A mock version of requests.get, so we don't need to call the API every time we run a test""" + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + if args[0] == HomeView.github_api: + json_path = Path(__file__).resolve().parent / "mock_github_api_response.json" + with open(json_path, 'r') as json_file: + mock_data = json.load(json_file) + + return MockResponse(mock_data, 200) + + return MockResponse(None, 404) + + +class TestRepositoryMetadataHelpers(TestCase): + + def setUp(self): + """Executed before each test method.""" + + self.home_view = HomeView() + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_returns_metadata(self, _): + """Test if the _get_repo_data helper actually returns what it should.""" + + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + self.assertEquals(len(metadata), len(self.home_view.repos)) + + def test_returns_cached_metadata(self): + """Test if the _get_repo_data helper returns cached data when available.""" + + repo_data = RepositoryMetadata( + repo_name="python-discord/site", + description="testrepo", + forks=42, + stargazers=42, + language="English", + ) + repo_data.save() + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + self.assertIsInstance(str(metadata[0]), str) + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_refresh_stale_metadata(self, _): + """Test if the _get_repo_data helper will refresh when the data is stale""" + + repo_data = RepositoryMetadata( + repo_name="python-discord/site", + description="testrepo", + forks=42, + stargazers=42, + language="English", + last_updated=timezone.now() - timedelta(seconds=121), # Make the data 2 minutes old. + ) + repo_data.save() + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_returns_api_data(self, _): + """Tests if the _get_api_data helper returns what it should.""" + + api_data = self.home_view._get_api_data() + repo = self.home_view.repos[0] + + self.assertIsInstance(api_data, dict) + self.assertEquals(len(api_data), len(self.home_view.repos)) + self.assertIn(repo, api_data.keys()) + self.assertIn("stargazers_count", api_data[repo]) diff --git a/pydis_site/apps/main/tests/test_templatetags.py b/pydis_site/apps/home/tests/test_templatetags.py index 44a5c491..813588c8 100644 --- a/pydis_site/apps/main/tests/test_templatetags.py +++ b/pydis_site/apps/home/tests/test_templatetags.py @@ -1,6 +1,6 @@ from django.test import TestCase -from pydis_site.apps.main.templatetags import starts_with +from pydis_site.apps.home.templatetags import starts_with class TestTemplateTags(TestCase): diff --git a/pydis_site/apps/main/tests/test_views.py b/pydis_site/apps/home/tests/test_views.py index 73678b0a..73678b0a 100644 --- a/pydis_site/apps/main/tests/test_views.py +++ b/pydis_site/apps/home/tests/test_views.py diff --git a/pydis_site/apps/main/urls.py b/pydis_site/apps/home/urls.py index edef9873..d8dba2f6 100644 --- a/pydis_site/apps/main/urls.py +++ b/pydis_site/apps/home/urls.py @@ -3,8 +3,7 @@ from django.urls import path from .views import HomeView - -app_name = 'main' +app_name = 'home' urlpatterns = [ path('', HomeView.as_view(), name='home'), path('admin/', admin.site.urls) diff --git a/pydis_site/apps/main/views/__init__.py b/pydis_site/apps/home/views/__init__.py index 971d73a3..971d73a3 100644 --- a/pydis_site/apps/main/views/__init__.py +++ b/pydis_site/apps/home/views/__init__.py diff --git a/pydis_site/apps/main/views/home.py b/pydis_site/apps/home/views/home.py index d9255ed2..c91d13e2 100644 --- a/pydis_site/apps/main/views/home.py +++ b/pydis_site/apps/home/views/home.py @@ -1,31 +1,40 @@ import requests -from django.conf import settings from django.shortcuts import render from django.utils import timezone from django.views import View -from pydis_site.apps.main.models import RepositoryMetadata - -GITHUB_API = "https://api.github.com/users/python-discord/repos" +from pydis_site.apps.home.models import RepositoryMetadata class HomeView(View): + """The view""" + + github_api = "https://api.github.com/users/python-discord/repos" + + # Which of our GitHub repos should be displayed on the front page, and in which order? + repos = [ + "python-discord/site", + "python-discord/bot", + "python-discord/snekbox", + "python-discord/seasonalbot", + "python-discord/django-simple-bulma", + "python-discord/django-crispy-bulma", + ] - @staticmethod - def _get_api_data(): + def _get_api_data(self): """Call the GitHub API and get information about our repos.""" - repo_dict = {repo_name: {} for repo_name in settings.HOMEPAGE_REPOS} + repo_dict = {repo_name: {} for repo_name in self.repos} # Fetch the data from the GitHub API - api_data = requests.get(GITHUB_API) + api_data = requests.get(self.github_api) api_data = api_data.json() # Process the API data into our dict for repo in api_data: full_name = repo["full_name"] - if full_name in settings.HOMEPAGE_REPOS: + if full_name in self.repos: repo_dict[full_name] = { "full_name": repo["full_name"], "description": repo["description"], @@ -46,11 +55,11 @@ class HomeView(View): if (timezone.now() - repo_data.last_updated).seconds > 120: # Get new data from API - api_data_container = self._get_api_data() - repo_data_container = [] + api_repositories = self._get_api_data() + database_repositories = [] - # Update or create all RepoData objects in settings.HOMEPAGE_REPOS - for repo_name, api_data in api_data_container.items(): + # Update or create all RepoData objects in self.repos + for repo_name, api_data in api_repositories.items(): try: repo_data = RepositoryMetadata.objects.get(repo_name=repo_name) repo_data.description = api_data["description"] @@ -66,8 +75,8 @@ class HomeView(View): language=api_data["language"], ) repo_data.save() - repo_data_container.append(repo_data) - return repo_data_container + database_repositories.append(repo_data) + return database_repositories # Otherwise, if the data is fresher than 2 minutes old, we should just return it. else: @@ -77,11 +86,11 @@ class HomeView(View): except RepositoryMetadata.DoesNotExist: # Get new data from API - api_data_container = self._get_api_data() - repo_data_container = [] + api_repositories = self._get_api_data() + database_repositories = [] # Create all the repodata records in the database. - for api_data in api_data_container.values(): + for api_data in api_repositories.values(): repo_data = RepositoryMetadata( repo_name=api_data["full_name"], description=api_data["description"], @@ -90,9 +99,9 @@ class HomeView(View): language=api_data["language"], ) repo_data.save() - repo_data_container.append(repo_data) + database_repositories.append(repo_data) - return repo_data_container + return database_repositories def get(self, request): """Collect repo data and render the homepage view""" diff --git a/pydis_site/apps/main/tests/test_repodata_helpers.py b/pydis_site/apps/main/tests/test_repodata_helpers.py deleted file mode 100644 index 040acb21..00000000 --- a/pydis_site/apps/main/tests/test_repodata_helpers.py +++ /dev/null @@ -1,66 +0,0 @@ -from datetime import timedelta - -from django.conf import settings -from django.test import TestCase -from django.utils import timezone - -from pydis_site.apps.main.models import RepositoryMetadata -from pydis_site.apps.main.views import HomeView - - -class TestRepositoryMetadataHelpers(TestCase): - - def test_returns_metadata(self): - """Test if the _get_repo_data helper actually returns what it should.""" - - home_view = HomeView() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - self.assertEquals(len(metadata), len(settings.HOMEPAGE_REPOS)) - - def test_returns_cached_metadata(self): - """Test if the _get_repo_data helper returns cached data when available.""" - - home_view = HomeView() - repo_data = RepositoryMetadata( - repo_name="python-discord/site", - description="testrepo", - forks=42, - stargazers=42, - language="English", - ) - repo_data.save() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - print(metadata[0]) # Tests the __str__ in the model - - def test_refresh_stale_metadata(self): - """Test if the _get_repo_data helper will refresh when the data is stale""" - - home_view = HomeView() - repo_data = RepositoryMetadata( - repo_name="python-discord/site", - description="testrepo", - forks=42, - stargazers=42, - language="English", - last_updated=timezone.now() - timedelta(seconds=121), # Make the data 2 minutes old. - ) - repo_data.save() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - - def test_returns_api_data(self): - """Tests if the _get_api_data helper returns what it should.""" - - home_view = HomeView() - api_data = home_view._get_api_data() - repo = settings.HOMEPAGE_REPOS[0] - - self.assertIsInstance(api_data, dict) - self.assertEquals(len(api_data), len(settings.HOMEPAGE_REPOS)) - self.assertIn(repo, api_data.keys()) - self.assertIn("stargazers_count", api_data[repo]) diff --git a/pydis_site/hosts.py b/pydis_site/hosts.py index 9e58628c..0fa4793d 100644 --- a/pydis_site/hosts.py +++ b/pydis_site/hosts.py @@ -5,5 +5,5 @@ host_patterns = patterns( '', host(r'admin', 'pydis_site.apps.admin.urls', name="admin"), host(r'api', 'pydis_site.apps.api.urls', name='api'), - host(r'.*', 'pydis_site.apps.main.urls', name=settings.DEFAULT_HOST) + host(r'.*', 'pydis_site.apps.home.urls', name=settings.DEFAULT_HOST) ) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index eb21de10..891084c9 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -63,7 +63,7 @@ else: INSTALLED_APPS = [ 'pydis_site.apps.api', - 'pydis_site.apps.main', + 'pydis_site.apps.home', 'django.contrib.admin', 'django.contrib.auth', @@ -258,13 +258,3 @@ BULMA_SETTINGS = { "footer-padding": "1rem 1.5rem 1rem", } } - -# Which of our GitHub repos should be displayed on the front page, and in which order? -HOMEPAGE_REPOS = [ - "python-discord/site", - "python-discord/bot", - "python-discord/snekbox", - "python-discord/seasonalbot", - "python-discord/django-simple-bulma", - "python-discord/django-crispy-bulma", -] diff --git a/pydis_site/static/css/base/base.css b/pydis_site/static/css/base/base.css index 969511f4..4f656189 100644 --- a/pydis_site/static/css/base/base.css +++ b/pydis_site/static/css/base/base.css @@ -1,15 +1,15 @@ html { - overflow:auto; + overflow: auto; } body.site { - display: flex; - min-height: 100vh; - flex-direction: column; + display: flex; + min-height: 100vh; + flex-direction: column; } main.site-content { - flex: 1; + flex: 1; } div.card.has-equal-height { @@ -19,20 +19,20 @@ div.card.has-equal-height { } #django-logo { - padding-bottom: 2px; - background: url(https://static.djangoproject.com/img/logos/django-logo-negative.png) no-repeat center; - filter: grayscale(1) invert(0.02); - background-size: 52px 25.5px; - background-position: -1px -2px; - color: #00000000; + padding-bottom: 2px; + background: url(https://static.djangoproject.com/img/logos/django-logo-negative.png) no-repeat center; + filter: grayscale(1) invert(0.02); + background-size: 52px 25.5px; + background-position: -1px -2px; + color: #00000000; } #bulma-logo { - padding-left: 18px; - height: 20px; - background: url(https://bulma.io/images/bulma-logo-white.png) no-repeat center; - background-size: 60px; - color: #00000000; + padding-left: 18px; + height: 20px; + background: url(https://bulma.io/images/bulma-logo-white.png) no-repeat center; + background-size: 60px; + color: #00000000; } #pydis-text { diff --git a/pydis_site/static/css/home/index.css b/pydis_site/static/css/home/index.css index 9aad02e5..0ad2e6b5 100644 --- a/pydis_site/static/css/home/index.css +++ b/pydis_site/static/css/home/index.css @@ -18,7 +18,7 @@ } .navbar-item.is-fullsize { - padding:0; + padding: 0; } .navbar-item.is-fullsize img { @@ -45,7 +45,7 @@ .video-container object, .video-container embed { width: 100%; - height: calc(92vw*0.5625); + height: calc(92vw * 0.5625); margin: 8px auto auto auto; } @@ -103,11 +103,13 @@ span.repo-language-dot.css { flex: none; width: 50%; } + .columns:not(.is-desktop) { display: flex; } + .video-container iframe { - height: calc(42vw*0.5625); + height: calc(42vw * 0.5625); max-height: 371px; max-width: 660px; } @@ -118,11 +120,13 @@ span.repo-language-dot.css { flex: none; width: 100%; } + .columns:not(.is-desktop) { display: block; } + .video-container iframe { - height: calc(92vw*0.5625); + height: calc(92vw * 0.5625); max-height: none; max-width: none; } diff --git a/pydis_site/templates/base/navbar.html b/pydis_site/templates/base/navbar.html index 6a7e683f..ed6ae118 100644 --- a/pydis_site/templates/base/navbar.html +++ b/pydis_site/templates/base/navbar.html @@ -8,7 +8,7 @@ <img src="{% static "images/navbar/pydis_banner_no_square.svg" %}" alt="Python Discord logo"/> </a> - <!-- The navbar "burger" which appears when rendered on screens that can't fit the entire nav --> + {# The navbar "burger" which appears when rendered on screens that can't fit the entire nav #} <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbar_menu"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html index 6057ca18..dfb74f96 100644 --- a/pydis_site/templates/home/index.html +++ b/pydis_site/templates/home/index.html @@ -11,7 +11,7 @@ <section class="section"> - <!-- Who are we? --> + {# Who are we? #} <div class="container is-spaced"> <h1 class="is-size-1">Who are we?</h1> <br> @@ -39,20 +39,20 @@ </p> </div> - <!-- Intro video --> + {# Intro video #} <div class="column is-half video-container"> <iframe src="https://www.youtube.com/embed/DIBXg8Qh7bA" frameborder="0" - allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" + allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> </div> </div> - <!-- Projects --> + {# Projects #} <h1 class="is-size-1">Projects</h1> <br> <div class="columns is-multiline"> - <!-- Display projects from settings.HOMEPAGE_REPOS --> + {# Display projects from settings.HOMEPAGE_REPOS #} {% for repo in repo_data %} <div class="column is-one-third"> <div class="card has-equal-height github-card"> @@ -77,7 +77,7 @@ </div> </section> - <!-- Sponsors --> + {# Sponsors #} <section class="section-sp hero is-light"> <div id="sponsors-hero" class="hero-body"> <div class="container"> @@ -85,8 +85,8 @@ Sponsors </h1> <a href="https://linode.com"><img src="{% static "images/sponsors/linode.png" %}" alt="Linode"/></a> - <a href="https://jetbrains.com"><img src="{% static "images/sponsors/jetbrains.png" %}" alt=""/></a> - <a href="https://adafruit.com"><img src="{% static "images/sponsors/adafruit.png" %}" alt=""/></a> + <a href="https://jetbrains.com"><img src="{% static "images/sponsors/jetbrains.png" %}" alt="JetBrains"/></a> + <a href="https://adafruit.com"><img src="{% static "images/sponsors/adafruit.png" %}" alt="Adafruit"/></a> </div> </div> </section> diff --git a/pydis_site/urls.py b/pydis_site/urls.py index e4ef058b..c68375da 100644 --- a/pydis_site/urls.py +++ b/pydis_site/urls.py @@ -2,5 +2,5 @@ from django.urls import include, path urlpatterns = ( - path('', include('pydis_site.apps.main.urls', namespace='home')), + path('', include('pydis_site.apps.home.urls', namespace='home')), ) |