unittest_magicsearch.py 10.6 KB
Newer Older
Adrien Di Mascio's avatar
Adrien Di Mascio committed
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# -*- coding: utf-8 -*-
"""Unit tests for magic_search service"""

import sys

from logilab.common.testlib import TestCase, unittest_main

from rql import BadRQLQuery, RQLSyntaxError

from cubicweb.devtools.apptest import EnvBasedTC, TestEnvironment


translations = {
    u'EUser' : u"Utilisateur",
#    u'Workcase' : u"Affaire",
    u'EmailAddress' : u"Adresse",
#    u'Division' : u"Division",
#    u'Comment' : u"Commentaire",
    u'name' : u"nom",
    u'alias' : u"nom",
    u'surname' : u"nom",
    u'firstname' : u"prénom",
    u'state' : u"état",
#    u'subject' : u"sujet",
    u'address' : u"adresse",
    u'use_email' : u"adel",
    }
def _translate(msgid):
    return translations.get(msgid, msgid)


from cubicweb.web.views.magicsearch import translate_rql_tree, QSPreProcessor, QueryTranslator

class QueryTranslatorTC(EnvBasedTC):
    """test suite for QueryTranslatorTC"""
    
    def setUp(self):
        super(QueryTranslatorTC, self).setUp()
        self.req = self.env.create_request()
        self.vreg.config.translations = {'en': _translate}
        proc = self.vreg.select_component('magicsearch', self.req)
        self.proc = [p for p in proc.processors if isinstance(p, QueryTranslator)][0]

    def test_basic_translations(self):
        """tests basic translations (no ambiguities)"""
        rql = "Any C WHERE C is Adresse, P adel C, C adresse 'Logilab'"
        rql, = self.proc.preprocess_query(rql, self.req)
        self.assertEquals(rql, "Any C WHERE C is EmailAddress, P use_email C, C address 'Logilab'")

    def test_ambiguous_translations(self):
        """tests possibly ambiguous translations"""
        rql = "Any P WHERE P adel C, C is EmailAddress, C nom 'Logilab'"
        rql, = self.proc.preprocess_query(rql, self.req)
        self.assertEquals(rql, "Any P WHERE P use_email C, C is EmailAddress, C alias 'Logilab'")
        rql = "Any P WHERE P is Utilisateur, P adel C, P nom 'Smith'"
        rql, = self.proc.preprocess_query(rql, self.req)
        self.assertEquals(rql, "Any P WHERE P is EUser, P use_email C, P surname 'Smith'")


