diff --git a/src/apps/dashboard/tests/test_models.py b/src/apps/dashboard/tests/test_models.py index 89347a6..79104a5 100644 --- a/src/apps/dashboard/tests/test_models.py +++ b/src/apps/dashboard/tests/test_models.py @@ -1,3 +1,5 @@ +from django.core.exceptions import ValidationError +from django.db.utils import IntegrityError from django.test import TestCase from ..models import Item, List @@ -28,4 +30,15 @@ class ListAndItemModelsTest(TestCase): self.assertEqual(first_saved_item.list, mylist) self.assertEqual(second_saved_item.text, "A sequel somehow better than the first") self.assertEqual(second_saved_item.list, mylist) - \ No newline at end of file + + def test_cannot_save_null_list_items(self): + mylist = List.objects.create() + item = Item(list=mylist, text=None) + with self.assertRaises(IntegrityError): + item.save() + + def test_cannot_save_empty_list_items(self): + mylist = List.objects.create() + item = Item(list=mylist, text="") + with self.assertRaises(ValidationError): + item.full_clean() diff --git a/src/apps/dashboard/tests/test_views.py b/src/apps/dashboard/tests/test_views.py index 111f574..e4ca212 100644 --- a/src/apps/dashboard/tests/test_views.py +++ b/src/apps/dashboard/tests/test_views.py @@ -1,4 +1,5 @@ from django.test import TestCase +from django.utils import html from ..models import Item, List import lxml.html @@ -56,6 +57,18 @@ class NewListTest(TestCase): new_list = List.objects.get() self.assertRedirects(response, f'/apps/dashboard/{new_list.id}/') + def test_validation_errors_are_sent_back_to_home_page_template(self): + response = self.client.post("/apps/dashboard/newlist", data={"item_text": ""}) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "apps/dashboard/home.html") + expected_error = html.escape("You can't have an empty list item") + self.assertContains(response, expected_error) + + def test_invalid_list_items_never_save(self): + self.client.post("/apps/dashboard/newlist", data={"item_text": ""}) + self.assertEqual(List.objects.count(), 0) + self.assertEqual(Item.objects.count(), 0) + class NewItemTest(TestCase): def test_can_save_a_POST_request_to_an_existing_list(self): other_list = List.objects.create() diff --git a/src/apps/dashboard/views.py b/src/apps/dashboard/views.py index 5ff91f2..840f5cf 100644 --- a/src/apps/dashboard/views.py +++ b/src/apps/dashboard/views.py @@ -1,18 +1,26 @@ +from django.core.exceptions import ValidationError from django.shortcuts import redirect, render from .models import Item, List def home_page(request): return render(request, 'apps/dashboard/home.html') +def new_list(request): + nulist = List.objects.create() + item = Item(text=request.POST['item_text'], list=nulist) + try: + item.full_clean() + item.save() + except ValidationError: + nulist.delete() + error = "You can't have an empty list item" + return render(request, "apps/dashboard/home.html", {"error": error}) + return redirect(f'/apps/dashboard/{nulist.id}/') + def view_list(request, list_id): our_list = List.objects.get(id=list_id) return render(request, 'apps/dashboard/list.html', {'list': our_list}) -def new_list(request): - nulist = List.objects.create() - Item.objects.create(text=request.POST['item_text'], list=nulist) - return redirect(f'/apps/dashboard/{nulist.id}/') - def add_item(request, list_id): our_list = List.objects.get(id=list_id) Item.objects.create(text=request.POST['item_text'], list=our_list) diff --git a/src/functional_tests/base.py b/src/functional_tests/base.py index 980b94b..03ee51c 100644 --- a/src/functional_tests/base.py +++ b/src/functional_tests/base.py @@ -18,6 +18,16 @@ class FunctionalTest(StaticLiveServerTestCase): def tearDown(self): self.browser.quit() + def wait_for(self, fn): + start_time = time.time() + while True: + try: + return fn() + except (AssertionError, WebDriverException): + if time.time() - start_time > MAX_WAIT: + raise + time.sleep(0.5) + def wait_for_row_in_list_table(self, row_text): start_time = time.time() while True: @@ -30,13 +40,3 @@ class FunctionalTest(StaticLiveServerTestCase): if time.time() - start_time > MAX_WAIT: raise time.sleep(0.5) - - def wait_for(self, fn): - start_time = time.time() - while True: - try: - return fn() - except (AssertionError, WebDriverException): - if time.time() - start_time > MAX_WAIT: - raise - time.sleep(0.5) \ No newline at end of file diff --git a/src/functional_tests/test_list_item_validation.py b/src/functional_tests/test_list_item_validation.py index 641a79c..9cf89e6 100644 --- a/src/functional_tests/test_list_item_validation.py +++ b/src/functional_tests/test_list_item_validation.py @@ -31,5 +31,3 @@ class ItemValidationTest(FunctionalTest): self.browser.find_element(By.ID, 'id-new-item').send_keys("Make tea") self.browser.find_element(By.ID, "id-new-item").send_keys(Keys.ENTER) self.wait_for_row_in_list_table("2. Make tea") - - self.fail("finish the fight!") diff --git a/src/templates/core/base.html b/src/templates/core/base.html index b90b2c8..44d646c 100644 --- a/src/templates/core/base.html +++ b/src/templates/core/base.html @@ -14,16 +14,20 @@
-

Dashboard | {% block header_text %}{% endblock header_text %}

+

Dashboard

+

{% block header_text %}{% endblock header_text %}

{% csrf_token %} + {% if error %} +
{{ error }}
+ {% endif %}