~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Testing LaunchpadFormView Instances
===================================

The LaunchpadFormHarness class is designed to help write tests for
view classes based on LaunchpadFormView.  It provides a convenient way
to check the form's behaviour with different inputs.

To demonstrate its use we'll create a sample schema and view class:

  >>> from zope.interface import Interface, implements
  >>> from zope.schema import Int, TextLine
  >>> from lp.app.browser.launchpadform import LaunchpadFormView, action

  >>> class IHarnessTest(Interface):
  ...     string = TextLine(title=u"String")
  ...     number = Int(title=u"Number")

  >>> class HarnessTest:
  ...     implements(IHarnessTest)
  ...     string = None
  ...     number = 0

  >>> class HarnessTestView(LaunchpadFormView):
  ...     schema = IHarnessTest
  ...     next_url = 'https://launchpad.net/'
  ...
  ...     def validate(self, data):
  ...         if len(data.get('string', '')) == data.get('number'):
  ...             self.addError("number must not be equal to string length")
  ...         if data.get('number') == 7:
  ...             self.setFieldError('number', 'number can not be 7')
  ...
  ...     @action("Submit")
  ...     def submit_action(self, action, data):
  ...         self.context.string = data['string']
  ...         self.context.number = data['number']

We can then create a harness to drive the view:

  >>> from canonical.launchpad.ftests import LaunchpadFormHarness
  >>> context = HarnessTest()
  >>> harness = LaunchpadFormHarness(context, HarnessTestView)

As we haven't submitted the form, there are no errors:

  >>> harness.hasErrors()
  False

If we submit the form with some invalid data, we will have some errors
though:

  >>> harness.submit('submit', {'field.string': 'abcdef',
  ...                           'field.number': '6' })
  >>> harness.hasErrors()
  True

We can then get a list of the whole-form errors:

  >>> for message in harness.getFormErrors():
  ...     print message
  number must not be equal to string length


We can also check for per-widget errors:

  >>> harness.submit('submit', {'field.string': 'abcdef',
  ...                           'field.number': 'not a number' })
  >>> harness.hasErrors()
  True
  >>> print harness.getFieldError('string')
  <BLANKLINE>
  >>> print harness.getFieldError('number')
  Invalid integer data


The getFieldError() method will also return custom error messages set
by setFieldError():

  >>> harness.submit('submit', {'field.string': 'abcdef',
  ...                           'field.number': '7' })
  >>> harness.hasErrors()
  True
  >>> print harness.getFieldError('number')
  number can not be 7


We can check to see if the view tried to redirect us.  When there are
input validation problems, the view will not normally redirect you:

  >>> harness.wasRedirected()
  False

But if we submit correct data to the form and get redirected, we can
see where we were redirected to:

  >>> harness.submit('submit', {'field.string': 'abcdef',
  ...                           'field.number': '42' })
  >>> harness.wasRedirected()
  True
  >>> harness.redirectionTarget()
  'https://launchpad.net/'

We can also see that the context object was updated by this form
submission:

  >>> context.string
  u'abcdef'
  >>> context.number
  42

By default LaunchpadFormHarness uses LaunchpadTestRequest as its request
class, but it's possible to change that by passing a request_class argument to
it.

    >>> harness.request
    <...LaunchpadTestRequest...

    >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest
    >>> class FormHarnessTestRequest(LaunchpadTestRequest):
    ...     pass
    >>> harness = LaunchpadFormHarness(context, HarnessTestView,
    ...     request_class=FormHarnessTestRequest)
    >>> harness.request
    <...FormHarnessTestRequest...