entities/test/unittest_base.py
changeset 0 b97547f5f1fa
child 1016 26387b836099
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 # -*- coding: utf-8 -*-
       
     2 """unit tests for cubicweb.entities.base module"""
       
     3 
       
     4 from mx.DateTime import now
       
     5 
       
     6 from logilab.common.testlib import unittest_main
       
     7 from logilab.common.decorators import clear_cache
       
     8 from logilab.common.interface import implements
       
     9 
       
    10 from cubicweb.devtools.apptest import EnvBasedTC
       
    11 
       
    12 from cubicweb import ValidationError
       
    13 from cubicweb.interfaces import IMileStone, IWorkflowable
       
    14 from cubicweb.entities import AnyEntity
       
    15 from cubicweb.entities.authobjs import EUser
       
    16 from cubicweb.web.widgets import AutoCompletionWidget
       
    17 
       
    18 
       
    19 class BaseEntityTC(EnvBasedTC):
       
    20 
       
    21     def setup_database(self):
       
    22         self.member = self.create_user('member')
       
    23     
       
    24                      
       
    25     
       
    26 class MetadataTC(BaseEntityTC):
       
    27 
       
    28     def test_creator(self):
       
    29         self.login(u'member')
       
    30         card = self.add_entity('Card', title=u"hello")
       
    31         self.commit()
       
    32         self.assertEquals(card.creator.eid, self.member.eid)
       
    33         self.assertEquals(card.dc_creator(), u'member')
       
    34 
       
    35     def test_type(self):
       
    36         self.assertEquals(self.member.dc_type(), 'euser')
       
    37 
       
    38     def test_custom_widget(self):
       
    39         class EUser2(EUser):
       
    40             widgets = {
       
    41                 'login' : 'AutoCompletionWidget',
       
    42                 }
       
    43         clear_cache(self.vreg, 'etype_class')
       
    44         self.vreg.register_vobject_class(EUser2)
       
    45         p = self.entity('EUser U WHERE U login "member"')
       
    46         self.failUnless(isinstance(p, EUser2))
       
    47         w = p.get_widget('login')
       
    48         self.failUnless(isinstance(w, AutoCompletionWidget))
       
    49 
       
    50     def test_format_vocabulary(self):
       
    51         card = self.add_entity('Card', title=u"hello")
       
    52         self.assertEquals(card.default_content_format(), 'text/html')
       
    53         self.execute('INSERT EProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
       
    54         self.commit()
       
    55         self.assertEquals(card.default_content_format(), 'text/rest')
       
    56         
       
    57 
       
    58 
       
    59 class EUserTC(BaseEntityTC):
       
    60     def test_dc_title_and_name(self):
       
    61         e = self.entity('EUser U WHERE U login "member"')
       
    62         self.assertEquals(e.dc_title(), 'member')
       
    63         self.assertEquals(e.name(), 'member')
       
    64         self.execute(u'SET X firstname "bouah" WHERE X is EUser, X login "member"')
       
    65         self.assertEquals(e.dc_title(), 'member')
       
    66         self.assertEquals(e.name(), u'bouah')
       
    67         self.execute(u'SET X surname "lôt" WHERE X is EUser, X login "member"')
       
    68         self.assertEquals(e.dc_title(), 'member')
       
    69         self.assertEquals(e.name(), u'bouah lôt')
       
    70 
       
    71     
       
    72 class StateAndTransitionsTC(BaseEntityTC):
       
    73         
       
    74     def test_transitions(self):
       
    75         user = self.entity('EUser X')
       
    76         e = self.entity('State S WHERE S name "activated"')
       
    77         trs = list(e.transitions(user))
       
    78         self.assertEquals(len(trs), 1)
       
    79         self.assertEquals(trs[0].name, u'deactivate')
       
    80         self.assertEquals(trs[0].destination().name, u'deactivated')
       
    81         self.assert_(user.can_pass_transition('deactivate'))
       
    82         self.assert_(not user.can_pass_transition('activate'))
       
    83         # test a std user get no possible transition
       
    84         self.login('member')
       
    85         # fetch the entity using the new session
       
    86         e = self.entity('State S WHERE S name "activated"')
       
    87         trs = list(e.transitions(user))
       
    88         self.assertEquals(len(trs), 0)
       
    89         user = self.entity('EUser X')
       
    90         self.assert_(not user.can_pass_transition('deactivate'))
       
    91         self.assert_(not user.can_pass_transition('activate'))
       
    92         
       
    93     def test_transitions_with_dest_specfied(self):
       
    94         user = self.entity('EUser X')
       
    95         e = self.entity('State S WHERE S name "activated"')
       
    96         e2 = self.entity('State S WHERE S name "deactivated"')
       
    97         trs = list(e.transitions(user, e2.eid))
       
    98         self.assertEquals(len(trs), 1)
       
    99         self.assertEquals(trs[0].name, u'deactivate')
       
   100         self.assertEquals(trs[0].destination().name, u'deactivated')
       
   101         trs = list(e.transitions(user, e.eid))
       
   102         self.assertEquals(len(trs), 0)
       
   103     
       
   104     def test_transitions_maybe_passed(self):
       
   105         self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
       
   106                      'X expression "X owned_by U", T condition X '
       
   107                      'WHERE T name "deactivate"')
       
   108         self._test_deactivated()
       
   109         
       
   110     def test_transitions_maybe_passed_using_has_update_perm(self):
       
   111         self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
       
   112                      'X expression "U has_update_permission X", T condition X '
       
   113                      'WHERE T name "deactivate"')
       
   114         self._test_deactivated()
       
   115         
       
   116         
       
   117     def _test_deactivated(self):
       
   118         ueid = self.create_user('toto').eid
       
   119         self.create_user('tutu')
       
   120         cnx = self.login('tutu')
       
   121         cu = cnx.cursor()
       
   122         self.assertRaises(ValidationError,
       
   123                           cu.execute, 'SET X in_state S WHERE X eid %(x)s, S name "deactivated"',
       
   124                           {'x': ueid}, 'x')
       
   125         cnx.close()
       
   126         cnx = self.login('toto')
       
   127         cu = cnx.cursor()
       
   128         cu.execute('SET X in_state S WHERE X eid %(x)s, S name "deactivated"',
       
   129                    {'x': ueid}, 'x')
       
   130         cnx.commit()
       
   131         self.assertRaises(ValidationError,
       
   132                           cu.execute, 'SET X in_state S WHERE X eid %(x)s, S name "activated"',
       
   133                           {'x': ueid}, 'x')
       
   134     
       
   135 
       
   136     def test_transitions_selection(self):
       
   137         """
       
   138         ------------------------  tr1    -----------------
       
   139         | state1 (Card, Bookmark) | ------> | state2 (Card) |
       
   140         ------------------------         -----------------
       
   141                   |  tr2    ------------------
       
   142                   `------>  | state3 (Bookmark) |
       
   143                             ------------------
       
   144         """
       
   145         state1 = self.add_entity('State', name=u'state1')
       
   146         state2 = self.add_entity('State', name=u'state2')
       
   147         state3 = self.add_entity('State', name=u'state3')
       
   148         tr1 = self.add_entity('Transition', name=u'tr1')
       
   149         tr2 = self.add_entity('Transition', name=u'tr2')
       
   150         self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is EEType, Y name "Card"' %
       
   151                       (state1.eid, state2.eid))
       
   152         self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is EEType, Y name "Bookmark"' %
       
   153                       (state1.eid, state3.eid))
       
   154         self.execute('SET X transition_of Y WHERE X eid %s, Y name "Card"' % tr1.eid)
       
   155         self.execute('SET X transition_of Y WHERE X eid %s, Y name "Bookmark"' % tr2.eid)
       
   156         self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
       
   157                       (state1.eid, tr1.eid))
       
   158         self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
       
   159                       (state1.eid, tr2.eid))
       
   160         self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
       
   161                       (tr1.eid, state2.eid))
       
   162         self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
       
   163                       (tr2.eid, state3.eid))
       
   164         self.execute('SET X initial_state Y WHERE Y eid %s, X name "Card"' % state1.eid)
       
   165         self.execute('SET X initial_state Y WHERE Y eid %s, X name "Bookmark"' % state1.eid)
       
   166         card = self.add_entity('Card', title=u't1')
       
   167         bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
       
   168         
       
   169         transitions = list(state1.transitions(card))
       
   170         self.assertEquals(len(transitions), 1)
       
   171         self.assertEquals(transitions[0].name, 'tr1')
       
   172         transitions = list(state1.transitions(bookmark))
       
   173         self.assertEquals(len(transitions), 1)
       
   174         self.assertEquals(transitions[0].name, 'tr2')
       
   175         
       
   176 
       
   177     def test_transitions_selection2(self):
       
   178         """
       
   179         ------------------------  tr1 (Bookmark)   -----------------------
       
   180         | state1 (Card, Bookmark) | -------------> | state2 (Card,Bookmark) |
       
   181         ------------------------                -----------------------
       
   182                   |  tr2 (Card)                     |
       
   183                   `---------------------------------/
       
   184         """
       
   185         state1 = self.add_entity('State', name=u'state1')
       
   186         state2 = self.add_entity('State', name=u'state2')
       
   187         tr1 = self.add_entity('Transition', name=u'tr1')
       
   188         tr2 = self.add_entity('Transition', name=u'tr2')
       
   189         self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is EEType, Y name "Card"' %
       
   190                       (state1.eid, state2.eid))
       
   191         self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is EEType, Y name "Bookmark"' %
       
   192                       (state1.eid, state2.eid))
       
   193         self.execute('SET X transition_of Y WHERE X eid %s, Y name "Card"' % tr1.eid)
       
   194         self.execute('SET X transition_of Y WHERE X eid %s, Y name "Bookmark"' % tr2.eid)
       
   195         self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
       
   196                       (state1.eid, tr1.eid))
       
   197         self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
       
   198                       (state1.eid, tr2.eid))
       
   199         self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
       
   200                       (tr1.eid, state2.eid))
       
   201         self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
       
   202                       (tr2.eid, state2.eid))
       
   203         self.execute('SET X initial_state Y WHERE Y eid %s, X name "Card"' % state1.eid)
       
   204         self.execute('SET X initial_state Y WHERE Y eid %s, X name "Bookmark"' % state1.eid)
       
   205         card = self.add_entity('Card', title=u't1')
       
   206         bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
       
   207         
       
   208         transitions = list(state1.transitions(card))
       
   209         self.assertEquals(len(transitions), 1)
       
   210         self.assertEquals(transitions[0].name, 'tr1')
       
   211         transitions = list(state1.transitions(bookmark))
       
   212         self.assertEquals(len(transitions), 1)
       
   213         self.assertEquals(transitions[0].name, 'tr2')
       
   214         
       
   215 
       
   216 class EmailAddressTC(BaseEntityTC):
       
   217     def test_canonical_form(self):
       
   218         eid1 = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"')[0][0]
       
   219         eid2 = self.execute('INSERT EmailAddress X: X address "maarten@philips.com", X canonical TRUE')[0][0]
       
   220         self.execute('SET X identical_to Y WHERE X eid %s, Y eid %s' % (eid1, eid2))
       
   221         email1 = self.entity('Any X WHERE X eid %(x)s', {'x':eid1}, 'x')
       
   222         email2 = self.entity('Any X WHERE X eid %(x)s', {'x':eid2}, 'x')
       
   223         self.assertEquals(email1.canonical_form().eid, eid2)
       
   224         self.assertEquals(email2.canonical_form(), email2)
       
   225         eid3 = self.execute('INSERT EmailAddress X: X address "toto@logilab.fr"')[0][0]
       
   226         email3 = self.entity('Any X WHERE X eid %s'%eid3)
       
   227         self.assertEquals(email3.canonical_form(), None)
       
   228 
       
   229     def test_mangling(self):
       
   230         eid = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"')[0][0]
       
   231         email = self.entity('Any X WHERE X eid %(x)s', {'x':eid}, 'x')
       
   232         self.assertEquals(email.display_address(), 'maarten.ter.huurne@philips.com')
       
   233         self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne@philips.com')
       
   234         self.vreg.config.global_set_option('mangle-emails', True)
       
   235         self.assertEquals(email.display_address(), 'maarten.ter.huurne at philips dot com')
       
   236         self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne at philips dot com')
       
   237         eid = self.execute('INSERT EmailAddress X: X address "syt"')[0][0]
       
   238         email = self.entity('Any X WHERE X eid %(x)s', {'x':eid}, 'x')
       
   239         self.assertEquals(email.display_address(), 'syt')
       
   240         self.assertEquals(email.printable_value('address'), 'syt')
       
   241 
       
   242 
       
   243 class EUserTC(BaseEntityTC):
       
   244     
       
   245     def test_complete(self):
       
   246         e = self.entity('EUser X WHERE X login "admin"')
       
   247         e.complete()
       
   248 
       
   249         
       
   250     def test_matching_groups(self):
       
   251         e = self.entity('EUser X WHERE X login "admin"')
       
   252         self.failUnless(e.matching_groups('managers'))
       
   253         self.failIf(e.matching_groups('xyz'))
       
   254         self.failUnless(e.matching_groups(('xyz', 'managers')))
       
   255         self.failIf(e.matching_groups(('xyz', 'abcd')))
       
   256 
       
   257     def test_subject_in_state_vocabulary(self):
       
   258         # on a new entity
       
   259         e = self.etype_instance('EUser')
       
   260         rschema = e.e_schema.subject_relation('in_state')
       
   261         states = list(e.subject_in_state_vocabulary(rschema))
       
   262         self.assertEquals(len(states), 1)
       
   263         self.assertEquals(states[0][0], u'activated') # list of (combobox view, state eid)
       
   264         # on an existant entity
       
   265         e = self.entity('Any X WHERE X is EUser')
       
   266         self.assertEquals(e.in_state[0].name, 'activated')
       
   267         states = list(e.subject_in_state_vocabulary(rschema))
       
   268         self.assertEquals(len(states), 1)
       
   269         self.assertEquals(states[0][0], u'deactivated') # list of (combobox view, state eid)
       
   270 
       
   271     def test_workflow_base(self):
       
   272         e = self.create_user('toto')
       
   273         self.assertEquals(e.state, 'activated')
       
   274         activatedeid = self.execute('State X WHERE X name "activated"')[0][0]
       
   275         deactivatedeid = self.execute('State X WHERE X name "deactivated"')[0][0]
       
   276         e.change_state(deactivatedeid, u'deactivate 1')
       
   277         self.commit()
       
   278         e.change_state(activatedeid, u'activate 1')
       
   279         self.commit()
       
   280         e.change_state(deactivatedeid, u'deactivate 2')
       
   281         self.commit()
       
   282         # get a fresh user to avoid potential cache issues
       
   283         e = self.entity('EUser X WHERE X eid %s' % e.eid)
       
   284         self.assertEquals([tr.comment for tr in e.reverse_wf_info_for],
       
   285                           [None, 'deactivate 1', 'activate 1', 'deactivate 2'])
       
   286         self.assertEquals(e.latest_trinfo().comment, 'deactivate 2')
       
   287 
       
   288 
       
   289 class InterfaceTC(EnvBasedTC):
       
   290 
       
   291     def test_nonregr_subclasses_and_mixins_interfaces(self):
       
   292         class MyUser(EUser):
       
   293             __implements__ = (IMileStone,)
       
   294         self.vreg.register_vobject_class(MyUser)
       
   295         self.failUnless(implements(EUser, IWorkflowable))
       
   296         self.failUnless(implements(MyUser, IMileStone))
       
   297         self.failUnless(implements(MyUser, IWorkflowable))
       
   298 
       
   299 
       
   300 class SpecializedEntityClassesTC(EnvBasedTC):
       
   301 
       
   302     def select_eclass(self, etype):
       
   303         # clear selector cache
       
   304         clear_cache(self.vreg, 'etype_class')
       
   305         return self.vreg.etype_class(etype)
       
   306         
       
   307     def test_etype_class_selection_and_specialization(self):
       
   308         # no specific class for Subdivisions, the default one should be selected
       
   309         eclass = self.select_eclass('SubDivision')
       
   310         self.failUnless(eclass.__autogenerated__)
       
   311         #self.assertEquals(eclass.__bases__, (AnyEntity,))
       
   312         # build class from most generic to most specific and make
       
   313         # sure the most specific is always selected
       
   314         for etype in ('Company', 'Division', 'SubDivision'):
       
   315             class Foo(AnyEntity):
       
   316                 id = etype
       
   317             self.vreg.register_vobject_class(Foo)
       
   318             eclass = self.select_eclass('SubDivision')
       
   319             if etype == 'SubDivision':
       
   320                 self.failUnless(eclass is Foo)
       
   321             else:
       
   322                 self.failUnless(eclass.__autogenerated__)
       
   323                 self.assertEquals(eclass.__bases__, (Foo,))
       
   324         # check Division eclass is still selected for plain Division entities
       
   325         eclass = self.select_eclass('Division')
       
   326         self.assertEquals(eclass.id, 'Division')
       
   327         
       
   328 if __name__ == '__main__':
       
   329     unittest_main()