Skip to content

Commit

Permalink
Add new tests for form events
Browse files Browse the repository at this point in the history
  • Loading branch information
Archmonger committed Dec 10, 2024
1 parent 3ed84db commit 55daaa2
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 5 deletions.
74 changes: 72 additions & 2 deletions tests/test_app/forms/components.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from reactpy import component, html
from reactpy import component, hooks, html

from reactpy_django.components import django_form

from .forms import BasicForm, DatabaseBackedForm
from .forms import BasicForm, DatabaseBackedForm, EventForm


@component
Expand All @@ -22,3 +22,73 @@ def bootstrap_form():
@component
def database_backed_form():
return django_form(DatabaseBackedForm, bottom_children=(html.input({"type": "submit"}),))


@component
def sync_event_form():
success, set_success = hooks.use_state(False)
error, set_error = hooks.use_state(False)
receive_data, set_receive_data = hooks.use_state(False)
change, set_change = hooks.use_state(False)

def on_success(event):
set_success(True)

def on_error(event):
set_error(True)

def on_receive_data(event):
set_receive_data(True)

def on_change(event):
set_change(True)

return django_form(
EventForm,
on_success=on_success,
on_error=on_error,
on_receive_data=on_receive_data,
on_change=on_change,
top_children=[
html.div({"id": "success", "data-value": success}, f"Success: {success}"),
html.div({"id": "error", "data-value": error}, f"Error: {error}"),
html.div({"id": "receive_data", "data-value": receive_data}, f"Receive Data: {receive_data}"),
html.div({"id": "change", "data-value": change}, f"Change: {change}"),
],
bottom_children=[html.input({"type": "submit"})],
)


@component
def async_event_form():
success, set_success = hooks.use_state(False)
error, set_error = hooks.use_state(False)
receive_data, set_receive_data = hooks.use_state(False)
change, set_change = hooks.use_state(False)

async def on_success(event):
set_success(True)

async def on_error(event):
set_error(True)

async def on_receive_data(event):
set_receive_data(True)

async def on_change(event):
set_change(True)

return django_form(
EventForm,
on_success=on_success,
on_error=on_error,
on_receive_data=on_receive_data,
on_change=on_change,
top_children=[
html.div({"id": "success", "data-value": success}, f"Success: {success}"),
html.div({"id": "error", "data-value": error}, f"Error: {error}"),
html.div({"id": "receive_data", "data-value": receive_data}, f"Receive Data: {receive_data}"),
html.div({"id": "change", "data-value": change}, f"Change: {change}"),
],
bottom_children=[html.input({"type": "submit"})],
)
6 changes: 5 additions & 1 deletion tests/test_app/forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class BasicForm(forms.Form):
# Render one of every Django field type
# https://docs.djangoproject.com/en/stable/ref/forms/fields/#field-types
boolean_field = forms.BooleanField(label="boolean")
char_field = forms.CharField(label="chars", max_length=7)
char_field = forms.CharField(label="chars")
choice_field = forms.ChoiceField(label="choice", choices=[("1", "One"), ("2", "Two")])
date_field = forms.DateField(label="date")
date_time_field = forms.DateTimeField(label="date time")
Expand Down Expand Up @@ -44,3 +44,7 @@ class DatabaseBackedForm(forms.ModelForm):
class Meta:
model = models.TodoItem
fields = "__all__"


class EventForm(forms.Form):
char_field = forms.CharField(label="chars")
2 changes: 2 additions & 0 deletions tests/test_app/forms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
path("form/", views.form),
path("form/bootstrap/", views.bootstrap_form),
path("form/model/", views.model_form),
path("form/sync_event/", views.sync_event_form),
path("form/async_event/", views.async_event_form),
]
8 changes: 8 additions & 0 deletions tests/test_app/forms/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ def bootstrap_form(request):

def model_form(request):
return render(request, "model_form.html", {})


def sync_event_form(request):
return render(request, "sync_event_form.html", {})


def async_event_form(request):
return render(request, "async_event_form.html", {})
26 changes: 26 additions & 0 deletions tests/test_app/templates/async_event_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% load static %} {% load reactpy %}
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}" />
<title>ReactPy</title>
<style>
iframe {
width: 100%;
height: 45px;
}
</style>
</head>

<body>
<h1>ReactPy Async Event Form Test Page</h1>
<hr>
{% component "test_app.forms.components.async_event_form" %}
<hr>
</body>

</html>
2 changes: 1 addition & 1 deletion tests/test_app/templates/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</head>

