From 004241d52d7bb6bab4ac0214c5d62a09ac829a75 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Fri, 23 Jan 2026 22:23:40 -0500 Subject: [PATCH] new form model in apps.dashboard.forms to handle existing item-lists; new test model in .tests.test_forms to accommodate; also new method in .test_views, but skipped for now --- src/apps/dashboard/forms.py | 13 +++++++++++++ src/apps/dashboard/tests/test_forms.py | 26 +++++++++++++++++++++++++- src/apps/dashboard/tests/test_views.py | 16 ++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/apps/dashboard/forms.py b/src/apps/dashboard/forms.py index ef3206f..3154db2 100644 --- a/src/apps/dashboard/forms.py +++ b/src/apps/dashboard/forms.py @@ -1,6 +1,8 @@ from django import forms +from django.core.exceptions import ValidationError from .models import Item +DUPLICATE_ITEM_ERROR = "You've already logged this to your list" EMPTY_ITEM_ERROR = "You can't have an empty list item" class ItemForm(forms.models.ModelForm): @@ -20,3 +22,14 @@ class ItemForm(forms.models.ModelForm): def save(self, for_list): self.instance.list = for_list return super().save() + +class ExistingListItemForm(ItemForm): + def __init__(self, for_list, *args, **kwargs): + super().__init__(*args, **kwargs) + self.instance.list = for_list + + def clean_text(self): + text = self.cleaned_data["text"] + if self.instance.list.item_set.filter(text=text).exists(): + raise forms.ValidationError(DUPLICATE_ITEM_ERROR) + return text \ No newline at end of file diff --git a/src/apps/dashboard/tests/test_forms.py b/src/apps/dashboard/tests/test_forms.py index bc06960..5991cf4 100644 --- a/src/apps/dashboard/tests/test_forms.py +++ b/src/apps/dashboard/tests/test_forms.py @@ -1,5 +1,10 @@ from django.test import TestCase -from ..forms import EMPTY_ITEM_ERROR, ItemForm +from ..forms import ( + DUPLICATE_ITEM_ERROR, + EMPTY_ITEM_ERROR, + ExistingListItemForm, + ItemForm, +) from ..models import Item, List class ItemFormTest(TestCase): @@ -25,3 +30,22 @@ class ItemFormTest(TestCase): self.assertEqual(new_item, Item.objects.get()) self.assertEqual(new_item.text, "do re mi") self.assertEqual(new_item.list, mylist) + +class ExistingListItemFormTest(TestCase): + def test_form_renders_item_text_input(self): + list_ = List.objects.create() + form = ExistingListItemForm(for_list=list_) + self.assertIn('placeholder="Enter a to-do item"', form.as_p()) + + def test_form_validation_for_blank_items(self): + list_ = List.objects.create() + form = ExistingListItemForm(for_list=list_, data={"text": ""}) + self.assertFalse(form.is_valid()) + self.assertEqual(form.errors["text"], [EMPTY_ITEM_ERROR]) + + def test_form_validation_for_duplicate_items(self): + list_ = List.objects.create() + Item.objects.create(list=list_, text="twins, basil") + form = ExistingListItemForm(for_list=list_, data={"text": "twins, basil"}) + self.assertFalse(form.is_valid()) + self.assertEqual(form.errors["text"], [DUPLICATE_ITEM_ERROR]) diff --git a/src/apps/dashboard/tests/test_views.py b/src/apps/dashboard/tests/test_views.py index 28d8983..76feeec 100644 --- a/src/apps/dashboard/tests/test_views.py +++ b/src/apps/dashboard/tests/test_views.py @@ -1,5 +1,6 @@ from django.test import TestCase from django.utils import html +from unittest import skip from ..forms import EMPTY_ITEM_ERROR from ..models import Item, List import lxml.html @@ -117,3 +118,18 @@ class DashViewTest(TestCase): def test_for_invalid_input_shows_error_on_page(self): response = self.post_invalid_input() self.assertContains(response, html.escape(EMPTY_ITEM_ERROR)) + + @skip + def test_duplicate_item_validation_errors_end_up_on_lists_page(self): + list1 = List.objects.create() + Item.objects.create(list=list1, text="lorem ipsum") + + response = self.client.post( + f"/apps/dashboard/{list1.id}/", + data={"text": "lorem ipsum"}, + ) + + expected_error = html.escape("You've already logged this to your list") + self.assertContains(response, expected_error) + self.assertTemplateUsed(response, "apps/dashboard/list.html") + self.assertEqual(Item.objects.all().count(), 1)