From 4724d02b2c8a7fac3029ae6380641c4093fa4554 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Wed, 27 Mar 2024 05:34:30 +0100 Subject: [PATCH] Catch POSTs to undefined targets, expand and refactor tests. --- plomtask/http.py | 5 ++++- tests/days.py | 46 ++++++++++++------------------------------- tests/misc.py | 17 ++++++++++++++++ tests/processes.py | 49 ++++++++++++++-------------------------------- tests/utils.py | 27 +++++++++++++++++-------- 5 files changed, 68 insertions(+), 76 deletions(-) create mode 100644 tests/misc.py diff --git a/plomtask/http.py b/plomtask/http.py index 3dde6e2..cd3e445 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -128,7 +128,10 @@ class TaskHandler(BaseHTTPRequestHandler): form_data = PostvarsParser(postvars) if site in ('day', 'process'): getattr(self, f'do_POST_{site}')(conn, params, form_data) - conn.commit() + conn.commit() + else: + msg = f'Page not known as POST target: /{site}' + raise NotFoundException(msg) conn.close() self._redirect('/') except HandledException as error: diff --git a/tests/days.py b/tests/days.py index 2850bb8..81dbcf5 100644 --- a/tests/days.py +++ b/tests/days.py @@ -92,39 +92,19 @@ class TestsWithServer(TestCaseWithServer): def test_do_GET(self) -> None: """Test /day and /calendar response codes, and / redirect.""" - self.conn.request('GET', '/day') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/day?date=3000-01-01') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/day?date=FOO') - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('GET', '/calendar') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/calendar?start=&end=') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/calendar?start=today&end=today') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/calendar?start=2024-01-01&end=2025-01-01') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/calendar?start=foo') - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('GET', '/') - response = self.conn.getresponse() - self.assertEqual(response.status, 302) - self.assertEqual(response.getheader('Location'), '/day') - self.conn.request('GET', '/foo') - self.assertEqual(self.conn.getresponse().status, 404) + self.check_get('/day', 200) + self.check_get('/day?date=3000-01-01', 200) + self.check_get('/day?date=FOO', 400) + self.check_get('/calendar', 200) + self.check_get('/calendar?start=&end=', 200) + self.check_get('/calendar?start=today&end=today', 200) + self.check_get('/calendar?start=2024-01-01&end=2025-01-01', 200) + self.check_get('/calendar?start=foo', 400) def test_do_POST_day(self) -> None: """Test POST /day.""" - headers = {'Content-type': 'application/x-www-form-urlencoded'} - form_data = 'comment=' - self.conn.request('POST', '/day', form_data, headers) - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('POST', '/day?date=foo', form_data, headers) - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('POST', '/day?date=2024-01-01', form_data, headers) - self.check_redirect('/') - form_data = 'foo=' - self.conn.request('POST', '/day?date=2024-01-01', form_data, headers) - self.assertEqual(self.conn.getresponse().status, 400) + form_data = {'comment': ''} + self.check_post(form_data, '/day', 400) + self.check_post(form_data, '/day?date=foo', 400) + self.check_post(form_data, '/day?date=2024-01-01', 302, '/') + self.check_post({'foo': ''}, '/day?date=2024-01-01', 400) diff --git a/tests/misc.py b/tests/misc.py new file mode 100644 index 0000000..893d67e --- /dev/null +++ b/tests/misc.py @@ -0,0 +1,17 @@ +"""Miscellaneous tests.""" +from tests.utils import TestCaseWithServer + + +class TestsWithServer(TestCaseWithServer): + """Tests against our HTTP server/handler (and database).""" + + def test_do_GET(self) -> None: + """Test / redirect, and unknown targets failing.""" + self.conn.request('GET', '/') + self.check_redirect('/day') + self.check_get('/foo', 404) + + def test_do_POST(self) -> None: + """Test POST to / and other unknown targets failing.""" + self.check_post({}, '/', 404) + self.check_post({}, '/foo', 404) diff --git a/tests/processes.py b/tests/processes.py index 88a7a6c..fb572f5 100644 --- a/tests/processes.py +++ b/tests/processes.py @@ -68,47 +68,28 @@ class TestsWithServer(TestCaseWithServer): def test_do_POST_process(self) -> None: """Test POST /process and its effect on the database.""" form_data = {'title': 'foo', 'description': 'foo', 'effort': 1.0} - self.post_to(form_data, '/process?id=FOO') - self.assertEqual(self.conn.getresponse().status, 400) + self.check_post(form_data, '/process?id=FOO', 400) form_data['effort'] = 'foo' - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) + self.check_post(form_data, '/process?id=', 400) form_data['effort'] = None - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) - form_data = {} - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) - form_data = {'title': '', 'description': ''} - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) - form_data = {'title': '', 'effort': 1} - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) - form_data = {'description': '', 'effort': 1} - self.post_to(form_data, '/process?id=') - self.assertEqual(self.conn.getresponse().status, 400) + self.check_post(form_data, '/process?id=', 400) + self.check_post({}, '/process?id=', 400) + self.check_post({'title': '', 'description': ''}, '/process?id=', 400) + self.check_post({'title': '', 'effort': 1}, '/process?id=', 400) + self.check_post({'description': '', 'effort': 1}, '/process?id=', 400) form_data = {'title': None, 'description': 1, 'effort': 1.0} - self.post_to(form_data, '/process?id=') - self.check_redirect('/') + self.check_post(form_data, '/process?id=', 302, '/') retrieved = Process.by_id(self.db_conn, 1) self.assertEqual(retrieved.title.newest, 'None') self.assertEqual([p.id_ for p in Process.all(self.db_conn)], [retrieved.id_]) - self.post_to(form_data, '/process?id=1') - self.check_redirect('/') - self.post_to(form_data, '/process') - self.check_redirect('/') + self.check_post(form_data, '/process?id=1', 302, '/') + self.check_post(form_data, '/process', 302, '/') def test_do_GET(self) -> None: """Test /process and /processes response codes.""" - self.conn.request('GET', '/process') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/process?id=') - self.assertEqual(self.conn.getresponse().status, 200) - self.conn.request('GET', '/process?id=0') - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('GET', '/process?id=FOO') - self.assertEqual(self.conn.getresponse().status, 400) - self.conn.request('GET', '/processes') - self.assertEqual(self.conn.getresponse().status, 200) + self.check_get('/process', 200) + self.check_get('/process?id=', 200) + self.check_get('/process?id=0', 400) + self.check_get('/process?id=FOO', 400) + self.check_get('/processes', 200) diff --git a/tests/utils.py b/tests/utils.py index 3ca0cb9..d41e7b3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -5,6 +5,7 @@ from http.client import HTTPConnection from urllib.parse import urlencode from datetime import datetime from os import remove as remove_file +from typing import Mapping from plomtask.db import DatabaseFile, DatabaseConnection from plomtask.http import TaskHandler, TaskServer @@ -41,16 +42,26 @@ class TestCaseWithServer(TestCaseWithDB): self.server_thread.join() super().tearDown() - def post_to(self, data: dict[str, object], target: str) -> None: - """Post form data to target URL.""" - encoded_form_data = urlencode(data).encode('utf-8') - headers = {'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': str(len(encoded_form_data))} - self.conn.request('POST', target, - body=encoded_form_data, headers=headers) - def check_redirect(self, target: str) -> None: """Check that self.conn answers with a 302 redirect to target.""" response = self.conn.getresponse() self.assertEqual(response.status, 302) self.assertEqual(response.getheader('Location'), target) + + def check_get(self, target: str, expected_code: int) -> None: + """Check that a GET to target yields expected_code.""" + self.conn.request('GET', target) + self.assertEqual(self.conn.getresponse().status, expected_code) + + def check_post(self, data: Mapping[str, object], target: str, + expected_code: int, redirect_location: str = '') -> None: + """Check that POST of data to target yields expected_code.""" + encoded_form_data = urlencode(data).encode('utf-8') + headers = {'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': str(len(encoded_form_data))} + self.conn.request('POST', target, + body=encoded_form_data, headers=headers) + if 302 == expected_code: + self.check_redirect(redirect_location) + else: + self.assertEqual(self.conn.getresponse().status, expected_code) -- 2.30.2