<body>
<h1>ReactPy Forms Test Page</h1>
<h1>ReactPy Form Test Page</h1>
<hr>
{% component "test_app.forms.components.basic_form" %}
<hr>
Expand Down
26 changes: 26 additions & 0 deletions tests/test_app/templates/sync_event_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% load static %} {% load reactpy %}
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}" />
<title>ReactPy</title>
<style>
iframe {
width: 100%;
height: 45px;
}
</style>
</head>

<body>
<h1>ReactPy Sync Event Form Test Page</h1>
<hr>
{% component "test_app.forms.components.sync_event_form" %}
<hr>
</body>

</html>
76 changes: 75 additions & 1 deletion tests/test_app/tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import socket
from time import sleep
from uuid import uuid4

import pytest
from playwright.sync_api import TimeoutError, expect
Expand Down Expand Up @@ -782,6 +783,7 @@ def test_bootstrap_form(self):
def test_model_form(self):
navigate_to_page(self, "/form/model/")

uuid = uuid4().hex
self.page.wait_for_selector("form")

sleep(1)
Expand All @@ -792,8 +794,9 @@ def test_model_form(self):
assert len(self.page.query_selector_all(".errorlist")) == 1

# Fill out the form
self.page.locator("#id_text").type("test", delay=CLICK_DELAY)
self.page.locator("#id_text").type(uuid, delay=CLICK_DELAY)

# Submit the form
self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY)

# Wait for the error message to disappear (indicating that the form has been re-rendered)
Expand All @@ -803,4 +806,75 @@ def test_model_form(self):
assert len(self.page.query_selector_all(".errorlist")) == 0

# Make sure text field is empty
expect(self.page.locator("#id_text")).to_be_empty()
assert self.page.locator("#id_text").get_attribute("value") == ""

# Check if `auto_save` created the TodoItem's database entry
try:
from test_app.models import TodoItem

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"

assert TodoItem.objects.filter(text=uuid).exists()
finally:
os.environ.pop("DJANGO_ALLOW_ASYNC_UNSAFE")

def test_sync_form_events(self):
navigate_to_page(self, "/form/sync_event/")
self.page.wait_for_selector("form")

# Check initial state
self.page.wait_for_selector("#success[data-value='false']")
self.page.wait_for_selector("#error[data-value='false']")
self.page.wait_for_selector("#receive_data[data-value='false']")
self.page.wait_for_selector("#change[data-value='false']")

# Submit empty the form
sleep(1)
self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY)

# The empty form was submitted, should result in an error
self.page.wait_for_selector("#success[data-value='false']")
self.page.wait_for_selector("#error[data-value='true']")
self.page.wait_for_selector("#receive_data[data-value='true']")
self.page.wait_for_selector("#change[data-value='false']")

# Fill out the form and re-submit
self.page.wait_for_selector("#id_char_field").type("test", delay=CLICK_DELAY)
self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY)

# Form should have been successfully submitted
self.page.wait_for_selector("#success[data-value='true']")
self.page.wait_for_selector("#error[data-value='true']")
self.page.wait_for_selector("#receive_data[data-value='true']")
self.page.wait_for_selector("#change[data-value='true']")

def test_async_form_events(self):
navigate_to_page(self, "/form/async_event/")
self.page.wait_for_selector("form")

# Check initial state
self.page.wait_for_selector("#success[data-value='false']")
self.page.wait_for_selector("#error[data-value='false']")
self.page.wait_for_selector("#receive_data[data-value='false']")
self.page.wait_for_selector("#change[data-value='false']")

# Submit empty the form
sleep(1)
self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY)

# The empty form was submitted, should result in an error
self.page.wait_for_selector("#success[data-value='false']")
self.page.wait_for_selector("#error[data-value='true']")
self.page.wait_for_selector("#receive_data[data-value='true']")
self.page.wait_for_selector("#change[data-value='false']")

# Fill out the form and re-submit
self.page.wait_for_selector("#id_char_field").type("test", delay=CLICK_DELAY)
self.page.wait_for_selector("input[type=submit]").click(delay=CLICK_DELAY)

# Form should have been successfully submitted
self.page.wait_for_selector("#success[data-value='true']")
self.page.wait_for_selector("#error[data-value='true']")
self.page.wait_for_selector("#receive_data[data-value='true']")
self.page.wait_for_selector("#change[data-value='true']")

0 comments on commit 55daaa2

Please sign in to comment.