class QSPreProcessorTC(EnvBasedTC):
    """test suite for QSPreProcessor"""
    def setUp(self):
        super(QSPreProcessorTC, self).setUp()
        self.vreg.config.translations = {'en': _translate}
        self.req = self.request()
        proc = self.vreg.select_component('magicsearch', self.req)
        self.proc = [p for p in proc.processors if isinstance(p, QSPreProcessor)][0]
        self.proc.req = self.req

    def test_entity_translation(self):
        """tests QSPreProcessor._get_entity_name()"""
        translate = self.proc._get_entity_type
        self.assertEquals(translate(u'EmailAddress'), "EmailAddress")
        self.assertEquals(translate(u'emailaddress'), "EmailAddress")
        self.assertEquals(translate(u'Adresse'), "EmailAddress")
        self.assertEquals(translate(u'adresse'), "EmailAddress")
        self.assertRaises(BadRQLQuery, translate, 'whatever')

    def test_attribute_translation(self):
        """tests QSPreProcessor._get_attribute_name"""
        translate = self.proc._get_attribute_name
        eschema = self.schema.eschema('EUser')
        self.assertEquals(translate(u'prénom', eschema), "firstname")
        self.assertEquals(translate(u'nom', eschema), 'surname')
        #self.assert_(translate(u'nom') in ('name', 'surname'))
        eschema = self.schema.eschema('EmailAddress')        
        self.assertEquals(translate(u'adresse', eschema), "address")
        self.assertEquals(translate(u'nom', eschema), 'alias')
        # should fail if the name is not an attribute for the given entity schema
        self.assertRaises(BadRQLQuery, translate, 'whatever', eschema)
        self.assertRaises(BadRQLQuery, translate, 'prénom', eschema)

    def test_one_word_query(self):
        """tests the 'one word shortcut queries'"""
        transform = self.proc._one_word_query
        self.assertEquals(transform('123'),
                          ('Any X WHERE X eid %(x)s', {'x': 123}, 'x'))
        self.assertEquals(transform('EUser'),
                          ('EUser E',))
        self.assertEquals(transform('Utilisateur'),
                          ('EUser E',))
        self.assertEquals(transform('Adresse'),
                          ('EmailAddress E',))
        self.assertEquals(transform('adresse'),
                          ('EmailAddress E',))
        self.assertRaises(BadRQLQuery, transform, 'Workcases')

    def test_two_words_query(self):
        """tests the 'two words shortcut queries'"""
        transform = self.proc._two_words_query
        self.assertEquals(transform('EUser', 'E'),
                          ("EUser E",))
        self.assertEquals(transform('EUser', 'Smith'),
                          ('EUser E WHERE E has_text %(text)s', {'text': 'Smith'}))
        self.assertEquals(transform('utilisateur', 'Smith'),
                          ('EUser E WHERE E has_text %(text)s', {'text': 'Smith'}))
        self.assertEquals(transform(u'adresse', 'Logilab'),
                          ('EmailAddress E WHERE E has_text %(text)s', {'text': 'Logilab'}))
        self.assertEquals(transform(u'adresse', 'Logi%'),
                          ('EmailAddress E WHERE E alias LIKE %(text)s', {'text': 'Logi%'}))
        self.assertRaises(BadRQLQuery, transform, "pers", "taratata")
        #self.assertEquals(transform('EUser', '%mi'), 'EUser E WHERE P surname LIKE "%mi"')

    def test_three_words_query(self):
        """tests the 'three words shortcut queries'"""
        transform = self.proc._three_words_query
        self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb'),
                          ('EUser E WHERE E firstname %(text)s', {'text': 'cubicweb'}))
        self.assertEquals(transform('utilisateur', 'nom', 'cubicweb'),
                          ('EUser E WHERE E surname %(text)s', {'text': 'cubicweb'}))
        self.assertEquals(transform(u'adresse', 'nom', 'cubicweb'),
                          ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
        self.assertEquals(transform('EmailAddress', 'nom', 'cubicweb'),
                          ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'})) 
        self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb%'),
                          ('EUser E WHERE E firstname LIKE %(text)s', {'text': 'cubicweb%'}))
        # expanded shortcuts
        self.assertEquals(transform('EUser', 'use_email', 'Logilab'),
                          ('EUser E WHERE E use_email E1, E1 has_text %(text)s', {'text': 'Logilab'}))
        self.assertEquals(transform('EUser', 'use_email', '%Logilab'),
                          ('EUser E WHERE E use_email E1, E1 alias LIKE %(text)s', {'text': '%Logilab'}))
        self.assertRaises(BadRQLQuery, transform, 'word1', 'word2', 'word3')
        
    def test_multiple_words_query(self):
        """tests multiple_words_query()"""
        self.assertEquals(self.proc._multiple_words_query(['a', 'b', 'c', 'd', 'e']),
                          ('a b c d e',))

    def test_quoted_queries(self):
        """tests how quoted queries are handled"""
        queries = [
            (u'Adresse "My own EmailAddress"', ('EmailAddress E WHERE E has_text %(text)s', {'text': u'My own EmailAddress'})),
            (u'Utilisateur prénom "Jean Paul"', ('EUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
            (u'Utilisateur firstname "Jean Paul"', ('EUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
            (u'EUser firstname "Jean Paul"', ('EUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
            ]
        transform = self.proc._quoted_words_query
        for query, expected in queries:
            self.assertEquals(transform(query), expected)
        self.assertRaises(BadRQLQuery, transform, "unquoted rql")
        self.assertRaises(BadRQLQuery, transform, 'pers "Jean Paul"')
        self.assertRaises(BadRQLQuery, transform, 'EUser firstname other "Jean Paul"')
    
    def test_process_query(self):
        """tests how queries are processed"""
        queries = [
            (u'Utilisateur', (u"EUser E",)),
            (u'Utilisateur P', (u"EUser P",)),
            (u'Utilisateur cubicweb', (u'EUser E WHERE E has_text %(text)s', {'text': u'cubicweb'})),
            (u'EUser prénom cubicweb', (u'EUser E WHERE E firstname %(text)s', {'text': 'cubicweb'},)),
            (u'Any X WHERE X is Something', (u"Any X WHERE X is Something",)),
            ]
        for query, expected in queries:
            self.assertEquals(self.proc.preprocess_query(query, self.req), expected)
        


## Processor Chains tests ############################################
        

class ProcessorChainTC(EnvBasedTC):
    """test suite for magic_search's processor chains"""

    def setUp(self):
        super(ProcessorChainTC, self).setUp()
        self.vreg.config.translations = {'en': _translate}
        self.req = self.request()
        self.proc = self.vreg.select_component('magicsearch', self.req)

    def test_main_preprocessor_chain(self):
        """tests QUERY_PROCESSOR"""
        queries = [
            (u'foo',
             ("Any X WHERE X has_text %(text)s", {'text': u'foo'})),
            # XXX this sounds like a language translator test...
            # and it fail
            (u'Utilisateur Smith',
             ('EUser E WHERE E has_text %(text)s', {'text': u'Smith'})),
            (u'utilisateur nom Smith',
             ('EUser E WHERE E surname %(text)s', {'text': u'Smith'})),
            (u'Any P WHERE P is Utilisateur, P nom "Smith"',
             ('Any P WHERE P is EUser, P surname "Smith"', None)),
            ]
        for query, expected in queries:
            rset = self.proc.process_query(query, self.req)
            self.assertEquals((rset.rql, rset.args), expected)

    def test_iso88591_fulltext(self):
        """we must be able to type accentuated characters in the search field"""
        rset = self.proc.process_query(u'écrire', self.req)
        self.assertEquals(rset.rql, "Any X WHERE X has_text %(text)s")
        self.assertEquals(rset.args, {'text': u'écrire'})

    def test_explicit_component(self):
        self.assertRaises(RQLSyntaxError,
                          self.proc.process_query, u'rql: EUser E WHERE E noattr "Smith",', self.req)
        self.assertRaises(BadRQLQuery,
                          self.proc.process_query, u'rql: EUser E WHERE E noattr "Smith"', self.req)
        rset = self.proc.process_query(u'text: utilisateur Smith', self.req)
        self.assertEquals(rset.rql, 'Any X WHERE X has_text %(text)s')
        self.assertEquals(rset.args, {'text': u'utilisateur Smith'})
                          
if __name__ == '__main__':
    unittest_main()