~launchpad-pqm/launchpad/devel

12293.1.11 by Curtis Hovey
Updated copyright.
1
# Copyright 2010-2011 Canonical Ltd.  This software is licensed under the
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4
__metaclass__ = type
5
12828.4.1 by Ian Booth
Fix popup picker non-ajax link and refactor
6
import simplejson
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
7
13107.1.1 by Ian Booth
Rework show_widget_id naming
8
from zope.interface import Interface
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
9
from zope.interface.interface import InterfaceClass
13107.1.1 by Ian Booth
Rework show_widget_id naming
10
from zope.schema import Choice
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
11
from zope.schema.vocabulary import getVocabularyRegistry
12
13
from canonical.launchpad.webapp.servers import LaunchpadTestRequest
14
from canonical.testing.layers import DatabaseFunctionalLayer
13378.1.5 by j.c.sackett
Added tests.
15
from lp.app.widgets.popup import (
16
    PersonPickerWidget,
17
    VocabularyPickerWidget,
18
    )
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
19
from lp.testing import TestCaseWithFactory
20
21
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
22
class TestMetaClass(InterfaceClass):
23
# We want to force creation of a field with an invalid HTML id.
24
    def __init__(self, name, bases=(), attrs=None, __doc__=None,
25
                 __module__=None):
26
        attrs = {
13107.1.6 by Ian Booth
Fix some tests
27
            "test_invalid_chars+":
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
28
            Choice(vocabulary='ValidTeamOwner'),
13107.1.8 by Ian Booth
Refactor to fix tests
29
            "test_valid.item":
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
30
            Choice(vocabulary='ValidTeamOwner')}
31
        super(TestMetaClass, self).__init__(
32
            name, bases=bases, attrs=attrs, __doc__=__doc__,
33
            __module__=__module__)
34
35
36
class ITest(Interface):
37
# The schema class for the widget we will test.
38
    __metaclass__ = TestMetaClass
39
40
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
41
class TestVocabularyPickerWidget(TestCaseWithFactory):
42
43
    layer = DatabaseFunctionalLayer
44
45
    def setUp(self):
46
        super(TestVocabularyPickerWidget, self).setUp()
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
47
        self.context = self.factory.makeTeam()
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
48
        vocabulary_registry = getVocabularyRegistry()
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
49
        self.vocabulary = vocabulary_registry.get(
50
            self.context, 'ValidTeamOwner')
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
51
        self.request = LaunchpadTestRequest()
52
12828.4.1 by Ian Booth
Fix popup picker non-ajax link and refactor
53
    def test_widget_template_properties(self):
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
54
        # Check the picker widget is correctly set up for a field which has a
55
        # name containing only valid HTML ID characters.
56
13107.1.8 by Ian Booth
Refactor to fix tests
57
        field = ITest['test_valid.item']
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
58
        bound_field = field.bind(self.context)
11954.6.17 by Curtis Hovey
Updated VocabularyPickerWidget to use the vocan step_title if the widget does not have
59
        picker_widget = VocabularyPickerWidget(
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
60
            bound_field, self.vocabulary, self.request)
61
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
62
        widget_config = simplejson.loads(picker_widget.json_config)
12828.4.1 by Ian Booth
Fix popup picker non-ajax link and refactor
63
        self.assertEqual(
64
            'ValidTeamOwner', picker_widget.vocabulary_name)
13465.1.1 by Ian Booth
Tidy up picker creation
65
        self.assertEqual(self.vocabulary.displayname, widget_config['header'])
66
        self.assertEqual(self.vocabulary.step_title,
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
67
            widget_config['step_title'])
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
68
        self.assertEqual(
13107.1.8 by Ian Booth
Refactor to fix tests
69
            'show-widget-field-test_valid-item', picker_widget.show_widget_id)
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
70
        self.assertEqual(
13107.1.8 by Ian Booth
Refactor to fix tests
71
            'field.test_valid.item', picker_widget.input_id)
13465.1.1 by Ian Booth
Tidy up picker creation
72
        self.assertIsNone(picker_widget.extra_no_results_message)
13146.1.6 by Curtis Hovey
Added missing test coverage.
73
        markup = picker_widget()
13465.1.1 by Ian Booth
Tidy up picker creation
74
        self.assertTextMatchesExpressionIgnoreWhitespace("""\
75
            .*
13465.1.4 by Ian Booth
Tweaks to fix tests
76
            var picker = Y\\.lp\\.app\\.picker\\.create\\('ValidTeamOwner',
77
                config,
13465.1.1 by Ian Booth
Tidy up picker creation
78
                'field\\.test_valid.item'\\);
79
            .*
80
            """, markup)
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
81
82
    def test_widget_fieldname_with_invalid_html_chars(self):
