diff --git a/web/tests/test_urls.py b/web/tests/test_urls.py index 50eba5b18..5934465a0 100644 --- a/web/tests/test_urls.py +++ b/web/tests/test_urls.py @@ -1,6 +1,8 @@ """Tests for codethesaur.us urls""" from django.test import SimpleTestCase from django.urls import reverse, resolve +from django.urls.exceptions import NoReverseMatch + from web.views import index, about, concepts, api_reference, api_compare @@ -36,3 +38,8 @@ def test_api_compare_url(self): """ensure the api compare url uses the api function""" url = reverse(api_compare, args=['classes', 'javascript', 'ECMAScript 2023', 'java', 'java17']) self.assertEqual(resolve(url).func, api_compare) + + def test_not_existing_reverse(self): + with self.assertRaises(NoReverseMatch): + url = reverse('this_page_name_doesnt_exist') + resolve(url) diff --git a/web/tests/test_views.py b/web/tests/test_views.py index 07d5ff16f..bdf3fb872 100644 --- a/web/tests/test_views.py +++ b/web/tests/test_views.py @@ -13,7 +13,7 @@ def test_index_view_GET(self): url = reverse('index') response = self.client.get(url) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, HTTPStatus.OK) self.assertTemplateUsed(response, 'index.html') self.assertTemplateUsed(response, 'base.html') @@ -22,15 +22,52 @@ def test_about_view_GET(self): url = reverse('about') response = self.client.get(url) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, HTTPStatus.OK) self.assertTemplateUsed(response, 'about.html') self.assertTemplateUsed(response, 'base.html') + def test_index_view_not_GET(self): + """test that index shouldn't allow POST/PUT/etc.""" + url = reverse('index') + response = self.client.post(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.put(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.head(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.options(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.delete(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + def test_about_view_not_GET(self): + """test that about shouldn't allow POST/PUT/etc.""" + url = reverse('about') + response = self.client.post(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.put(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.head(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.options(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + + response = self.client.delete(url) + self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) + def test_invalid_page_gives_404_error(self): + """ test if a page that doesn't exist returns a 404""" url = 'no_real_page' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateUsed(response, 'error404.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateNotUsed(response, 'concepts.html') @@ -38,75 +75,157 @@ def test_invalid_page_gives_404_error(self): def test_compare_concepts_view_both_valid_languages(self): """test if compare with 2 valid languages uses the correct templates""" url = reverse('index') + \ - '?concept=data_types&lang=python%3B3&lang=java%3B17' + '?concept=data_types&lang=python%3B3&lang=java%3B17' response = self.client.get(url) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, HTTPStatus.OK) self.assertTemplateUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') - def test_compare_concepts_view_invalid_languages(self): + def test_compare_concepts_view_both_invalid_languages(self): """test if compare with invalid languages uses the correct templates""" url = reverse('index') + '?concept=data_types&lang=cupcake&lang=donut' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateNotUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateUsed(response, 'errormisc.html') def test_compare_concepts_view_one_valid_one_invalid_language(self): """ - test if compare with one invalid language uses the corret templates + test if compare with one invalid language uses the correct templates """ url = reverse('index') + '?concept=data_types&lang=python&lang=donut' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateNotUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateUsed(response, 'errormisc.html') def test_compare_concepts_view_invalid_concept(self): - """test if compare with an invalid concept uses the corret tempates""" + """test if compare with an invalid concept uses the correct templates""" url = reverse('index') + '?concept=boop&lang=python&lang=haskell' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateNotUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateUsed(response, 'errormisc.html') - def test_single_concepts_view_valid_language(self): - """test if reference with a valid language uses the corret templates""" + """test if reference with a valid language uses the correct templates""" url = reverse('index') + '?concept=data_types&lang=python%3B3' response = self.client.get(url) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, HTTPStatus.OK) self.assertTemplateUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') def test_single_concepts_view_invalid_languages(self): """ - test if reference with an invalid language uses the corret templates + test if reference with an invalid language uses the correct templates """ url = reverse('index') + '?concept=data_types&lang=cupcake' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateNotUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateUsed(response, 'errormisc.html') def test_single_concepts_view_invalid_concept(self): """ - test if reference with an invalid concept uses the corret tempates + test if reference with an invalid concept uses the correct templates """ url = reverse('index') + '?concept=boop&lang=python' response = self.client.get(url) - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + def test_compare_concepts_view_both_valid_friendly_languages(self): + """test if compare with 2 valid languages uses the correct templates""" + url = reverse('index') + \ + '?concept=data_types&lang=Python%3B3&lang=Java%3B17' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateUsed(response, 'errormisc.html') + self.assertTemplateUsed(response, 'base.html') + + def test_compare_concepts_view_both_invalid_friendly_languages(self): + """test if compare with invalid languages uses the correct templates""" + url = reverse('index') + '?concept=data_types&lang=Cupcake&lang=Donut' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + def test_compare_concepts_view_one_valid_one_invalid_friendly_language(self): + """ + test if compare with one invalid language uses the correct templates + """ + url = reverse('index') + '?concept=data_types&lang=Python&lang=donut' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + url = reverse('index') + '?concept=data_types&lang=python&lang=Donut' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + def test_compare_concepts_view_invalid_friendly_concept(self): + """test if compare with an invalid concept uses the correct templates""" + url = reverse('index') + '?concept=Boop&lang=python&lang=haskell' + + response = self.client.get(url) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + def test_single_concepts_view_valid_friendly_language(self): + """test if reference with a valid language uses the correct templates""" + url = reverse('index') + '?concept=Data Types&lang=python%3B3' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateUsed(response, 'errormisc.html') + self.assertTemplateUsed(response, 'base.html') + + def test_single_concepts_view_invalid_friendly_language(self): + """ + test if reference with an invalid language uses the correct templates + """ + url = reverse('index') + '?concept=data_types&lang=Cupcake' + response = self.client.get(url) + + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + self.assertTemplateNotUsed(response, 'concepts.html') + self.assertTemplateUsed(response, 'base.html') + self.assertTemplateUsed(response, 'errormisc.html') + + def test_single_concepts_view_invalid_friendly_concept(self): + """ + test if reference with an invalid concept uses the correct templates + """ + url = reverse('index') + '?concept=Boop&lang=python' + + response = self.client.get(url) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) self.assertTemplateNotUsed(response, 'concepts.html') self.assertTemplateUsed(response, 'base.html') self.assertTemplateUsed(response, 'errormisc.html') diff --git a/web/views.py b/web/views.py index 9584e7ef7..bd89f087d 100644 --- a/web/views.py +++ b/web/views.py @@ -1,10 +1,9 @@ """codethesaur.us views""" import logging -import random import os +import random -from jsonmerge import merge - +from django.conf import settings from django.http import ( HttpResponseBadRequest, HttpResponseForbidden, @@ -13,12 +12,13 @@ ) from django.shortcuts import HttpResponse, render from django.utils.html import escape, strip_tags +from django.views.decorators.http import require_http_methods from pygments import highlight from pygments.formatters.html import HtmlFormatter from pygments.lexers import get_lexer_by_name from pygments.util import ClassNotFound -from django.conf import settings +from codethesaurus.settings import BASE_DIR from web.models import ( Language, LookupData, @@ -29,8 +29,6 @@ ) from web.thesaurus_template_generators import generate_language_template -from codethesaurus.settings import BASE_DIR - def store_url_info(request): if 'HTTP_USER_AGENT' in request.META: @@ -64,6 +62,7 @@ def store_lookup_info(request, visit, language1, version1, language2, version2, info.save() +@require_http_methods(['GET']) def index(request): """ Renders the home page (/) @@ -115,6 +114,7 @@ def index(request): return render(request, 'index.html', content) +@require_http_methods(['GET']) def about(request): """ Renders the about page (/about) @@ -131,6 +131,7 @@ def about(request): return render(request, 'about.html', content) +@require_http_methods(['GET']) def concepts(request): """ Renders the page comparing two language structures (/compare) @@ -220,6 +221,7 @@ def concepts(request): return render_concepts(request, languages, meta_structure, all_categories) +@require_http_methods(['GET']) def render_concepts(request, languages, structure, all_categories): """Renders the `structure` page for all `languages`"""