web/test/unittest_form.py
changeset 4172 4d4cef034eec
parent 3998 94cc7cad3d2d
child 4252 6c4f109c2b03
equal deleted inserted replaced
4171:f1b9f0ed1253 4172:4d4cef034eec
    13 from logilab.common.compat import any
    13 from logilab.common.compat import any
    14 
    14 
    15 from cubicweb import Binary
    15 from cubicweb import Binary
    16 from cubicweb.devtools.testlib import CubicWebTC
    16 from cubicweb.devtools.testlib import CubicWebTC
    17 from cubicweb.web.formfields import (IntField, StringField, RichTextField,
    17 from cubicweb.web.formfields import (IntField, StringField, RichTextField,
    18                                      DateTimeField, DateTimePicker,
    18                                      PasswordField, DateTimeField, DateTimePicker,
    19                                      FileField, EditableFileField)
    19                                      FileField, EditableFileField)
    20 from cubicweb.web.formwidgets import PasswordInput, Input
    20 from cubicweb.web.formwidgets import PasswordInput, Input
    21 from cubicweb.web.views.forms import EntityFieldsForm, FieldsForm
    21 from cubicweb.web.views.forms import EntityFieldsForm, FieldsForm
    22 from cubicweb.web.views.workflow import ChangeStateForm
    22 from cubicweb.web.views.workflow import ChangeStateForm
    23 from cubicweb.web.views.formrenderers import FormRenderer
    23 from cubicweb.web.views.formrenderers import FormRenderer
    25 
    25 
    26 class FieldsFormTC(CubicWebTC):
    26 class FieldsFormTC(CubicWebTC):
    27 
    27 
    28     def test_form_field_format(self):
    28     def test_form_field_format(self):
    29         form = FieldsForm(self.request(), None)
    29         form = FieldsForm(self.request(), None)
    30         self.assertEquals(form.form_field_format(None), 'text/html')
    30         self.assertEquals(StringField().format(form), 'text/html')
    31         self.execute('INSERT CWProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
    31         self.execute('INSERT CWProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
    32         self.commit()
    32         self.commit()
    33         self.assertEquals(form.form_field_format(None), 'text/rest')
    33         self.assertEquals(StringField().format(form), 'text/rest')
    34 
    34 
    35 
    35 
    36 class EntityFieldsFormTC(CubicWebTC):
    36 class EntityFieldsFormTC(CubicWebTC):
    37 
    37 
    38     def setUp(self):
    38     def setUp(self):
    39         super(EntityFieldsFormTC, self).setUp()
    39         super(EntityFieldsFormTC, self).setUp()
    40         self.req = self.request()
    40         self.req = self.request()
    41         self.entity = self.user(self.req)
    41         self.entity = self.user(self.req)
    42 
    42 
    43     def test_form_field_vocabulary_unrelated(self):
    43     def test_form_field_vocabulary_unrelated(self):
    44         b = self.add_entity('BlogEntry', title=u'di mascii code', content=u'a best-seller')
    44         b = self.req.create_entity('BlogEntry', title=u'di mascii code', content=u'a best-seller')
    45         t = self.add_entity('Tag', name=u'x')
    45         t = self.req.create_entity('Tag', name=u'x')
    46         form1 = EntityFieldsForm(self.request(), None, entity=t)
    46         form1 = self.vreg['forms'].select('edition', self.req, entity=t)
    47         unrelated = [reid for rview, reid in form1.subject_relation_vocabulary('tags')]
    47         unrelated = [reid for rview, reid in form1.field_by_name('tags', 'subject', t.e_schema).choices(form1)]
    48         self.failUnless(b.eid in unrelated, unrelated)
    48         self.failUnless(b.eid in unrelated, unrelated)
    49         form2 = EntityFieldsForm(self.request(), None, entity=b)
    49         form2 = self.vreg['forms'].select('edition', self.req, entity=b)
    50         unrelated = [reid for rview, reid in form2.object_relation_vocabulary('tags')]
    50         unrelated = [reid for rview, reid in form2.field_by_name('tags', 'object', t.e_schema).choices(form2)]
    51         self.failUnless(t.eid in unrelated, unrelated)
    51         self.failUnless(t.eid in unrelated, unrelated)
    52         self.execute('SET X tags Y WHERE X is Tag, Y is BlogEntry')
    52         self.execute('SET X tags Y WHERE X is Tag, Y is BlogEntry')
    53         unrelated = [reid for rview, reid in form1.subject_relation_vocabulary('tags')]
    53         unrelated = [reid for rview, reid in form1.field_by_name('tags', 'subject', t.e_schema).choices(form1)]
    54         self.failIf(b.eid in unrelated, unrelated)
    54         self.failIf(b.eid in unrelated, unrelated)
    55         unrelated = [reid for rview, reid in form2.object_relation_vocabulary('tags')]
    55         unrelated = [reid for rview, reid in form2.field_by_name('tags', 'object', t.e_schema).choices(form2)]
    56         self.failIf(t.eid in unrelated, unrelated)
    56         self.failIf(t.eid in unrelated, unrelated)
    57 
    57 
    58 
    58 
    59     def test_form_field_vocabulary_new_entity(self):
    59     def test_form_field_vocabulary_new_entity(self):
    60         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    60         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    61         form = EntityFieldsForm(e.req, None, entity=e)
    61         form = self.vreg['forms'].select('edition', self.req, entity=e)
    62         unrelated = [rview for rview, reid in form.subject_relation_vocabulary('in_group')]
    62         unrelated = [rview for rview, reid in form.field_by_name('in_group', 'subject').choices(form)]
    63         # should be default groups but owners, i.e. managers, users, guests
    63         # should be default groups but owners, i.e. managers, users, guests
    64         self.assertEquals(unrelated, [u'guests', u'managers', u'users'])
    64         self.assertEquals(unrelated, [u'guests', u'managers', u'users'])
    65 
       
    66     # def test_subject_in_state_vocabulary(self):
       
    67     #     # on a new entity
       
    68     #     e = self.etype_instance('CWUser')
       
    69     #     form = EntityFieldsForm(self.request(), None, entity=e)
       
    70     #     states = list(form.subject_in_state_vocabulary('in_state'))
       
    71     #     self.assertEquals(len(states), 1)
       
    72     #     self.assertEquals(states[0][0], u'activated') # list of (combobox view, state eid)
       
    73     #     # on an existant entity
       
    74     #     e = self.user()
       
    75     #     form = EntityFieldsForm(self.request(), None, entity=e)
       
    76     #     states = list(form.subject_in_state_vocabulary('in_state'))
       
    77     #     self.assertEquals(len(states), 1)
       
    78     #     self.assertEquals(states[0][0], u'deactivated') # list of (combobox view, state eid)
       
    79 
    65 
    80     def test_consider_req_form_params(self):
    66     def test_consider_req_form_params(self):
    81         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    67         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    82         e.eid = 'A'
    68         e.eid = 'A'
    83         form = EntityFieldsForm(self.request(login=u'toto'), None, entity=e)
    69         form = EntityFieldsForm(self.request(login=u'toto'), None, entity=e)
    84         field = StringField(name='login', eidparam=True)
    70         field = StringField(name='login', eidparam=True)
    85         form.append_field(field)
    71         form.append_field(field)
    86         form.build_context({})
    72         form.build_context({})
    87         self.assertEquals(form.form_field_display_value(field, {}), 'toto')
    73         self.assertEquals(field.display_value(form), 'toto')
    88 
    74 
    89 
    75 
    90     def test_linkto_field_duplication(self):
    76     def test_linkto_field_duplication(self):
    91         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    77         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
    92         e.eid = 'A'
    78         e.eid = 'A'
    93         e.req = self.req
    79         e._cw = self.req
    94         geid = self.execute('CWGroup X WHERE X name "users"')[0][0]
    80         geid = self.execute('CWGroup X WHERE X name "users"')[0][0]
    95         self.req.form['__linkto'] = 'in_group:%s:subject' % geid
    81         self.req.form['__linkto'] = 'in_group:%s:subject' % geid
    96         form = self.vreg['forms'].select('edition', self.req, entity=e)
    82         form = self.vreg['forms'].select('edition', self.req, entity=e)
    97         form.content_type = 'text/html'
    83         form.content_type = 'text/html'
    98         pageinfo = self._check_html(form.render(), form, template=None)
    84         pageinfo = self._check_html(form.render(), form, template=None)
    99         inputs = pageinfo.find_tag('select', False)
    85         inputs = pageinfo.find_tag('select', False)
   100         self.failUnless(any(attrs for t, attrs in inputs if attrs.get('name') == 'in_group:A'))
    86         self.failUnless(any(attrs for t, attrs in inputs if attrs.get('name') == 'in_group-subject:A'))
   101         inputs = pageinfo.find_tag('input', False)
    87         inputs = pageinfo.find_tag('input', False)
   102         self.failIf(any(attrs for t, attrs in inputs if attrs.get('name') == '__linkto'))
    88         self.failIf(any(attrs for t, attrs in inputs if attrs.get('name') == '__linkto'))
   103 
    89 
   104     def test_reledit_composite_field(self):
    90     def test_reledit_composite_field(self):
   105         rset = self.execute('INSERT BlogEntry X: X title "cubicweb.org", X content "hop"')
    91         rset = self.execute('INSERT BlogEntry X: X title "cubicweb.org", X content "hop"')
   106         form = self.vreg['views'].select('doreledit', self.request(),
    92         form = self.vreg['views'].select('doreledit', self.request(),
   107                                          rset=rset, row=0, rtype='content')
    93                                          rset=rset, row=0, rtype='content')
   108         data = form.render(row=0, rtype='content')
    94         data = form.render(row=0, rtype='content')
   109         self.failUnless('edits-content' in data)
    95         self.failUnless('content_format' in data)
   110         self.failUnless('edits-content_format' in data)
       
   111 
    96 
   112     # form view tests #########################################################
    97     # form view tests #########################################################
   113 
    98 
   114     def test_massmailing_formview(self):
    99     def test_massmailing_formview(self):
   115         self.execute('INSERT EmailAddress X: X address L + "@cubicweb.org", '
   100         self.execute('INSERT EmailAddress X: X address L + "@cubicweb.org", '
   138     # fields tests ############################################################
   123     # fields tests ############################################################
   139 
   124 
   140     def _render_entity_field(self, name, form):
   125     def _render_entity_field(self, name, form):
   141         form.build_context({})
   126         form.build_context({})
   142         renderer = FormRenderer(self.req)
   127         renderer = FormRenderer(self.req)
   143         return form.field_by_name(name).render(form, renderer)
   128         return form.field_by_name(name, 'subject').render(form, renderer)
   144 
   129 
   145     def _test_richtextfield(self, expected):
   130     def _test_richtextfield(self, expected):
   146         class RTFForm(EntityFieldsForm):
   131         class RTFForm(EntityFieldsForm):
   147             description = RichTextField()
   132             description = RichTextField(eidparam=True, role='subject')
   148         state = self.execute('State X WHERE X name "activated", X state_of WF, WF workflow_of ET, ET name "CWUser"').get_entity(0, 0)
   133         state = self.execute('State X WHERE X name "activated", X state_of WF, WF workflow_of ET, ET name "CWUser"').get_entity(0, 0)
   149         form = RTFForm(self.req, redirect_path='perdu.com', entity=state)
   134         form = RTFForm(self.req, redirect_path='perdu.com', entity=state)
   150         # make it think it can use fck editor anyway
   135         # make it think it can use fck editor anyway
   151         form.form_field_format = lambda x: 'text/html'
   136         form.field_by_name('description', 'subject').format = lambda x: 'text/html'
   152         self.assertTextEquals(self._render_entity_field('description', form),
   137         self.assertTextEquals(self._render_entity_field('description', form),
   153                               expected % {'eid': state.eid})
   138                               expected % {'eid': state.eid})
   154 
   139 
   155 
   140 
   156     def test_richtextfield_1(self):
   141     def test_richtextfield_1(self):
   157         self.req.use_fckeditor = lambda: False
   142         self.req.use_fckeditor = lambda: False
   158         self._test_richtextfield('''<select id="description_format:%(eid)s" name="description_format:%(eid)s" size="1" style="display: block" tabindex="1">
   143         self._test_richtextfield('''<select id="description_format-subject:%(eid)s" name="description_format-subject:%(eid)s" size="1" style="display: block" tabindex="1">
   159 <option value="text/cubicweb-page-template">text/cubicweb-page-template</option>
   144 <option value="text/cubicweb-page-template">text/cubicweb-page-template</option>
   160 <option value="text/html">text/html</option>
   145 <option selected="selected" value="text/html">text/html</option>
   161 <option value="text/plain">text/plain</option>
   146 <option value="text/plain">text/plain</option>
   162 <option selected="selected" value="text/rest">text/rest</option>
   147 <option value="text/rest">text/rest</option>
   163 </select><textarea cols="80" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="2"></textarea>''')
   148 </select><textarea cols="80" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="2"></textarea>''')
   164 
   149 
   165 
   150 
   166     def test_richtextfield_2(self):
   151     def test_richtextfield_2(self):
   167         self.req.use_fckeditor = lambda: True
   152         self.req.use_fckeditor = lambda: True
   168         self._test_richtextfield('<input name="description_format:%(eid)s" type="hidden" value="text/rest" /><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="1"></textarea>')
   153         self._test_richtextfield('<input name="description_format-subject:%(eid)s" type="hidden" value="text/html" /><textarea cols="80" cubicweb:type="wysiwyg" id="description-subject:%(eid)s" name="description-subject:%(eid)s" onkeyup="autogrow(this)" rows="2" tabindex="1"></textarea>')
   169 
   154 
   170 
   155 
   171     def test_filefield(self):
   156     def test_filefield(self):
   172         class FFForm(EntityFieldsForm):
   157         class FFForm(EntityFieldsForm):
   173             data = FileField(format_field=StringField(name='data_format', max_length=50),
   158             data = FileField(
   174                              encoding_field=StringField(name='data_encoding', max_length=20))
   159                 format_field=StringField(name='data_format', max_length=50,
   175         file = self.add_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
   160                                          eidparam=True, role='subject'),
       
   161                 encoding_field=StringField(name='data_encoding', max_length=20,
       
   162                                            eidparam=True, role='subject'),
       
   163                 eidparam=True, role='subject')
       
   164         file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
   176                                data=Binary('new widgets system'))
   165                                data=Binary('new widgets system'))
   177         form = FFForm(self.req, redirect_path='perdu.com', entity=file)
   166         form = FFForm(self.req, redirect_path='perdu.com', entity=file)
   178         self.assertTextEquals(self._render_entity_field('data', form),
   167         self.assertTextEquals(self._render_entity_field('data', form),
   179                               '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="1" type="file" value="" />
   168                               '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
   180 <a href="javascript: toggleVisibility(&#39;data:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
   169 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
   181 <div id="data:%(eid)s-advanced" class="hidden">
   170 <div id="data-subject:%(eid)s-advanced" class="hidden">
   182 <label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" maxlength="50" name="data_format:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
   171 <label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
   183 <label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" maxlength="20" name="data_encoding:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
   172 <label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
   184 </div>
   173 </div>
   185 <br/>
   174 <br/>
   186 <input name="data:%(eid)s__detach" type="checkbox" />
   175 <input name="data-subject__detach:%(eid)s" type="checkbox" />
   187 detach attached file
   176 detach attached file
   188 ''' % {'eid': file.eid})
   177 ''' % {'eid': file.eid})
   189 
   178 
   190 
   179 
   191     def test_editablefilefield(self):
   180     def test_editablefilefield(self):
   192         class EFFForm(EntityFieldsForm):
   181         class EFFForm(EntityFieldsForm):
   193             data = EditableFileField(format_field=StringField(name='data_format', max_length=50),
   182             data = EditableFileField(
   194                                      encoding_field=StringField(name='data_encoding', max_length=20))
   183                 format_field=StringField('data_format', max_length=50,
   195             def form_field_encoding(self, field):
   184                                          eidparam=True, role='subject'),
   196                 return 'ascii'
   185                 encoding_field=StringField('data_encoding', max_length=20,
   197             def form_field_format(self, field):
   186                                            eidparam=True, role='subject'),
   198                 return 'text/plain'
   187                 eidparam=True, role='subject')
   199         file = self.add_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
   188         file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
   200                                data=Binary('new widgets system'))
   189                                data=Binary('new widgets system'))
   201         form = EFFForm(self.req, redirect_path='perdu.com', entity=file)
   190         form = EFFForm(self.req, redirect_path='perdu.com', entity=file)
   202         self.assertTextEquals(self._render_entity_field('data', form),
   191         self.assertTextEquals(self._render_entity_field('data', form),
   203                               '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="1" type="file" value="" />
   192                               '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
   204 <a href="javascript: toggleVisibility(&#39;data:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
   193 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
   205 <div id="data:%(eid)s-advanced" class="hidden">
   194 <div id="data-subject:%(eid)s-advanced" class="hidden">
   206 <label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" maxlength="50" name="data_format:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
   195 <label for="data_format-subject:%(eid)s">data_format</label><input id="data_format-subject:%(eid)s" maxlength="50" name="data_format-subject:%(eid)s" size="45" tabindex="2" type="text" value="text/plain" /><br/>
   207 <label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" maxlength="20" name="data_encoding:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
   196 <label for="data_encoding-subject:%(eid)s">data_encoding</label><input id="data_encoding-subject:%(eid)s" maxlength="20" name="data_encoding-subject:%(eid)s" size="20" tabindex="3" type="text" value="UTF-8" /><br/>
   208 </div>
   197 </div>
   209 <br/>
   198 <br/>
   210 <input name="data:%(eid)s__detach" type="checkbox" />
   199 <input name="data-subject__detach:%(eid)s" type="checkbox" />
   211 detach attached file
   200 detach attached file
   212 <p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
   201 <p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
   213 <textarea cols="80" name="data:%(eid)s" onkeyup="autogrow(this)" rows="3" tabindex="4">new widgets system</textarea>''' % {'eid': file.eid})
   202 <textarea cols="80" name="data-subject:%(eid)s" onkeyup="autogrow(this)" rows="3" tabindex="4">new widgets system</textarea>''' % {'eid': file.eid})
   214 
   203 
   215 
   204 
   216     def test_passwordfield(self):
   205     def test_passwordfield(self):
   217         class PFForm(EntityFieldsForm):
   206         class PFForm(EntityFieldsForm):
   218             upassword = StringField(widget=PasswordInput)
   207             upassword = PasswordField(eidparam=True, role='subject')
   219         form = PFForm(self.req, redirect_path='perdu.com', entity=self.entity)
   208         form = PFForm(self.req, redirect_path='perdu.com', entity=self.entity)
   220         self.assertTextEquals(self._render_entity_field('upassword', form),
   209         self.assertTextEquals(self._render_entity_field('upassword', form),
   221                               '''<input id="upassword:%(eid)s" name="upassword:%(eid)s" tabindex="1" type="password" value="__cubicweb_internal_field__" />
   210                               '''<input id="upassword-subject:%(eid)s" name="upassword-subject:%(eid)s" tabindex="1" type="password" value="__cubicweb_internal_field__" />
   222 <br/>
   211 <br/>
   223 <input name="upassword-confirm:%(eid)s" tabindex="1" type="password" value="__cubicweb_internal_field__" />
   212 <input name="upassword-subject-confirm:%(eid)s" tabindex="1" type="password" value="__cubicweb_internal_field__" />
   224 &#160;
   213 &#160;
   225 <span class="emphasis">confirm password</span>''' % {'eid': self.entity.eid})
   214 <span class="emphasis">confirm password</span>''' % {'eid': self.entity.eid})
   226 
   215 
   227 
   216 
   228     def test_datefield(self):
   217     # def test_datefield(self):
   229         class DFForm(EntityFieldsForm):
   218     #     class DFForm(EntityFieldsForm):
   230             creation_date = DateTimeField(widget=Input)
   219     #         creation_date = DateTimeField(widget=Input)
   231         form = DFForm(self.req, entity=self.entity)
   220     #     form = DFForm(self.req, entity=self.entity)
   232         init, cur = (fromstring(self._render_entity_field(attr, form)).get('value')
   221     #     init, cur = (fromstring(self._render_entity_field(attr, form)).get('value')
   233                      for attr in ('edits-creation_date', 'creation_date'))
   222     #                  for attr in ('edits-creation_date', 'creation_date'))
   234         self.assertEquals(init, cur)
   223     #     self.assertEquals(init, cur)
   235 
   224 
   236 if __name__ == '__main__':
   225 if __name__ == '__main__':
   237     unittest_main()
   226     unittest_main()