83
        # Check the picker widget is correctly set up for a field which has a
84
        # name containing some invalid HTML ID characters.
85
13107.1.6 by Ian Booth
Fix some tests
86
        field = ITest['test_invalid_chars+']
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
87
        bound_field = field.bind(self.context)
88
        picker_widget = VocabularyPickerWidget(
89
            bound_field, self.vocabulary, self.request)
90
13107.1.1 by Ian Booth
Rework show_widget_id naming
91
        # The widget name is encoded to get the widget's ID. It must only
92
        # contain valid HTML characters.
93
        self.assertEqual(
13146.1.6 by Curtis Hovey
Added missing test coverage.
94
            'show-widget-field-test_invalid_chars-'
95
            'ZmllbGQudGVzdF9pbnZhbGlkX2NoYXJzKw',
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
96
            picker_widget.show_widget_id)
97
        self.assertEqual(
13107.1.8 by Ian Booth
Refactor to fix tests
98
            'field.test_invalid_chars-ZmllbGQudGVzdF9pbnZhbGlkX2NoYXJzKw',
13107.1.3 by Ian Booth
Encode fields with invalid names but leave valid fields alone
99
            picker_widget.input_id)
13146.1.6 by Curtis Hovey
Added missing test coverage.
100
101
    def test_widget_suggestions(self):
102
        # The suggestions menu is shown when the input is invalid and there
103
        # are matches to suggest to the user.
104
        field = ITest['test_valid.item']
105
        bound_field = field.bind(self.context)
106
        request = LaunchpadTestRequest(form={'field.test_valid.item': 'foo'})
107
        picker_widget = VocabularyPickerWidget(
108
            bound_field, self.vocabulary, request)
109
        matches = list(picker_widget.matches)
110
        self.assertEqual(1, len(matches))
111
        self.assertEqual('Foo Bar', matches[0].title)
112
        markup = picker_widget()
113
        self.assertIn('id="field.test_valid.item-suggestions"', markup)
114
        self.assertIn(
115
            "Y.DOM.byId('field.test_valid.item-suggestions')", markup)
116
        self.assertTextMatchesExpressionIgnoreWhitespace(
117
            'Y.lp.app.picker.connect_select_menu\( '
118
            'select_menu, text_input\);',
119
            markup)
13378.1.5 by j.c.sackett
Added tests.
120
121
    def test_widget_extra_buttons(self):
122
        # The picker widgets define defaults for the display of extra buttons.
123
        field = ITest['test_valid.item']
124
        bound_field = field.bind(self.context)
125
126
        # A vocabulary widget does not show the extra buttons by default.
127
        picker_widget = VocabularyPickerWidget(
128
            bound_field, self.vocabulary, self.request)
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
129
        self.assertEqual('false',
130
            picker_widget.config['show_assign_me_button'])
131
        self.assertEqual('false',
13429.1.6 by Ian Booth
Code review tweaks, rename picker entry meta attribute name to metadata
132
            picker_widget.config['show_remove_button'])
13378.1.5 by j.c.sackett
Added tests.
133
134
        # A person picker widget does show them by default.
135
        person_picker_widget = PersonPickerWidget(
136
            bound_field, self.vocabulary, self.request)
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
137
        self.assertEqual('true',
138
            person_picker_widget.config['show_assign_me_button'])
139
        self.assertEqual('true',
13429.1.6 by Ian Booth
Code review tweaks, rename picker entry meta attribute name to metadata
140
            person_picker_widget.config['show_remove_button'])
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
141
142
    def test_widget_personvalue_meta(self):
143
        # The person picker has the correct meta value for a person value.
144
        person = self.factory.makePerson()
145
        bound_field = ITest['test_valid.item'].bind(person)
146
        person_picker_widget = PersonPickerWidget(
147
            bound_field, self.vocabulary, self.request)
148
        person_picker_widget.setRenderedValue(person)
149
        self.assertEqual('person',
13429.1.6 by Ian Booth
Code review tweaks, rename picker entry meta attribute name to metadata
150
            person_picker_widget.config['selected_value_metadata'])
13429.1.2 by Ian Booth
Add meta attribute support to picker widgets
151
152
    def test_widget_teamvalue_meta(self):
153
        # The person picker has the correct meta value for a team value.
154
        team = self.factory.makeTeam()
155
        bound_field = ITest['test_valid.item'].bind(team)
156
        person_picker_widget = PersonPickerWidget(
157
            bound_field, self.vocabulary, self.request)
158
        person_picker_widget.setRenderedValue(team)
159
        self.assertEqual('team',
13429.1.6 by Ian Booth
Code review tweaks, rename picker entry meta attribute name to metadata
160
            person_picker_widget.config['selected_value_metadata'])