diff --git a/src/apps/dashboard/forms.py b/src/apps/dashboard/forms.py index 955a7f9..0ed90d0 100644 --- a/src/apps/dashboard/forms.py +++ b/src/apps/dashboard/forms.py @@ -5,40 +5,28 @@ 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): - class Meta: - model = Item - fields = ("text",) - widgets = { - "text": forms.widgets.TextInput( - attrs={ - "placeholder": "Enter a to-do item", - "class": "form-control form-control-lg", - } - ), - } - error_messages = {"text": {"required": EMPTY_ITEM_ERROR}} +class ItemForm(forms.Form): + text = forms.CharField( + error_messages = {"required": EMPTY_ITEM_ERROR}, + required=True, + ) - def is_valid(self): - result = super().is_valid() - if not result: - self.fields["text"].widget.attrs["class"] += " is-invalid" - return result - def save(self, for_list): - self.instance.list = for_list - return super().save() + return Item.objects.create( + list=for_list, + text=self.cleaned_data["text"], + ) class ExistingListItemForm(ItemForm): def __init__(self, for_list, *args, **kwargs): super().__init__(*args, **kwargs) - self.instance.list = for_list + self._for_list = for_list def clean_text(self): text = self.cleaned_data["text"] - if self.instance.list.item_set.filter(text=text).exists(): + if self._for_list.item_set.filter(text=text).exists(): raise forms.ValidationError(DUPLICATE_ITEM_ERROR) return text def save(self): - return forms.models.ModelForm.save(self) + return super().save(for_list=self._for_list) diff --git a/src/apps/dashboard/tests/test_forms.py b/src/apps/dashboard/tests/test_forms.py index eafd4b5..939d043 100644 --- a/src/apps/dashboard/tests/test_forms.py +++ b/src/apps/dashboard/tests/test_forms.py @@ -8,12 +8,6 @@ from ..forms import ( from ..models import Item, List class ItemFormTest(TestCase): - def test_form_item_has_placeholder_and_css_classes(self): - form = ItemForm() - rendered = form.as_p() - self.assertIn('placeholder="Enter a to-do item"', rendered) - self.assertIn('class="form-control form-control-lg"', rendered) - def test_form_validation_for_blank_items(self): form = ItemForm(data={"text": ""}) form.save() @@ -23,15 +17,6 @@ class ItemFormTest(TestCase): self.assertFalse(form.is_valid()) self.assertEqual(form.errors["text"], [EMPTY_ITEM_ERROR]) - def test_invalid_form_has_bootstrap_is_invalid_css_class(self): - form = ItemForm(data={"text": ""}) - self.assertFalse(form.is_valid()) - field = form.fields["text"] - self.assertEqual( - field.widget.attrs["class"], - "form-control form-control-lg is-invalid", - ) - def test_form_save_handles_saving_to_a_list(self): mylist = List.objects.create() form = ItemForm(data={"text": "do re mi"}) @@ -41,11 +26,6 @@ class ItemFormTest(TestCase): 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": ""}) diff --git a/src/apps/dashboard/tests/test_views.py b/src/apps/dashboard/tests/test_views.py index 15b73a0..155d968 100644 --- a/src/apps/dashboard/tests/test_views.py +++ b/src/apps/dashboard/tests/test_views.py @@ -50,7 +50,7 @@ class NewListTest(TestCase): response = self.post_invalid_input() self.assertContains(response, html.escape(EMPTY_ITEM_ERROR)) -class DashViewTest(TestCase): +class ListViewTest(TestCase): def test_uses_list_template(self): mylist = List.objects.create() response = self.client.get(f'/apps/dashboard/{mylist.id}/') @@ -122,6 +122,12 @@ class DashViewTest(TestCase): response = self.post_invalid_input() self.assertContains(response, html.escape(EMPTY_ITEM_ERROR)) + def test_for_invalid_input_sets_is_invalid_class(self): + response = self.post_invalid_input() + parsed = lxml.html.fromstring(response.content) + [input] = parsed.cssselect("input[name=text]") + self.assertIn("is-invalid", set(input.classes)) + def test_duplicate_item_validation_errors_end_up_on_lists_page(self): list1 = List.objects.create() Item.objects.create(list=list1, text="lorem ipsum") diff --git a/src/templates/core/base.html b/src/templates/core/base.html index 03ad956..7b816c7 100644 --- a/src/templates/core/base.html +++ b/src/templates/core/base.html @@ -18,10 +18,20 @@

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

- {{ form.text }} {% csrf_token %} + {% if form.errors %} -
{{ form.errors.text }}
+
+ {{ form.errors.text.0 }} +
{% endif %}