unittest_magicsearch.py 10.6 KB
Newer Older
Adrien Di Mascio's avatar
Adrien Di Mascio committed
1
# -*- coding: utf-8 -*-
2
3
4
5
6
7
8
"""Unit tests for magic_search service

:organization: Logilab
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
Adrien Di Mascio's avatar
Adrien Di Mascio committed
9
10
11
12
13
14
15
16
17
18
19

import sys

from logilab.common.testlib import TestCase, unittest_main

from rql import BadRQLQuery, RQLSyntaxError

from cubicweb.devtools.apptest import EnvBasedTC, TestEnvironment


translations = {
20
    u'CWUser' : u"Utilisateur",
Adrien Di Mascio's avatar
Adrien Di Mascio committed
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#    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"""
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
42

Adrien Di Mascio's avatar
Adrien Di Mascio committed
43
44
45
46
    def setUp(self):
        super(QueryTranslatorTC, self).setUp()
        self.req = self.env.create_request()
        self.vreg.config.translations = {'en': _translate}
47
        proc = self.vreg.select('components', 'magicsearch', self.req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
        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)
63
        self.assertEquals(rql, "Any P WHERE P is CWUser, P use_email C, P surname 'Smith'")
Adrien Di Mascio's avatar
Adrien Di Mascio committed
64
65
66
67
68
69
70
71


class QSPreProcessorTC(EnvBasedTC):
    """test suite for QSPreProcessor"""
    def setUp(self):
        super(QSPreProcessorTC, self).setUp()
        self.vreg.config.translations = {'en': _translate}
        self.req = self.request()
72
        proc = self.vreg.select('components', 'magicsearch', self.req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        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
88
        eschema = self.schema.eschema('CWUser')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
89
90
91
        self.assertEquals(translate(u'prénom', eschema), "firstname")
        self.assertEquals(translate(u'nom', eschema), 'surname')
        #self.assert_(translate(u'nom') in ('name', 'surname'))
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
92
        eschema = self.schema.eschema('EmailAddress')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
93
94
95
96
97
98
99
100
101
102
103
        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'))
104
        self.assertEquals(transform('CWUser'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
105
                          ('CWUser C',))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
106
        self.assertEquals(transform('Utilisateur'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
107
                          ('CWUser C',))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
108
109
110
111
112
113
114
115
116
        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
117
118
119
        self.assertEquals(transform('CWUser', 'E'),
                          ("CWUser E",))
        self.assertEquals(transform('CWUser', 'Smith'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
120
                          ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
121
        self.assertEquals(transform('utilisateur', 'Smith'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
122
                          ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
123
124
125
126
127
        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")
128
        #self.assertEquals(transform('CWUser', '%mi'), 'CWUser E WHERE P surname LIKE "%mi"')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
129
130
131
132
133

    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'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
134
                          ('CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
135
        self.assertEquals(transform('utilisateur', 'nom', 'cubicweb'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
136
                          ('CWUser C WHERE C surname %(text)s', {'text': 'cubicweb'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
137
138
139
        self.assertEquals(transform(u'adresse', 'nom', 'cubicweb'),
                          ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
        self.assertEquals(transform('EmailAddress', 'nom', 'cubicweb'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
140
                          ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
141
        self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb%'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
142
                          ('CWUser C WHERE C firstname LIKE %(text)s', {'text': 'cubicweb%'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
143
        # expanded shortcuts
144
        self.assertEquals(transform('CWUser', 'use_email', 'Logilab'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
145
                          ('CWUser C WHERE C use_email C1, C1 has_text %(text)s', {'text': 'Logilab'}))
146
        self.assertEquals(transform('CWUser', 'use_email', '%Logilab'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
147
                          ('CWUser C WHERE C use_email C1, C1 alias LIKE %(text)s', {'text': '%Logilab'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
148
        self.assertRaises(BadRQLQuery, transform, 'word1', 'word2', 'word3')
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
149

Adrien Di Mascio's avatar
Adrien Di Mascio committed
150
151
152
153
    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'})),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
154
155
156
            (u'Utilisateur prénom "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
            (u'Utilisateur firstname "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
            (u'CWUser firstname "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
157
158
159
160
161
162
            ]
        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"')
163
        self.assertRaises(BadRQLQuery, transform, 'CWUser firstname other "Jean Paul"')
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
164

Adrien Di Mascio's avatar
Adrien Di Mascio committed
165
166
167
    def test_process_query(self):
        """tests how queries are processed"""
        queries = [
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
168
            (u'Utilisateur', (u"CWUser C",)),
169
            (u'Utilisateur P', (u"CWUser P",)),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
170
171
            (u'Utilisateur cubicweb', (u'CWUser C WHERE C has_text %(text)s', {'text': u'cubicweb'})),
            (u'CWUser prénom cubicweb', (u'CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'},)),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
172
173
174
            ]
        for query, expected in queries:
            self.assertEquals(self.proc.preprocess_query(query, self.req), expected)
Sylvain Thénault's avatar
Sylvain Thénault committed
175
176
        self.assertRaises(BadRQLQuery,
                          self.proc.preprocess_query, 'Any X WHERE X is Something', self.req)
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
177

Adrien Di Mascio's avatar
Adrien Di Mascio committed
178
179
180


## Processor Chains tests ############################################
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
181

Adrien Di Mascio's avatar
Adrien Di Mascio committed
182
183
184
185
186
187
188
189

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()
190
        self.proc = self.vreg.select('components', 'magicsearch', self.req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
191
192
193
194
195
196
197
198
199

    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',
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
200
             ('CWUser C WHERE C has_text %(text)s', {'text': u'Smith'})),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
201
            (u'utilisateur nom Smith',
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
202
             ('CWUser C WHERE C surname %(text)s', {'text': u'Smith'})),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
203
            (u'Any P WHERE P is Utilisateur, P nom "Smith"',
204
             ('Any P WHERE P is CWUser, P surname "Smith"', None)),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
205
206
207
208
209
210
211
212
213
214
215
216
217
            ]
        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,
218
                          self.proc.process_query, u'rql: CWUser E WHERE E noattr "Smith",', self.req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
219
        self.assertRaises(BadRQLQuery,
220
                          self.proc.process_query, u'rql: CWUser E WHERE E noattr "Smith"', self.req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
221
222
223
        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'})
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
224

Adrien Di Mascio's avatar
Adrien Di Mascio committed
225
226
if __name__ == '__main__':
    unittest_main()