From: Christian Heller Date: Wed, 27 Mar 2024 01:33:28 +0000 (+0100) Subject: Extend POST tests, and handling of missing form data. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%7B%7B%20web_path%20%7D%7D/decks/static/condition?a=commitdiff_plain;h=11c4e6fc42ab96a13b18e8195c264899e31dddf0;p=plomtask Extend POST tests, and handling of missing form data. --- diff --git a/plomtask/http.py b/plomtask/http.py index c1de987..3396125 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -107,6 +107,8 @@ class TaskHandler(BaseHTTPRequestHandler): date: str, postvars: dict[str, list[str]]) -> None: """Update or insert Day of date and fields defined in postvars.""" day = Day.by_date(conn, date, create=True) + if 'comment' not in postvars.keys(): + raise BadFormatException('missing Day.comment value') day.comment = postvars['comment'][0] day.save(conn) @@ -114,6 +116,12 @@ class TaskHandler(BaseHTTPRequestHandler): postvars: dict[str, list[str]]) -> None: """Update or insert Process of id_ and fields defined in postvars.""" process = Process.by_id(conn, id_, create=True) + if 'title' not in postvars.keys(): + raise BadFormatException('missing Process.title value') + if 'description' not in postvars.keys(): + raise BadFormatException('missing Process.description value') + if 'effort' not in postvars.keys(): + raise BadFormatException('missing Process.effort value') process.title.set(postvars['title'][0]) process.description.set(postvars['description'][0]) effort = postvars['effort'][0] diff --git a/tests/days.py b/tests/days.py index 7cb0f4f..2850bb8 100644 --- a/tests/days.py +++ b/tests/days.py @@ -114,3 +114,17 @@ class TestsWithServer(TestCaseWithServer): self.assertEqual(response.getheader('Location'), '/day') self.conn.request('GET', '/foo') self.assertEqual(self.conn.getresponse().status, 404) + + 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) diff --git a/tests/processes.py b/tests/processes.py index e8967f7..88a7a6c 100644 --- a/tests/processes.py +++ b/tests/processes.py @@ -1,6 +1,5 @@ """Test Processes module.""" from unittest import TestCase -from urllib.parse import urlencode from tests.utils import TestCaseWithDB, TestCaseWithServer from plomtask.processes import Process from plomtask.exceptions import NotFoundException, BadFormatException @@ -68,26 +67,38 @@ class TestsWithServer(TestCaseWithServer): def test_do_POST_process(self) -> None: """Test POST /process and its effect on the database.""" - def post_data_to_expect(form_data: dict[str, object], - to_: str, expect: int) -> None: - encoded_form_data = urlencode(form_data).encode('utf-8') - headers = {'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': str(len(encoded_form_data))} - self.conn.request('POST', to_, - body=encoded_form_data, headers=headers) - self.assertEqual(self.conn.getresponse().status, expect) form_data = {'title': 'foo', 'description': 'foo', 'effort': 1.0} - post_data_to_expect(form_data, '/process?id=FOO', 400) + self.post_to(form_data, '/process?id=FOO') + self.assertEqual(self.conn.getresponse().status, 400) form_data['effort'] = 'foo' - post_data_to_expect(form_data, '/process?id=', 400) + self.post_to(form_data, '/process?id=') + self.assertEqual(self.conn.getresponse().status, 400) form_data['effort'] = None - post_data_to_expect(form_data, '/process?id=', 400) + 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) form_data = {'title': None, 'description': 1, 'effort': 1.0} - post_data_to_expect(form_data, '/process?id=', 302) + self.post_to(form_data, '/process?id=') + self.check_redirect('/') 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('/') def test_do_GET(self) -> None: """Test /process and /processes response codes.""" diff --git a/tests/utils.py b/tests/utils.py index 9964201..3ca0cb9 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,6 +2,7 @@ from unittest import TestCase from threading import Thread from http.client import HTTPConnection +from urllib.parse import urlencode from datetime import datetime from os import remove as remove_file from plomtask.db import DatabaseFile, DatabaseConnection @@ -39,3 +40,17 @@ class TestCaseWithServer(TestCaseWithDB): self.httpd.server_close() 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)