emancipated hardcoded form views & html from base.html, apps.dashboard.views, apps.dashboard.tests.test_views; added get_item_input_box() helper method to functional_tests.base & retrofitted the other FTs to utilize it

This commit is contained in:
Disco DeDisco
2026-01-20 15:14:05 -05:00
parent 93cc6632c4
commit 1d96871d7b
7 changed files with 59 additions and 54 deletions

View File

@@ -1,5 +1,6 @@
from django.test import TestCase from django.test import TestCase
from django.utils import html from django.utils import html
from ..forms import EMPTY_ITEM_ERROR
from ..models import Item, List from ..models import Item, List
import lxml.html import lxml.html
@@ -28,17 +29,22 @@ class NewListTest(TestCase):
new_list = List.objects.get() new_list = List.objects.get()
self.assertRedirects(response, f'/apps/dashboard/{new_list.id}/') self.assertRedirects(response, f'/apps/dashboard/{new_list.id}/')
def test_validation_errors_are_sent_back_to_home_page_template(self): # Post invalid input helper
response = self.client.post("/apps/dashboard/newlist", data={"text": ""}) def post_invalid_input(self):
return self.client.post("/apps/dashboard/newlist", data={"text": ""})
def test_for_invalid_input_nothing_saved_to_db(self):
self.post_invalid_input()
self.assertEqual(Item.objects.count(), 0)
def test_for_invalid_input_renders_list_template(self):
response = self.post_invalid_input()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "apps/dashboard/home.html") 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): def test_for_invalid_input_shows_error_on_page(self):
self.client.post("/apps/dashboard/newlist", data={"text": ""}) response = self.post_invalid_input()
self.assertEqual(List.objects.count(), 0) self.assertContains(response, html.escape(EMPTY_ITEM_ERROR))
self.assertEqual(Item.objects.count(), 0)
class DashViewTest(TestCase): class DashViewTest(TestCase):
def test_uses_list_template(self): def test_uses_list_template(self):
@@ -94,13 +100,20 @@ class DashViewTest(TestCase):
self.assertRedirects(response, f'/apps/dashboard/{correct_list.id}/') self.assertRedirects(response, f'/apps/dashboard/{correct_list.id}/')
def test_validation_errors_end_up_on_lists_page(self): # Post invalid input helper
list_ = List.objects.create() def post_invalid_input(self):
response = self.client.post( mylist = List.objects.create()
f"/apps/dashboard/{list_.id}/", return self.client.post(f"/apps/dashboard/{mylist.id}/", data={"text": ""})
data={"text": ""},
) def test_for_invalid_input_nothing_saved_to_db(self):
self.post_invalid_input()
self.assertEqual(Item.objects.count(), 0)
def test_for_invalid_input_renders_list_template(self):
response = self.post_invalid_input()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "apps/dashboard/list.html") self.assertTemplateUsed(response, "apps/dashboard/list.html")
expected_error = html.escape("You can't have an empty list item")
self.assertContains(response, expected_error) def test_for_invalid_input_shows_error_on_page(self):
response = self.post_invalid_input()
self.assertContains(response, html.escape(EMPTY_ITEM_ERROR))

View File

