@@ -0,0 +1,307 @@
1+# -*- coding: utf-8 -*-
2+from collections import defaultdict
3+import mock
4+from searx.engines import wolframalpha_api
5+from searx.testing import SearxTestCase
6+
7+
8+class TestWolframAlphaAPIEngine(SearxTestCase):
9+
10+ def test_request(self):
11+ query = 'test_query'
12+ api_key = 'XXXXXX-XXXXXXXXXX'
13+ dicto = defaultdict(dict)
14+ dicto['api_key'] = api_key
15+ params = wolframalpha_api.request(query, dicto)
16+
17+ self.assertIn('url', params)
18+ self.assertIn(query, params['url'])
19+ self.assertIn('wolframalpha.com', params['url'])
20+
21+ self.assertIn('api_key', params)
22+ self.assertIn(api_key, params['api_key'])
23+
24+ def test_response(self):
25+ self.assertRaises(AttributeError, wolframalpha_api.response, None)
26+ self.assertRaises(AttributeError, wolframalpha_api.response, [])
27+ self.assertRaises(AttributeError, wolframalpha_api.response, '')
28+ self.assertRaises(AttributeError, wolframalpha_api.response, '[]')
29+
30+ xml = '''<?xml version='1.0' encoding='UTF-8'?>
31+ <queryresult success='false' error='false' />
32+ '''
33+ # test failure
34+ response = mock.Mock(content=xml)
35+ self.assertEqual(wolframalpha_api.response(response), [])
36+
37+ xml = """<?xml version='1.0' encoding='UTF-8'?>
38+ <queryresult success='true'
39+ error='false'
40+ numpods='6'
41+ datatypes=''
42+ timedout=''
43+ timedoutpods=''
44+ timing='0.684'
45+ parsetiming='0.138'
46+ parsetimedout='false'
47+ recalculate=''
48+ id='MSPa416020a7966dachc463600000f9c66cc21444cfg'
49+ host='http://www3.wolframalpha.com'
50+ server='6'
51+ related='http://www3.wolframalpha.com/api/v2/relatedQueries.jsp?...'
52+ version='2.6'>
53+ <pod title='Input'
54+ scanner='Identity'
55+ id='Input'
56+ position='100'
57+ error='false'
58+ numsubpods='1'>
59+ <subpod title=''>
60+ <plaintext>sqrt(-1)</plaintext>
61+ </subpod>
62+ </pod>
63+ <pod title='Result'
64+ scanner='Simplification'
65+ id='Result'
66+ position='200'
67+ error='false'
68+ numsubpods='1'
69+ primary='true'>
70+ <subpod title=''>
71+ <plaintext></plaintext>
72+ </subpod>
73+ <states count='1'>
74+ <state name='Step-by-step solution'
75+ input='Result__Step-by-step solution' />
76+ </states>
77+ </pod>
78+ <pod title='Polar coordinates'
79+ scanner='Numeric'
80+ id='PolarCoordinates'
81+ position='300'
82+ error='false'
83+ numsubpods='1'>
84+ <subpod title=''>
85+ <plaintext>r1 (radius), θ90° (angle)</plaintext>
86+ </subpod>
87+ </pod>
88+ <pod title='Position in the complex plane'
89+ scanner='Numeric'
90+ id='PositionInTheComplexPlane'
91+ position='400'
92+ error='false'
93+ numsubpods='1'>
94+ <subpod title=''>
95+ <plaintext></plaintext>
96+ </subpod>
97+ </pod>
98+ <pod title='All 2nd roots of -1'
99+ scanner='RootsOfUnity'
100+ id=''
101+ position='500'
102+ error='false'
103+ numsubpods='2'>
104+ <subpod title=''>
105+ <plaintext> (principal root)</plaintext>
106+ </subpod>
107+ <subpod title=''>
108+ <plaintext>-</plaintext>
109+ </subpod>
110+ </pod>
111+ <pod title='Plot of all roots in the complex plane'
112+ scanner='RootsOfUnity'
113+ id='PlotOfAllRootsInTheComplexPlane'
114+ position='600'
115+ error='false'
116+ numsubpods='1'>
117+ <subpod title=''>
118+ <plaintext></plaintext>
119+ </subpod>
120+ </pod>
121+ </queryresult>
122+ """
123+ # test private user area char in response
124+ response = mock.Mock(content=xml)
125+ results = wolframalpha_api.response(response)
126+ self.assertEqual(type(results), list)
127+ self.assertEqual(len(results), 2)
128+ self.assertIn('i', results[0]['answer'])
129+ self.assertIn('sqrt(-1) - Wolfram|Alpha', results[1]['title'])
130+ self.assertEquals('http://www.wolframalpha.com/input/?i=sqrt%28-1%29', results[1]['url'])
131+
132+ xml = """<?xml version='1.0' encoding='UTF-8'?>
133+ <queryresult success='true'
134+ error='false'
135+ numpods='2'
136+ datatypes=''
137+ timedout=''
138+ timedoutpods=''
139+ timing='1.286'
140+ parsetiming='0.255'
141+ parsetimedout='false'
142+ recalculate=''
143+ id='MSPa195222ad740ede5214h30000480ca61h003d3gd6'
144+ host='http://www3.wolframalpha.com'
145+ server='20'
146+ related='http://www3.wolframalpha.com/api/v2/relatedQueries.jsp?id=...'
147+ version='2.6'>
148+ <pod title='Indefinite integral'
149+ scanner='Integral'
150+ id='IndefiniteIntegral'
151+ position='100'
152+ error='false'
153+ numsubpods='1'
154+ primary='true'>
155+ <subpod title=''>
156+ <plaintext>∫1/xxlog(x)+constant</plaintext>
157+ </subpod>
158+ <states count='1'>
159+ <state name='Step-by-step solution'
160+ input='IndefiniteIntegral__Step-by-step solution' />
161+ </states>
162+ <infos count='1'>
163+ <info text='log(x) is the natural logarithm'>
164+ <link url='http://reference.wolfram.com/mathematica/ref/Log.html'
165+ text='Documentation'
166+ title='Mathematica' />
167+ <link url='http://functions.wolfram.com/ElementaryFunctions/Log'
168+ text='Properties'
169+ title='Wolfram Functions Site' />
170+ <link url='http://mathworld.wolfram.com/NaturalLogarithm.html'
171+ text='Definition'
172+ title='MathWorld' />
173+ </info>
174+ </infos>
175+ </pod>
176+ <pod title='Plots of the integral'
177+ scanner='Integral'
178+ id='Plot'
179+ position='200'
180+ error='false'
181+ numsubpods='2'>
182+ <subpod title=''>
183+ <plaintext></plaintext>
184+ <states count='1'>
185+ <statelist count='2'
186+ value='Complex-valued plot'
187+ delimiters=''>
188+ <state name='Complex-valued plot'
189+ input='Plot__1_Complex-valued plot' />
190+ <state name='Real-valued plot'
191+ input='Plot__1_Real-valued plot' />
192+ </statelist>
193+ </states>
194+ </subpod>
195+ <subpod title=''>
196+ <plaintext></plaintext>
197+ <states count='1'>
198+ <statelist count='2'
199+ value='Complex-valued plot'
200+ delimiters=''>
201+ <state name='Complex-valued plot'
202+ input='Plot__2_Complex-valued plot' />
203+ <state name='Real-valued plot'
204+ input='Plot__2_Real-valued plot' />
205+ </statelist>
206+ </states>
207+ </subpod>
208+ </pod>
209+ <assumptions count='1'>
210+ <assumption type='Clash'
211+ word='integral'
212+ template='Assuming "${word}" is ${desc1}. Use as ${desc2} instead'
213+ count='2'>
214+ <value name='IntegralsWord'
215+ desc='an integral'
216+ input='*C.integral-_*IntegralsWord-' />
217+ <value name='MathematicalFunctionIdentityPropertyClass'
218+ desc='a function property'
219+ input='*C.integral-_*MathematicalFunctionIdentityPropertyClass-' />
220+ </assumption>
221+ </assumptions>
222+ </queryresult>
223+ """
224+ # test integral
225+ response = mock.Mock(content=xml)
226+ results = wolframalpha_api.response(response)
227+ self.assertEqual(type(results), list)
228+ self.assertEqual(len(results), 2)
229+ self.assertIn('log(x)+c', results[0]['answer'])
230+ self.assertIn('∫1/xx - Wolfram|Alpha'.decode('utf-8'), results[1]['title'])
231+ self.assertEquals('http://www.wolframalpha.com/input/?i=%E2%88%AB1%2Fx%EF%9D%8Cx', results[1]['url'])
232+
233+ xml = """<?xml version='1.0' encoding='UTF-8'?>
234+ <queryresult success='true'
235+ error='false'
236+ numpods='4'
237+ datatypes='Solve'
238+ timedout=''
239+ timedoutpods=''
240+ timing='0.79'
241+ parsetiming='0.338'
242+ parsetimedout='false'
243+ recalculate=''
244+ id='MSPa7481f7i06d25h3deh2900004810i3a78d9b4fdc'
245+ host='http://www5b.wolframalpha.com'
246+ server='23'
247+ related='http://www5b.wolframalpha.com/api/v2/relatedQueries.jsp?id=...'
248+ version='2.6'>
249+ <pod title='Input interpretation'
250+ scanner='Identity'
251+ id='Input'
252+ position='100'
253+ error='false'
254+ numsubpods='1'>
255+ <subpod title=''>
256+ <plaintext>solve x^2+x0</plaintext>
257+ </subpod>
258+ </pod>
259+ <pod title='Results'
260+ scanner='Solve'
261+ id='Result'
262+ position='200'
263+ error='false'
264+ numsubpods='2'
265+ primary='true'>
266+ <subpod title=''>
267+ <plaintext>x-1</plaintext>
268+ </subpod>
269+ <subpod title=''>
270+ <plaintext>x0</plaintext>
271+ </subpod>
272+ <states count='1'>
273+ <state name='Step-by-step solution'
274+ input='Result__Step-by-step solution' />
275+ </states>
276+ </pod>
277+ <pod title='Root plot'
278+ scanner='Solve'
279+ id='RootPlot'
280+ position='300'
281+ error='false'
282+ numsubpods='1'>
283+ <subpod title=''>
284+ <plaintext></plaintext>
285+ </subpod>
286+ </pod>
287+ <pod title='Number line'
288+ scanner='Solve'
289+ id='NumberLine'
290+ position='400'
291+ error='false'
292+ numsubpods='1'>
293+ <subpod title=''>
294+ <plaintext></plaintext>
295+ </subpod>
296+ </pod>
297+ </queryresult>
298+ """
299+ # test ecuation with multiple answers
300+ response = mock.Mock(content=xml)
301+ results = wolframalpha_api.response(response)
302+ self.assertEqual(type(results), list)
303+ self.assertEqual(len(results), 3)
304+ self.assertIn('x=-1', results[0]['answer'])
305+ self.assertIn('x=0', results[1]['answer'])
306+ self.assertIn('solve x^2+x0 - Wolfram|Alpha'.decode('utf-8'), results[2]['title'])
307+ self.assertEquals('http://www.wolframalpha.com/input/?i=solve+x%5E2%2Bx%EF%9F%990', results[2]['url'])