Skip to content

Introduction of formsets in wizards. #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
23 changes: 22 additions & 1 deletion src/merlin/tests/fixtures/testproject/forms.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
from django import forms

from django.forms import formsets
from django.forms.util import ErrorList

class UserDetailsForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
email = forms.EmailField()

UserDetailsFormSet = formsets.formset_factory(UserDetailsForm)

class UserDetailsFormSet(formsets.BaseFormSet):

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, form=UserDetailsForm,
extra= 1, can_order=False,
can_delete=False, max_num=10):

self.form = form
self.extra = extra
self.can_order = can_order
self.can_delete = can_delete
self.max_num = max_num

super(UserDetailsFormSet, self).__init__(data=data, files=files,
auto_id=auto_id, prefix=prefix,
initial=initial,
error_class=error_class)


class ContactDetailsForm(forms.Form):
street_address = forms.CharField()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "forms/base.html" %}

{% block content %}
<form action="." method="post">{% csrf_token %}
<table>
{{ formset }}
</table>
{% if previous_step %}
<a class="back" href="{{ url_base }}{{ previous_step.slug }}">Back</a>
{% endif %}
{% if next_step %}
<a class="next" href="{{ url_base }}{{ next_step.slug }}">Next</a>
{% else %}
<input type="submit">
{% endif %}
<input type="hidden" name="current_step" value="{{ current_step.slug }}" />
</form>
{% endblock %}
6 changes: 4 additions & 2 deletions src/merlin/tests/fixtures/testproject/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.conf.urls.defaults import *

from merlin.tests.fixtures.testproject.wizard import MockWizard
from merlin.tests.fixtures.testproject.wizard import (MockWizard,
FormSetWizard)
from merlin.wizards.utils import Step
from merlin.wizards.session import SessionWizard

Expand All @@ -17,6 +17,8 @@
url(r'^bettertest/(?P<slug>[A-Za-z0-9_-]+)$', MockWizard([
Step('user-details', forms.UserDetailsForm),
Step('contact-details', forms.ContactDetailsForm)])),
url(r'^formsettest/(?P<slug>[A-Za-z0-9_-]+)$', FormSetWizard([
Step('user-details', forms.UserDetailsFormSet),])),
url(r'^$', views.index, name='test-index'),
url(r'^more$', views.more, name='test-more'),
)
17 changes: 17 additions & 0 deletions src/merlin/tests/fixtures/testproject/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@
from merlin.wizards.utils import Step


class FormSetWizard(SessionWizard):

def get_template(self, request, step, form):
return "forms/formset_wizard.html"

def done(self, request):
form_data = self.get_form_data(request)

assert len(form_data['user-details']) == 1
assert form_data['user-details'][0]['first_name'] == 'Yorgos'
assert form_data['user-details'][0]['last_name'] == 'Pagles'
assert form_data['user-details'][0]['email'] == '[email protected]'

self.clear(request)

return HttpResponse("All done", mimetype="text/plain")

class MockWizard(SessionWizard):
def initialize(self, request, wizard_state):
if not 'global_id' in wizard_state:
Expand Down
48 changes: 48 additions & 0 deletions src/merlin/tests/test_session_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,29 @@ def test_type_error_if_step_is_not_type_step(self):
except Exception as e:
self.fail("We should only fail with a TypeError, exception was %s" % e)

def test_raises_on_duplicate_steps(self):
try:
SessionWizard([
Step('user-details', forms.UserDetailsForm),
Step('user-details', forms.ContactDetailsForm)]
)
self.fail("We shouldn't be allowed to create a SessionWizard "
"with duplicate step names")
except ValueError as ve:
self.assertEquals(ve.message, 'Step slugs must be unique.')

def test_session_wizard_no_slug(self):
response = self.client.get('/simpletest')
self.assertEquals(response.status_code, 404)

def test_session_wizard_wrong_slug(self):
response = self.client.get('/simpletest/qwerty')
self.assertEquals(response.status_code, 404)

def test_method_not_valid(self):
response = self.client.head('/simpletest/user-details')
self.assertEquals(response.status_code, 404)

def test_form_not_valid(self):
response = self.client.get('/simpletest/user-details')
self.assertEquals(response.status_code, 200)
Expand Down Expand Up @@ -153,6 +172,35 @@ def test_session_wizard_cancel_with_redirect(self):
self.assertEquals(response.status_code, 200)


class FormsetWizardTest(TestCase):

def test_mock_wizard(self):
response = self.client.get('/formsettest/user-details')
self.assertEquals(response.status_code, 200)

soup = BeautifulSoup(response.content)

self.assertTrue(soup.find('input', id='id_form-TOTAL_FORMS'))
self.assertTrue(soup.find('input', id='id_form-INITIAL_FORMS'))
self.assertTrue(soup.find('input', id='id_form-MAX_NUM_FORMS'))

self.assertTrue(soup.find('input', id='id_form-0-first_name'))
self.assertTrue(soup.find('input', id='id_form-0-last_name'))
self.assertTrue(soup.find('input', id='id_form-0-email'))

post = self.client.post('/formsettest/user-details', {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-MAX_NUM_FORMS': '3',
'form-0-first_name': 'Yorgos',
'form-0-last_name': 'Pagles',
'form-0-email': '[email protected]'
}, follow=True)

self.assertEquals(post.status_code, 200)
self.assertEquals(post.content, 'All done')


class MockWizardTest(TestCase):

def test_mock_wizard(self):
Expand Down
15 changes: 15 additions & 0 deletions src/merlin/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest

from django.forms.formsets import formset_factory

from merlin.tests.fixtures.testproject.forms import *
from merlin.wizards.utils import *

Expand Down Expand Up @@ -41,6 +43,19 @@ def test_step_object_methods(self):

self.assertEquals('Step: %s' % repr(step1), 'Step: step1')

def test_step_with_formset(self):
"""
Just checks that a step can be created using a formset
"""
UserDetailsFormSet = formset_factory(UserDetailsForm)
step = Step('step', UserDetailsFormSet)

self.assertEqual(step.form, None)
self.assertEqual(step.formset.__class__,
UserDetailsFormSet.__class__)
self.assertEquals(str(step), 'step')
self.assertEquals(unicode(step), u'step')

def test_wizard_expansion(self):
state = WizardState()

Expand Down
Loading