@@ -4,26 +4,24 @@ from .forms import ItemForm
from .models import Item, List from .models import Item, List
def home_page(request): def home_page(request):
# return render(request, 'apps/dashboard/home.html', {"form": ItemForm()}) return render(request, 'apps/dashboard/home.html', {"form": ItemForm()})
return render(request, "apps/dashboard/home.html")
def new_list(request): def new_list(request):
form = ItemForm(data=request.POST)
if form.is_valid():
nulist = List.objects.create() nulist = List.objects.create()
item = Item(text=request.POST['text'], list=nulist) Item.objects.create(text=request.POST["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(nulist) return redirect(nulist)
else:
return render(request, "apps/dashboard/home.html", {"form": form})
def view_list(request, list_id): def view_list(request, list_id):
our_list = List.objects.get(id=list_id) our_list = List.objects.get(id=list_id)
error = None error = None
form = ItemForm()
if request.method == "POST": if request.method == "POST":
form = ItemForm(data=request.POST)
try: try:
item = Item(text=request.POST['text'], list=our_list) item = Item(text=request.POST['text'], list=our_list)
item.full_clean() item.full_clean()
@@ -32,5 +30,5 @@ def view_list(request, list_id):
except ValidationError: except ValidationError:
error = "You can't have an empty list item" error = "You can't have an empty list item"
return render(request, 'apps/dashboard/list.html', {'list': our_list, "error": error}) return render(request, 'apps/dashboard/list.html', {'list': our_list, "form": form, "error": error})

View File

@@ -40,3 +40,6 @@ class FunctionalTest(StaticLiveServerTestCase):
if time.time() - start_time > MAX_WAIT: if time.time() - start_time > MAX_WAIT:
raise raise
time.sleep(0.5) time.sleep(0.5)
def get_item_input_box(self):
return self.browser.find_element(By.ID, "id-text")

View File

@@ -10,7 +10,7 @@ class LayoutAndStylingTest(FunctionalTest):
self.browser.set_window_size(1024, 768) self.browser.set_window_size(1024, 768)
# print("Viewport width:", self.browser.execute_script("return window.innerWidth")) # print("Viewport width:", self.browser.execute_script("return window.innerWidth"))
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
self.assertAlmostEqual( self.assertAlmostEqual(
inputbox.location['x'] + inputbox.size['width'] / 2, inputbox.location['x'] + inputbox.size['width'] / 2,
512, 512,
@@ -20,7 +20,7 @@ class LayoutAndStylingTest(FunctionalTest):
inputbox.send_keys('testing') inputbox.send_keys('testing')
inputbox.send_keys(Keys.ENTER) inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1. testing') self.wait_for_row_in_list_table('1. testing')
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
self.assertAlmostEqual( self.assertAlmostEqual(
inputbox.location['x'] + inputbox.size['width'] / 2, inputbox.location['x'] + inputbox.size['width'] / 2,
512, 512,

View File

@@ -6,7 +6,7 @@ from .base import FunctionalTest
class ItemValidationTest(FunctionalTest): class ItemValidationTest(FunctionalTest):
def test_cannot_add_empty_list_items(self): def test_cannot_add_empty_list_items(self):
self.browser.get(self.live_server_url) self.browser.get(self.live_server_url)
self.browser.find_element(By.ID, "id-new-item").send_keys(Keys.ENTER) self.get_item_input_box().send_keys(Keys.ENTER)
self.wait_for( self.wait_for(
lambda: self.assertEqual( lambda: self.assertEqual(
@@ -15,12 +15,12 @@ class ItemValidationTest(FunctionalTest):
) )
) )
self.browser.find_element(By.ID, "id-new-item").send_keys("Purchase milk") self.get_item_input_box().send_keys("Purchase milk")
self.browser.find_element(By.ID, "id-new-item").send_keys(Keys.ENTER) self.get_item_input_box().send_keys(Keys.ENTER)
self.wait_for_row_in_list_table("1. Purchase milk") self.wait_for_row_in_list_table("1. Purchase milk")
self.browser.find_element(By.ID, "id-new-item").send_keys(Keys.ENTER) self.get_item_input_box().send_keys(Keys.ENTER)
self.wait_for( self.wait_for(
lambda: self.assertEqual( lambda: self.assertEqual(
@@ -29,6 +29,6 @@ class ItemValidationTest(FunctionalTest):
) )
) )
self.browser.find_element(By.ID, 'id-new-item').send_keys("Make tea") self.get_item_input_box().send_keys("Make tea")
self.browser.find_element(By.ID, "id-new-item").send_keys(Keys.ENTER) self.get_item_input_box().send_keys(Keys.ENTER)
self.wait_for_row_in_list_table("2. Make tea") self.wait_for_row_in_list_table("2. Make tea")

View File

@@ -14,7 +14,7 @@ class NewVisitorTest(FunctionalTest):
header_text = self.browser.find_element(By.TAG_NAME, 'h1').text header_text = self.browser.find_element(By.TAG_NAME, 'h1').text
self.assertIn('Dashboard', header_text) self.assertIn('Dashboard', header_text)
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
self.assertEqual(inputbox.get_attribute('placeholder'), 'Enter a to-do item') self.assertEqual(inputbox.get_attribute('placeholder'), 'Enter a to-do item')
inputbox.send_keys('Buy peacock feathers') inputbox.send_keys('Buy peacock feathers')
@@ -22,7 +22,7 @@ class NewVisitorTest(FunctionalTest):
inputbox.send_keys(Keys.ENTER) inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1. Buy peacock feathers') self.wait_for_row_in_list_table('1. Buy peacock feathers')
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
inputbox.send_keys('Use peacock feathers to make a fly') inputbox.send_keys('Use peacock feathers to make a fly')
inputbox.send_keys(Keys.ENTER) inputbox.send_keys(Keys.ENTER)
@@ -31,7 +31,7 @@ class NewVisitorTest(FunctionalTest):
def test_multiple_users_can_start_lists_at_different_urls(self): def test_multiple_users_can_start_lists_at_different_urls(self):
self.browser.get(self.live_server_url) self.browser.get(self.live_server_url)
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
inputbox.send_keys('Buy peacock feathers') inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER) inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1. Buy peacock feathers') self.wait_for_row_in_list_table('1. Buy peacock feathers')
@@ -45,7 +45,7 @@ class NewVisitorTest(FunctionalTest):
page_text = self.browser.find_element(By.TAG_NAME, 'body').text page_text = self.browser.find_element(By.TAG_NAME, 'body').text
self.assertNotIn('Buy peacock feathers', page_text) self.assertNotIn('Buy peacock feathers', page_text)
inputbox = self.browser.find_element(By.ID, 'id-new-item') inputbox = self.get_item_input_box()
inputbox.send_keys('Buy milk') inputbox.send_keys('Buy milk')
inputbox.send_keys(Keys.ENTER) inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1. Buy milk') self.wait_for_row_in_list_table('1. Buy milk')

View File

@@ -18,19 +18,10 @@
<h2 class="display-2 mb-2">{% block header_text %}{% endblock header_text %}</h2> <h2 class="display-2 mb-2">{% block header_text %}{% endblock header_text %}</h2>
<form method="POST" action="{% block form_action %}{% endblock form_action %}"> <form method="POST" action="{% block form_action %}{% endblock form_action %}">
{% if form %}
{{ form.text }} {{ form.text }}
{% else %}
<input
class="form-control form-control-lg{% if error %} is-invalid{% endif %}"
name="text"
id="id-new-item"
placeholder="Enter a to-do item"
/>
{% endif %}
{% csrf_token %} {% csrf_token %}
{% if error %} {% if form.errors %}
<div class="invalid-feedback">{{ error }}</div> <div class="invalid-feedback">{{ form.errors.text }}</div>
{% endif %} {% endif %}
</form> </form>
</div> </div>