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
# -*- 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 = {
14
    u'CWUser' : u"Utilisateur",
Adrien Di Mascio's avatar
Adrien Di Mascio committed
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#    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
36

Adrien Di Mascio's avatar
Adrien Di Mascio committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    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)
57
        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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81


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
82
        eschema = self.schema.eschema('CWUser')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
83
84
85
        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
86
        eschema = self.schema.eschema('EmailAddress')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
87
88
89
90
91
92
93
94
95
96
97
        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'))
98
        self.assertEquals(transform('CWUser'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
99
                          ('CWUser C',))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
100
        self.assertEquals(transform('Utilisateur'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
101
                          ('CWUser C',))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
102
103
104
105
106
107
108
109
110
        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
111
112
113
        self.assertEquals(transform('CWUser', 'E'),
                          ("CWUser E",))
        self.assertEquals(transform('CWUser', 'Smith'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
114
                          ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
115
        self.assertEquals(transform('utilisateur', 'Smith'),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
116
                          ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
117
118
119
120
121
        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")
122
        #self.assertEquals(transform('CWUser', '%mi'), 'CWUser E WHERE P surname LIKE "%mi"')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
123
124
125
126
127

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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
144
145
146
147
148
149
150
151
152
    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'})),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
153
154
155
            (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
156
157
158
159
160
161
            ]
        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"')
162
        self.assertRaises(BadRQLQuery, transform, 'CWUser firstname other "Jean Paul"')
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
163

Adrien Di Mascio's avatar
Adrien Di Mascio committed
164
165
166
    def test_process_query(self):
        """tests how queries are processed"""
        queries = [
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
167
            (u'Utilisateur', (u"CWUser C",)),
168
            (u'Utilisateur P', (u"CWUser P",)),
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
169
170
            (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
171
172
173
174
            (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)
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
175

Adrien Di Mascio's avatar
Adrien Di Mascio committed
176
177
178


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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
223
224
if __name__ == '__main__':
    unittest_main()