on master help sign in
Merge branch 'master' into bug/oscar-theme
commit70f7142824cc44afddb5704fd59e3a4194f3dc0e authorMarkus Heiser <markus.heiser@darmarIT.de> dateMon 23 Dec 2019, 18:47 (7 years ago) parent6a5aae63e14bf4
77 files changed+42−9272
searx/engines/gigablast.py+28−13 searx/engines/openstreetmap.py+1−1 searx/engines/qwant.py+1 searx/engines/wikipedia.py+7−2 searx/webapp.py+5−5 tests/unit/engines/__init__.py tests/unit/engines/pubmed.py−37 tests/unit/engines/seedpeer_fixture.html−110 tests/unit/engines/test_acgsou.py−78 tests/unit/engines/test_archlinux.py−111 tests/unit/engines/test_arxiv.py−58 tests/unit/engines/test_base.py−91 tests/unit/engines/test_bing.py−178 tests/unit/engines/test_bing_images.py−132 tests/unit/engines/test_bing_news.py−147 tests/unit/engines/test_bing_videos.py−72 tests/unit/engines/test_btdigg.py−112 tests/unit/engines/test_currency_convert.py−56 tests/unit/engines/test_dailymotion.py−112 tests/unit/engines/test_deezer.py−57 tests/unit/engines/test_deviantart.py−24 tests/unit/engines/test_digbt.py−61 tests/unit/engines/test_digg.py−16 tests/unit/engines/test_doku.py−79 tests/unit/engines/test_duckduckgo.py−106 tests/unit/engines/test_duckduckgo_definitions.py−255 tests/unit/engines/test_duckduckgo_images.py−75 tests/unit/engines/test_duden.py−47 tests/unit/engines/test_dummy.py−26 tests/unit/engines/test_faroo.py−113 tests/unit/engines/test_fdroid.py−60 tests/unit/engines/test_flickr.py−142 tests/unit/engines/test_flickr_noapi.py−357 tests/unit/engines/test_framalibre.py−103 tests/unit/engines/test_frinkiac.py−50 tests/unit/engines/test_genius.py−231 tests/unit/engines/test_gigablast.py−119 tests/unit/engines/test_github.py−61 tests/unit/engines/test_google.py−194 tests/unit/engines/test_google_images.py−27 tests/unit/engines/test_google_news.py−102 tests/unit/engines/test_google_videos.py−79 tests/unit/engines/test_ina.py−64 tests/unit/engines/test_kickass.py−397 tests/unit/engines/test_mediawiki.py−130 tests/unit/engines/test_mixcloud.py−67 tests/unit/engines/test_nyaa.py−124 tests/unit/engines/test_openstreetmap.py−199 tests/unit/engines/test_pdbe.py−109 tests/unit/engines/test_photon.py−166 tests/unit/engines/test_piratebay.py−166 tests/unit/engines/test_qwant.py−339 tests/unit/engines/test_reddit.py−71 tests/unit/engines/test_scanr_structures.py−175 tests/unit/engines/test_searchcode_code.py−75 tests/unit/engines/test_searchcode_doc.py−70 tests/unit/engines/test_seedpeer.py−66 tests/unit/engines/test_soundcloud.py−192 tests/unit/engines/test_spotify.py−124 tests/unit/engines/test_stackoverflow.py−106 tests/unit/engines/test_startpage.py−67 tests/unit/engines/test_tokyotoshokan.py−110 tests/unit/engines/test_torrentz.py−87 tests/unit/engines/test_twitter.py−502 tests/unit/engines/test_unsplash.py−38 tests/unit/engines/test_vimeo.py−36 tests/unit/engines/test_wikidata.py−514 tests/unit/engines/test_wikipedia.py−263 tests/unit/engines/test_wolframalpha_api.py−166 tests/unit/engines/test_wolframalpha_noapi.py−224 tests/unit/engines/test_www1x.py−14 tests/unit/engines/test_yacy.py−96 tests/unit/engines/test_yahoo.py−190 tests/unit/engines/test_yahoo_news.py−150 tests/unit/engines/test_youtube_api.py−111 tests/unit/engines/test_youtube_noapi.py−124 tests/unit/engines/unsplash_fixture.json−241
searx/engines/gigablast.py+28−13
@@ -14,6 +14,7 @@ import random
1414from json import loads
1515from time import time
1616from lxml.html import fromstring
17+from searx.poolrequests import get
1718from searx.url_utils import urlencode
1819from searx.utils import eval_xpath
1920
@@ -31,13 +32,9 @@ search_string = 'search?{query}'\
3132 '&c=main'\
3233 '&s={offset}'\
3334 '&format=json'\
34− '&qh=0'\
35− '&qlang={lang}'\
35+ '&langcountry={lang}'\
3636 '&ff={safesearch}'\
37− '&rxiec={rxieu}'\
38− '&ulse={ulse}'\
39− '&rand={rxikd}'\
40− '&dbez={dbez}'
37+ '&rand={rxikd}'
4138# specific xpath variables
4239results_xpath = '//response//result'
4340url_xpath = './/url'
@@ -46,9 +43,26 @@ content_xpath = './/sum'
4643
4744supported_languages_url = 'https://gigablast.com/search?&rxikd=1'
4845
46+extra_param = '' # gigablast requires a random extra parameter
47+# which can be extracted from the source code of the search page
48+
49+
50+def parse_extra_param(text):
51+ global extra_param
52+ param_lines = [x for x in text.splitlines() if x.startswith('var url=') or x.startswith('url=url+')]
53+ extra_param = ''
54+ for l in param_lines:
55+ extra_param += l.split("'")[1]
56+ extra_param = extra_param.split('&')[-1]
57+
58+
59+def init(engine_settings=None):
60+ parse_extra_param(get('http://gigablast.com/search?c=main&qlangcountry=en-us&q=south&s=10').text)
61+
4962
5063# do search-request
5164def request(query, params):
65+ print("EXTRAPARAM:", extra_param)
5266 offset = (params['pageno'] - 1) * number_of_results
5367
5468 if params['language'] == 'all':
@@ -67,14 +81,11 @@ def request(query, params):
6781 search_path = search_string.format(query=urlencode({'q': query}),
6882 offset=offset,
6983 number_of_results=number_of_results,
70− rxikd=int(time() * 1000),
71− rxieu=random.randint(1000000000, 9999999999),
72− ulse=random.randint(100000000, 999999999),
7384 lang=language,
74− safesearch=safesearch,
75− dbez=random.randint(100000000, 999999999))
85+ rxikd=int(time() * 1000),
86+ safesearch=safesearch)
7687
77− params['url'] = base_url + search_path
88+ params['url'] = base_url + search_path + '&' + extra_param
7889
7990 return params
8091
@@ -84,7 +95,11 @@ def response(resp):
8495 results = []
8596
8697 # parse results
87− response_json = loads(resp.text)
98+ try:
99+ response_json = loads(resp.text)
100+ except:
101+ parse_extra_param(resp.text)
102+ raise Exception('extra param expired, please reload')
88103
89104 for result in response_json['results']:
90105 # append result
searx/engines/openstreetmap.py+1−1
@@ -24,7 +24,7 @@ result_base_url = 'https://openstreetmap.org/{osm_type}/{osm_id}'
2424
2525# do search-request
2626def request(query, params):
27− params['url'] = base_url + search_string.format(query=query)
27+ params['url'] = base_url + search_string.format(query=query.decode('utf-8'))
2828
2929 return params
3030
searx/engines/qwant.py+1
@@ -50,6 +50,7 @@ def request(query, params):
5050 language = match_language(params['language'], supported_languages, language_aliases)
5151 params['url'] += '&locale=' + language.replace('-', '_').lower()
5252
53+ params['headers']['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0'
5354 return params
5455
5556
searx/engines/wikipedia.py+7−2
@@ -21,7 +21,8 @@ search_url = base_url + u'w/api.php?'\
2121 'action=query'\
2222 '&format=json'\
2323 '&{query}'\
24− '&prop=extracts|pageimages'\
24+ '&prop=extracts|pageimages|pageprops'\
25+ '&ppprop=disambiguation'\
2526 '&exintro'\
2627 '&explaintext'\
2728 '&pithumbsize=300'\
@@ -79,12 +80,15 @@ def response(resp):
7980
8081 # wikipedia article's unique id
8182 # first valid id is assumed to be the requested article
83+ if 'pages' not in search_result['query']:
84+ return results
85+
8286 for article_id in search_result['query']['pages']:
8387 page = search_result['query']['pages'][article_id]
8488 if int(article_id) > 0:
8589 break
8690
87− if int(article_id) < 0:
91+ if int(article_id) < 0 or 'disambiguation' in page.get('pageprops', {}):
8892 return []
8993
9094 title = page.get('title')
@@ -96,6 +100,7 @@ def response(resp):
96100 extract = page.get('extract')
97101
98102 summary = extract_first_paragraph(extract, title, image)
103+ summary = summary.replace('() ', '')
99104
100105 # link to wikipedia article
101106 wikipedia_link = base_url.format(language=url_lang(resp.search_params['language'])) \
searx/webapp.py+5−5
@@ -606,11 +606,11 @@ def index():
606606 # HTML output format
607607
608608 # suggestions: use RawTextQuery to get the suggestion URLs with the same bang
609− suggestion_urls = map(lambda suggestion: {
610− 'url': raw_text_query.changeSearchQuery(suggestion).getFullQuery(),
611− 'title': suggestion
612− },
613− result_container.suggestions)
609+ suggestion_urls = list(map(lambda suggestion: {
610+ 'url': raw_text_query.changeSearchQuery(suggestion).getFullQuery(),
611+ 'title': suggestion
612+ },
613+ result_container.suggestions))
614614
615615 correction_urls = list(map(lambda correction: {
616616 'url': raw_text_query.changeSearchQuery(correction).getFullQuery(),
tests/unit/engines/__init__.pydeleted

No changes to the content.

tests/unit/engines/pubmed.pydeleted−37
@@ -1,37 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import pubmed
5−from searx.testing import SearxTestCase
6−
7−
8−class TestPubmedEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = pubmed.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn('eutils.ncbi.nlm.nih.gov/', params['url'])
17− self.assertIn('term', params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, pubmed.response, None)
21− self.assertRaises(AttributeError, pubmed.response, [])
22− self.assertRaises(AttributeError, pubmed.response, '')
23− self.assertRaises(AttributeError, pubmed.response, '[]')
24−
25− response = mock.Mock(text='<PubmedArticleSet></PubmedArticleSet>')
26− self.assertEqual(pubmed.response(response), [])
27−
28− xml_mock = """<eSearchResult><Count>1</Count><RetMax>1</RetMax><RetStart>0</RetStart><IdList>
29−<Id>1</Id>
30−</IdList></eSearchResult>
31−"""
32−
33− response = mock.Mock(text=xml_mock.encode('utf-8'))
34− results = pubmed.response(response)
35− self.assertEqual(type(results), list)
36− self.assertEqual(len(results), 1)
37− self.assertEqual(results[0]['content'], 'No abstract is available for this publication.')
tests/unit/engines/seedpeer_fixture.htmldeleted−110
@@ -1,110 +0,0 @@
1−<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2− <html xmlns="http://www.w3.org/1999/xhtml">
3− <head>
4− </head>
5− <body>
6− <div id="header">
7− <div id="whoIsYou">
8− <a href="/lang.php"><small>SeedPeer in your own language?</small></a>&nbsp;&nbsp;&nbsp;<a href="http://www.seedpeer.eu"><img src="/images/flags/uk.gif" width="16px" alt="Torrents EN" /></a> <a href="http://spanish.seedpeer.eu"><img src="/images/flags/es.gif" width="16px" alt="Torrents ES" /></a> <a href="http://german.seedpeer.eu"><img src="/images/flags/de.gif" width="16px" alt="Torrents DE" /></a> <a href="http://french.seedpeer.eu"><img src="/images/flags/fr.gif" width="16px" alt="Torrents FR" /></a> <a href="http://portuguese.seedpeer.eu"><img src="/images/flags/pt.gif" width="16px" alt="Torrents Portuguese" /></a> <a href="http://swedish.seedpeer.eu"><img src="/images/flags/se.gif" width="16px" alt="Torrents Sweden" /></a>
9− </div>
10−
11− <script type="text/javascript">
12− whoIsYou();
13− </script>
14− <div id="search">
15− <form action="/search.php" method="get">
16− <input id="topsearchbar" name="search" value="narcos season 2" />
17− <input type="submit" class="searchbutton" value="Torrents" />
18− <input style="color:#000" type="submit" class="searchbutton" name="usenet" value="Usenet Binaries" />
19− </form>
20− <div id="suggestion"></div>
21− </div>
22− <div id="logo"><a href="/"><img src="/images/logo2.gif" alt="Seedpeer homepage" width="415" height="143" /></a></div>
23− <div id="subtext"><a href="/">Home</a> &gt; <a href="/search.html">Torrent search</a> &gt; Narcos season 2 | page 1</div>
24− </div>
25− <div id="nav">
26− <ul>
27− <!--
28− <li><font style="color:red;font-size:9px;font-weight:bold;">NEW</font><a title="Download TOP Games for FREE" rel="nofollow" href="http://www.bigrebelads.com/affiliate/index?ref=9301" target="_blank">FREE Games</a></li>
29−
30− -->
31− <li style="border-left:none" id="categories"><a title="Browse Torrent Categories" href="/browse.html">Categories</a>
32− <ul>
33− <li><a title="Browse Anime Torrents" href="/browse.html#6">Anime</a></li>
34− <li><a title="Browse Game Torrents" href="/browse.html#4">Games</a></li>
35− <li><a title="Browse Movie Torrents" href="/browse.html#1">Movies</a></li>
36− <li><a title="Browse Music Torrents" href="/browse.html#3">Music</a></li>
37− <li><a title="Browse Software Torrents" href="/browse.html#5">Software</a></li>
38− <li><a title="Browse TV Torrents" href="/browse.html#2">TV Shows</a></li>
39− <li><a title="Browse Other Torrents" href="/browse.html#7">Others</a></li>
40− </ul>
41− </li>
42− <li><a title="Upload A Torrents" href="/upload.html">Upload torrent</a></li>
43− <li id="verified"><a title="Verified Torrents" href="/verified.html">Verified</a></li>
44− <li id="searchoptions"><a title="Search Torrents" href="/search.html">Torrent search</a></li>
45− <li id="newsgroups"><a style="color:#212b3e" title="News Groups" href="/usenet.html">Usenet Binaries</a></li>
46− <li id="about" style="border-right:none"><a rel="nofollow" href="/faq.html">About Us</a>
47− <ul>
48− <li><a title="SeedPeer Statistics" href="/stats.html">Statistics</a></li>
49− <li><a title="Contact Us" href="/contact.html">Contact</a></li>
50− <li><a title="Frequently Asked Questions" href="/faq.html">FAQ</a></li>
51− <li><a title="SeedPeer API" href="http://api.seedpeer.eu">Our API</a></li>
52− <li><a title="SeedPeer Blog" href="/blog">Blog</a></li>
53− </ul>
54− </li>
55− <!--<li><a href="/toolbar.php">Our Toolbar</a></li>-->
56− </ul>
57− <div class="clear"></div>
58− </div>
59− <div id="body"><div id="pageTop"></div>
60− <div id="headerbox"><h1>Verified <font class="colored">Narcos season 2</font> torrents</h1></div><table width="100%"><tr><th>
61− <span style="float:right">
62− <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> |
63− <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a>
64− </span>
65− <a href="/search/narcos-season-2/1/1.html">Torrent name</a></th><th class="right"><a href="/search/narcos-season-2/2/1.html">Age</a></th><th class="right"><a href="/search/narcos-season-2/3/1.html">Size</a></th><th class="right"><a href="/search/narcos-season-2/4/1.html">Seeds</a></th><th class="right"><a href="/search/narcos-season-2/5/1.html">Peers</a></th><th class="center"><a href="/search/narcos-season-2/6/1.html">Health</a></th><td class="tableAd" rowspan="6"><iframe src="http://creative.wwwpromoter.com/13689?d=300x250" width="300" height="250" style="border: none;" frameborder="0" scrolling="no"></iframe></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_1" href="" data-tad="431726" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> Full Version</a></td><td class="right">20 hours</td><td class="right">681.3 MB</td><td class="right"><font color="green">28</font> </td><td class="right"><font color="navy">654</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class="tdark"><td><a class="pblink" id="pblink_table_item_2" href="" data-tad="431727" data-url="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> Trusted Source</a></td><td class="right">12 hours</td><td class="right">787.1 MB</td><td class="right"><font color="green">64</font> </td><td class="right"><font color="navy">220</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_3" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Full Narcos season 2 Download</strong></a> <small><a class="pblink" id="pblink_table_item_4" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Usenet</a></small></td><td class="right">24 hours</td><td class="right">775.5 MB</td><td class="right"><font color="green">60</font> </td><td class="right"><font color="navy">236</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class="tdark"><td><a class="pblink" id="pblink_table_item_5" href="" data-tad="431730" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> 2014 - DIRECT STREAMING</a> <small><a class="pblink" id="pblink_table_item_6" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Movies</a></small></td><td class="right">17 hours</td><td class="right">654.1 MB</td><td class="right"><font color="green">2</font> </td><td class="right"><font color="navy">391</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_7" href="" data-tad="431731" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> 2014</a> <small><a class="pblink" id="pblink_table_item_8" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Movies</a></small></td><td class="right">20 hours</td><td class="right">754.5 MB</td><td class="right"><font color="green">21</font> </td><td class="right"><font color="navy">919</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr></table><br /><br /><center><iframe src='http://creative.wwwpromoter.com/13689?d=728x90' width='728' height='90' style='border: none;' frameborder='0' scrolling='no'></iframe><center><span style="float:right;margin:1em .2em 0 0"><a title="Download at the speed of your connection" href="/usenet.php?search=narcos+season+2"><img src="/images/dlf.gif" alt="Search Binaries" /></a></span><div style="margin-bottom:1em;margin-right:290px" id="headerbox"><h1><a href="/searchfeed/narcos+season+2.xml" target="_blank" title="SeedPeer RSS Torrent Search Feed fornarcos season 2"><img src="/images/feedIcon.png" border="0" /></a>&nbsp;2 <font class="colored">Narcos season 2</font> Torrents were found</h1></div><table width="100%"><tr><th>
66− <span style="float:right">
67− <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> |
68− <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a>
69− </span>
70− <a href="/search/narcos-season-2/1/1.html">Torrent name</a></th><th class="right"><a href="/search/narcos-season-2/2/1.html">Age</a></th><th class="right"><a href="/search/narcos-season-2/3/1.html">Size</a></th><th class="right"><a href="/search/narcos-season-2/4/1.html">Seeds</a></th><th class="right"><a href="/search/narcos-season-2/5/1.html">Peers</a></th><th class="center"><a href="/search/narcos-season-2/6/1.html">Health</a></th></tr><tr class=""><td><small class="comments"><a href="http://www.facebook.com/sharer.php?t=Download%20<strong class='colored'>Narcos</strong> <strong class='colored'>Season</strong> <strong class='colored'>2</strong> Complete 7<strong class='colored'>2</strong>0p WebRip EN-SUB x<strong class='colored'>2</strong>64-[MULVAcoded] S0<strong class='colored'>2</strong>%20 torrent&u=http://seedpeer.seedpeer.eu/details/11686840/Narcos-Season-2-Complete-720p-WebRip-EN-SUB-x264-[MULVAcoded]-S02.html"><img src="/images/facebook.png" alt="Add to Facebook" width="14" height="14" /></a></small><a href="/details/11686840/Narcos-Season-2-Complete-720p-WebRip-EN-SUB-x264-[MULVAcoded]-S02.html"><strong class='colored'>Narcos</strong> <strong class='colored'>Season</strong> <strong class='colored'>2</strong> Complete 7<strong class='colored'>2</strong>0p WebRip EN-SUB x<strong class='colored'>2</strong>64-[MULVAcoded] S0<strong class='colored'>2</strong> <small><a href="/browse.html#11686840"></a></small></a></td><td class="right">19 hours</td><td class="right">4.39 GB</td><td class="right"><font color="green">715</font> </td><td class="right"><font color="navy">183</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" width="40" height="11" /></td></tr><tr class="tdark"><td><small class="comments"><a href="http://www.facebook.com/sharer.php?t=Download%20<strong class='colored'>Narcos</strong> - <strong class='colored'>Season</strong> <strong class='colored'>2</strong> - 7<strong class='colored'>2</strong>0p WEBRiP - x<strong class='colored'>2</strong>65 HEVC - ShAaNiG%20 torrent&u=http://seedpeer.seedpeer.eu/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html"><img src="/images/facebook.png" alt="Add to Facebook" width="14" height="14" /></a></small><a href="/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html"><strong class='colored'>Narcos</strong> - <strong class='colored'>Season</strong> <strong class='colored'>2</strong> - 7<strong class='colored'>2</strong>0p WEBRiP - x<strong class='colored'>2</strong>65 HEVC - ShAaNiG <small><a href="/browse.html#11685972"></a></small></a></td><td class="right">1 day</td><td class="right">2.48 GB</td><td class="right"><font color="green">861</font> </td><td class="right"><font color="navy">332</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" width="40" height="11" /></td></tr></table><div id="headerbox"><h1>Related searches for: <font class="colored">Narcos season 2</font></h1></div><div id="search_suggestions"><br />Other suggested searches: </div><br /><a href="http://torrentz2.eu/search?f=narcos-season-2">Search for "narcos-season-2" on Torrentz2.eu</a><br /><a href="http://torrent-finder.info/show.php?q=narcos-season-2">Search for "narcos-season-2" on Torrent-Finder</a><br /><center><iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe>&nbsp;<iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe>&nbsp;<iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe></center><div id="footer">
71− <table width="100%">
72− <tr>
73− <td width="30%">
74− <h2>Torrents Download</h2>
75− <a href="/">Torrent search</a><br />
76− <a href="/browse.html">Browse categories</a><br />
77− <a href="/verified.html">Verified Torrents</a><br />
78− <a href="/order-date.html">Today's torrents</a><br />
79− <a href="/yesterday.html">Yesterday's torrents</a><br />
80− <a href="/stats.html">Statistics</a><br />
81− <br />
82− <a href="/faq.html#copyright"><strong>Copyright & Removal</strong></a>
83− </td>
84− <td width="30%"><h2>Cool Stuff</h2>
85− <a href="/promotional.php">Promotional</a><br />
86− <a href="/contact.html">Advertising Information</a><br />
87− <strong><a href="/plugins.php" title="Add a search plugin to Firefox or Internet Explorer">Search Plugin <span style="color:red">*</span></a></strong><br />
88− <a href="http://www.utorrent.com">&micro;Torrent Client</a><br />
89− <a href="/blog">Seedpeer Blog</a><br />
90− </td>
91− <td width="30%"><h2>Links</h2>
92− <a href="http://www.sumotorrent.com" target="_blank"><strong>SumoTorrent</strong></a><br />
93− <a href="http://www.torrent-finder.info" target="_blank"><strong>Torrent Finder</strong></a><br />
94− <a href="http://www.torrentpond.com" target="_blank"><strong>TorrentPond</strong></a><br />
95− <a href="https://www.limetorrents.cc" target="_blank">LimeTorrents.cc</a><br />
96− <a href="http://www.torrents.to/" target="_blank">Torrents.to</a><br />
97− <a href="http://www.torrentfunk.com" target="_blank">TorrentFunk</a><br />
98− <a href="https://monova.org" target="_blank">Monova</a><br />
99− <a href="http://www.torrentroom.com" target="_blank">TorrentRoom</a><br />
100− <a href="http://www.katcr.co/" target="_blank">Kickass Torrents Community</a><br />
101− </td>
102− <td width="10%"><div id="bottomlogo"></div></td>
103− </tr>
104− </table>
105− <br />
106− <br />
107− </div>
108− </div>
109− </body>
110− </html>
tests/unit/engines/test_acgsou.pydeleted−78
@@ -1,78 +0,0 @@
1−# coding=utf-8
2−from collections import defaultdict
3−import mock
4−from searx.engines import acgsou
5−from searx.testing import SearxTestCase
6−
7−
8−class TestAcgsouEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dic = defaultdict(dict)
13− dic['pageno'] = 1
14− params = acgsou.request(query, dic)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('acgsou.com' in params['url'])
18−
19− def test_response(self):
20− resp = mock.Mock(text='<html></html>')
21− self.assertEqual(acgsou.response(resp), [])
22−
23− html = u"""
24− <html>
25−<table id="listTable" class="list_style table_fixed">
26− <thead class="tcat">
27− <tr>
28− <th axis="string" class="l1 tableHeaderOver">test</th>
29− <th axis="string" class="l2 tableHeaderOver">test</th>
30− <th axis="string" class="l3 tableHeaderOver">test</th>
31− <th axis="size" class="l4 tableHeaderOver">test</th>
32− <th axis="number" class="l5 tableHeaderOver">test</th>
33− <th axis="number" class="l6 tableHeaderOver">test</th>
34− <th axis="number" class="l7 tableHeaderOver">test</th>
35− <th axis="string" class="l8 tableHeaderOver">test</th>
36− </tr>
37− </thead>
38− <tbody class="tbody" id="data_list">
39− <tr class="alt1 ">
40− <td nowrap="nowrap">date</td>
41− <td><a href="category.html">testcategory テスト</a></td>
42− <td style="text-align:left;">
43− <a href="show-torrentid.html" target="_blank">torrentname テスト</a>
44− </td>
45− <td>1MB</td>
46− <td nowrap="nowrap">
47− <span class="bts_1">
48− 29
49− </span>
50− </td>
51− <td nowrap="nowrap">
52− <span class="btl_1">
53− 211
54− </span>
55− </td>
56− <td nowrap="nowrap">
57− <span class="btc_">
58− 168
59− </span>
60− </td>
61− <td><a href="random.html">user</a></td>
62− </tr>
63− </tbody>
64−</table>
65−</html>
66− """
67−
68− resp = mock.Mock(text=html)
69− results = acgsou.response(resp)
70−
71− self.assertEqual(type(results), list)
72− self.assertEqual(len(results), 1)
73−
74− r = results[0]
75− self.assertEqual(r['url'], 'http://www.acgsou.com/show-torrentid.html')
76− self.assertEqual(r['content'], u'Category: "testcategory テスト".')
77− self.assertEqual(r['title'], u'torrentname テスト')
78− self.assertEqual(r['filesize'], 1048576)
tests/unit/engines/test_archlinux.pydeleted−111
@@ -1,111 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import archlinux
4−from searx.testing import SearxTestCase
5−
6−domains = {
7− 'all': 'https://wiki.archlinux.org',
8− 'de': 'https://wiki.archlinux.de',
9− 'fr': 'https://wiki.archlinux.fr',
10− 'ja': 'https://wiki.archlinuxjp.org',
11− 'ro': 'http://wiki.archlinux.ro',
12− 'tr': 'http://archtr.org/wiki'
13−}
14−
15−
16−class TestArchLinuxEngine(SearxTestCase):
17−
18− def test_request(self):
19− query = 'test_query'
20− dic = defaultdict(dict)
21− dic['pageno'] = 1
22− dic['language'] = 'en-US'
23− params = archlinux.request(query, dic)
24− self.assertTrue('url' in params)
25− self.assertTrue(query in params['url'])
26− self.assertTrue('wiki.archlinux.org' in params['url'])
27−
28− for lang, name in archlinux.main_langs:
29− dic['language'] = lang
30− params = archlinux.request(query, dic)
31− self.assertTrue(name in params['url'])
32−
33− for lang, domain in domains.items():
34− dic['language'] = lang
35− params = archlinux.request(query, dic)
36− self.assertTrue(domain in params['url'])
37−
38− def test_response(self):
39− response = mock.Mock(text='<html></html>',
40− search_params={'language': 'en_US'})
41− self.assertEqual(archlinux.response(response), [])
42−
43− html = """
44− <ul class="mw-search-results">
45− <li>
46− <div class="mw-search-result-heading">
47− <a href="/index.php/ATI" title="ATI">ATI</a>
48− </div>
49− <div class="searchresult">
50− Lorem ipsum dolor sit amet
51− </div>
52− <div class="mw-search-result-data">
53− 30 KB (4,630 words) - 19:04, 17 March 2016</div>
54− </li>
55− <li>
56− <div class="mw-search-result-heading">
57− <a href="/index.php/Frequently_asked_questions" title="Frequently asked questions">
58− Frequently asked questions
59− </a>
60− </div>
61− <div class="searchresult">
62− CPUs with AMDs instruction set "AMD64"
63− </div>
64− <div class="mw-search-result-data">
65− 17 KB (2,722 words) - 20:13, 21 March 2016
66− </div>
67− </li>
68− <li>
69− <div class="mw-search-result-heading">
70− <a href="/index.php/CPU_frequency_scaling" title="CPU frequency scaling">CPU frequency scaling</a>
71− </div>
72− <div class="searchresult">
73− ondemand for AMD and older Intel CPU
74− </div>
75− <div class="mw-search-result-data">
76− 15 KB (2,319 words) - 23:46, 16 March 2016
77− </div>
78− </li>
79− </ul>
80− """
81−
82− expected = [
83− {
84− 'title': 'ATI',
85− 'url': 'https://wiki.archlinux.org/index.php/ATI'
86− },
87− {
88− 'title': 'Frequently asked questions',
89− 'url': 'https://wiki.archlinux.org/index.php/Frequently_asked_questions'
90− },
91− {
92− 'title': 'CPU frequency scaling',
93− 'url': 'https://wiki.archlinux.org/index.php/CPU_frequency_scaling'
94− }
95− ]
96−
97− response = mock.Mock(text=html)
98− response.search_params = {
99− 'language': 'en_US'
100− }
101− results = archlinux.response(response)
102−
103− self.assertEqual(type(results), list)
104− self.assertEqual(len(results), len(expected))
105−
106− i = 0
107− for exp in expected:
108− res = results[i]
109− i += 1
110− for key, value in exp.items():
111− self.assertEqual(res[key], value)
tests/unit/engines/test_arxiv.pydeleted−58
@@ -1,58 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import arxiv
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBaseEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'.encode('utf-8')
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = arxiv.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn('export.arxiv.org/api/', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, arxiv.response, None)
20− self.assertRaises(AttributeError, arxiv.response, [])
21− self.assertRaises(AttributeError, arxiv.response, '')
22− self.assertRaises(AttributeError, arxiv.response, '[]')
23−
24− response = mock.Mock(content=b'''<?xml version="1.0" encoding="UTF-8"?>
25−<feed xmlns="http://www.w3.org/2005/Atom"></feed>''')
26− self.assertEqual(arxiv.response(response), [])
27−
28− xml_mock = b'''<?xml version="1.0" encoding="UTF-8"?>
29−<feed xmlns="http://www.w3.org/2005/Atom">
30− <title type="html">ArXiv Query: search_query=all:test_query&amp;id_list=&amp;start=0&amp;max_results=1</title>
31− <id>http://arxiv.org/api/1</id>
32− <updated>2000-01-21T00:00:00-01:00</updated>
33− <opensearch:totalResults xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">1</opensearch:totalResults>
34− <opensearch:startIndex xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">0</opensearch:startIndex>
35− <opensearch:itemsPerPage xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">1</opensearch:itemsPerPage>
36− <entry>
37− <id>http://arxiv.org/1</id>
38− <updated>2000-01-01T00:00:01Z</updated>
39− <published>2000-01-01T00:00:01Z</published>
40− <title>Mathematical proof.</title>
41− <summary>Mathematical formula.</summary>
42− <author>
43− <name>A. B.</name>
44− </author>
45− <link href="http://arxiv.org/1" rel="alternate" type="text/html"/>
46− <link title="pdf" href="http://arxiv.org/1" rel="related" type="application/pdf"/>
47− <category term="math.QA" scheme="http://arxiv.org/schemas/atom"/>
48− <category term="1" scheme="http://arxiv.org/schemas/atom"/>
49− </entry>
50−</feed>
51−'''
52−
53− response = mock.Mock(content=xml_mock)
54− results = arxiv.response(response)
55− self.assertEqual(type(results), list)
56− self.assertEqual(len(results), 1)
57− self.assertEqual(results[0]['title'], 'Mathematical proof.')
58− self.assertEqual(results[0]['content'], 'Mathematical formula.')
tests/unit/engines/test_base.pydeleted−91
@@ -1,91 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import base
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBaseEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = base.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn('base-search.net', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, base.response, None)
20− self.assertRaises(AttributeError, base.response, [])
21− self.assertRaises(AttributeError, base.response, '')
22− self.assertRaises(AttributeError, base.response, '[]')
23−
24− response = mock.Mock(content=b'<response></response>')
25− self.assertEqual(base.response(response), [])
26−
27− xml_mock = b"""<?xml version="1.0"?>
28−<response>
29− <lst name="responseHeader">
30− <int name="status">0</int>
31− <int name="QTime">1</int>
32− </lst>
33− <result name="response" numFound="1" start="0">
34− <doc>
35− <date name="dchdate">2000-01-01T01:01:01Z</date>
36− <str name="dcdocid">1</str>
37− <str name="dccontinent">cna</str>
38− <str name="dccountry">us</str>
39− <str name="dccollection">ftciteseerx</str>
40− <str name="dcprovider">CiteSeerX</str>
41− <str name="dctitle">Science and more</str>
42− <arr name="dccreator">
43− <str>Someone</str>
44− </arr>
45− <arr name="dcperson">
46− <str>Someone</str>
47− </arr>
48− <arr name="dcsubject">
49− <str>Science and more</str>
50− </arr>
51− <str name="dcdescription">Science, and even more.</str>
52− <arr name="dccontributor">
53− <str>The neighbour</str>
54− </arr>
55− <str name="dcdate">2001</str>
56− <int name="dcyear">2001</int>
57− <arr name="dctype">
58− <str>text</str>
59− </arr>
60− <arr name="dctypenorm">
61− <str>1</str>
62− </arr>
63− <arr name="dcformat">
64− <str>application/pdf</str>
65− </arr>
66− <arr name="dccontenttype">
67− <str>application/pdf</str>
68− </arr>
69− <arr name="dcidentifier">
70− <str>http://example.org/</str>
71− </arr>
72− <str name="dclink">http://example.org</str>
73− <str name="dcsource">http://example.org</str>
74− <arr name="dclanguage">
75− <str>en</str>
76− </arr>
77− <str name="dcrights">Under the example.org licence</str>
78− <int name="dcoa">1</int>
79− <arr name="dclang">
80− <str>eng</str>
81− </arr>
82− </doc>
83− </result>
84−</response>"""
85−
86− response = mock.Mock(content=xml_mock)
87− results = base.response(response)
88− self.assertEqual(type(results), list)
89− self.assertEqual(len(results), 1)
90− self.assertEqual(results[0]['title'], 'Science and more')
91− self.assertEqual(results[0]['content'], 'Science, and even more.')
tests/unit/engines/test_bing.pydeleted−178
@@ -1,178 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import bing
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBingEngine(SearxTestCase):
9−
10− def test_request(self):
11− bing.supported_languages = ['en', 'fr', 'zh-CHS', 'zh-CHT', 'pt-PT', 'pt-BR']
12− query = u'test_query'
13− dicto = defaultdict(dict)
14− dicto['pageno'] = 1
15− dicto['language'] = 'fr-FR'
16− params = bing.request(query.encode('utf-8'), dicto)
17− self.assertTrue('url' in params)
18− self.assertTrue(query in params['url'])
19− self.assertTrue('language%3AFR' in params['url'])
20− self.assertTrue('bing.com' in params['url'])
21−
22− dicto['language'] = 'all'
23− params = bing.request(query.encode('utf-8'), dicto)
24− self.assertTrue('language' in params['url'])
25−
26− def test_response(self):
27− dicto = defaultdict(dict)
28− dicto['pageno'] = 1
29− dicto['language'] = 'fr-FR'
30− self.assertRaises(AttributeError, bing.response, None)
31− self.assertRaises(AttributeError, bing.response, [])
32− self.assertRaises(AttributeError, bing.response, '')
33− self.assertRaises(AttributeError, bing.response, '[]')
34−
35− response = mock.Mock(text='<html></html>')
36− response.search_params = dicto
37− self.assertEqual(bing.response(response), [])
38−
39− response = mock.Mock(text='<html></html>')
40− response.search_params = dicto
41− self.assertEqual(bing.response(response), [])
42−
43− html = """
44− <div>
45− <div id="b_tween">
46− <span class="sb_count" data-bm="4">23 900 000 résultats</span>
47− </div>
48− <ol id="b_results" role="main">
49− <div class="sa_cc" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
50− <div Class="sa_mc">
51− <div class="sb_tlst">
52− <h3>
53− <a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
54− <strong>This</strong> should be the title</a>
55− </h3>
56− </div>
57− <div class="sb_meta"><cite><strong>this</strong>.meta.com</cite>
58− <span class="c_tlbxTrg">
59− <span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
60− </span>
61− </span>
62− </div>
63− <p><strong>This</strong> should be the content.</p>
64− </div>
65− </div>
66− </ol>
67− </div>
68− """
69− response = mock.Mock(text=html)
70− response.search_params = dicto
71− results = bing.response(response)
72− self.assertEqual(type(results), list)
73− self.assertEqual(len(results), 2)
74− self.assertEqual(results[0]['title'], 'This should be the title')
75− self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
76− self.assertEqual(results[0]['content'], 'This should be the content.')
77− self.assertEqual(results[-1]['number_of_results'], 23900000)
78−
79− html = """
80− <div>
81− <div id="b_tween">
82− <span class="sb_count" data-bm="4">9-18 résultats sur 23 900 000</span>
83− </div>
84− <ol id="b_results" role="main">
85− <li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
86− <div Class="sa_mc">
87− <div class="sb_tlst">
88− <h2>
89− <a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
90− <strong>This</strong> should be the title</a>
91− </h2>
92− </div>
93− <div class="sb_meta"><cite><strong>this</strong>.meta.com</cite>
94− <span class="c_tlbxTrg">
95− <span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
96− </span>
97− </span>
98− </div>
99− <p><strong>This</strong> should be the content.</p>
100− </div>
101− </li>
102− </ol>
103− </div>
104− """
105− dicto['pageno'] = 2
106− response = mock.Mock(text=html)
107− response.search_params = dicto
108− results = bing.response(response)
109− self.assertEqual(type(results), list)
110− self.assertEqual(len(results), 2)
111− self.assertEqual(results[0]['title'], 'This should be the title')
112− self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
113− self.assertEqual(results[0]['content'], 'This should be the content.')
114− self.assertEqual(results[-1]['number_of_results'], 23900000)
115−
116− html = """
117− <div>
118− <div id="b_tween">
119− <span class="sb_count" data-bm="4">23 900 000 résultats</span>
120− </div>
121− <ol id="b_results" role="main">
122− <li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
123− <div Class="sa_mc">
124− <div class="sb_tlst">
125− <h2>
126− <a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
127− <strong>This</strong> should be the title</a>
128− </h2>
129− </div>
130− <div class="sb_meta"><cite><strong>this</strong>.meta.com</cite>
131− <span class="c_tlbxTrg">
132− <span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
133− </span>
134− </span>
135− </div>
136− <p><strong>This</strong> should be the content.</p>
137− </div>
138− </li>
139− </ol>
140− </div>
141− """
142− dicto['pageno'] = 33900000
143− response = mock.Mock(text=html)
144− response.search_params = dicto
145− results = bing.response(response)
146− self.assertEqual(bing.response(response), [])
147−
148− def test_fetch_supported_languages(self):
149− html = """<html></html>"""
150− response = mock.Mock(text=html)
151− results = bing._fetch_supported_languages(response)
152− self.assertEqual(type(results), list)
153− self.assertEqual(len(results), 0)
154−
155− html = """
156− <html>
157− <body>
158− <form>
159− <div id="limit-languages">
160− <div>
161− <div><input id="es" value="es"></input></div>
162− </div>
163− <div>
164− <div><input id="pt_BR" value="pt_BR"></input></div>
165− <div><input id="pt_PT" value="pt_PT"></input></div>
166− </div>
167− </div>
168− </form>
169− </body>
170− </html>
171− """
172− response = mock.Mock(text=html)
173− languages = bing._fetch_supported_languages(response)
174− self.assertEqual(type(languages), list)
175− self.assertEqual(len(languages), 3)
176− self.assertIn('es', languages)
177− self.assertIn('pt-BR', languages)
178− self.assertIn('pt-PT', languages)
tests/unit/engines/test_bing_images.pydeleted−132
@@ -1,132 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import bing_images
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBingImagesEngine(SearxTestCase):
9−
10− def test_request(self):
11− bing_images.supported_languages = ['fr-FR', 'en-US']
12− bing_images.language_aliases = {}
13− query = 'test_query'
14− dicto = defaultdict(dict)
15− dicto['pageno'] = 1
16− dicto['language'] = 'fr-FR'
17− dicto['safesearch'] = 1
18− dicto['time_range'] = ''
19− params = bing_images.request(query, dicto)
20− self.assertTrue('url' in params)
21− self.assertTrue(query in params['url'])
22− self.assertTrue('bing.com' in params['url'])
23− self.assertTrue('SRCHHPGUSR' in params['cookies'])
24− self.assertTrue('DEMOTE' in params['cookies']['SRCHHPGUSR'])
25− self.assertTrue('_EDGE_S' in params['cookies'])
26− self.assertTrue('fr-fr' in params['cookies']['_EDGE_S'])
27−
28− dicto['language'] = 'fr'
29− params = bing_images.request(query, dicto)
30− self.assertTrue('_EDGE_S' in params['cookies'])
31− self.assertTrue('fr-fr' in params['cookies']['_EDGE_S'])
32−
33− dicto['language'] = 'all'
34− params = bing_images.request(query, dicto)
35− self.assertTrue('_EDGE_S' in params['cookies'])
36− self.assertTrue('en-us' in params['cookies']['_EDGE_S'])
37−
38− def test_response(self):
39− self.assertRaises(AttributeError, bing_images.response, None)
40− self.assertRaises(AttributeError, bing_images.response, [])
41− self.assertRaises(AttributeError, bing_images.response, '')
42− self.assertRaises(AttributeError, bing_images.response, '[]')
43−
44− response = mock.Mock(text='<html></html>')
45− self.assertEqual(bing_images.response(response), [])
46−
47− response = mock.Mock(text='<html></html>')
48− self.assertEqual(bing_images.response(response), [])
49−
50− html = """
51− <div id="mmComponent_images_1">
52− <ul>
53− <li>
54− <div>
55− <div class="imgpt">
56− <a m='{"purl":"page_url","murl":"img_url","turl":"thumb_url","t":"Page 1 title"}'>
57− <img src="" alt="alt text" />
58− </a>
59− <div class="img_info">
60− <span>1 x 1 - jpeg</span>
61− <a>1.example.org</a>
62− </div>
63− </div>
64− <div></div>
65− </div>
66− <div>
67− <div class="imgpt">
68− <a m='{"purl":"page_url2","murl":"img_url2","turl":"thumb_url2","t":"Page 2 title"}'>
69− <img src="" alt="alt text 2" />
70− </a>
71− <div class="img_info">
72− <span>2 x 2 - jpeg</span>
73− <a>2.example.org</a>
74− </div>
75− </div>
76− </div>
77− </li>
78− </ul>
79− <ul>
80− <li>
81− <div>
82− <div class="imgpt">
83− <a m='{"purl":"page_url3","murl":"img_url3","turl":"thumb_url3","t":"Page 3 title"}'>
84− <img src="" alt="alt text 3" />
85− </a>
86− <div class="img_info">
87− <span>3 x 3 - jpeg</span>
88− <a>3.example.org</a>
89− </div>
90− </div>
91− </div>
92− </li>
93− </ul>
94− </div>
95− """
96− html = html.replace('\r\n', '').replace('\n', '').replace('\r', '')
97− response = mock.Mock(text=html)
98− results = bing_images.response(response)
99− self.assertEqual(type(results), list)
100− self.assertEqual(len(results), 3)
101− self.assertEqual(results[0]['title'], 'Page 1 title')
102− self.assertEqual(results[0]['url'], 'page_url')
103− self.assertEqual(results[0]['content'], '')
104− self.assertEqual(results[0]['thumbnail_src'], 'thumb_url')
105− self.assertEqual(results[0]['img_src'], 'img_url')
106− self.assertEqual(results[0]['img_format'], '1 x 1 - jpeg')
107− self.assertEqual(results[0]['source'], '1.example.org')
108−
109− def test_fetch_supported_languages(self):
110− html = """
111− <div>
112− <div id="region-section-content">
113− <ul class="b_vList">
114− <li>
115− <a href="https://bing...&setmkt=de-DE&s...">Germany</a>
116− <a href="https://bing...&setmkt=nb-NO&s...">Norway</a>
117− </li>
118− </ul>
119− <ul class="b_vList">
120− <li>
121− <a href="https://bing...&setmkt=es-AR&s...">Argentina</a>
122− </li>
123− </ul>
124− </div>
125− </div>
126− """
127− response = mock.Mock(text=html)
128− languages = list(bing_images._fetch_supported_languages(response))
129− self.assertEqual(len(languages), 3)
130− self.assertIn('de-DE', languages)
131− self.assertIn('no-NO', languages)
132− self.assertIn('es-AR', languages)
tests/unit/engines/test_bing_news.pydeleted−147
@@ -1,147 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import bing_news
4−from searx.testing import SearxTestCase
5−import lxml
6−
7−
8−class TestBingNewsEngine(SearxTestCase):
9−
10− def test_request(self):
11− bing_news.supported_languages = ['en', 'fr']
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− dicto['pageno'] = 1
15− dicto['language'] = 'fr-FR'
16− dicto['time_range'] = ''
17− params = bing_news.request(query, dicto)
18− self.assertIn('url', params)
19− self.assertIn(query, params['url'])
20− self.assertIn('bing.com', params['url'])
21− self.assertIn('fr', params['url'])
22−
23− dicto['language'] = 'all'
24− params = bing_news.request(query, dicto)
25− self.assertIn('en', params['url'])
26−
27− def test_no_url_in_request_year_time_range(self):
28− dicto = defaultdict(dict)
29− query = 'test_query'
30− dicto['time_range'] = 'year'
31− params = bing_news.request(query, dicto)
32− self.assertEqual({}, params['url'])
33−
34− def test_response(self):
35− self.assertRaises(AttributeError, bing_news.response, None)
36− self.assertRaises(AttributeError, bing_news.response, [])
37− self.assertRaises(AttributeError, bing_news.response, '')
38− self.assertRaises(AttributeError, bing_news.response, '[]')
39−
40− response = mock.Mock(content='<html></html>')
41− self.assertEqual(bing_news.response(response), [])
42−
43− response = mock.Mock(content='<html></html>')
44− self.assertEqual(bing_news.response(response), [])
45−
46− html = """<?xml version="1.0" encoding="utf-8" ?>
47−<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS">
48− <channel>
49− <title>python - Bing News</title>
50− <link>https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
51− <description>Search results</description>
52− <image>
53− <url>http://10.53.64.9/rsslogo.gif</url>
54− <title>test</title>
55− <link>https://www.bing.com:443/news/search?q=test&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
56− </image>
57− <copyright>Copyright</copyright>
58− <item>
59− <title>Title</title>
60− <link>https://www.bing.com/news/apiclick.aspx?ref=FexRss&amp;aid=&amp;tid=c237eccc50bd4758b106a5e3c94fce09&amp;url=http%3a%2f%2furl.of.article%2f&amp;c=xxxxxxxxx&amp;mkt=en-us</link>
61− <description>Article Content</description>
62− <pubDate>Tue, 02 Jun 2015 13:37:00 GMT</pubDate>
63− <News:Source>Infoworld</News:Source>
64− <News:Image>http://a1.bing4.com/th?id=ON.13371337133713371337133713371337&amp;pid=News</News:Image>
65− <News:ImageSize>w={0}&amp;h={1}&amp;c=7</News:ImageSize>
66− <News:ImageKeepOriginalRatio></News:ImageKeepOriginalRatio>
67− <News:ImageMaxWidth>620</News:ImageMaxWidth>
68− <News:ImageMaxHeight>413</News:ImageMaxHeight>
69− </item>
70− <item>
71− <title>Another Title</title>
72− <link>https://www.bing.com/news/apiclick.aspx?ref=FexRss&amp;aid=&amp;tid=c237eccc50bd4758b106a5e3c94fce09&amp;url=http%3a%2f%2fanother.url.of.article%2f&amp;c=xxxxxxxxx&amp;mkt=en-us</link>
73− <description>Another Article Content</description>
74− <pubDate>Tue, 02 Jun 2015 13:37:00 GMT</pubDate>
75− </item>
76− </channel>
77−</rss>""" # noqa
78− response = mock.Mock(content=html.encode('utf-8'))
79− results = bing_news.response(response)
80− self.assertEqual(type(results), list)
81− self.assertEqual(len(results), 2)
82− self.assertEqual(results[0]['title'], 'Title')
83− self.assertEqual(results[0]['url'], 'http://url.of.article/')
84− self.assertEqual(results[0]['content'], 'Article Content')
85− self.assertEqual(results[0]['img_src'], 'https://www.bing.com/th?id=ON.13371337133713371337133713371337')
86− self.assertEqual(results[1]['title'], 'Another Title')
87− self.assertEqual(results[1]['url'], 'http://another.url.of.article/')
88− self.assertEqual(results[1]['content'], 'Another Article Content')
89− self.assertNotIn('img_src', results[1])
90−
91− html = """<?xml version="1.0" encoding="utf-8" ?>
92−<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS">
93− <channel>
94− <title>python - Bing News</title>
95− <link>https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
96− <description>Search results</description>
97− <image>
98− <url>http://10.53.64.9/rsslogo.gif</url>
99− <title>test</title>
100− <link>https://www.bing.com:443/news/search?q=test&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
101− </image>
102− <copyright>Copyright</copyright>
103− <item>
104− <title>Title</title>
105− <link>http://another.url.of.article/</link>
106− <description>Article Content</description>
107− <pubDate>garbage</pubDate>
108− <News:Source>Infoworld</News:Source>
109− <News:Image>http://another.bing.com/image</News:Image>
110− <News:ImageSize>w={0}&amp;h={1}&amp;c=7</News:ImageSize>
111− <News:ImageKeepOriginalRatio></News:ImageKeepOriginalRatio>
112− <News:ImageMaxWidth>620</News:ImageMaxWidth>
113− <News:ImageMaxHeight>413</News:ImageMaxHeight>
114− </item>
115− </channel>
116−</rss>""" # noqa
117− response = mock.Mock(content=html.encode('utf-8'))
118− results = bing_news.response(response)
119− self.assertEqual(type(results), list)
120− self.assertEqual(len(results), 1)
121− self.assertEqual(results[0]['title'], 'Title')
122− self.assertEqual(results[0]['url'], 'http://another.url.of.article/')
123− self.assertEqual(results[0]['content'], 'Article Content')
124− self.assertEqual(results[0]['img_src'], 'http://another.bing.com/image')
125−
126− html = """<?xml version="1.0" encoding="utf-8" ?>
127−<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS">
128− <channel>
129− <title>python - Bing News</title>
130− <link>https://www.bing.com:443/news/search?q=python&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
131− <description>Search results</description>
132− <image>
133− <url>http://10.53.64.9/rsslogo.gif</url>
134− <title>test</title>
135− <link>https://www.bing.com:443/news/search?q=test&amp;setmkt=en-US&amp;first=1&amp;format=RSS</link>
136− </image>
137− </channel>
138−</rss>""" # noqa
139−
140− response = mock.Mock(content=html.encode('utf-8'))
141− results = bing_news.response(response)
142− self.assertEqual(type(results), list)
143− self.assertEqual(len(results), 0)
144−
145− html = """<?xml version="1.0" encoding="utf-8" ?>gabarge"""
146− response = mock.Mock(content=html.encode('utf-8'))
147− self.assertRaises(lxml.etree.XMLSyntaxError, bing_news.response, response)
tests/unit/engines/test_bing_videos.pydeleted−72
@@ -1,72 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import bing_videos
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBingVideosEngine(SearxTestCase):
9−
10− def test_request(self):
11− bing_videos.supported_languages = ['fr-FR', 'en-US']
12− bing_videos.language_aliases = {}
13− query = 'test_query'
14− dicto = defaultdict(dict)
15− dicto['pageno'] = 1
16− dicto['language'] = 'fr-FR'
17− dicto['safesearch'] = 0
18− dicto['time_range'] = ''
19− params = bing_videos.request(query, dicto)
20− self.assertTrue('url' in params)
21− self.assertTrue(query in params['url'])
22− self.assertTrue('bing.com' in params['url'])
23− self.assertTrue('SRCHHPGUSR' in params['cookies'])
24− self.assertTrue('OFF' in params['cookies']['SRCHHPGUSR'])
25− self.assertTrue('_EDGE_S' in params['cookies'])
26− self.assertTrue('fr-fr' in params['cookies']['_EDGE_S'])
27−
28− dicto['pageno'] = 2
29− dicto['time_range'] = 'day'
30− dicto['safesearch'] = 2
31− params = bing_videos.request(query, dicto)
32− self.assertTrue('first=29' in params['url'])
33− self.assertTrue('1440' in params['url'])
34− self.assertIn('SRCHHPGUSR', params['cookies'])
35− self.assertTrue('STRICT' in params['cookies']['SRCHHPGUSR'])
36−
37− def test_response(self):
38− self.assertRaises(AttributeError, bing_videos.response, None)
39− self.assertRaises(AttributeError, bing_videos.response, [])
40− self.assertRaises(AttributeError, bing_videos.response, '')
41− self.assertRaises(AttributeError, bing_videos.response, '[]')
42−
43− response = mock.Mock(text='<html></html>')
44− self.assertEqual(bing_videos.response(response), [])
45−
46− response = mock.Mock(text='<html></html>')
47− self.assertEqual(bing_videos.response(response), [])
48−
49− html = """
50− <div class="dg_u">
51− <div>
52− <a>
53− <div>
54− <div>
55− <div class="mc_vtvc_meta_block">
56− <div><span>100 views</span><span>1 year ago</span></div><div><span>ExampleTube</span><span>Channel 1<span></div> #noqa
57− </div>
58− </div>
59− <div class="vrhdata" vrhm='{"du":"01:11","murl":"https://www.example.com/watch?v=DEADBEEF","thid":"OVP.BINGTHUMB1","vt":"Title 1"}'></div> # noqa
60− </div>
61− </a>
62− </div>
63− </div>
64− """
65− response = mock.Mock(text=html)
66− results = bing_videos.response(response)
67− self.assertEqual(type(results), list)
68− self.assertEqual(len(results), 1)
69− self.assertEqual(results[0]['title'], 'Title 1')
70− self.assertEqual(results[0]['url'], 'https://www.example.com/watch?v=DEADBEEF')
71− self.assertEqual(results[0]['content'], '01:11 - 100 views - 1 year ago - ExampleTube - Channel 1')
72− self.assertEqual(results[0]['thumbnail'], 'https://www.bing.com/th?id=OVP.BINGTHUMB1')
tests/unit/engines/test_btdigg.pydeleted−112
@@ -1,112 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import btdigg
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBtdiggEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 0
14− params = btdigg.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('btdig.com', params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, btdigg.response, None)
21− self.assertRaises(AttributeError, btdigg.response, [])
22− self.assertRaises(AttributeError, btdigg.response, '')
23− self.assertRaises(AttributeError, btdigg.response, '[]')
24−
25− response = mock.Mock(text='<html></html>')
26− self.assertEqual(btdigg.response(response), [])
27−
28− html = u"""
29− <div class="one_result" style="display:table-row;background-color:#e8e8e8">
30− <div style="display:table-cell;color:rgb(0, 0, 0)">
31− <div style="display:table">
32− <div style="display:table-row">
33− <div class="torrent_name" style="display:table-cell">
34− <a style="color:rgb(0, 0, 204);text-decoration:underline;font-size:150%"
35− href="http://btdig.com/a72f35b7ee3a10928f02bb799e40ae5db701ed1c/pdf?q=pdf&amp;p=1&amp;order=0"
36− >3.9GBdeLibrosByHuasoFromHell(3de4)</a>
37− </div>
38− </div>
39− </div>
40− <div style="display:table">
41− <div style="display:table-row">
42− <div style="display:table-cell">
43− <span class="torrent_files" style="color:#666;padding-left:10px">4217</span> files <span
44− class="torrent_size" style="color:#666;padding-left:10px">1 GB</span><span
45− class="torrent_age" style="color:rgb(0, 102, 0);padding-left:10px;margin: 0px 4px"
46− >found 3 years ago</span>
47− </div>
48− </div>
49− </div>
50− <div style="display:table;width:100%;padding:10px">
51− <div style="display:table-row">
52− <div class="torrent_magnet" style="display:table-cell">
53− <div class="fa fa-magnet" style="color:#cc0000">
54− <a href="magnet:?xt=urn:btih:a72f35b7ee3a10928f02bb799e40ae5db701ed1c&amp;dn=3.9GBdeLibrosBy..."
55− title="Download via magnet-link"> magnet:?xt=urn:btih:a72f35b7ee...</a>
56− </div>
57− </div>
58− <div style="display:table-cell;color:rgb(0, 0, 0);text-align:right">
59− <span style="color:rgb(136, 136, 136);margin: 0px 0px 0px 4px"></span><span
60− style="color:rgb(0, 102, 0);margin: 0px 4px">found 3 years ago</span>
61− </div>
62− </div>
63− </div>
64− <div class="torrent_excerpt" style="display:table;padding:10px;white-space:nowrap">
65− <div class="fa fa-folder-open" style="padding-left:0em"> 3.9GBdeLibrosByHuasoFromHell(3de4)</div><br/>
66− <div class="fa fa-folder-open" style="padding-left:1em"> Libros H-Z</div><br/>
67− <div class="fa fa-folder-open" style="padding-left:2em"> H</div><br/><div class="fa fa-file-archive-o"
68− style="padding-left:3em"> H.H. Hollis - El truco de la espada-<b
69− style="color:red; background-color:yellow">pdf</b>.zip</div><span
70− style="color:#666;padding-left:10px">17 KB</span><br/>
71− <div class="fa fa-file-archive-o" style="padding-left:3em"> Hagakure - El Libro del Samurai-<b
72− style="color:red; background-color:yellow">pdf</b>.zip</div><span
73− style="color:#666;padding-left:10px">95 KB</span><br/>
74− <div class="fa fa-folder-open" style="padding-left:3em"> Hamsun, Knut (1859-1952)</div><br/>
75− <div class="fa fa-file-archive-o" style="padding-left:4em"> Hamsun, Knut - Hambre-<b
76− style="color:red; background-color:yellow">pdf</b>.zip</div><span
77− style="color:#666;padding-left:10px">786 KB</span><br/>
78− <div class="fa fa-plus-circle"><a
79− href="http://btdig.com/a72f35b7ee3a10928f02bb799e40ae5db701ed1c/pdf?q=pdf&amp;p=1&amp;order=0"
80− > 4214 hidden files<span style="color:#666;padding-left:10px">1 GB</span></a></div>
81− </div>
82− </div>
83− </div>
84− """
85− response = mock.Mock(text=html.encode('utf-8'))
86− results = btdigg.response(response)
87− self.assertEqual(type(results), list)
88− self.assertEqual(len(results), 1)
89− self.assertEqual(results[0]['title'], '3.9GBdeLibrosByHuasoFromHell(3de4)')
90− self.assertEqual(results[0]['url'],
91− 'http://btdig.com/a72f35b7ee3a10928f02bb799e40ae5db701ed1c/pdf?q=pdf&p=1&order=0')
92− self.assertEqual(results[0]['content'],
93− '3.9GBdeLibrosByHuasoFromHell(3de4) | ' +
94− 'Libros H-Z | ' +
95− 'H H.H. Hollis - El truco de la espada-pdf.zip17 KB | ' +
96− 'Hagakure - El Libro del Samurai-pdf.zip95 KB | ' +
97− 'Hamsun, Knut (1859-1952) | Hamsun, Knut - Hambre-pdf.zip786 KB | ' +
98− '4214 hidden files1 GB')
99− self.assertEqual(results[0]['filesize'], 1 * 1024 * 1024 * 1024)
100− self.assertEqual(results[0]['files'], 4217)
101− self.assertEqual(results[0]['magnetlink'],
102− 'magnet:?xt=urn:btih:a72f35b7ee3a10928f02bb799e40ae5db701ed1c&dn=3.9GBdeLibrosBy...')
103−
104− html = """
105− <div style="display:table-row;background-color:#e8e8e8">
106−
107− </div>
108− """
109− response = mock.Mock(text=html.encode('utf-8'))
110− results = btdigg.response(response)
111− self.assertEqual(type(results), list)
112− self.assertEqual(len(results), 0)
tests/unit/engines/test_currency_convert.pydeleted−56
@@ -1,56 +0,0 @@
1−from collections import defaultdict
2−from datetime import datetime
3−import mock
4−from searx.engines import currency_convert
5−from searx.testing import SearxTestCase
6−
7−
8−class TestCurrencyConvertEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = b'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = currency_convert.request(query, dicto)
15− self.assertNotIn('url', params)
16−
17− query = b'convert 10 Pound Sterlings to United States Dollars'
18− params = currency_convert.request(query, dicto)
19− self.assertIn('url', params)
20− self.assertIn('duckduckgo.com', params['url'])
21− self.assertIn('GBP', params['url'])
22− self.assertIn('USD', params['url'])
23−
24− def test_response(self):
25− dicto = defaultdict(dict)
26− dicto['amount'] = float(10)
27− dicto['from'] = "GBP"
28− dicto['to'] = "USD"
29− dicto['from_name'] = "pound sterling"
30− dicto['to_name'] = "United States dollar"
31− response = mock.Mock(text='a,b,c,d', search_params=dicto)
32− self.assertEqual(currency_convert.response(response), [])
33− body = """ddg_spice_currency(
34− {
35− "conversion":{
36− "converted-amount": "0.5"
37− },
38− "topConversions":[
39− {
40− },
41− {
42− }
43− ]
44− }
45− );
46− """
47− response = mock.Mock(text=body, search_params=dicto)
48− results = currency_convert.response(response)
49− self.assertEqual(type(results), list)
50− self.assertEqual(len(results), 1)
51− self.assertEqual(results[0]['answer'], '10.0 GBP = 5.0 USD, 1 GBP (pound sterling)' +
52− ' = 0.5 USD (United States dollar)')
53−
54− target_url = 'https://duckduckgo.com/js/spice/currency/1/{}/{}'.format(
55− dicto['from'], dicto['to'])
56− self.assertEqual(results[0]['url'], target_url)
tests/unit/engines/test_dailymotion.pydeleted−112
@@ -1,112 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import dailymotion
5−from searx.testing import SearxTestCase
6−
7−
8−class TestDailymotionEngine(SearxTestCase):
9−
10− def test_request(self):
11− dailymotion.supported_languages = ['en', 'fr']
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− dicto['pageno'] = 0
15− dicto['language'] = 'fr-FR'
16− params = dailymotion.request(query, dicto)
17− self.assertTrue('url' in params)
18− self.assertTrue(query in params['url'])
19− self.assertTrue('dailymotion.com' in params['url'])
20− self.assertTrue('fr' in params['url'])
21−
22− dicto['language'] = 'all'
23− params = dailymotion.request(query, dicto)
24− self.assertTrue('en' in params['url'])
25−
26− def test_response(self):
27− self.assertRaises(AttributeError, dailymotion.response, None)
28− self.assertRaises(AttributeError, dailymotion.response, [])
29− self.assertRaises(AttributeError, dailymotion.response, '')
30− self.assertRaises(AttributeError, dailymotion.response, '[]')
31−
32− response = mock.Mock(text='{}')
33− self.assertEqual(dailymotion.response(response), [])
34−
35− response = mock.Mock(text='{"data": []}')
36− self.assertEqual(dailymotion.response(response), [])
37−
38− json = """
39− {
40− "page": 1,
41− "limit": 5,
42− "explicit": false,
43− "total": 289487,
44− "has_more": true,
45− "list": [
46− {
47− "created_time": 1422173451,
48− "title": "Title",
49− "description": "Description",
50− "duration": 81,
51− "url": "http://www.url",
52− "thumbnail_360_url": "http://thumbnail",
53− "id": "x2fit7q"
54− }
55− ]
56− }
57− """
58− response = mock.Mock(text=json)
59− results = dailymotion.response(response)
60− self.assertEqual(type(results), list)
61− self.assertEqual(len(results), 1)
62− self.assertEqual(results[0]['title'], 'Title')
63− self.assertEqual(results[0]['url'], 'http://www.url')
64− self.assertEqual(results[0]['content'], 'Description')
65− self.assertIn('x2fit7q', results[0]['embedded'])
66−
67− json = r"""
68− {"toto":[
69− {"id":200,"name":"Artist Name",
70− "link":"http:\/\/www.dailymotion.com\/artist\/1217","type":"artist"}
71− ]}
72− """
73− response = mock.Mock(text=json)
74− results = dailymotion.response(response)
75− self.assertEqual(type(results), list)
76− self.assertEqual(len(results), 0)
77−
78− def test_fetch_supported_languages(self):
79− json = r"""
80− {"list":[{"code":"af","name":"Afrikaans","native_name":"Afrikaans",
81− "localized_name":"Afrikaans","display_name":"Afrikaans"},
82− {"code":"ar","name":"Arabic","native_name":"\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
83− "localized_name":"Arabic","display_name":"Arabic"},
84− {"code":"la","name":"Latin","native_name":null,
85− "localized_name":"Latin","display_name":"Latin"}
86− ]}
87− """
88− response = mock.Mock(text=json)
89− languages = dailymotion._fetch_supported_languages(response)
90− self.assertEqual(type(languages), dict)
91− self.assertEqual(len(languages), 3)
92− self.assertIn('af', languages)
93− self.assertIn('ar', languages)
94− self.assertIn('la', languages)
95−
96− self.assertEqual(type(languages['af']), dict)
97− self.assertEqual(type(languages['ar']), dict)
98− self.assertEqual(type(languages['la']), dict)
99−
100− self.assertIn('name', languages['af'])
101− self.assertIn('name', languages['ar'])
102− self.assertNotIn('name', languages['la'])
103−
104− self.assertIn('english_name', languages['af'])
105− self.assertIn('english_name', languages['ar'])
106− self.assertIn('english_name', languages['la'])
107−
108− self.assertEqual(languages['af']['name'], 'Afrikaans')
109− self.assertEqual(languages['af']['english_name'], 'Afrikaans')
110− self.assertEqual(languages['ar']['name'], u'العربية')
111− self.assertEqual(languages['ar']['english_name'], 'Arabic')
112− self.assertEqual(languages['la']['english_name'], 'Latin')
tests/unit/engines/test_deezer.pydeleted−57
@@ -1,57 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import deezer
4−from searx.testing import SearxTestCase
5−
6−
7−class TestDeezerEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = deezer.request(query, dicto)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('deezer.com' in params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, deezer.response, None)
20− self.assertRaises(AttributeError, deezer.response, [])
21− self.assertRaises(AttributeError, deezer.response, '')
22− self.assertRaises(AttributeError, deezer.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(deezer.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(deezer.response(response), [])
29−
30− json = r"""
31− {"data":[
32− {"id":100, "title":"Title of track",
33− "link":"https:\/\/www.deezer.com\/track\/1094042","duration":232,
34− "artist":{"id":200,"name":"Artist Name",
35− "link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"},
36− "album":{"id":118106,"title":"Album Title","type":"album"},"type":"track"}
37− ]}
38− """
39− response = mock.Mock(text=json)
40− results = deezer.response(response)
41− self.assertEqual(type(results), list)
42− self.assertEqual(len(results), 1)
43− self.assertEqual(results[0]['title'], 'Title of track')
44− self.assertEqual(results[0]['url'], 'https://www.deezer.com/track/1094042')
45− self.assertEqual(results[0]['content'], 'Artist Name - Album Title - Title of track')
46− self.assertTrue('100' in results[0]['embedded'])
47−
48− json = r"""
49− {"data":[
50− {"id":200,"name":"Artist Name",
51− "link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"}
52− ]}
53− """
54− response = mock.Mock(text=json)
55− results = deezer.response(response)
56− self.assertEqual(type(results), list)
57− self.assertEqual(len(results), 0)
tests/unit/engines/test_deviantart.pydeleted−24
@@ -1,24 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import deviantart
4−from searx.testing import SearxTestCase
5−
6−
7−class TestDeviantartEngine(SearxTestCase):
8−
9− def test_request(self):
10− dicto = defaultdict(dict)
11− query = 'test_query'
12− dicto['pageno'] = 0
13− dicto['time_range'] = ''
14− params = deviantart.request(query, dicto)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('deviantart.com' in params['url'])
18−
19− def test_no_url_in_request_year_time_range(self):
20− dicto = defaultdict(dict)
21− query = 'test_query'
22− dicto['time_range'] = 'year'
23− params = deviantart.request(query, dicto)
24− self.assertEqual({}, params['url'])
tests/unit/engines/test_digbt.pydeleted−61
@@ -1,61 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import digbt
4−from searx.testing import SearxTestCase
5−
6−
7−class TestDigBTEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = digbt.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16− self.assertIn('digbt.org', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, digbt.response, None)
20− self.assertRaises(AttributeError, digbt.response, [])
21− self.assertRaises(AttributeError, digbt.response, '')
22− self.assertRaises(AttributeError, digbt.response, '[]')
23−
24− response = mock.Mock(text='<html></html>')
25− self.assertEqual(digbt.response(response), [])
26−
27− html = """
28− <table class="table">
29− <tr><td class="x-item">
30− <div>
31− <a title="The Big Bang Theory" class="title" href="/The-Big-Bang-Theory-d2.html">
32− The Big <span class="highlight">Bang</span> Theory
33− </a>
34− <span class="ctime"><span style="color:red;">4 hours ago</span></span>
35− </div>
36− <div class="files">
37− <ul>
38− <li>The Big Bang Theory 2.9 GB</li>
39− <li>....</li>
40− </ul>
41− </div>
42− <div class="tail">
43− Files: 1 Size: 2.9 GB Downloads: 1 Updated: <span style="color:red;">4 hours ago</span>
44− &nbsp; &nbsp;
45− <a class="title" href="magnet:?xt=urn:btih:a&amp;dn=The+Big+Bang+Theory">
46− <span class="glyphicon glyphicon-magnet"></span> magnet-link
47− </a>
48− &nbsp; &nbsp;
49− </div>
50− </td></tr>
51− </table>
52− """
53− response = mock.Mock(text=html.encode('utf-8'))
54− results = digbt.response(response)
55− self.assertEqual(type(results), list)
56− self.assertEqual(len(results), 1)
57− self.assertEqual(results[0]['title'], 'The Big Bang Theory')
58− self.assertEqual(results[0]['url'], 'https://digbt.org/The-Big-Bang-Theory-d2.html')
59− self.assertEqual(results[0]['content'], 'The Big Bang Theory 2.9 GB ....')
60− self.assertEqual(results[0]['filesize'], 3113851289)
61− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:a&dn=The+Big+Bang+Theory')
tests/unit/engines/test_digg.pydeleted−16
@@ -1,16 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import digg
4−from searx.testing import SearxTestCase
5−
6−
7−class TestDiggEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 1
13− params = digg.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16− self.assertIn('digg.com', params['url'])
tests/unit/engines/test_doku.pydeleted−79
@@ -1,79 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import doku
5−from searx.testing import SearxTestCase
6−
7−
8−class TestDokuEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− params = doku.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16−
17− def test_response(self):
18− self.assertRaises(AttributeError, doku.response, None)
19− self.assertRaises(AttributeError, doku.response, [])
20− self.assertRaises(AttributeError, doku.response, '')
21− self.assertRaises(AttributeError, doku.response, '[]')
22−
23− response = mock.Mock(text='<html></html>')
24− self.assertEqual(doku.response(response), [])
25−
26− html = u"""
27− <div class="search_quickresult">
28− <h3>Pages trouvées :</h3>
29− <ul class="search_quickhits">
30− <li> <a href="/xfconf-query" class="wikilink1" title="xfconf-query">xfconf-query</a></li>
31− </ul>
32− <div class="clearer"></div>
33− </div>
34− """
35− response = mock.Mock(text=html)
36− results = doku.response(response)
37− expected = [{'content': '', 'title': 'xfconf-query', 'url': 'http://localhost:8090/xfconf-query'}]
38− self.assertEqual(doku.response(response), expected)
39−
40− html = u"""
41− <dl class="search_results">
42− <dt><a href="/xvnc?s[]=query" class="wikilink1" title="xvnc">xvnc</a>: 40 Occurrences trouvées</dt>
43− <dd>er = /usr/bin/Xvnc
44− server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 640x480 ... er = /usr/bin/Xvnc
45− server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 800x600 ... er = /usr/bin/Xvnc
46− server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 1024x768 ... er = /usr/bin/Xvnc
47− server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 1280x1024 -depth 8 -Sec</dd>
48− <dt><a href="/postfix_mysql_tls_sasl_1404?s[]=query"
49− class="wikilink1"
50− title="postfix_mysql_tls_sasl_1404">postfix_mysql_tls_sasl_1404</a>: 14 Occurrences trouvées</dt>
51− <dd>tdepasse
52− hosts = 127.0.0.1
53− dbname = postfix
54− <strong class="search_hit">query</strong> = SELECT goto FROM alias WHERE address='%s' AND a... tdepasse
55− hosts = 127.0.0.1
56− dbname = postfix
57− <strong class="search_hit">query</strong> = SELECT domain FROM domain WHERE domain='%s'
58− #optional <strong class="search_hit">query</strong> to use when relaying for backup MX
59− #<strong class="search_hit">query</strong> = SELECT domain FROM domain WHERE domain='%s' and backupmx =</dd>
60− <dt><a href="/bind9?s[]=query" class="wikilink1" title="bind9">bind9</a>: 12 Occurrences trouvées</dt>
61− <dd> printcmd
62−;; Got answer:
63−;; -&gt;&gt;HEADER&lt;&lt;- opcode: <strong class="search_hit">QUERY</strong>, status: NOERROR, id: 13427
64−;; flags: qr aa rd ra; <strong class="search_hit">QUERY</strong>: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
65−
66−[...]
67−
68−;; <strong class="search_hit">Query</strong> time: 1 msec
69−;; SERVER: 127.0.0.1#53(127.0.0.1)
70−;... par la requête (<strong class="search_hit">Query</strong> time) , entre la première et la deuxième requête.</dd>
71− </dl>
72− """
73− response = mock.Mock(text=html)
74− results = doku.response(response)
75− self.assertEqual(type(results), list)
76− self.assertEqual(len(results), 3)
77− self.assertEqual(results[0]['title'], 'xvnc')
78−# FIXME self.assertEqual(results[0]['url'], u'http://this.should.be.the.link/ű')
79−# FIXME self.assertEqual(results[0]['content'], 'This should be the content.')
tests/unit/engines/test_duckduckgo.pydeleted−106
@@ -1,106 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import load_engine, duckduckgo
5−from searx.testing import SearxTestCase
6−
7−
8−class TestDuckduckgoEngine(SearxTestCase):
9−
10− def test_request(self):
11− duckduckgo = load_engine({'engine': 'duckduckgo', 'name': 'duckduckgo'})
12−
13− query = 'test_query'
14− dicto = defaultdict(dict)
15− dicto['pageno'] = 1
16− dicto['time_range'] = ''
17−
18− dicto['language'] = 'de-CH'
19− params = duckduckgo.request(query, dicto)
20− self.assertIn('url', params)
21− self.assertIn(query, params['url'])
22− self.assertIn('duckduckgo.com', params['url'])
23− self.assertIn('ch-de', params['url'])
24− self.assertIn('s=0', params['url'])
25−
26− # when ddg uses non standard codes
27− dicto['language'] = 'zh-HK'
28− params = duckduckgo.request(query, dicto)
29− self.assertIn('hk-tzh', params['url'])
30−
31− dicto['language'] = 'en-GB'
32− params = duckduckgo.request(query, dicto)
33− self.assertIn('uk-en', params['url'])
34−
35− # no country given
36− dicto['language'] = 'en'
37− params = duckduckgo.request(query, dicto)
38− self.assertIn('us-en', params['url'])
39−
40− def test_no_url_in_request_year_time_range(self):
41− dicto = defaultdict(dict)
42− query = 'test_query'
43− dicto['time_range'] = 'year'
44− params = duckduckgo.request(query, dicto)
45− self.assertEqual({}, params['url'])
46−
47− def test_response(self):
48− self.assertRaises(AttributeError, duckduckgo.response, None)
49− self.assertRaises(AttributeError, duckduckgo.response, [])
50− self.assertRaises(AttributeError, duckduckgo.response, '')
51− self.assertRaises(AttributeError, duckduckgo.response, '[]')
52−
53− response = mock.Mock(text='<html></html>')
54− self.assertEqual(duckduckgo.response(response), [])
55−
56− html = u"""
57− <div class="result results_links results_links_deep web-result result--no-result">
58− <div class="links_main links_deep result__body">
59− <h2 class="result__title">
60− </h2>
61− <div class="no-results">No results</div>
62− <div class="result__extras">
63− </div>
64− </div>
65− </div>
66− """
67− response = mock.Mock(text=html)
68− results = duckduckgo.response(response)
69− self.assertEqual(duckduckgo.response(response), [])
70−
71− html = u"""
72− <div class="result results_links results_links_deep web-result ">
73− <div class="links_main links_deep result__body">
74− <h2 class="result__title">
75− <a rel="nofollow" class="result__a" href="http://this.should.be.the.link/ű">
76− This <b>is</b> <b>the</b> title
77− </a>
78− </h2>
79− <a class="result__snippet" href="http://this.should.be.the.link/ű">
80− <b>This</b> should be the content.
81− </a>
82− <div class="result__extras">
83− </div>
84− </div>
85− </div>
86− """
87− response = mock.Mock(text=html)
88− results = duckduckgo.response(response)
89− self.assertEqual(type(results), list)
90− self.assertEqual(len(results), 1)
91− self.assertEqual(results[0]['title'], 'This is the title')
92− self.assertEqual(results[0]['url'], u'http://this.should.be.the.link/ű')
93− self.assertEqual(results[0]['content'], 'This should be the content.')
94−
95− def test_fetch_supported_languages(self):
96− js = """some code...regions:{
97− "wt-wt":"All Results","ar-es":"Argentina","au-en":"Australia","at-de":"Austria","be-fr":"Belgium (fr)"
98− }some more code..."""
99− response = mock.Mock(text=js)
100− languages = list(duckduckgo._fetch_supported_languages(response))
101− self.assertEqual(len(languages), 5)
102− self.assertIn('wt-WT', languages)
103− self.assertIn('es-AR', languages)
104− self.assertIn('en-AU', languages)
105− self.assertIn('de-AT', languages)
106− self.assertIn('fr-BE', languages)
tests/unit/engines/test_duckduckgo_definitions.pydeleted−255
@@ -1,255 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import duckduckgo_definitions
4−from searx.testing import SearxTestCase
5−
6−
7−class TestDDGDefinitionsEngine(SearxTestCase):
8−
9− def test_result_to_text(self):
10− url = ''
11− text = 'Text'
12− html_result = 'Html'
13− result = duckduckgo_definitions.result_to_text(url, text, html_result)
14− self.assertEqual(result, text)
15−
16− html_result = '<a href="url">Text in link</a>'
17− result = duckduckgo_definitions.result_to_text(url, text, html_result)
18− self.assertEqual(result, 'Text in link')
19−
20− def test_request(self):
21− duckduckgo_definitions.supported_languages = ['en-US', 'es-ES']
22− query = 'test_query'
23− dicto = defaultdict(dict)
24− dicto['pageno'] = 1
25− dicto['language'] = 'es'
26− params = duckduckgo_definitions.request(query, dicto)
27− self.assertIn('url', params)
28− self.assertIn(query, params['url'])
29− self.assertIn('duckduckgo.com', params['url'])
30− self.assertIn('headers', params)
31− self.assertIn('Accept-Language', params['headers'])
32− self.assertIn('es', params['headers']['Accept-Language'])
33−
34− def test_response(self):
35− self.assertRaises(AttributeError, duckduckgo_definitions.response, None)
36− self.assertRaises(AttributeError, duckduckgo_definitions.response, [])
37− self.assertRaises(AttributeError, duckduckgo_definitions.response, '')
38− self.assertRaises(AttributeError, duckduckgo_definitions.response, '[]')
39−
40− response = mock.Mock(text='{}')
41− self.assertEqual(duckduckgo_definitions.response(response), [])
42−
43− response = mock.Mock(text='{"data": []}')
44− self.assertEqual(duckduckgo_definitions.response(response), [])
45−
46− json = """
47− {
48− "DefinitionSource": "definition source",
49− "Heading": "heading",
50− "ImageWidth": 0,
51− "RelatedTopics": [
52− {
53− "Result": "Top-level domains",
54− "Icon": {
55− "URL": "",
56− "Height": "",
57− "Width": ""
58− },
59− "FirstURL": "https://first.url",
60− "Text": "text"
61− },
62− {
63− "Topics": [
64− {
65− "Result": "result topic",
66− "Icon": {
67− "URL": "",
68− "Height": "",
69− "Width": ""
70− },
71− "FirstURL": "https://duckduckgo.com/?q=2%2F2",
72− "Text": "result topic text"
73− }
74− ],
75− "Name": "name"
76− }
77− ],
78− "Entity": "Entity",
79− "Type": "A",
80− "Redirect": "",
81− "DefinitionURL": "http://definition.url",
82− "AbstractURL": "https://abstract.url",
83− "Definition": "this is the definition",
84− "AbstractSource": "abstract source",
85− "Infobox": {
86− "content": [
87− {
88− "data_type": "string",
89− "value": "1999",
90− "label": "Introduced",
91− "wiki_order": 0
92− }
93− ],
94− "meta": [
95− {
96− "data_type": "string",
97− "value": ".test",
98− "label": "article_title"
99− }
100− ]
101− },
102− "Image": "image.png",
103− "ImageIsLogo": 0,
104− "Abstract": "abstract",
105− "AbstractText": "abstract text",
106− "AnswerType": "",
107− "ImageHeight": 0,
108− "Results": [{
109− "Result" : "result title",
110− "Icon" : {
111− "URL" : "result url",
112− "Height" : 16,
113− "Width" : 16
114− },
115− "FirstURL" : "result first url",
116− "Text" : "result text"
117− }
118− ],
119− "Answer": "answer"
120− }
121− """
122− response = mock.Mock(text=json)
123− results = duckduckgo_definitions.response(response)
124− self.assertEqual(type(results), list)
125− self.assertEqual(len(results), 4)
126− self.assertEqual(results[0]['answer'], 'answer')
127− self.assertEqual(results[1]['title'], 'heading')
128− self.assertEqual(results[1]['url'], 'result first url')
129− self.assertEqual(results[2]['suggestion'], 'text')
130− self.assertEqual(results[3]['infobox'], 'heading')
131− self.assertEqual(results[3]['id'], 'https://definition.url')
132− self.assertEqual(results[3]['entity'], 'Entity')
133− self.assertIn('abstract', results[3]['content'])
134− self.assertIn('this is the definition', results[3]['content'])
135− self.assertEqual(results[3]['img_src'], 'image.png')
136− self.assertIn('Introduced', results[3]['attributes'][0]['label'])
137− self.assertIn('1999', results[3]['attributes'][0]['value'])
138− self.assertIn({'url': 'https://abstract.url', 'title': 'abstract source'}, results[3]['urls'])
139− self.assertIn({'url': 'http://definition.url', 'title': 'definition source'}, results[3]['urls'])
140− self.assertIn({'name': 'name', 'suggestions': ['result topic text']}, results[3]['relatedTopics'])
141−
142− json = """
143− {
144− "DefinitionSource": "definition source",
145− "Heading": "heading",
146− "ImageWidth": 0,
147− "RelatedTopics": [],
148− "Entity": "Entity",
149− "Type": "A",
150− "Redirect": "",
151− "DefinitionURL": "",
152− "AbstractURL": "https://abstract.url",
153− "Definition": "",
154− "AbstractSource": "abstract source",
155− "Image": "",
156− "ImageIsLogo": 0,
157− "Abstract": "",
158− "AbstractText": "abstract text",
159− "AnswerType": "",
160− "ImageHeight": 0,
161− "Results": [],
162− "Answer": ""
163− }
164− """
165− response = mock.Mock(text=json)
166− results = duckduckgo_definitions.response(response)
167− self.assertEqual(type(results), list)
168− self.assertEqual(len(results), 1)
169− self.assertEqual(results[0]['url'], 'https://abstract.url')
170− self.assertEqual(results[0]['title'], 'heading')
171− self.assertEqual(results[0]['content'], '')
172−
173− json = """
174− {
175− "DefinitionSource": "definition source",
176− "Heading": "heading",
177− "ImageWidth": 0,
178− "RelatedTopics": [
179− {
180− "Result": "Top-level domains",
181− "Icon": {
182− "URL": "",
183− "Height": "",
184− "Width": ""
185− },
186− "FirstURL": "https://first.url",
187− "Text": "heading"
188− },
189− {
190− "Name": "name"
191− },
192− {
193− "Topics": [
194− {
195− "Result": "result topic",
196− "Icon": {
197− "URL": "",
198− "Height": "",
199− "Width": ""
200− },
201− "FirstURL": "https://duckduckgo.com/?q=2%2F2",
202− "Text": "heading"
203− }
204− ],
205− "Name": "name"
206− }
207− ],
208− "Entity": "Entity",
209− "Type": "A",
210− "Redirect": "",
211− "DefinitionURL": "http://definition.url",
212− "AbstractURL": "https://abstract.url",
213− "Definition": "this is the definition",
214− "AbstractSource": "abstract source",
215− "Infobox": {
216− "meta": [
217− {
218− "data_type": "string",
219− "value": ".test",
220− "label": "article_title"
221− }
222− ]
223− },
224− "Image": "image.png",
225− "ImageIsLogo": 0,
226− "Abstract": "abstract",
227− "AbstractText": "abstract text",
228− "AnswerType": "",
229− "ImageHeight": 0,
230− "Results": [{
231− "Result" : "result title",
232− "Icon" : {
233− "URL" : "result url",
234− "Height" : 16,
235− "Width" : 16
236− },
237− "Text" : "result text"
238− }
239− ],
240− "Answer": ""
241− }
242− """
243− response = mock.Mock(text=json)
244− results = duckduckgo_definitions.response(response)
245− self.assertEqual(type(results), list)
246− self.assertEqual(len(results), 1)
247− self.assertEqual(results[0]['infobox'], 'heading')
248− self.assertEqual(results[0]['id'], 'https://definition.url')
249− self.assertEqual(results[0]['entity'], 'Entity')
250− self.assertIn('abstract', results[0]['content'])
251− self.assertIn('this is the definition', results[0]['content'])
252− self.assertEqual(results[0]['img_src'], 'image.png')
253− self.assertIn({'url': 'https://abstract.url', 'title': 'abstract source'}, results[0]['urls'])
254− self.assertIn({'url': 'http://definition.url', 'title': 'definition source'}, results[0]['urls'])
255− self.assertIn({'name': 'name', 'suggestions': []}, results[0]['relatedTopics'])
tests/unit/engines/test_duckduckgo_images.pydeleted−75
@@ -1,75 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import duckduckgo_images
5−from searx.testing import SearxTestCase
6−
7−
8−class TestDuckduckgoImagesEngine(SearxTestCase):
9−
10− def test_request(self):
11− duckduckgo_images.supported_languages = ['de-CH', 'en-US']
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− dicto['is_test'] = True
15− dicto['pageno'] = 1
16− dicto['safesearch'] = 0
17− dicto['language'] = 'all'
18− params = duckduckgo_images.request(query, dicto)
19− self.assertIn('url', params)
20− self.assertIn(query, params['url'])
21− self.assertIn('duckduckgo.com', params['url'])
22− self.assertIn('s=0', params['url'])
23− self.assertIn('p=-1', params['url'])
24− self.assertIn('vqd=12345', params['url'])
25−
26− # test paging, safe search and language
27− dicto['pageno'] = 2
28− dicto['safesearch'] = 2
29− dicto['language'] = 'de'
30− params = duckduckgo_images.request(query, dicto)
31− self.assertIn('url', params)
32− self.assertIn(query, params['url'])
33− self.assertIn('s=50', params['url'])
34− self.assertIn('p=1', params['url'])
35− self.assertIn('ch-de', params['url'])
36−
37− def test_response(self):
38− self.assertRaises(AttributeError, duckduckgo_images.response, None)
39− self.assertRaises(AttributeError, duckduckgo_images.response, [])
40− self.assertRaises(AttributeError, duckduckgo_images.response, '')
41− self.assertRaises(AttributeError, duckduckgo_images.response, '[]')
42−
43− response = mock.Mock(text='If this error persists, please let us know: ops@duckduckgo.com')
44− self.assertRaises(Exception, duckduckgo_images.response, response)
45−
46− json = u"""
47− {
48− "query": "test_query",
49− "results": [
50− {
51− "title": "Result 1",
52− "url": "https://site1.url",
53− "thumbnail": "https://thumb1.nail",
54− "image": "https://image1"
55− },
56− {
57− "title": "Result 2",
58− "url": "https://site2.url",
59− "thumbnail": "https://thumb2.nail",
60− "image": "https://image2"
61− }
62− ]
63− }
64− """
65− response = mock.Mock(text=json)
66− results = duckduckgo_images.response(response)
67− self.assertEqual(len(results), 2)
68− self.assertEqual(results[0]['title'], 'Result 1')
69− self.assertEqual(results[0]['url'], 'https://site1.url')
70− self.assertEqual(results[0]['thumbnail_src'], 'https://thumb1.nail')
71− self.assertEqual(results[0]['img_src'], 'https://image1')
72− self.assertEqual(results[1]['title'], 'Result 2')
73− self.assertEqual(results[1]['url'], 'https://site2.url')
74− self.assertEqual(results[1]['thumbnail_src'], 'https://thumb2.nail')
75− self.assertEqual(results[1]['img_src'], 'https://image2')
tests/unit/engines/test_duden.pydeleted−47
@@ -1,47 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import duden
4−from searx.testing import SearxTestCase
5−from datetime import datetime
6−
7−
8−class TestDudenEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'Haus'
12− dic = defaultdict(dict)
13− data = [
14− [1, 'https://www.duden.de/suchen/dudenonline/Haus'],
15− [2, 'https://www.duden.de/suchen/dudenonline/Haus?search_api_fulltext=&page=1']
16− ]
17− for page_no, exp_res in data:
18− dic['pageno'] = page_no
19− params = duden.request(query, dic)
20− self.assertTrue('url' in params)
21− self.assertTrue(query in params['url'])
22− self.assertTrue('duden.de' in params['url'])
23− self.assertEqual(params['url'], exp_res)
24−
25− def test_response(self):
26− resp = mock.Mock(text='<html></html>')
27− self.assertEqual(duden.response(resp), [])
28−
29− html = """
30− <section class="vignette">
31− <h2"> <a href="/rechtschreibung/Haus">
32− <strong>This is the title also here</strong>
33− </a> </h2>
34− <p>This is the content</p>
35− </section>
36− """
37− resp = mock.Mock(text=html)
38− results = duden.response(resp)
39−
40− self.assertEqual(len(results), 1)
41− self.assertEqual(type(results), list)
42−
43− # testing result (dictionary entry)
44− r = results[0]
45− self.assertEqual(r['url'], 'https://www.duden.de/rechtschreibung/Haus')
46− self.assertEqual(r['title'], 'This is the title also here')
47− self.assertEqual(r['content'], 'This is the content')
tests/unit/engines/test_dummy.pydeleted−26
@@ -1,26 +0,0 @@
1−from searx.engines import dummy
2−from searx.testing import SearxTestCase
3−
4−
5−class TestDummyEngine(SearxTestCase):
6−
7− def test_request(self):
8− test_params = [
9− [1, 2, 3],
10− ['a'],
11− [],
12− 1
13− ]
14− for params in test_params:
15− self.assertEqual(dummy.request(None, params), params)
16−
17− def test_response(self):
18− responses = [
19− None,
20− [],
21− True,
22− dict(),
23− tuple()
24− ]
25− for response in responses:
26− self.assertEqual(dummy.response(response), [])
tests/unit/engines/test_faroo.pydeleted−113
@@ -1,113 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import faroo
5−from searx.testing import SearxTestCase
6−
7−
8−class TestFarooEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− dicto['language'] = 'fr-FR'
15− dicto['category'] = 'general'
16− params = faroo.request(query, dicto)
17− self.assertIn('url', params)
18− self.assertIn(query, params['url'])
19− self.assertIn('faroo.com', params['url'])
20− self.assertIn('en', params['url'])
21− self.assertIn('web', params['url'])
22−
23− dicto['language'] = 'all'
24− params = faroo.request(query, dicto)
25− self.assertIn('en', params['url'])
26−
27− dicto['language'] = 'de-DE'
28− params = faroo.request(query, dicto)
29− self.assertIn('de', params['url'])
30−
31− def test_response(self):
32− self.assertRaises(AttributeError, faroo.response, None)
33− self.assertRaises(AttributeError, faroo.response, [])
34− self.assertRaises(AttributeError, faroo.response, '')
35− self.assertRaises(AttributeError, faroo.response, '[]')
36−
37− response = mock.Mock(text='{}')
38− self.assertEqual(faroo.response(response), [])
39−
40− response = mock.Mock(text='{"data": []}')
41− self.assertEqual(faroo.response(response), [])
42−
43− response = mock.Mock(text='{"data": []}', status_code=429)
44− self.assertRaises(Exception, faroo.response, response)
45−
46− json = """
47− {
48− "results": [
49− {
50− "title": "This is the title",
51− "kwic": "This is the content",
52− "content": "",
53− "url": "http://this.is.the.url/",
54− "iurl": "",
55− "domain": "css3test.com",
56− "author": "Jim Dalrymple",
57− "news": true,
58− "votes": "10",
59− "date": 1360622563000,
60− "related": []
61− },
62− {
63− "title": "This is the title2",
64− "kwic": "This is the content2",
65− "content": "",
66− "url": "http://this.is.the.url2/",
67− "iurl": "",
68− "domain": "css3test.com",
69− "author": "Jim Dalrymple",
70− "news": false,
71− "votes": "10",
72− "related": []
73− },
74− {
75− "title": "This is the title3",
76− "kwic": "This is the content3",
77− "content": "",
78− "url": "http://this.is.the.url3/",
79− "iurl": "http://upload.wikimedia.org/optimized.jpg",
80− "domain": "css3test.com",
81− "author": "Jim Dalrymple",
82− "news": false,
83− "votes": "10",
84− "related": []
85− }
86− ],
87− "query": "test",
88− "suggestions": [],
89− "count": 100,
90− "start": 1,
91− "length": 10,
92− "time": "15"
93− }
94− """
95− response = mock.Mock(text=json)
96− results = faroo.response(response)
97− self.assertEqual(type(results), list)
98− self.assertEqual(len(results), 3)
99− self.assertEqual(results[0]['title'], 'This is the title')
100− self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
101− self.assertEqual(results[0]['content'], 'This is the content')
102− self.assertEqual(results[1]['title'], 'This is the title2')
103− self.assertEqual(results[1]['url'], 'http://this.is.the.url2/')
104− self.assertEqual(results[1]['content'], 'This is the content2')
105− self.assertEqual(results[2]['thumbnail'], 'http://upload.wikimedia.org/optimized.jpg')
106−
107− json = """
108− {}
109− """
110− response = mock.Mock(text=json)
111− results = faroo.response(response)
112− self.assertEqual(type(results), list)
113− self.assertEqual(len(results), 0)
tests/unit/engines/test_fdroid.pydeleted−60
@@ -1,60 +0,0 @@
1−import mock
2−from collections import defaultdict
3−from searx.engines import fdroid
4−from searx.testing import SearxTestCase
5−
6−
7−class TestFdroidEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dic = defaultdict(dict)
12− dic['pageno'] = 1
13− params = fdroid.request(query, dic)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('search.f-droid.org' in params['url'])
17−
18− def test_response_empty(self):
19− resp = mock.Mock(text='<html></html>')
20− self.assertEqual(fdroid.response(resp), [])
21−
22− def test_response_oneresult(self):
23− html = """
24−<!DOCTYPE html>
25−<html>
26−<head>
27− <title>test</title>
28−</head>
29−<body>
30− <div class="site-wrapper">
31− <div class="main-content">
32− <a class="package-header" href="https://example.com/app.url">
33− <img class="package-icon" src="https://example.com/appexample.logo.png" />
34−
35− <div class="package-info">
36− <h4 class="package-name">
37− App Example 1
38− </h4>
39−
40− <div class="package-desc">
41− <span class="package-summary">Description App Example 1</span>
42− <span class="package-license">GPL-3.0-only</span>
43− </div>
44− </div>
45− </a>
46− </div>
47− </div>
48−</body>
49−</html>
50− """
51−
52− resp = mock.Mock(text=html)
53− results = fdroid.response(resp)
54−
55− self.assertEqual(type(results), list)
56− self.assertEqual(len(results), 1)
57− self.assertEqual(results[0]['url'], 'https://example.com/app.url')
58− self.assertEqual(results[0]['title'], 'App Example 1')
59− self.assertEqual(results[0]['content'], 'Description App Example 1 - GPL-3.0-only')
60− self.assertEqual(results[0]['img_src'], 'https://example.com/appexample.logo.png')
tests/unit/engines/test_flickr.pydeleted−142
@@ -1,142 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import flickr
4−from searx.testing import SearxTestCase
5−
6−
7−class TestFlickrEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = flickr.request(query, dicto)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('flickr.com' in params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, flickr.response, None)
20− self.assertRaises(AttributeError, flickr.response, [])
21− self.assertRaises(AttributeError, flickr.response, '')
22− self.assertRaises(AttributeError, flickr.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(flickr.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(flickr.response(response), [])
29−
30− json = r"""
31− { "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
32− "photo": [
33− { "id": "15751017054", "owner": "66847915@N08",
34− "secret": "69c22afc40", "server": "7285", "farm": 8,
35− "title": "Photo title", "ispublic": 1,
36− "isfriend": 0, "isfamily": 0,
37− "description": { "_content": "Description" },
38− "ownername": "Owner",
39− "url_o": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_9178e0f963_o.jpg",
40− "height_o": "2100", "width_o": "2653",
41− "url_n": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_n.jpg",
42− "height_n": "253", "width_n": "320",
43− "url_z": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_z.jpg",
44− "height_z": "507", "width_z": "640" }
45− ] }, "stat": "ok" }
46− """
47− response = mock.Mock(text=json)
48− results = flickr.response(response)
49− self.assertEqual(type(results), list)
50− self.assertEqual(len(results), 1)
51− self.assertEqual(results[0]['title'], 'Photo title')
52− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
53− self.assertTrue('o.jpg' in results[0]['img_src'])
54− self.assertTrue('n.jpg' in results[0]['thumbnail_src'])
55− self.assertTrue('Owner' in results[0]['author'])
56− self.assertTrue('Description' in results[0]['content'])
57−
58− json = r"""
59− { "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
60− "photo": [
61− { "id": "15751017054", "owner": "66847915@N08",
62− "secret": "69c22afc40", "server": "7285", "farm": 8,
63− "title": "Photo title", "ispublic": 1,
64− "isfriend": 0, "isfamily": 0,
65− "description": { "_content": "Description" },
66− "ownername": "Owner",
67− "url_z": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_z.jpg",
68− "height_z": "507", "width_z": "640" }
69− ] }, "stat": "ok" }
70− """
71− response = mock.Mock(text=json)
72− results = flickr.response(response)
73− self.assertEqual(type(results), list)
74− self.assertEqual(len(results), 1)
75− self.assertEqual(results[0]['title'], 'Photo title')
76− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
77− self.assertTrue('z.jpg' in results[0]['img_src'])
78− self.assertTrue('z.jpg' in results[0]['thumbnail_src'])
79− self.assertTrue('Owner' in results[0]['author'])
80− self.assertTrue('Description' in results[0]['content'])
81−
82− json = r"""
83− { "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
84− "photo": [
85− { "id": "15751017054", "owner": "66847915@N08",
86− "secret": "69c22afc40", "server": "7285", "farm": 8,
87− "title": "Photo title", "ispublic": 1,
88− "isfriend": 0, "isfamily": 0,
89− "description": { "_content": "Description" },
90− "ownername": "Owner",
91− "url_o": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_9178e0f963_o.jpg",
92− "height_o": "2100", "width_o": "2653" }
93− ] }, "stat": "ok" }
94− """
95− response = mock.Mock(text=json)
96− results = flickr.response(response)
97− self.assertEqual(type(results), list)
98− self.assertEqual(len(results), 1)
99− self.assertEqual(results[0]['title'], 'Photo title')
100− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
101− self.assertTrue('o.jpg' in results[0]['img_src'])
102− self.assertTrue('o.jpg' in results[0]['thumbnail_src'])
103− self.assertTrue('Owner' in results[0]['author'])
104− self.assertTrue('Description' in results[0]['content'])
105−
106− json = r"""
107− { "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
108− "photo": [
109− { "id": "15751017054", "owner": "66847915@N08",
110− "secret": "69c22afc40", "server": "7285", "farm": 8,
111− "title": "Photo title", "ispublic": 1,
112− "isfriend": 0, "isfamily": 0,
113− "description": { "_content": "Description" },
114− "ownername": "Owner",
115− "url_n": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_n.jpg",
116− "height_n": "253", "width_n": "320" }
117− ] }, "stat": "ok" }
118− """
119− response = mock.Mock(text=json)
120− results = flickr.response(response)
121− self.assertEqual(type(results), list)
122− self.assertEqual(len(results), 0)
123−
124− json = """
125− { "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
126− "toto": [] }, "stat": "ok" }
127− """
128− response = mock.Mock(text=json)
129− results = flickr.response(response)
130− self.assertEqual(type(results), list)
131− self.assertEqual(len(results), 0)
132−
133− json = r"""
134− {"toto":[
135− {"id":200,"name":"Artist Name",
136− "link":"http:\/\/www.flickr.com\/artist\/1217","type":"artist"}
137− ]}
138− """
139− response = mock.Mock(text=json)
140− results = flickr.response(response)
141− self.assertEqual(type(results), list)
142− self.assertEqual(len(results), 0)
tests/unit/engines/test_flickr_noapi.pydeleted−357
@@ -1,357 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import flickr_noapi
4−from searx.testing import SearxTestCase
5−
6−
7−class TestFlickrNoapiEngine(SearxTestCase):
8−
9− def test_build_flickr_url(self):
10− url = flickr_noapi.build_flickr_url("uid", "pid")
11− self.assertIn("uid", url)
12− self.assertIn("pid", url)
13−
14− def test_request(self):
15− query = 'test_query'
16− dicto = defaultdict(dict)
17− dicto['pageno'] = 1
18− dicto['time_range'] = ''
19− params = flickr_noapi.request(query, dicto)
20− self.assertIn('url', params)
21− self.assertIn(query, params['url'])
22− self.assertIn('flickr.com', params['url'])
23−
24− def test_response(self):
25− self.assertRaises(AttributeError, flickr_noapi.response, None)
26− self.assertRaises(AttributeError, flickr_noapi.response, [])
27− self.assertRaises(AttributeError, flickr_noapi.response, '')
28− self.assertRaises(AttributeError, flickr_noapi.response, '[]')
29−
30− response = mock.Mock(text='"modelExport:{"legend":[],"main":{"search-photos-lite-models":[{"photos":{}}]}}')
31− self.assertEqual(flickr_noapi.response(response), [])
32−
33− response = \
34− mock.Mock(text='"modelExport:{"legend":[],"main":{"search-photos-lite-models":[{"photos":{"_data":[]}}]}}')
35− self.assertEqual(flickr_noapi.response(response), [])
36−
37− # everthing is ok test
38− json = """
39− modelExport: {
40− "legend": [
41− [
42− "search-photos-lite-models",
43− "0",
44− "photos",
45− "_data",
46− "0"
47− ]
48− ],
49− "main": {
50− "search-photos-lite-models": [
51− {
52− "photos": {
53− "_data": [
54− {
55− "_flickrModelRegistry": "photo-lite-models",
56− "title": "This%20is%20the%20title",
57− "username": "Owner",
58− "pathAlias": "klink692",
59− "realname": "Owner",
60− "license": 0,
61− "ownerNsid": "59729010@N00",
62− "canComment": false,
63− "commentCount": 14,
64− "faveCount": 21,
65− "id": "14001294434",
66− "sizes": {
67− "c": {
68− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_c.jpg",
69− "width": 541,
70− "height": 800,
71− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_c.jpg",
72− "key": "c"
73− },
74− "h": {
75− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_761d32237a_h.jpg",
76− "width": 1081,
77− "height": 1600,
78− "url": "//c4.staticflickr.com/8/7246/14001294434_761d32237a_h.jpg",
79− "key": "h"
80− },
81− "k": {
82− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_f145a2c11a_k.jpg",
83− "width": 1383,
84− "height": 2048,
85− "url": "//c4.staticflickr.com/8/7246/14001294434_f145a2c11a_k.jpg",
86− "key": "k"
87− },
88− "l": {
89− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_b.jpg",
90− "width": 692,
91− "height": 1024,
92− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_b.jpg",
93− "key": "l"
94− },
95− "m": {
96− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777.jpg",
97− "width": 338,
98− "height": 500,
99− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777.jpg",
100− "key": "m"
101− },
102− "n": {
103− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_n.jpg",
104− "width": 216,
105− "height": 320,
106− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_n.jpg",
107− "key": "n"
108− },
109− "q": {
110− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_q.jpg",
111− "width": 150,
112− "height": 150,
113− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_q.jpg",
114− "key": "q"
115− },
116− "s": {
117− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_m.jpg",
118− "width": 162,
119− "height": 240,
120− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_m.jpg",
121− "key": "s"
122− },
123− "sq": {
124− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_s.jpg",
125− "width": 75,
126− "height": 75,
127− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_s.jpg",
128− "key": "sq"
129− },
130− "t": {
131− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_t.jpg",
132− "width": 68,
133− "height": 100,
134− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_t.jpg",
135− "key": "t"
136− },
137− "z": {
138− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_z.jpg",
139− "width": 433,
140− "height": 640,
141− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_z.jpg",
142− "key": "z"
143− }
144− }
145− }
146− ]
147− }
148− }
149− ]
150− }
151− }
152− """
153− # Flickr serves search results in a json block named 'modelExport' buried inside a script tag,
154− # this json is served as a single line terminating with a comma.
155− json = ''.join(json.split()) + ',\n'
156− response = mock.Mock(text=json)
157− results = flickr_noapi.response(response)
158− self.assertEqual(type(results), list)
159− self.assertEqual(len(results), 1)
160− self.assertEqual(results[0]['title'], 'This is the title')
161− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
162− self.assertIn('k.jpg', results[0]['img_src'])
163− self.assertIn('n.jpg', results[0]['thumbnail_src'])
164− self.assertIn('Owner', results[0]['author'])
165−
166− # no n size, only the z size
167− json = """
168− modelExport: {
169− "legend": [
170− [
171− "search-photos-lite-models",
172− "0",
173− "photos",
174− "_data",
175− "0"
176− ]
177− ],
178− "main": {
179− "search-photos-lite-models": [
180− {
181− "photos": {
182− "_data": [
183− {
184− "_flickrModelRegistry": "photo-lite-models",
185− "title": "This%20is%20the%20title",
186− "username": "Owner",
187− "pathAlias": "klink692",
188− "realname": "Owner",
189− "license": 0,
190− "ownerNsid": "59729010@N00",
191− "canComment": false,
192− "commentCount": 14,
193− "faveCount": 21,
194− "id": "14001294434",
195− "sizes": {
196− "z": {
197− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_z.jpg",
198− "width": 433,
199− "height": 640,
200− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_z.jpg",
201− "key": "z"
202− }
203− }
204− }
205− ]
206− }
207− }
208− ]
209− }
210− }
211− """
212− json = ''.join(json.split()) + ',\n'
213− response = mock.Mock(text=json)
214− results = flickr_noapi.response(response)
215− self.assertEqual(type(results), list)
216− self.assertEqual(len(results), 1)
217− self.assertEqual(results[0]['title'], 'This is the title')
218− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
219− self.assertIn('z.jpg', results[0]['img_src'])
220− self.assertIn('z.jpg', results[0]['thumbnail_src'])
221− self.assertIn('Owner', results[0]['author'])
222−
223− # no z or n size
224− json = """
225− modelExport: {
226− "legend": [
227− [
228− "search-photos-lite-models",
229− "0",
230− "photos",
231− "_data",
232− "0"
233− ]
234− ],
235− "main": {
236− "search-photos-lite-models": [
237− {
238− "photos": {
239− "_data": [
240− {
241− "_flickrModelRegistry": "photo-lite-models",
242− "title": "This%20is%20the%20title",
243− "username": "Owner",
244− "pathAlias": "klink692",
245− "realname": "Owner",
246− "license": 0,
247− "ownerNsid": "59729010@N00",
248− "canComment": false,
249− "commentCount": 14,
250− "faveCount": 21,
251− "id": "14001294434",
252− "sizes": {
253− "o": {
254− "displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_o.jpg",
255− "width": 433,
256− "height": 640,
257− "url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_o.jpg",
258− "key": "o"
259− }
260− }
261− }
262− ]
263− }
264− }
265− ]
266− }
267− }
268− """
269− json = ''.join(json.split()) + ',\n'
270− response = mock.Mock(text=json)
271− results = flickr_noapi.response(response)
272− self.assertEqual(type(results), list)
273− self.assertEqual(len(results), 1)
274− self.assertEqual(results[0]['title'], 'This is the title')
275− self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
276− self.assertIn('o.jpg', results[0]['img_src'])
277− self.assertIn('o.jpg', results[0]['thumbnail_src'])
278− self.assertIn('Owner', results[0]['author'])
279−
280− # no image test
281− json = """
282− modelExport: {
283− "legend": [
284− [
285− "search-photos-lite-models",
286− "0",
287− "photos",
288− "_data",
289− "0"
290− ]
291− ],
292− "main": {
293− "search-photos-lite-models": [
294− {
295− "photos": {
296− "_data": [
297− {
298− "_flickrModelRegistry": "photo-lite-models",
299− "title": "This is the title",
300− "username": "Owner",
301− "pathAlias": "klink692",
302− "realname": "Owner",
303− "license": 0,
304− "ownerNsid": "59729010@N00",
305− "canComment": false,
306− "commentCount": 14,
307− "faveCount": 21,
308− "id": "14001294434",
309− "sizes": {
310− }
311− }
312− ]
313− }
314− }
315− ]
316− }
317− }
318− """
319− json = ''.join(json.split()) + ',\n'
320− response = mock.Mock(text=json)
321− results = flickr_noapi.response(response)
322− self.assertEqual(type(results), list)
323− self.assertEqual(len(results), 0)
324−
325− # null test
326− json = """
327− modelExport: {
328− "legend": [null],
329− "main": {
330− "search-photos-lite-models": [
331− {
332− "photos": {
333− "_data": [null]
334− }
335− }
336− ]
337− }
338− }
339− """
340− json = ''.join(json.split()) + ',\n'
341− response = mock.Mock(text=json)
342− results = flickr_noapi.response(response)
343− self.assertEqual(type(results), list)
344− self.assertEqual(len(results), 0)
345−
346− # garbage test
347− json = r"""
348− {"toto":[
349− {"id":200,"name":"Artist Name",
350− "link":"http:\/\/www.flickr.com\/artist\/1217","type":"artist"}
351− ]}
352− """
353− json = ''.join(json.split()) + ',\n'
354− response = mock.Mock(text=json)
355− results = flickr_noapi.response(response)
356− self.assertEqual(type(results), list)
357− self.assertEqual(len(results), 0)
tests/unit/engines/test_framalibre.pydeleted−103
@@ -1,103 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import framalibre
5−from searx.testing import SearxTestCase
6−
7−
8−class TestFramalibreEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 0
14− params = framalibre.request(query, dicto)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('framalibre.org' in params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, framalibre.response, None)
21− self.assertRaises(AttributeError, framalibre.response, [])
22− self.assertRaises(AttributeError, framalibre.response, '')
23− self.assertRaises(AttributeError, framalibre.response, '[]')
24−
25− response = mock.Mock(text='{}')
26− self.assertEqual(framalibre.response(response), [])
27−
28− response = mock.Mock(text='{"data": []}')
29− self.assertEqual(framalibre.response(response), [])
30−
31− html = u"""
32− <div class="nodes-list-row">
33− <div id="node-431"
34− class="node node-logiciel-annuaires node-promoted node-teaser node-teaser node-sheet clearfix nodes-list"
35− about="/content/gogs" typeof="sioc:Item foaf:Document">
36− <header class="media">
37− <div class="media-left">
38− <div class="field field-name-field-logo field-type-image field-label-hidden">
39− <div class="field-items">
40− <div class="field-item even">
41− <a href="/content/gogs">
42− <img class="media-object img-responsive" typeof="foaf:Image"
43− src="https://framalibre.org/sites/default/files/styles/teaser_logo/public/leslogos/gogs-lg.png?itok=rrCxKKBy"
44− width="70" height="70" alt="" />
45− </a>
46− </div>
47− </div>
48− </div>
49− </div>
50− <div class="media-body">
51− <h3 class="node-title"><a href="/content/gogs">Gogs</a></h3>
52− <span property="dc:title" content="Gogs" class="rdf-meta element-hidden"></span>
53− <div class="field field-name-field-annuaires field-type-taxonomy-term-reference field-label-hidden">
54− <div class="field-items">
55− <div class="field-item even">
56− <a href="/annuaires/cloudwebapps"
57− typeof="skos:Concept" property="rdfs:label skos:prefLabel"
58− datatype="" class="label label-primary">Cloud/webApps</a>
59− </div>
60− </div>
61− </div>
62− </div>
63− </header>
64− <div class="content">
65− <div class="field field-name-field-votre-appr-ciation field-type-fivestar field-label-hidden">
66− <div class="field-items">
67− <div class="field-item even">
68− </div>
69− </div>
70− </div>
71− <div class="field field-name-body field-type-text-with-summary field-label-hidden">
72− <div class="field-items">
73− <div class="field-item even" property="content:encoded">
74− <p>Gogs est une interface web basée sur git et une bonne alternative à GitHub.</p>
75− </div>
76− </div>
77− </div>
78− </div>
79− <footer>
80− <a href="/content/gogs" class="read-more btn btn-default btn-sm">Voir la notice</a>
81− <div class="field field-name-field-lien-officiel field-type-link-field field-label-hidden">
82− <div class="field-items">
83− <div class="field-item even">
84− <a href="https://gogs.io/" target="_blank" title="Voir le site officiel">
85− <span class="glyphicon glyphicon-globe"></span>
86− <span class="sr-only">Lien officiel</span>
87− </a>
88− </div>
89− </div>
90− </div>
91− </footer>
92− </div>
93− </div>
94− """
95− response = mock.Mock(text=html)
96− results = framalibre.response(response)
97− self.assertEqual(type(results), list)
98− self.assertEqual(len(results), 1)
99− self.assertEqual(results[0]['title'], 'Gogs')
100− self.assertEqual(results[0]['url'],
101− 'https://framalibre.org/content/gogs')
102− self.assertEqual(results[0]['content'],
103− u"Gogs est une interface web basée sur git et une bonne alternative à GitHub.")
tests/unit/engines/test_frinkiac.pydeleted−50
@@ -1,50 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import frinkiac
5−from searx.testing import SearxTestCase
6−
7−
8−class TestFrinkiacEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− request_dict = defaultdict(dict)
13− params = frinkiac.request(query, request_dict)
14− self.assertTrue('url' in params)
15−
16− def test_response(self):
17− self.assertRaises(AttributeError, frinkiac.response, None)
18− self.assertRaises(AttributeError, frinkiac.response, [])
19− self.assertRaises(AttributeError, frinkiac.response, '')
20− self.assertRaises(AttributeError, frinkiac.response, '[]')
21−
22− text = """
23−[{"Id":770931,
24− "Episode":"S06E18",
25− "Timestamp":534616,
26− "Filename":""},
27− {"Id":1657080,
28− "Episode":"S12E14",
29− "Timestamp":910868,
30− "Filename":""},
31− {"Id":1943753,
32− "Episode":"S14E21",
33− "Timestamp":773439,
34− "Filename":""},
35− {"Id":107835,
36− "Episode":"S02E03",
37− "Timestamp":531709,
38− "Filename":""}]
39− """
40−
41− response = mock.Mock(text=text)
42− results = frinkiac.response(response)
43− self.assertEqual(type(results), list)
44− self.assertEqual(len(results), 4)
45− self.assertEqual(results[0]['title'], u'S06E18')
46− self.assertIn('p=caption', results[0]['url'])
47− self.assertIn('e=S06E18', results[0]['url'])
48− self.assertIn('t=534616', results[0]['url'])
49− self.assertEqual(results[0]['thumbnail_src'], 'https://frinkiac.com/img/S06E18/534616/medium.jpg')
50− self.assertEqual(results[0]['img_src'], 'https://frinkiac.com/img/S06E18/534616.jpg')
tests/unit/engines/test_genius.pydeleted−231
@@ -1,231 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from datetime import datetime
4−from searx.engines import genius
5−from searx.testing import SearxTestCase
6−
7−
8−class TestGeniusEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = genius.request(query, dicto)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('genius.com' in params['url'])
18−
19− def test_response(self):
20−
21− json_empty = """
22− {
23− "meta": {
24− "status": 200
25− },
26− "response": {
27− "sections": [
28− {
29− "type": "top_hit",
30− "hits": []
31− },
32− {
33− "type": "song",
34− "hits": []
35− },
36− {
37− "type": "lyric",
38− "hits": []
39− },
40− {
41− "type": "artist",
42− "hits": []
43− },
44− {
45− "type": "album",
46− "hits": []
47− },
48− {
49− "type": "tag",
50− "hits": []
51− },
52− {
53− "type": "video",
54− "hits": []
55− },
56− {
57− "type": "article",
58− "hits": []
59− },
60− {
61− "type": "user",
62− "hits": []
63− }
64− ]
65− }
66− }
67− """
68−
69− resp = mock.Mock(text=json_empty)
70− self.assertEqual(genius.response(resp), [])
71−
72− json = """
73− {
74− "meta": {
75− "status": 200
76− },
77− "response": {
78− "sections": [
79− {
80− "type": "lyric",
81− "hits": [
82− {
83− "highlights": [
84− {
85− "property": "lyrics",
86− "value": "Sample lyrics",
87− "snippet": true,
88− "ranges": []
89− }
90− ],
91− "index": "lyric",
92− "type": "song",
93− "result": {
94− "_type": "song",
95− "annotation_count": 45,
96− "api_path": "/songs/52916",
97− "full_title": "J't'emmerde by MC Jean Gab'1",
98− "header_image_thumbnail_url": "https://images.genius.com/xxx.300x300x1.jpg",
99− "header_image_url": "https://images.genius.com/ef9f736a86df3c3b1772f3fb7fbdb21c.1000x1000x1.jpg",
100− "id": 52916,
101− "instrumental": false,
102− "lyrics_owner_id": 15586,
103− "lyrics_state": "complete",
104− "lyrics_updated_at": 1498744545,
105− "path": "/Mc-jean-gab1-jtemmerde-lyrics",
106− "pyongs_count": 4,
107− "song_art_image_thumbnail_url": "https://images.genius.com/xxx.300x300x1.jpg",
108− "stats": {
109− "hot": false,
110− "unreviewed_annotations": 0,
111− "pageviews": 62490
112− },
113− "title": "J't'emmerde",
114− "title_with_featured": "J't'emmerde",
115− "updated_by_human_at": 1498744546,
116− "url": "https://genius.com/Mc-jean-gab1-jtemmerde-lyrics",
117− "primary_artist": {
118− "_type": "artist",
119− "api_path": "/artists/12691",
120− "header_image_url": "https://images.genius.com/c7847662a58f8c2b0f02a6e217d60907.960x657x1.jpg",
121− "id": 12691,
122− "image_url": "https://s3.amazonaws.com/rapgenius/Mc-jean-gab1.jpg",
123− "index_character": "m",
124− "is_meme_verified": false,
125− "is_verified": false,
126− "name": "MC Jean Gab'1",
127− "slug": "Mc-jean-gab1",
128− "url": "https://genius.com/artists/Mc-jean-gab1"
129− }
130− }
131− }
132− ]
133− },
134− {
135− "type": "artist",
136− "hits": [
137− {
138− "highlights": [],
139− "index": "artist",
140− "type": "artist",
141− "result": {
142− "_type": "artist",
143− "api_path": "/artists/191580",
144− "header_image_url": "https://assets.genius.com/images/default_avatar_300.png?1503090542",
145− "id": 191580,
146− "image_url": "https://assets.genius.com/images/default_avatar_300.png?1503090542",
147− "index_character": "a",
148− "is_meme_verified": false,
149− "is_verified": false,
150− "name": "ASDF Guy",
151− "slug": "Asdf-guy",
152− "url": "https://genius.com/artists/Asdf-guy"
153− }
154− }
155− ]
156− },
157− {
158− "type": "album",
159− "hits": [
160− {
161− "highlights": [],
162− "index": "album",
163− "type": "album",
164− "result": {
165− "_type": "album",
166− "api_path": "/albums/132332",
167− "cover_art_thumbnail_url": "https://images.genius.com/xxx.300x300x1.jpg",
168− "cover_art_url": "https://images.genius.com/xxx.600x600x1.jpg",
169− "full_title": "ASD by A Skylit Drive",
170− "id": 132332,
171− "name": "ASD",
172− "name_with_artist": "ASD (artist: A Skylit Drive)",
173− "release_date_components": {
174− "year": 2015,
175− "month": null,
176− "day": null
177− },
178− "url": "https://genius.com/albums/A-skylit-drive/Asd",
179− "artist": {
180− "_type": "artist",
181− "api_path": "/artists/48712",
182− "header_image_url": "https://images.genius.com/814c1551293172c56306d0e310c6aa89.620x400x1.jpg",
183− "id": 48712,
184− "image_url": "https://images.genius.com/814c1551293172c56306d0e310c6aa89.620x400x1.jpg",
185− "index_character": "s",
186− "is_meme_verified": false,
187− "is_verified": false,
188− "name": "A Skylit Drive",
189− "slug": "A-skylit-drive",
190− "url": "https://genius.com/artists/A-skylit-drive"
191− }
192− }
193− }
194− ]
195− }
196− ]
197− }
198− }
199− """
200−
201− resp = mock.Mock(text=json)
202− results = genius.response(resp)
203−
204− self.assertEqual(len(results), 3)
205− self.assertEqual(type(results), list)
206−
207− # check lyric parsing
208− r = results[0]
209− self.assertEqual(r['url'], 'https://genius.com/Mc-jean-gab1-jtemmerde-lyrics')
210− self.assertEqual(r['title'], "J't'emmerde by MC Jean Gab'1")
211− self.assertEqual(r['content'], "Sample lyrics")
212− self.assertEqual(r['template'], 'videos.html')
213− self.assertEqual(r['thumbnail'], 'https://images.genius.com/xxx.300x300x1.jpg')
214− created = datetime.fromtimestamp(1498744545)
215− self.assertEqual(r['publishedDate'], created)
216−
217− # check artist parsing
218− r = results[1]
219− self.assertEqual(r['url'], 'https://genius.com/artists/Asdf-guy')
220− self.assertEqual(r['title'], "ASDF Guy")
221− self.assertEqual(r['content'], None)
222− self.assertEqual(r['template'], 'videos.html')
223− self.assertEqual(r['thumbnail'], 'https://assets.genius.com/images/default_avatar_300.png?1503090542')
224−
225− # check album parsing
226− r = results[2]
227− self.assertEqual(r['url'], 'https://genius.com/albums/A-skylit-drive/Asd')
228− self.assertEqual(r['title'], "ASD by A Skylit Drive")
229− self.assertEqual(r['content'], "Released: 2015")
230− self.assertEqual(r['template'], 'videos.html')
231− self.assertEqual(r['thumbnail'], 'https://images.genius.com/xxx.600x600x1.jpg')
tests/unit/engines/test_gigablast.pydeleted−119
@@ -1,119 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import gigablast
4−from searx.testing import SearxTestCase
5−
6−
7−class TestGigablastEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− dicto['safesearch'] = 0
14− dicto['language'] = 'all'
15− params = gigablast.request(query, dicto)
16− self.assertTrue('url' in params)
17− self.assertTrue(query in params['url'])
18− self.assertTrue('gigablast.com' in params['url'])
19− self.assertTrue('xx' in params['url'])
20−
21− dicto['language'] = 'en-US'
22− params = gigablast.request(query, dicto)
23− self.assertTrue('en' in params['url'])
24− self.assertFalse('en-US' in params['url'])
25−
26− def test_response(self):
27− self.assertRaises(AttributeError, gigablast.response, None)
28− self.assertRaises(AttributeError, gigablast.response, [])
29− self.assertRaises(AttributeError, gigablast.response, '')
30− self.assertRaises(AttributeError, gigablast.response, '[]')
31−
32− response = mock.Mock(text='{"results": []}')
33− self.assertEqual(gigablast.response(response), [])
34−
35− json = """{"results": [
36− {
37− "title":"South by Southwest 2016",
38− "dmozEntry":{
39− "dmozCatId":1041152,
40− "directCatId":1,
41− "dmozCatStr":"Top: Regional: North America: United States",
42− "dmozTitle":"South by Southwest (SXSW)",
43− "dmozSum":"Annual music, film, and interactive conference.",
44− "dmozAnchor":""
45− },
46− "dmozEntry":{
47− "dmozCatId":763945,
48− "directCatId":1,
49− "dmozCatStr":"Top: Regional: North America: United States",
50− "dmozTitle":"South by Southwest (SXSW)",
51− "dmozSum":"",
52− "dmozAnchor":"www.sxsw.com"
53− },
54− "dmozEntry":{
55− "dmozCatId":761446,
56− "directCatId":1,
57− "dmozCatStr":"Top: Regional: North America: United States",
58− "dmozTitle":"South by Southwest (SXSW)",
59− "dmozSum":"Music, film, and interactive conference and festival.",
60− "dmozAnchor":""
61− },
62− "indirectDmozCatId":1041152,
63− "indirectDmozCatId":763945,
64− "indirectDmozCatId":761446,
65− "contentType":"html",
66− "sum":"This should be the content.",
67− "url":"www.sxsw.com",
68− "hopCount":0,
69− "size":" 102k",
70− "sizeInBytes":104306,
71− "bytesUsedToComputeSummary":70000,
72− "docId":269411794364,
73− "docScore":586571136.000000,
74− "summaryGenTimeMS":12,
75− "summaryTagdbLookupTimeMS":0,
76− "summaryTitleRecLoadTimeMS":1,
77− "site":"www.sxsw.com",
78− "spidered":1452203608,
79− "firstIndexedDateUTC":1444167123,
80− "contentHash32":2170650347,
81− "language":"English",
82− "langAbbr":"en"
83− }
84−]}
85− """
86− response = mock.Mock(text=json)
87− results = gigablast.response(response)
88− self.assertEqual(type(results), list)
89− self.assertEqual(len(results), 1)
90− self.assertEqual(results[0]['title'], 'South by Southwest 2016')
91− self.assertEqual(results[0]['url'], 'www.sxsw.com')
92− self.assertEqual(results[0]['content'], 'This should be the content.')
93−
94− def test_fetch_supported_languages(self):
95− html = """<html></html>"""
96− response = mock.Mock(text=html)
97− results = gigablast._fetch_supported_languages(response)
98− self.assertEqual(type(results), list)
99− self.assertEqual(len(results), 0)
100−
101− html = """
102− <html>
103− <body>
104− <span id="menu2">
105− <a href="/search?&rxikd=1&qlang=xx"></a>
106− <a href="/search?&rxikd=1&qlang=en"></a>
107− <a href="/search?&rxikd=1&prepend=gblang%3Aen"></a>
108− <a href="/search?&rxikd=1&qlang=zh_"></a>
109− <a href="/search?&rxikd=1&prepend=gblang%3Azh_tw"></a>
110− </span>
111− </body>
112− </html>
113− """
114− response = mock.Mock(text=html)
115− languages = gigablast._fetch_supported_languages(response)
116− self.assertEqual(type(languages), list)
117− self.assertEqual(len(languages), 2)
118− self.assertIn('en', languages)
119− self.assertIn('zh-TW', languages)
tests/unit/engines/test_github.pydeleted−61
@@ -1,61 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import github
4−from searx.testing import SearxTestCase
5−
6−
7−class TestGitHubEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− params = github.request(query, defaultdict(dict))
12− self.assertTrue('url' in params)
13− self.assertTrue(query in params['url'])
14− self.assertTrue('github.com' in params['url'])
15− self.assertEqual(params['headers']['Accept'], github.accept_header)
16−
17− def test_response(self):
18− self.assertRaises(AttributeError, github.response, None)
19− self.assertRaises(AttributeError, github.response, [])
20− self.assertRaises(AttributeError, github.response, '')
21− self.assertRaises(AttributeError, github.response, '[]')
22−
23− response = mock.Mock(text='{}')
24− self.assertEqual(github.response(response), [])
25−
26− response = mock.Mock(text='{"items": []}')
27− self.assertEqual(github.response(response), [])
28−
29− json = """
30− {
31− "items": [
32− {
33− "name": "title",
34− "html_url": "url",
35− "description": ""
36− }
37− ]
38− }
39− """
40− response = mock.Mock(text=json)
41− results = github.response(response)
42− self.assertEqual(type(results), list)
43− self.assertEqual(len(results), 1)
44− self.assertEqual(results[0]['title'], 'title')
45− self.assertEqual(results[0]['url'], 'url')
46− self.assertEqual(results[0]['content'], '')
47−
48− json = """
49− {
50− "items": [
51− {
52− "name": "title",
53− "html_url": "url",
54− "description": "desc"
55− }
56− ]
57− }
58− """
59− response = mock.Mock(text=json)
60− results = github.response(response)
61− self.assertEqual(results[0]['content'], "desc")
tests/unit/engines/test_google.pydeleted−194
@@ -1,194 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−import lxml
5−from searx.engines import google
6−from searx.testing import SearxTestCase
7−
8−
9−class TestGoogleEngine(SearxTestCase):
10−
11− def mock_response(self, text):
12− response = mock.Mock(text=text, url='https://www.google.com/search?q=test&start=0&gbv=1&gws_rd=cr')
13− response.search_params = mock.Mock()
14− response.search_params.get = mock.Mock(return_value='www.google.com')
15− return response
16−
17− def test_request(self):
18− google.supported_languages = ['en', 'fr', 'zh-CN', 'iw']
19− google.language_aliases = {'he': 'iw'}
20−
21− query = 'test_query'
22− dicto = defaultdict(dict)
23− dicto['pageno'] = 1
24− dicto['language'] = 'fr-FR'
25− dicto['time_range'] = ''
26− params = google.request(query, dicto)
27− self.assertIn('url', params)
28− self.assertIn(query, params['url'])
29− self.assertIn('google.fr', params['url'])
30− self.assertIn('fr', params['url'])
31− self.assertIn('fr', params['headers']['Accept-Language'])
32−
33− dicto['language'] = 'en-US'
34− params = google.request(query, dicto)
35− self.assertIn('google.com', params['url'])
36− self.assertIn('en', params['url'])
37− self.assertIn('en', params['headers']['Accept-Language'])
38−
39− dicto['language'] = 'zh'
40− params = google.request(query, dicto)
41− self.assertIn('google.com', params['url'])
42− self.assertIn('zh-CN', params['url'])
43− self.assertIn('zh-CN', params['headers']['Accept-Language'])
44−
45− dicto['language'] = 'he'
46− params = google.request(query, dicto)
47− self.assertIn('google.com', params['url'])
48− self.assertIn('iw', params['url'])
49− self.assertIn('iw', params['headers']['Accept-Language'])
50−
51− def test_response(self):
52− self.assertRaises(AttributeError, google.response, None)
53− self.assertRaises(AttributeError, google.response, [])
54− self.assertRaises(AttributeError, google.response, '')
55− self.assertRaises(AttributeError, google.response, '[]')
56−
57− response = self.mock_response('<html></html>')
58− self.assertEqual(google.response(response), [])
59−
60− html = """
61− <div class="ZINbbc xpd O9g5cc uUPGi">
62− <div>
63− <div class="kCrYT">
64− <a href="/url?q=http://this.should.be.the.link/">
65− <div class="BNeawe">
66− <b>This</b> is <b>the</b> title
67− </div>
68− <div class="BNeawe">
69− http://website
70− </div>
71− </a>
72− </div>
73− <div class="kCrYT">
74− <div>
75− <div class="BNeawe">
76− <div>
77− <div class="BNeawe">
78− This should be the content.
79− </div>
80− </div>
81− </div>
82− </div>
83− </div>
84− </div>
85− </p>
86− <div class="ZINbbc xpd O9g5cc uUPGi">
87− <div>
88− <div class="kCrYT">
89− <span>
90− <div class="BNeawe">
91− Related searches
92− </div>
93− </span>
94− </div>
95− <div class="rVLSBd">
96− <a>
97− <div>
98− <div class="BNeawe">
99− suggestion title
100− </div>
101− </div>
102− </a>
103− </div>
104− </div>
105− </p>
106− """
107− response = self.mock_response(html)
108− results = google.response(response)
109− self.assertEqual(type(results), list)
110− self.assertEqual(len(results), 2)
111− self.assertEqual(results[0]['title'], 'This is the title')
112− self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
113− self.assertEqual(results[0]['content'], 'This should be the content.')
114− self.assertEqual(results[1]['suggestion'], 'suggestion title')
115−
116− html = """
117− <li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
118− </li>
119− """
120− response = self.mock_response(html)
121− results = google.response(response)
122− self.assertEqual(type(results), list)
123− self.assertEqual(len(results), 0)
124−
125− response = mock.Mock(text='<html></html>', url='https://sorry.google.com')
126− response.search_params = mock.Mock()
127− response.search_params.get = mock.Mock(return_value='www.google.com')
128− self.assertRaises(RuntimeWarning, google.response, response)
129−
130− response = mock.Mock(text='<html></html>', url='https://www.google.com/sorry/IndexRedirect')
131− response.search_params = mock.Mock()
132− response.search_params.get = mock.Mock(return_value='www.google.com')
133− self.assertRaises(RuntimeWarning, google.response, response)
134−
135− def test_parse_images(self):
136− html = """
137− <li>
138− <div>
139− <a href="http://www.google.com/url?q=http://this.is.the.url/">
140− <img style="margin:3px 0;margin-right:6px;padding:0" height="90"
141− src="https://this.is.the.image/image.jpg" width="60" align="middle" alt="" border="0">
142− </a>
143− </div>
144− </li>
145− """
146− dom = lxml.html.fromstring(html)
147− results = google.parse_images(dom, 'www.google.com')
148− self.assertEqual(type(results), list)
149− self.assertEqual(len(results), 1)
150− self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
151− self.assertEqual(results[0]['title'], '')
152− self.assertEqual(results[0]['content'], '')
153− self.assertEqual(results[0]['img_src'], 'https://this.is.the.image/image.jpg')
154−
155− def test_fetch_supported_languages(self):
156− html = """<html></html>"""
157− response = mock.Mock(text=html)
158− languages = google._fetch_supported_languages(response)
159− self.assertEqual(type(languages), dict)
160− self.assertEqual(len(languages), 0)
161−
162− html = u"""
163− <html>
164− <body>
165− <div id="langSec">
166− <div>
167− <input name="lr" data-name="english" value="lang_en" />
168− <input name="lr" data-name="中文 (简体)" value="lang_zh-CN" />
169− <input name="lr" data-name="中文 (繁體)" value="lang_zh-TW" />
170− </div>
171− </div>
172− </body>
173− </html>
174− """
175− response = mock.Mock(text=html)
176− languages = google._fetch_supported_languages(response)
177− self.assertEqual(type(languages), dict)
178− self.assertEqual(len(languages), 3)
179−
180− self.assertIn('en', languages)
181− self.assertIn('zh-CN', languages)
182− self.assertIn('zh-TW', languages)
183−
184− self.assertEquals(type(languages['en']), dict)
185− self.assertEquals(type(languages['zh-CN']), dict)
186− self.assertEquals(type(languages['zh-TW']), dict)
187−
188− self.assertIn('name', languages['en'])
189− self.assertIn('name', languages['zh-CN'])
190− self.assertIn('name', languages['zh-TW'])
191−
192− self.assertEquals(languages['en']['name'], 'English')
193− self.assertEquals(languages['zh-CN']['name'], u'中文 (简体)')
194− self.assertEquals(languages['zh-TW']['name'], u'中文 (繁體)')
tests/unit/engines/test_google_images.pydeleted−27
@@ -1,27 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import google_images
4−from searx.testing import SearxTestCase
5−
6−
7−class TestGoogleImagesEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 1
13− dicto['safesearch'] = 1
14− dicto['time_range'] = ''
15− params = google_images.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18−
19− dicto['safesearch'] = 0
20− params = google_images.request(query, dicto)
21− self.assertNotIn('safe', params['url'])
22−
23− def test_response(self):
24− self.assertRaises(AttributeError, google_images.response, None)
25− self.assertRaises(AttributeError, google_images.response, [])
26− self.assertRaises(AttributeError, google_images.response, '')
27− self.assertRaises(AttributeError, google_images.response, '[]')
tests/unit/engines/test_google_news.pydeleted−102
@@ -1,102 +0,0 @@
1−# -*- coding: utf-8 -*-
2−
3−from collections import defaultdict
4−import mock
5−from searx.engines import google_news
6−from searx.testing import SearxTestCase
7−
8−
9−class TestGoogleNewsEngine(SearxTestCase):
10−
11− def test_request(self):
12− google_news.supported_languages = ['en-US', 'fr-FR']
13− google_news.language_aliases = {}
14− query = 'test_query'
15− dicto = defaultdict(dict)
16− dicto['pageno'] = 1
17− dicto['language'] = 'fr-FR'
18− dicto['time_range'] = 'w'
19− params = google_news.request(query, dicto)
20− self.assertIn('url', params)
21− self.assertIn(query, params['url'])
22− self.assertIn('fr', params['url'])
23−
24− dicto['language'] = 'all'
25− params = google_news.request(query, dicto)
26− self.assertIn('url', params)
27− self.assertNotIn('fr', params['url'])
28−
29− def test_response(self):
30− self.assertRaises(AttributeError, google_news.response, None)
31− self.assertRaises(AttributeError, google_news.response, [])
32− self.assertRaises(AttributeError, google_news.response, '')
33− self.assertRaises(AttributeError, google_news.response, '[]')
34−
35− response = mock.Mock(text='{}')
36− self.assertEqual(google_news.response(response), [])
37−
38− response = mock.Mock(text='{"data": []}')
39− self.assertEqual(google_news.response(response), [])
40−
41− html = u"""
42−<h2 class="hd">Search Results</h2>
43−<div data-async-context="query:searx" id="ires">
44− <div eid="oC2oWcGXCafR6ASkwoCwDA" id="rso">
45− <div class="_NId">
46− <!--m-->
47− <div class="g _cy">
48− <div class="ts _JGs _JHs _tJs _KGs _jHs">
49− <div class="_hJs">
50− <h3 class="r _gJs">
51− <a class="l lLrAF" href="https://example.com/" onmousedown="return rwt(this,'','','','11','AFQjCNEyehpzD5cJK1KUfXBx9RmsbqqG9g','','0ahUKEwjB58OR54HWAhWnKJoKHSQhAMY4ChCpAggiKAAwAA','','',event)">Example title</a>
52− </h3>
53− <div class="slp">
54− <span class="_OHs _PHs">
55− Mac &amp; i</span>
56− <span class="_QGs">
57− -</span>
58− <span class="f nsa _QHs">
59− Mar 21, 2016</span>
60− </div>
61− <div class="st">Example description</div>
62− </div>
63− </div>
64− </div>
65− <div class="g _cy">
66− <div class="ts _JGs _JHs _oGs _KGs _jHs">
67− <a class="top _xGs _SHs" href="https://example2.com/" onmousedown="return rwt(this,'','','','12','AFQjCNHObfH7sYmLWI1SC-YhWXKZFRzRjw','','0ahUKEwjB58OR54HWAhWnKJoKHSQhAMY4ChC8iAEIJDAB','','',event)">
68− <img class="th _RGs" src="https://example2.com/image.jpg" alt="Story image for searx from Golem.de" onload="typeof google==='object'&&google.aft&&google.aft(this)">
69− </a>
70− <div class="_hJs">
71− <h3 class="r _gJs">
72− <a class="l lLrAF" href="https://example2.com/" onmousedown="return rwt(this,'','','','12','AFQjCNHObfH7sYmLWI1SC-YhWXKZFRzRjw','','0ahUKEwjB58OR54HWAhWnKJoKHSQhAMY4ChCpAgglKAAwAQ','','',event)">Example title 2</a>
73− </h3>
74− <div class="slp">
75− <span class="_OHs _PHs">
76− Golem.de</span>
77− <span class="_QGs">
78− -</span>
79− <span class="f nsa _QHs">
80− Oct 4, 2016</span>
81− </div>
82− <div class="st">Example description 2</div>
83− </div>
84− </div>
85− </div>
86− </div>
87− </div>
88−</div>
89−
90−
91− """ # noqa
92− response = mock.Mock(text=html)
93− results = google_news.response(response)
94− self.assertEqual(type(results), list)
95− self.assertEqual(len(results), 2)
96− self.assertEqual(results[0]['title'], u'Example title')
97− self.assertEqual(results[0]['url'], 'https://example.com/')
98− self.assertEqual(results[0]['content'], 'Example description')
99− self.assertEqual(results[1]['title'], u'Example title 2')
100− self.assertEqual(results[1]['url'], 'https://example2.com/')
101− self.assertEqual(results[1]['content'], 'Example description 2')
102− self.assertEqual(results[1]['img_src'], 'https://example2.com/image.jpg')
tests/unit/engines/test_google_videos.pydeleted−79
@@ -1,79 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import google_videos
4−from searx.testing import SearxTestCase
5−
6−
7−class TestGoogleVideosEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 1
13− dicto['safesearch'] = 1
14− dicto['time_range'] = ''
15− params = google_videos.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18−
19− dicto['safesearch'] = 0
20− params = google_videos.request(query, dicto)
21− self.assertNotIn('safe', params['url'])
22−
23− def test_response(self):
24− self.assertRaises(AttributeError, google_videos.response, None)
25− self.assertRaises(AttributeError, google_videos.response, [])
26− self.assertRaises(AttributeError, google_videos.response, '')
27− self.assertRaises(AttributeError, google_videos.response, '[]')
28−
29− html = r"""
30− <div>
31− <div>
32− <div class="g">
33− <div class="r">
34− <a href="url_1"><h3>Title 1</h3></a>
35− </div>
36− <div class="s">
37− <div>
38− <a>
39− <g-img>
40− <img id="vidthumb1">
41− </g-img>
42− </a>
43− </div>
44− </div>
45− <div>
46− <span class="st">Content 1</span>
47− </div>
48− </div>
49− <div class="g">
50− <div class="r">
51− <a href="url_2"><h3>Title 2</h3></a>
52− </div>
53− <div class="s">
54− <div>
55− <a>
56− <g-img>
57− <img id="vidthumb2">
58− </g-img>
59− </a>
60− </div>
61− </div>
62− <div>
63− <span class="st">Content 2</span>
64− </div>
65− </div>
66− </div>
67− </div>
68− <script>function _setImagesSrc(c,d,e){}</script>
69− """
70− response = mock.Mock(text=html)
71− results = google_videos.response(response)
72− self.assertEqual(type(results), list)
73− self.assertEqual(len(results), 2)
74− self.assertEqual(results[0]['url'], u'url_1')
75− self.assertEqual(results[0]['title'], u'Title 1')
76− self.assertEqual(results[0]['content'], u'Content 1')
77− self.assertEqual(results[1]['url'], u'url_2')
78− self.assertEqual(results[1]['title'], u'Title 2')
79− self.assertEqual(results[1]['content'], u'Content 2')
tests/unit/engines/test_ina.pydeleted−64
@@ -1,64 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import ina
4−from searx.testing import SearxTestCase
5−
6−
7−class TestInaEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = ina.request(query, dicto)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('ina.fr' in params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, ina.response, None)
20− self.assertRaises(AttributeError, ina.response, [])
21− self.assertRaises(AttributeError, ina.response, '')
22− self.assertRaises(AttributeError, ina.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(ina.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(ina.response(response), [])
29−
30− json = """
31− {"content":"\\t<div class=\\"container\\">\\n\\t\\n\
32− <!-- DEBUT CONTENU PRINCIPAL -->\\n<div class=\\"row\\">\\n\
33− <div class=\\"search-results--list\\"><div class=\\"media\\">\\n\
34− \\t\\t\\t\\t<a class=\\"media-left media-video premium xiti_click_action\\" \
35− data-xiti-params=\\"recherche_v4::resultats_conference_de_presse_du_general_de_gaulle::N\\" \
36− href=\\"\\/video\\/CAF89035682\\/conference-de-presse-du-general-de-gaulle-video.html\\">\\n\
37− <img src=\\"https:\\/\\/www.ina.fr\\/images_v2\\/140x105\\/CAF89035682.jpeg\\" \
38− alt=\\"Conf\\u00e9rence de presse du G\\u00e9n\\u00e9ral de Gaulle \\">\\n\
39− \\t\\t\\t\\t\\t<\\/a>\\n\
40− \\t\\t\\t\\t\\t<div class=\\"media-body\\">\\n\\t\\t\\t\\t\\t\\t<h3 class=\\"h3--title media-heading\\">\\n\
41− \\t\\t\\t\\t\\t\\t\\t<a class=\\"xiti_click_action\\" \
42− data-xiti-params=\\"recherche_v4::resultats_conference_de_presse_du_general_de_gaulle::N\\" \
43− href=\\"\\/video\\/CAF89035682\\/conference-de-presse-du-general-de-gaulle-video.html\\">\
44− Conf\\u00e9rence de presse du G\\u00e9n\\u00e9ral de Gaulle <\\/a>\\n\
45− <\\/h3>\\n\
46− <div class=\\"media-body__info\\">\\n<span class=\\"broadcast\\">27\\/11\\/1967<\\/span>\\n\
47− <span class=\\"views\\">29321 vues<\\/span>\\n\
48− <span class=\\"duration\\">01h 33m 07s<\\/span>\\n\
49− <\\/div>\\n\
50− <p class=\\"media-body__summary\\">VERSION INTEGRALE DE LA CONFERENCE DE PRESSE DU GENERAL DE GAULLE . \
51− - PA le Pr\\u00e9sident DE GAULLE : il ouvre les bras et s'assied. DP journalis...<\\/p>\\n\
52− <\\/div>\\n<\\/div><!-- \\/.media -->\\n"
53− }
54− """
55− response = mock.Mock(text=json)
56− results = ina.response(response)
57− self.assertEqual(type(results), list)
58− self.assertEqual(len(results), 1)
59− self.assertEqual(results[0]['title'], u'Conf\xe9rence de presse du G\xe9n\xe9ral de Gaulle')
60− self.assertEqual(results[0]['url'],
61− 'https://www.ina.fr/video/CAF89035682/conference-de-presse-du-general-de-gaulle-video.html')
62− self.assertEqual(results[0]['content'],
63− u"VERSION INTEGRALE DE LA CONFERENCE DE PRESSE DU GENERAL DE GAULLE ."
64− u" - PA le Pr\u00e9sident DE GAULLE : il ouvre les bras et s'assied. DP journalis...")
tests/unit/engines/test_kickass.pydeleted−397
@@ -1,397 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import kickass
5−from searx.testing import SearxTestCase
6−
7−
8−class TestKickassEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = kickass.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('kickass.cd', params['url'])
18− self.assertFalse(params['verify'])
19−
20− def test_response(self):
21− self.assertRaises(AttributeError, kickass.response, None)
22− self.assertRaises(AttributeError, kickass.response, [])
23− self.assertRaises(AttributeError, kickass.response, '')
24− self.assertRaises(AttributeError, kickass.response, '[]')
25−
26− response = mock.Mock(text='<html></html>')
27− self.assertEqual(kickass.response(response), [])
28−
29− html = """
30− <table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
31− <tr class="firstr">
32− <th class="width100perc nopad">torrent name</th>
33− <th class="center">
34− <a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
35− </th>
36− <th class="center"><span class="files">
37− <a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
38− </th>
39− <th class="center"><span>
40− <a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
41− </th>
42− <th class="center"><span class="seed">
43− <a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
44− </th>
45− <th class="lasttd nobr center">
46− <a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
47− </th>
48− </tr>
49− <tr class="even" id="torrent_test6478745">
50− <td>
51− <div class="iaconbox center floatright">
52− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
53− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
54− <i class="ka ka-comment"></i>
55− </a>
56− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
57− <i class="ka ka16 ka-verify ka-green"></i>
58− </a>
59− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
60− <i class="ka ka16 ka-arrow-down partner1Button"></i>
61− </a>
62− <a title="Torrent magnet link"
63− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
64− <i class="ka ka16 ka-magnet"></i>
65− </a>
66− <a title="Download torrent file"
67− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
68− <i class="ka ka16 ka-arrow-down"></i>
69− </a>
70− </div>
71− <div class="torrentname">
72− <a href="/test-t6478745.html" class="torType txtType"></a>
73− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
74− <div class="markeredBlock torType txtType">
75− <a href="/url.html" class="cellMainLink">
76− <strong class="red">This should be the title</strong>
77− </a>
78− <span class="font11px lightgrey block">
79− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
80− <a class="plain" href="/user/riri/">riri</a> in
81− <span id="cat_6478745">
82− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
83− </span>
84− </span>
85− </div>
86− </td>
87− <td class="nobr center">449 bytes</td>
88− <td class="center">4</td>
89− <td class="center">2&nbsp;years</td>
90− <td class="green center">10</td>
91− <td class="red lasttd center">1</td>
92− </tr>
93− </table>
94− """
95− response = mock.Mock(text=html)
96− results = kickass.response(response)
97− self.assertEqual(type(results), list)
98− self.assertEqual(len(results), 1)
99− self.assertEqual(results[0]['title'], 'This should be the title')
100− self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html')
101− self.assertEqual(results[0]['content'], 'Posted by riri in Other > Unsorted')
102− self.assertEqual(results[0]['seed'], 10)
103− self.assertEqual(results[0]['leech'], 1)
104− self.assertEqual(results[0]['filesize'], 449)
105− self.assertEqual(results[0]['files'], 4)
106− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
107− self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
108−
109− html = """
110− <table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
111− <tr class="firstr">
112− <th class="width100perc nopad">torrent name</th>
113− <th class="center">
114− <a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
115− </th>
116− <th class="center"><span class="files">
117− <a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
118− </th>
119− <th class="center"><span>
120− <a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
121− </th>
122− <th class="center"><span class="seed">
123− <a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
124− </th>
125− <th class="lasttd nobr center">
126− <a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
127− </th>
128− </tr>
129− </table>
130− """
131− response = mock.Mock(text=html)
132− results = kickass.response(response)
133− self.assertEqual(type(results), list)
134− self.assertEqual(len(results), 0)
135−
136− html = """
137− <table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
138− <tr class="firstr">
139− <th class="width100perc nopad">torrent name</th>
140− <th class="center">
141− <a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
142− </th>
143− <th class="center"><span class="files">
144− <a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
145− </th>
146− <th class="center"><span>
147− <a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
148− </th>
149− <th class="center"><span class="seed">
150− <a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
151− </th>
152− <th class="lasttd nobr center">
153− <a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
154− </th>
155− </tr>
156− <tr class="even" id="torrent_test6478745">
157− <td>
158− <div class="iaconbox center floatright">
159− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
160− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
161− <i class="ka ka-comment"></i>
162− </a>
163− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
164− <i class="ka ka16 ka-verify ka-green"></i>
165− </a>
166− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
167− <i class="ka ka16 ka-arrow-down partner1Button"></i>
168− </a>
169− <a title="Torrent magnet link"
170− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
171− <i class="ka ka16 ka-magnet"></i>
172− </a>
173− <a title="Download torrent file"
174− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
175− <i class="ka ka16 ka-arrow-down"></i>
176− </a>
177− </div>
178− <div class="torrentname">
179− <a href="/test-t6478745.html" class="torType txtType"></a>
180− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
181− <div class="markeredBlock torType txtType">
182− <a href="/url.html" class="cellMainLink">
183− <strong class="red">This should be the title</strong>
184− </a>
185− <span class="font11px lightgrey block">
186− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
187− <a class="plain" href="/user/riri/">riri</a> in
188− <span id="cat_6478745">
189− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
190− </span>
191− </span>
192− </div>
193− </td>
194− <td class="nobr center">1 KiB</td>
195− <td class="center">4</td>
196− <td class="center">2&nbsp;years</td>
197− <td class="green center">10</td>
198− <td class="red lasttd center">1</td>
199− </tr>
200− <tr class="even" id="torrent_test6478745">
201− <td>
202− <div class="iaconbox center floatright">
203− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
204− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
205− <i class="ka ka-comment"></i>
206− </a>
207− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
208− <i class="ka ka16 ka-verify ka-green"></i>
209− </a>
210− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
211− <i class="ka ka16 ka-arrow-down partner1Button"></i>
212− </a>
213− <a title="Torrent magnet link"
214− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
215− <i class="ka ka16 ka-magnet"></i>
216− </a>
217− <a title="Download torrent file"
218− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
219− <i class="ka ka16 ka-arrow-down"></i>
220− </a>
221− </div>
222− <div class="torrentname">
223− <a href="/test-t6478745.html" class="torType txtType"></a>
224− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
225− <div class="markeredBlock torType txtType">
226− <a href="/url.html" class="cellMainLink">
227− <strong class="red">This should be the title</strong>
228− </a>
229− <span class="font11px lightgrey block">
230− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
231− <a class="plain" href="/user/riri/">riri</a> in
232− <span id="cat_6478745">
233− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
234− </span>
235− </span>
236− </div>
237− </td>
238− <td class="nobr center">1 MiB</td>
239− <td class="center">4</td>
240− <td class="center">2&nbsp;years</td>
241− <td class="green center">9</td>
242− <td class="red lasttd center">1</td>
243− </tr>
244− <tr class="even" id="torrent_test6478745">
245− <td>
246− <div class="iaconbox center floatright">
247− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
248− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
249− <i class="ka ka-comment"></i>
250− </a>
251− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
252− <i class="ka ka16 ka-verify ka-green"></i>
253− </a>
254− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
255− <i class="ka ka16 ka-arrow-down partner1Button"></i>
256− </a>
257− <a title="Torrent magnet link"
258− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
259− <i class="ka ka16 ka-magnet"></i>
260− </a>
261− <a title="Download torrent file"
262− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
263− <i class="ka ka16 ka-arrow-down"></i>
264− </a>
265− </div>
266− <div class="torrentname">
267− <a href="/test-t6478745.html" class="torType txtType"></a>
268− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
269− <div class="markeredBlock torType txtType">
270− <a href="/url.html" class="cellMainLink">
271− <strong class="red">This should be the title</strong>
272− </a>
273− <span class="font11px lightgrey block">
274− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
275− <a class="plain" href="/user/riri/">riri</a> in
276− <span id="cat_6478745">
277− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
278− </span>
279− </span>
280− </div>
281− </td>
282− <td class="nobr center">1 GiB</td>
283− <td class="center">4</td>
284− <td class="center">2&nbsp;years</td>
285− <td class="green center">8</td>
286− <td class="red lasttd center">1</td>
287− </tr>
288− <tr class="even" id="torrent_test6478745">
289− <td>
290− <div class="iaconbox center floatright">
291− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
292− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
293− <i class="ka ka-comment"></i>
294− </a>
295− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
296− <i class="ka ka16 ka-verify ka-green"></i>
297− </a>
298− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
299− <i class="ka ka16 ka-arrow-down partner1Button"></i>
300− </a>
301− <a title="Torrent magnet link"
302− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
303− <i class="ka ka16 ka-magnet"></i>
304− </a>
305− <a title="Download torrent file"
306− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
307− <i class="ka ka16 ka-arrow-down"></i>
308− </a>
309− </div>
310− <div class="torrentname">
311− <a href="/test-t6478745.html" class="torType txtType"></a>
312− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
313− <div class="markeredBlock torType txtType">
314− <a href="/url.html" class="cellMainLink">
315− <strong class="red">This should be the title</strong>
316− </a>
317− <span class="font11px lightgrey block">
318− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
319− <a class="plain" href="/user/riri/">riri</a> in
320− <span id="cat_6478745">
321− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
322− </span>
323− </span>
324− </div>
325− </td>
326− <td class="nobr center">1 TiB</td>
327− <td class="center">4</td>
328− <td class="center">2&nbsp;years</td>
329− <td class="green center">7</td>
330− <td class="red lasttd center">1</td>
331− </tr>
332− <tr class="even" id="torrent_test6478745">
333− <td>
334− <div class="iaconbox center floatright">
335− <a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
336− <em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
337− <i class="ka ka-comment"></i>
338− </a>
339− <a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
340− <i class="ka ka16 ka-verify ka-green"></i>
341− </a>
342− <a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
343− <i class="ka ka16 ka-arrow-down partner1Button"></i>
344− </a>
345− <a title="Torrent magnet link"
346− href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
347− <i class="ka ka16 ka-magnet"></i>
348− </a>
349− <a title="Download torrent file"
350− href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
351− <i class="ka ka16 ka-arrow-down"></i>
352− </a>
353− </div>
354− <div class="torrentname">
355− <a href="/test-t6478745.html" class="torType txtType"></a>
356− <a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
357− <div class="markeredBlock torType txtType">
358− <a href="/url.html" class="cellMainLink">
359− <strong class="red">This should be the title</strong>
360− </a>
361− <span class="font11px lightgrey block">
362− Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
363− <a class="plain" href="/user/riri/">riri</a> in
364− <span id="cat_6478745">
365− <strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
366− </span>
367− </span>
368− </div>
369− </td>
370− <td class="nobr center">z bytes</td>
371− <td class="center">r</td>
372− <td class="center">2&nbsp;years</td>
373− <td class="green center">a</td>
374− <td class="red lasttd center">t</td>
375− </tr>
376− </table>
377− """
378− response = mock.Mock(text=html)
379− results = kickass.response(response)
380− self.assertEqual(type(results), list)
381− self.assertEqual(len(results), 5)
382− self.assertEqual(results[0]['title'], 'This should be the title')
383− self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html')
384− self.assertEqual(results[0]['content'], 'Posted by riri in Other > Unsorted')
385− self.assertEqual(results[0]['seed'], 10)
386− self.assertEqual(results[0]['leech'], 1)
387− self.assertEqual(results[0]['files'], 4)
388− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
389− self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
390− self.assertEqual(results[0]['filesize'], 1000)
391− self.assertEqual(results[1]['filesize'], 1000000)
392− self.assertEqual(results[2]['filesize'], 1000000000)
393− self.assertEqual(results[3]['filesize'], 1000000000000)
394− self.assertEqual(results[4]['seed'], 0)
395− self.assertEqual(results[4]['leech'], 0)
396− self.assertEqual(results[4]['files'], None)
397− self.assertEqual(results[4]['filesize'], None)
tests/unit/engines/test_mediawiki.pydeleted−130
@@ -1,130 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import mediawiki
5−from searx.testing import SearxTestCase
6−
7−
8−class TestMediawikiEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− dicto['language'] = 'fr_FR'
15− params = mediawiki.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18− self.assertIn('wikipedia.org', params['url'])
19− self.assertIn('fr', params['url'])
20−
21− dicto['language'] = 'all'
22− params = mediawiki.request(query, dicto)
23− self.assertIn('en', params['url'])
24−
25− mediawiki.base_url = "http://test.url/"
26− mediawiki.search_url = mediawiki.base_url +\
27− 'w/api.php?action=query'\
28− '&list=search'\
29− '&{query}'\
30− '&srprop=timestamp'\
31− '&format=json'\
32− '&sroffset={offset}'\
33− '&srlimit={limit}' # noqa
34− params = mediawiki.request(query, dicto)
35− self.assertIn('test.url', params['url'])
36−
37− def test_response(self):
38− dicto = defaultdict(dict)
39− dicto['language'] = 'fr'
40− mediawiki.base_url = "https://{language}.wikipedia.org/"
41−
42− self.assertRaises(AttributeError, mediawiki.response, None)
43− self.assertRaises(AttributeError, mediawiki.response, [])
44− self.assertRaises(AttributeError, mediawiki.response, '')
45− self.assertRaises(AttributeError, mediawiki.response, '[]')
46−
47− response = mock.Mock(text='{}', search_params=dicto)
48− self.assertEqual(mediawiki.response(response), [])
49−
50− response = mock.Mock(text='{"data": []}', search_params=dicto)
51− self.assertEqual(mediawiki.response(response), [])
52−
53− json = """
54− {
55− "query-continue": {
56− "search": {
57− "sroffset": 1
58− }
59− },
60− "query": {
61− "searchinfo": {
62− "totalhits": 29721
63− },
64− "search": [
65− {
66− "ns": 0,
67− "title": "This is the title étude",
68− "timestamp": "2014-12-19T17:42:52Z"
69− }
70− ]
71− }
72− }
73− """
74− response = mock.Mock(text=json, search_params=dicto)
75− results = mediawiki.response(response)
76− self.assertEqual(type(results), list)
77− self.assertEqual(len(results), 1)
78− self.assertEqual(results[0]['title'], u'This is the title étude')
79− self.assertIn('fr.wikipedia.org', results[0]['url'])
80− self.assertIn('This_is_the_title', results[0]['url'])
81− self.assertIn('%C3%A9tude', results[0]['url'])
82− self.assertEqual(results[0]['content'], '')
83−
84− json = """
85− {
86− "query-continue": {
87− "search": {
88− "sroffset": 1
89− }
90− },
91− "query": {
92− "searchinfo": {
93− "totalhits": 29721
94− },
95− "search": [
96− ]
97− }
98− }
99− """
100− response = mock.Mock(text=json, search_params=dicto)
101− results = mediawiki.response(response)
102− self.assertEqual(type(results), list)
103− self.assertEqual(len(results), 0)
104−
105− json = """
106− {
107− "query-continue": {
108− "search": {
109− "sroffset": 1
110− }
111− },
112− "query": {
113− }
114− }
115− """
116− response = mock.Mock(text=json, search_params=dicto)
117− results = mediawiki.response(response)
118− self.assertEqual(type(results), list)
119− self.assertEqual(len(results), 0)
120−
121− json = r"""
122− {"toto":[
123− {"id":200,"name":"Artist Name",
124− "link":"http:\/\/www.mediawiki.com\/artist\/1217","type":"artist"}
125− ]}
126− """
127− response = mock.Mock(text=json, search_params=dicto)
128− results = mediawiki.response(response)
129− self.assertEqual(type(results), list)
130− self.assertEqual(len(results), 0)
tests/unit/engines/test_mixcloud.pydeleted−67
@@ -1,67 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import mixcloud
4−from searx.testing import SearxTestCase
5−
6−
7−class TestMixcloudEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = mixcloud.request(query, dicto)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('mixcloud.com' in params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, mixcloud.response, None)
20− self.assertRaises(AttributeError, mixcloud.response, [])
21− self.assertRaises(AttributeError, mixcloud.response, '')
22− self.assertRaises(AttributeError, mixcloud.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(mixcloud.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(mixcloud.response(response), [])
29−
30− json = """
31− {"data":[
32− {
33− "user": {
34− "url": "http://www.mixcloud.com/user/",
35− "username": "user",
36− "name": "User",
37− "key": "/user/"
38− },
39− "key": "/user/this-is-the-url/",
40− "created_time": "2014-11-14T13:30:02Z",
41− "audio_length": 3728,
42− "slug": "this-is-the-url",
43− "name": "Title of track",
44− "url": "http://www.mixcloud.com/user/this-is-the-url/",
45− "updated_time": "2014-11-14T13:14:10Z"
46− }
47− ]}
48− """
49− response = mock.Mock(text=json)
50− results = mixcloud.response(response)
51− self.assertEqual(type(results), list)
52− self.assertEqual(len(results), 1)
53− self.assertEqual(results[0]['title'], 'Title of track')
54− self.assertEqual(results[0]['url'], 'http://www.mixcloud.com/user/this-is-the-url/')
55− self.assertEqual(results[0]['content'], 'User')
56− self.assertTrue('http://www.mixcloud.com/user/this-is-the-url/' in results[0]['embedded'])
57−
58− json = r"""
59− {"toto":[
60− {"id":200,"name":"Artist Name",
61− "link":"http:\/\/www.mixcloud.com\/artist\/1217","type":"artist"}
62− ]}
63− """
64− response = mock.Mock(text=json)
65− results = mixcloud.response(response)
66− self.assertEqual(type(results), list)
67− self.assertEqual(len(results), 0)
tests/unit/engines/test_nyaa.pydeleted−124
@@ -1,124 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import nyaa
4−from searx.testing import SearxTestCase
5−
6−
7−class TestNyaaEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dic = defaultdict(dict)
12− dic['pageno'] = 1
13− params = nyaa.request(query, dic)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('nyaa.si' in params['url'])
17−
18− def test_response(self):
19− resp = mock.Mock(text='<html></html>')
20− self.assertEqual(nyaa.response(resp), [])
21−
22− html = """
23− <table class="table table-bordered table-hover table-striped torrent-list">
24− <thead>
25− <tr>
26− <th class="hdr-category text-center" style="width:80px;">
27− <div>Category</div>
28− </th>
29− <th class="hdr-name" style="width:auto;">
30− <div>Name</div>
31− </th>
32− <th class="hdr-comments sorting text-center" title="Comments" style="width:50px;">
33− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=comments&amp;o=desc"></a>
34− <i class="fa fa-comments-o"></i>
35− </th>
36− <th class="hdr-link text-center" style="width:70px;">
37− <div>Link</div>
38− </th>
39− <th class="hdr-size sorting text-center" style="width:100px;">
40− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=size&amp;o=desc"></a>
41− <div>Size</div>
42− </th>
43− <th class="hdr-date sorting_desc text-center" title="In local time" style="width:140px;">
44− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=id&amp;o=asc"></a>
45− <div>Date</div>
46− </th>
47− <th class="hdr-seeders sorting text-center" title="Seeders" style="width:50px;">
48− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=seeders&amp;o=desc"></a>
49− <i class="fa fa-arrow-up" aria-hidden="true"></i>
50− </th>
51− <th class="hdr-leechers sorting text-center" title="Leechers" style="width:50px;">
52− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=leechers&amp;o=desc"></a>
53− <i class="fa fa-arrow-down" aria-hidden="true"></i>
54− </th>
55− <th class="hdr-downloads sorting text-center" title="Completed downloads" style="width:50px;">
56− <a href="/?f=0&amp;c=0_0&amp;q=Death+Parade&amp;s=downloads&amp;o=desc"></a>
57− <i class="fa fa-check" aria-hidden="true"></i>
58− </th>
59− </tr>
60− </thead>
61− <tbody>
62− <tr class="default">
63− <td style="padding:0 4px;">
64− <a href="/?c=1_2" title="Anime - English-translated">
65− <img src="/static/img/icons/nyaa/1_2.png" alt="Anime - English-translated">
66− </a>
67− </td>
68− <td colspan="2">
69− <a href="/view/1" title="Sample title 1">Sample title 1</a>
70− </td>
71− <td class="text-center" style="white-space: nowrap;">
72− <a href="/download/1.torrent"><i class="fa fa-fw fa-download"></i></a>
73− <a href="magnet:?xt=urn:btih:2"><i class="fa fa-fw fa-magnet"></i></a>
74− </td>
75− <td class="text-center">723.7 MiB</td>
76− <td class="text-center" data-timestamp="1503307456" title="1 week 3
77− days 9 hours 44 minutes 39 seconds ago">2017-08-21 11:24</td>
78− <td class="text-center" style="color: green;">1</td>
79− <td class="text-center" style="color: red;">3</td>
80− <td class="text-center">12</td>
81− </tr>
82− <tr class="default">
83− <td style="padding:0 4px;">
84− <a href="/?c=1_2" title="Anime - English-translated">
85− <img src="/static/img/icons/nyaa/1_2.png" alt="Anime - English-translated">
86− </a>
87− </td>
88− <td colspan="2">
89− <a href="/view/2" title="Sample title 2">Sample title 2</a>
90− </td>
91− <td class="text-center" style="white-space: nowrap;">
92− <a href="magnet:?xt=urn:btih:2"><i class="fa fa-fw fa-magnet"></i></a>
93− </td>
94− <td class="text-center">8.2 GiB</td>
95− <td class="text-center" data-timestamp="1491608400" title="4 months 3
96− weeks 4 days 19 hours 28 minutes 55 seconds ago">2017-04-08 01:40</td>
97− <td class="text-center" style="color: green;">10</td>
98− <td class="text-center" style="color: red;">1</td>
99− <td class="text-center">206</td>
100− </tr>
101− </tbody>
102− </table>
103− """
104−
105− resp = mock.Mock(text=html)
106− results = nyaa.response(resp)
107−
108− self.assertEqual(type(results), list)
109− self.assertEqual(len(results), 2)
110−
111− r = results[0]
112− self.assertTrue(r['url'].find('1') >= 0)
113− self.assertTrue(r['torrentfile'].find('1.torrent') >= 0)
114− self.assertTrue(r['content'].find('Anime - English-translated') >= 0)
115− self.assertTrue(r['content'].find('Downloaded 12 times.') >= 0)
116−
117− self.assertEqual(r['title'], 'Sample title 1')
118− self.assertEqual(r['seed'], 1)
119− self.assertEqual(r['leech'], 3)
120− self.assertEqual(r['filesize'], 723700000)
121−
122− r = results[1]
123− self.assertTrue(r['url'].find('2') >= 0)
124− self.assertTrue(r['magnetlink'].find('magnet:') >= 0)
tests/unit/engines/test_openstreetmap.pydeleted−199
@@ -1,199 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import openstreetmap
5−from searx.testing import SearxTestCase
6−
7−
8−class TestOpenstreetmapEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = openstreetmap.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('openstreetmap.org', params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, openstreetmap.response, None)
21− self.assertRaises(AttributeError, openstreetmap.response, [])
22− self.assertRaises(AttributeError, openstreetmap.response, '')
23− self.assertRaises(AttributeError, openstreetmap.response, '[]')
24−
25− response = mock.Mock(text='{}')
26− self.assertEqual(openstreetmap.response(response), [])
27−
28− response = mock.Mock(text='{"data": []}')
29− self.assertEqual(openstreetmap.response(response), [])
30−
31− json = """
32− [
33− {
34− "place_id": "127732055",
35− "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
36− "osm_type": "relation",
37− "osm_id": "7444",
38− "boundingbox": [
39− "48.8155755",
40− "48.902156",
41− "2.224122",
42− "2.4697602"
43− ],
44− "lat": "48.8565056",
45− "lon": "2.3521334",
46− "display_name": "This is the title",
47− "class": "place",
48− "type": "city",
49− "importance": 0.96893459932191,
50− "icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
51− "address": {
52− "city": "Paris",
53− "county": "Paris",
54− "state": "Île-de-France",
55− "country": "France",
56− "country_code": "fr"
57− },
58− "geojson": {
59− "type": "Polygon",
60− "coordinates": [
61− [
62− [
63− 2.224122,
64− 48.854199
65− ]
66− ]
67− ]
68− }
69− }
70− ]
71− """
72− response = mock.Mock(text=json)
73− results = openstreetmap.response(response)
74− self.assertEqual(type(results), list)
75− self.assertEqual(len(results), 1)
76− self.assertEqual(results[0]['title'], 'This is the title')
77− self.assertEqual(results[0]['url'], 'https://openstreetmap.org/relation/7444')
78− self.assertIn('coordinates', results[0]['geojson'])
79− self.assertEqual(results[0]['geojson']['coordinates'][0][0][0], 2.224122)
80− self.assertEqual(results[0]['geojson']['coordinates'][0][0][1], 48.854199)
81− self.assertEqual(results[0]['address'], None)
82− self.assertIn('48.8155755', results[0]['boundingbox'])
83− self.assertIn('48.902156', results[0]['boundingbox'])
84− self.assertIn('2.224122', results[0]['boundingbox'])
85− self.assertIn('2.4697602', results[0]['boundingbox'])
86−
87− json = """
88− [
89− {
90− "place_id": "127732055",
91− "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
92− "osm_type": "relation",
93− "osm_id": "7444",
94− "boundingbox": [
95− "48.8155755",
96− "48.902156",
97− "2.224122",
98− "2.4697602"
99− ],
100− "lat": "48.8565056",
101− "lon": "2.3521334",
102− "display_name": "This is the title",
103− "class": "tourism",
104− "type": "city",
105− "importance": 0.96893459932191,
106− "icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
107− "address": {
108− "city": "Paris",
109− "county": "Paris",
110− "state": "Île-de-France",
111− "country": "France",
112− "country_code": "fr",
113− "address29": "Address"
114− },
115− "geojson": {
116− "type": "Polygon",
117− "coordinates": [
118− [
119− [
120− 2.224122,
121− 48.854199
122− ]
123− ]
124− ]
125− }
126− },
127− {
128− "place_id": "127732055",
129− "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
130− "osm_type": "relation",
131− "osm_id": "7444",
132− "boundingbox": [
133− "48.8155755",
134− "48.902156",
135− "2.224122",
136− "2.4697602"
137− ],
138− "lat": "48.8565056",
139− "lon": "2.3521334",
140− "display_name": "This is the title",
141− "class": "tourism",
142− "type": "city",
143− "importance": 0.96893459932191,
144− "icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
145− "address": {
146− "city": "Paris",
147− "county": "Paris",
148− "state": "Île-de-France",
149− "country": "France",
150− "postcode": 75000,
151− "country_code": "fr"
152− },
153− "geojson": {
154− "type": "Polygon",
155− "coordinates": [
156− [
157− [
158− 2.224122,
159− 48.854199
160− ]
161− ]
162− ]
163− }
164− },
165− {
166− "place_id": "127732055",
167− "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
168− "osm_type": "node",
169− "osm_id": "7444",
170− "boundingbox": [
171− "48.8155755",
172− "48.902156",
173− "2.224122",
174− "2.4697602"
175− ],
176− "lat": "48.8565056",
177− "lon": "2.3521334",
178− "display_name": "This is the title",
179− "class": "tourism",
180− "type": "city",
181− "importance": 0.96893459932191,
182− "icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
183− "address": {
184− "city": "Paris",
185− "county": "Paris",
186− "state": "Île-de-France",
187− "country": "France",
188− "country_code": "fr",
189− "address29": "Address"
190− }
191− }
192− ]
193− """
194− response = mock.Mock(text=json)
195− results = openstreetmap.response(response)
196− self.assertEqual(type(results), list)
197− self.assertEqual(len(results), 3)
198− self.assertIn('48.8565056', results[2]['geojson']['coordinates'])
199− self.assertIn('2.3521334', results[2]['geojson']['coordinates'])
tests/unit/engines/test_pdbe.pydeleted−109
@@ -1,109 +0,0 @@
1−import mock
2−from collections import defaultdict
3−from searx.engines import pdbe
4−from searx.testing import SearxTestCase
5−
6−
7−class TestPdbeEngine(SearxTestCase):
8− def test_request(self):
9− query = 'test_query'
10− dicto = defaultdict(dict)
11− params = pdbe.request(query, dicto)
12− self.assertTrue('url' in params)
13− self.assertTrue('ebi.ac.uk' in params['url'])
14− self.assertTrue('data' in params)
15− self.assertTrue('q' in params['data'])
16− self.assertTrue(query in params['data']['q'])
17− self.assertTrue('wt' in params['data'])
18− self.assertTrue('json' in params['data']['wt'])
19− self.assertTrue('method' in params)
20− self.assertTrue(params['method'] == 'POST')
21−
22− def test_response(self):
23− self.assertRaises(AttributeError, pdbe.response, None)
24− self.assertRaises(AttributeError, pdbe.response, [])
25− self.assertRaises(AttributeError, pdbe.response, '')
26− self.assertRaises(AttributeError, pdbe.response, '[]')
27−
28− json = """
29−{
30− "response": {
31− "docs": [
32− {
33− "citation_title": "X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.",
34− "citation_year": 1993,
35− "entry_author_list": [
36− "Conti E, Moser C, Rizzi M, Mattevi A, Lionetti C, Coda A, Ascenzi P, Brunori M, Bolognesi M"
37− ],
38− "journal": "J. Mol. Biol.",
39− "journal_page": "498-508",
40− "journal_volume": "233",
41− "pdb_id": "2fal",
42− "status": "REL",
43− "title": "X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES"
44− }
45− ],
46− "numFound": 1,
47− "start": 0
48− },
49− "responseHeader": {
50− "QTime": 0,
51− "params": {
52− "q": "2fal",
53− "wt": "json"
54− },
55− "status": 0
56− }
57−}
58−"""
59−
60− response = mock.Mock(text=json)
61− results = pdbe.response(response)
62− self.assertEqual(type(results), list)
63− self.assertEqual(len(results), 1)
64− self.assertEqual(results[0]['title'],
65− 'X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES')
66− self.assertEqual(results[0]['url'], pdbe.pdbe_entry_url.format(pdb_id='2fal'))
67− self.assertEqual(results[0]['img_src'], pdbe.pdbe_preview_url.format(pdb_id='2fal'))
68− self.assertTrue('Conti E' in results[0]['content'])
69− self.assertTrue('X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.' in
70− results[0]['content'])
71− self.assertTrue('1993' in results[0]['content'])
72−
73− # Testing proper handling of PDB entries marked as obsolete
74− json = """
75−{
76− "response": {
77− "docs": [
78− {
79− "citation_title": "Obsolete entry test",
80− "citation_year": 2016,
81− "entry_author_list": ["Doe J"],
82− "journal": "J. Obs.",
83− "journal_page": "1-2",
84− "journal_volume": "1",
85− "pdb_id": "xxxx",
86− "status": "OBS",
87− "title": "OBSOLETE ENTRY TEST",
88− "superseded_by": "yyyy"
89− }
90− ],
91− "numFound": 1,
92− "start": 0
93− },
94− "responseHeader": {
95− "QTime": 0,
96− "params": {
97− "q": "xxxx",
98− "wt": "json"
99− },
100− "status": 0
101− }
102−}
103−"""
104− response = mock.Mock(text=json)
105− results = pdbe.response(response)
106− self.assertEqual(type(results), list)
107− self.assertEqual(len(results), 1)
108− self.assertEqual(results[0]['title'], 'OBSOLETE ENTRY TEST (OBSOLETE)')
109− self.assertTrue(results[0]['content'].startswith('This entry has been superseded by'))
tests/unit/engines/test_photon.pydeleted−166
@@ -1,166 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import photon
5−from searx.testing import SearxTestCase
6−
7−
8−class TestPhotonEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− dicto['language'] = 'all'
15− params = photon.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18− self.assertIn('photon.komoot.de', params['url'])
19−
20− dicto['language'] = 'all'
21− params = photon.request(query, dicto)
22− self.assertNotIn('lang', params['url'])
23−
24− dicto['language'] = 'al'
25− params = photon.request(query, dicto)
26− self.assertNotIn('lang', params['url'])
27−
28− dicto['language'] = 'fr'
29− params = photon.request(query, dicto)
30− self.assertIn('fr', params['url'])
31−
32− def test_response(self):
33− self.assertRaises(AttributeError, photon.response, None)
34− self.assertRaises(AttributeError, photon.response, [])
35− self.assertRaises(AttributeError, photon.response, '')
36− self.assertRaises(AttributeError, photon.response, '[]')
37−
38− response = mock.Mock(text='{}')
39− self.assertEqual(photon.response(response), [])
40−
41− response = mock.Mock(text='{"data": []}')
42− self.assertEqual(photon.response(response), [])
43−
44− json = """
45− {
46− "features": [
47− {
48− "properties": {
49− "osm_key": "waterway",
50− "extent": [
51− -1.4508446,
52− 51.1614997,
53− -1.4408036,
54− 51.1525635
55− ],
56− "name": "This is the title",
57− "state": "England",
58− "osm_id": 114823817,
59− "osm_type": "W",
60− "osm_value": "river",
61− "city": "Test Valley",
62− "country": "United Kingdom"
63− },
64− "type": "Feature",
65− "geometry": {
66− "type": "Point",
67− "coordinates": [
68− -1.4458571,
69− 51.1576661
70− ]
71− }
72− },
73− {
74− "properties": {
75− "osm_key": "place",
76− "street": "Rue",
77− "state": "Ile-de-France",
78− "osm_id": 129211377,
79− "osm_type": "R",
80− "housenumber": "10",
81− "postcode": "75011",
82− "osm_value": "house",
83− "city": "Paris",
84− "country": "France"
85− },
86− "type": "Feature",
87− "geometry": {
88− "type": "Point",
89− "coordinates": [
90− 2.3725025,
91− 48.8654481
92− ]
93− }
94− },
95− {
96− "properties": {
97− "osm_key": "amenity",
98− "street": "Allée",
99− "name": "Bibliothèque",
100− "state": "Ile-de-France",
101− "osm_id": 1028573132,
102− "osm_type": "N",
103− "postcode": "75001",
104− "osm_value": "library",
105− "city": "Paris",
106− "country": "France"
107− },
108− "type": "Feature",
109− "geometry": {
110− "type": "Point",
111− "coordinates": [
112− 2.3445634,
113− 48.862494
114− ]
115− }
116− },
117− {
118− "properties": {
119− "osm_key": "amenity",
120− "osm_id": 1028573132,
121− "osm_type": "Y",
122− "postcode": "75001",
123− "osm_value": "library",
124− "city": "Paris",
125− "country": "France"
126− },
127− "type": "Feature",
128− "geometry": {
129− "type": "Point",
130− "coordinates": [
131− 2.3445634,
132− 48.862494
133− ]
134− }
135− },
136− {
137− }
138− ],
139− "type": "FeatureCollection"
140− }
141− """
142− response = mock.Mock(text=json)
143− results = photon.response(response)
144− self.assertEqual(type(results), list)
145− self.assertEqual(len(results), 3)
146− self.assertEqual(results[0]['title'], 'This is the title')
147− self.assertEqual(results[0]['content'], '')
148− self.assertEqual(results[0]['longitude'], -1.4458571)
149− self.assertEqual(results[0]['latitude'], 51.1576661)
150− self.assertIn(-1.4508446, results[0]['boundingbox'])
151− self.assertIn(51.1614997, results[0]['boundingbox'])
152− self.assertIn(-1.4408036, results[0]['boundingbox'])
153− self.assertIn(51.1525635, results[0]['boundingbox'])
154− self.assertIn('type', results[0]['geojson'])
155− self.assertEqual(results[0]['geojson']['type'], 'Point')
156− self.assertEqual(results[0]['address'], None)
157− self.assertEqual(results[0]['osm']['type'], 'way')
158− self.assertEqual(results[0]['osm']['id'], 114823817)
159− self.assertEqual(results[0]['url'], 'https://openstreetmap.org/way/114823817')
160− self.assertEqual(results[1]['osm']['type'], 'relation')
161− self.assertEqual(results[2]['address']['name'], u'Bibliothèque')
162− self.assertEqual(results[2]['address']['house_number'], None)
163− self.assertEqual(results[2]['address']['locality'], 'Paris')
164− self.assertEqual(results[2]['address']['postcode'], '75001')
165− self.assertEqual(results[2]['address']['country'], 'France')
166− self.assertEqual(results[2]['osm']['type'], 'node')
tests/unit/engines/test_piratebay.pydeleted−166
@@ -1,166 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import piratebay
5−from searx.testing import SearxTestCase
6−
7−
8−class TestPiratebayEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− dicto['category'] = 'Toto'
15− params = piratebay.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18− self.assertIn('piratebay.org', params['url'])
19− self.assertIn('0', params['url'])
20−
21− dicto['category'] = 'music'
22− params = piratebay.request(query, dicto)
23− self.assertIn('100', params['url'])
24−
25− def test_response(self):
26− self.assertRaises(AttributeError, piratebay.response, None)
27− self.assertRaises(AttributeError, piratebay.response, [])
28− self.assertRaises(AttributeError, piratebay.response, '')
29− self.assertRaises(AttributeError, piratebay.response, '[]')
30−
31− response = mock.Mock(text='<html></html>')
32− self.assertEqual(piratebay.response(response), [])
33−
34− html = """
35− <table id="searchResult">
36− <tr>
37− </tr>
38− <tr>
39− <td class="vertTh">
40− <center>
41− <a href="#" title="More from this category">Anime</a><br/>
42− (<a href="#" title="More from this category">Anime</a>)
43− </center>
44− </td>
45− <td>
46− <div class="detName">
47− <a href="/this.is.the.link" class="detLink" title="Title">
48− This is the title
49− </a>
50− </div>
51− <a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
52− <img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
53− </a>
54− <a href="http://torcache.net/torrent/TORRENTFILE.torrent" title="Download this torrent">
55− <img src="/static/img/dl.gif" class="dl" alt="Download"/>
56− </a>
57− <a href="/user/HorribleSubs">
58− <img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
59− </a>
60− <img src="/static/img/11x11p.png"/>
61− <font class="detDesc">
62− This is the content <span>and should be</span> OK
63− </font>
64− </td>
65− <td align="right">13</td>
66− <td align="right">334</td>
67− </tr>
68− <tr>
69− <td class="vertTh">
70− <center>
71− <a href="#" title="More from this category">Anime</a><br/>
72− (<a href="#" title="More from this category">Anime</a>)
73− </center>
74− </td>
75− <td>
76− <div class="detName">
77− <a href="/this.is.the.link" class="detLink" title="Title">
78− This is the title
79− </a>
80− </div>
81− <a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
82− <img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
83− </a>
84− <a href="/user/HorribleSubs">
85− <img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
86− </a>
87− <img src="/static/img/11x11p.png"/>
88− <font class="detDesc">
89− This is the content <span>and should be</span> OK
90− </font>
91− </td>
92− <td align="right">13</td>
93− <td align="right">334</td>
94− </tr>
95− </table>
96− """
97− response = mock.Mock(text=html)
98− results = piratebay.response(response)
99− self.assertEqual(type(results), list)
100− self.assertEqual(len(results), 2)
101− self.assertEqual(results[0]['title'], 'This is the title')
102− self.assertEqual(results[0]['url'], 'https://thepiratebay.org/this.is.the.link')
103− self.assertEqual(results[0]['content'], 'This is the content and should be OK')
104− self.assertEqual(results[0]['seed'], 13)
105− self.assertEqual(results[0]['leech'], 334)
106− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETLINK')
107− self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/TORRENTFILE.torrent')
108−
109− self.assertEqual(results[1]['torrentfile'], None)
110−
111− html = """
112− <table id="searchResult">
113− <tr>
114− </tr>
115− <tr>
116− <td class="vertTh">
117− <center>
118− <a href="#" title="More from this category">Anime</a><br/>
119− (<a href="#" title="More from this category">Anime</a>)
120− </center>
121− </td>
122− <td>
123− <div class="detName">
124− <a href="/this.is.the.link" class="detLink" title="Title">
125− This is the title
126− </a>
127− </div>
128− <a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
129− <img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
130− </a>
131− <a href="http://torcache.net/torrent/TORRENTFILE.torrent" title="Download this torrent">
132− <img src="/static/img/dl.gif" class="dl" alt="Download"/>
133− </a>
134− <a href="/user/HorribleSubs">
135− <img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
136− </a>
137− <img src="/static/img/11x11p.png"/>
138− <font class="detDesc">
139− This is the content <span>and should be</span> OK
140− </font>
141− </td>
142− <td align="right">s</td>
143− <td align="right">d</td>
144− </tr>
145− </table>
146− """
147− response = mock.Mock(text=html)
148− results = piratebay.response(response)
149− self.assertEqual(type(results), list)
150− self.assertEqual(len(results), 1)
151− self.assertEqual(results[0]['title'], 'This is the title')
152− self.assertEqual(results[0]['url'], 'https://thepiratebay.org/this.is.the.link')
153− self.assertEqual(results[0]['content'], 'This is the content and should be OK')
154− self.assertEqual(results[0]['seed'], 0)
155− self.assertEqual(results[0]['leech'], 0)
156− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETLINK')
157− self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/TORRENTFILE.torrent')
158−
159− html = """
160− <table id="searchResult">
161− </table>
162− """
163− response = mock.Mock(text=html)
164− results = piratebay.response(response)
165− self.assertEqual(type(results), list)
166− self.assertEqual(len(results), 0)
tests/unit/engines/test_qwant.pydeleted−339
@@ -1,339 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import qwant
4−from searx.testing import SearxTestCase
5−
6−
7−class TestQwantEngine(SearxTestCase):
8−
9− def test_request(self):
10− qwant.supported_languages = ['en-US', 'fr-CA', 'fr-FR']
11− qwant.language_aliases = {}
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− dicto['pageno'] = 0
15− dicto['language'] = 'fr-FR'
16− qwant.categories = ['']
17− params = qwant.request(query, dicto)
18− self.assertIn('url', params)
19− self.assertIn(query, params['url'])
20− self.assertIn('web', params['url'])
21− self.assertIn('qwant.com', params['url'])
22− self.assertIn('fr_fr', params['url'])
23−
24− dicto['language'] = 'all'
25− qwant.categories = ['news']
26− params = qwant.request(query, dicto)
27− self.assertFalse('fr' in params['url'])
28− self.assertIn('news', params['url'])
29−
30− dicto['language'] = 'fr'
31− params = qwant.request(query, dicto)
32− self.assertIn('fr_fr', params['url'])
33−
34− def test_response(self):
35− self.assertRaises(AttributeError, qwant.response, None)
36− self.assertRaises(AttributeError, qwant.response, [])
37− self.assertRaises(AttributeError, qwant.response, '')
38− self.assertRaises(AttributeError, qwant.response, '[]')
39−
40− response = mock.Mock(text='{}')
41− self.assertEqual(qwant.response(response), [])
42−
43− response = mock.Mock(text='{"data": {}}')
44− self.assertEqual(qwant.response(response), [])
45−
46− json = """
47− {
48− "status": "success",
49− "data": {
50− "query": {
51− "locale": "en_us",
52− "query": "Test",
53− "offset": 10
54− },
55− "result": {
56− "items": [
57− {
58− "title": "Title",
59− "score": 9999,
60− "url": "http://www.url.xyz",
61− "source": "...",
62− "desc": "Description",
63− "date": "",
64− "_id": "db0aadd62c2a8565567ffc382f5c61fa",
65− "favicon": "https://s.qwant.com/fav.ico"
66− }
67− ],
68− "filters": []
69− },
70− "cache": {
71− "key": "e66aa864c00147a0e3a16ff7a5efafde",
72− "created": 1433092754,
73− "expiration": 259200,
74− "status": "miss",
75− "age": 0
76− }
77− }
78− }
79− """
80− response = mock.Mock(text=json)
81− qwant.categories = ['general']
82− results = qwant.response(response)
83− self.assertEqual(type(results), list)
84− self.assertEqual(len(results), 1)
85− self.assertEqual(results[0]['title'], 'Title')
86− self.assertEqual(results[0]['url'], 'http://www.url.xyz')
87− self.assertEqual(results[0]['content'], 'Description')
88−
89− json = """
90− {
91− "status": "success",
92− "data": {
93− "query": {
94− "locale": "en_us",
95− "query": "Test",
96− "offset": 10
97− },
98− "result": {
99− "items": [
100− {
101− "title": "Title",
102− "score": 9999,
103− "url": "http://www.url.xyz",
104− "source": "...",
105− "media": "http://image.jpg",
106− "desc": "",
107− "thumbnail": "http://thumbnail.jpg",
108− "date": "",
109− "_id": "db0aadd62c2a8565567ffc382f5c61fa",
110− "favicon": "https://s.qwant.com/fav.ico"
111− }
112− ],
113− "filters": []
114− },
115− "cache": {
116− "key": "e66aa864c00147a0e3a16ff7a5efafde",
117− "created": 1433092754,
118− "expiration": 259200,
119− "status": "miss",
120− "age": 0
121− }
122− }
123− }
124− """
125− response = mock.Mock(text=json)
126− qwant.categories = ['images']
127− results = qwant.response(response)
128− self.assertEqual(type(results), list)
129− self.assertEqual(len(results), 1)
130− self.assertEqual(results[0]['title'], 'Title')
131− self.assertEqual(results[0]['url'], 'http://www.url.xyz')
132− self.assertEqual(results[0]['content'], '')
133− self.assertEqual(results[0]['thumbnail_src'], 'http://thumbnail.jpg')
134− self.assertEqual(results[0]['img_src'], 'http://image.jpg')
135−
136− json = """
137− {
138− "status": "success",
139− "data": {
140− "query": {
141− "locale": "en_us",
142− "query": "Test",
143− "offset": 10
144− },
145− "result": {
146− "items": [
147− {
148− "title": "Title",
149− "score": 9999,
150− "url": "http://www.url.xyz",
151− "source": "...",
152− "desc": "Description",
153− "date": 1433260920,
154− "_id": "db0aadd62c2a8565567ffc382f5c61fa",
155− "favicon": "https://s.qwant.com/fav.ico"
156− }
157− ],
158− "filters": []
159− },
160− "cache": {
161− "key": "e66aa864c00147a0e3a16ff7a5efafde",
162− "created": 1433092754,
163− "expiration": 259200,
164− "status": "miss",
165− "age": 0
166− }
167− }
168− }
169− """
170− response = mock.Mock(text=json)
171− qwant.categories = ['news']
172− results = qwant.response(response)
173− self.assertEqual(type(results), list)
174− self.assertEqual(len(results), 1)
175− self.assertEqual(results[0]['title'], 'Title')
176− self.assertEqual(results[0]['url'], 'http://www.url.xyz')
177− self.assertEqual(results[0]['content'], 'Description')
178− self.assertIn('publishedDate', results[0])
179−
180− json = """
181− {
182− "status": "success",
183− "data": {
184− "query": {
185− "locale": "en_us",
186− "query": "Test",
187− "offset": 10
188− },
189− "result": {
190− "items": [
191− {
192− "title": "Title",
193− "score": 9999,
194− "url": "http://www.url.xyz",
195− "source": "...",
196− "desc": "Description",
197− "date": 1433260920,
198− "_id": "db0aadd62c2a8565567ffc382f5c61fa",
199− "favicon": "https://s.qwant.com/fav.ico"
200− }
201− ],
202− "filters": []
203− },
204− "cache": {
205− "key": "e66aa864c00147a0e3a16ff7a5efafde",
206− "created": 1433092754,
207− "expiration": 259200,
208− "status": "miss",
209− "age": 0
210− }
211− }
212− }
213− """
214− response = mock.Mock(text=json)
215− qwant.categories = ['social media']
216− results = qwant.response(response)
217− self.assertEqual(type(results), list)
218− self.assertEqual(len(results), 1)
219− self.assertEqual(results[0]['title'], 'Title')
220− self.assertEqual(results[0]['url'], 'http://www.url.xyz')
221− self.assertEqual(results[0]['content'], 'Description')
222− self.assertIn('publishedDate', results[0])
223−
224− json = """
225− {
226− "status": "success",
227− "data": {
228− "query": {
229− "locale": "en_us",
230− "query": "Test",
231− "offset": 10
232− },
233− "result": {
234− "items": [
235− {
236− "title": "Title",
237− "score": 9999,
238− "url": "http://www.url.xyz",
239− "source": "...",
240− "desc": "Description",
241− "date": 1433260920,
242− "_id": "db0aadd62c2a8565567ffc382f5c61fa",
243− "favicon": "https://s.qwant.com/fav.ico"
244− }
245− ],
246− "filters": []
247− },
248− "cache": {
249− "key": "e66aa864c00147a0e3a16ff7a5efafde",
250− "created": 1433092754,
251− "expiration": 259200,
252− "status": "miss",
253− "age": 0
254− }
255− }
256− }
257− """
258− response = mock.Mock(text=json)
259− qwant.categories = ['']
260− results = qwant.response(response)
261− self.assertEqual(type(results), list)
262− self.assertEqual(len(results), 0)
263−
264− json = """
265− {
266− "status": "success",
267− "data": {
268− "query": {
269− "locale": "en_us",
270− "query": "Test",
271− "offset": 10
272− },
273− "result": {
274− "filters": []
275− },
276− "cache": {
277− "key": "e66aa864c00147a0e3a16ff7a5efafde",
278− "created": 1433092754,
279− "expiration": 259200,
280− "status": "miss",
281− "age": 0
282− }
283− }
284− }
285− """
286− response = mock.Mock(text=json)
287− results = qwant.response(response)
288− self.assertEqual(type(results), list)
289− self.assertEqual(len(results), 0)
290−
291− json = """
292− {
293− "status": "success",
294− "data": {
295− "query": {
296− "locale": "en_us",
297− "query": "Test",
298− "offset": 10
299− },
300− "cache": {
301− "key": "e66aa864c00147a0e3a16ff7a5efafde",
302− "created": 1433092754,
303− "expiration": 259200,
304− "status": "miss",
305− "age": 0
306− }
307− }
308− }
309− """
310− response = mock.Mock(text=json)
311− results = qwant.response(response)
312− self.assertEqual(type(results), list)
313− self.assertEqual(len(results), 0)
314−
315− json = """
316− {
317− "status": "success"
318− }
319− """
320− response = mock.Mock(text=json)
321− results = qwant.response(response)
322− self.assertEqual(type(results), list)
323− self.assertEqual(len(results), 0)
324−
325− def test_fetch_supported_languages(self):
326− page = """some code...
327− config_set('project.regionalisation', {"continents":{},"languages":
328− {"de":{"code":"de","name":"Deutsch","countries":["DE","CH","AT"]},
329− "it":{"code":"it","name":"Italiano","countries":["IT","CH"]}}});
330− some more code..."""
331− response = mock.Mock(text=page)
332− languages = qwant._fetch_supported_languages(response)
333− self.assertEqual(type(languages), list)
334− self.assertEqual(len(languages), 5)
335− self.assertIn('de-DE', languages)
336− self.assertIn('de-CH', languages)
337− self.assertIn('de-AT', languages)
338− self.assertIn('it-IT', languages)
339− self.assertIn('it-CH', languages)
tests/unit/engines/test_reddit.pydeleted−71
@@ -1,71 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import reddit
4−from searx.testing import SearxTestCase
5−from datetime import datetime
6−
7−
8−class TestRedditEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dic = defaultdict(dict)
13− params = reddit.request(query, dic)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('reddit.com' in params['url'])
17−
18− def test_response(self):
19− resp = mock.Mock(text='{}')
20− self.assertEqual(reddit.response(resp), [])
21−
22− json = """
23− {
24− "kind": "Listing",
25− "data": {
26− "children": [{
27− "data": {
28− "url": "http://google2.com/",
29− "permalink": "http://google.com/",
30− "title": "Title number one",
31− "selftext": "Sample",
32− "created_utc": 1401219957.0,
33− "thumbnail": "http://image.com/picture.jpg"
34− }
35− }, {
36− "data": {
37− "url": "https://reddit2.com/",
38− "permalink": "https://reddit.com/",
39− "title": "Title number two",
40− "selftext": "Dominus vobiscum",
41− "created_utc": 1438792533.0,
42− "thumbnail": "self"
43− }
44− }]
45− }
46− }
47− """
48−
49− resp = mock.Mock(text=json)
50− results = reddit.response(resp)
51−
52− self.assertEqual(len(results), 2)
53− self.assertEqual(type(results), list)
54−
55− # testing first result (picture)
56− r = results[0]
57− self.assertEqual(r['url'], 'http://google.com/')
58− self.assertEqual(r['title'], 'Title number one')
59− self.assertEqual(r['template'], 'images.html')
60− self.assertEqual(r['img_src'], 'http://google2.com/')
61− self.assertEqual(r['thumbnail_src'], 'http://image.com/picture.jpg')
62−
63− # testing second result (self-post)
64− r = results[1]
65− self.assertEqual(r['url'], 'https://reddit.com/')
66− self.assertEqual(r['title'], 'Title number two')
67− self.assertEqual(r['content'], 'Dominus vobiscum')
68− created = datetime.fromtimestamp(1438792533.0)
69− self.assertEqual(r['publishedDate'], created)
70− self.assertTrue('thumbnail_src' not in r)
71− self.assertTrue('img_src' not in r)
tests/unit/engines/test_scanr_structures.pydeleted−175
@@ -1,175 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import scanr_structures
4−from searx.testing import SearxTestCase
5−
6−
7−class TestScanrStructuresEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 1
13− params = scanr_structures.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['data'])
16− self.assertIn('scanr.enseignementsup-recherche.gouv.fr', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, scanr_structures.response, None)
20− self.assertRaises(AttributeError, scanr_structures.response, [])
21− self.assertRaises(AttributeError, scanr_structures.response, '')
22− self.assertRaises(AttributeError, scanr_structures.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(scanr_structures.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(scanr_structures.response(response), [])
29−
30− json = u"""
31− {
32− "request":
33− {
34− "query":"test_query",
35− "page":1,
36− "pageSize":20,
37− "sortOrder":"RELEVANCY",
38− "sortDirection":"ASC",
39− "searchField":"ALL",
40− "from":0
41− },
42− "total":2471,
43− "results":[
44− {
45− "id":"200711886U",
46− "label":"Laboratoire d'Informatique de Grenoble",
47− "kind":"RNSR",
48− "publicEntity":true,
49− "address":{"city":"Grenoble","departement":"38"},
50− "logo":"/static/logos/200711886U.png",
51− "acronym":"LIG",
52− "type":{"code":"UR","label":"Unit\xe9 de recherche"},
53− "level":2,
54− "institutions":[
55− {
56− "id":"193819125",
57− "label":"Grenoble INP",
58− "acronym":"IPG",
59− "code":"UMR 5217"
60− },
61− {
62− "id":"130021397",
63− "label":"Universit\xe9 de Grenoble Alpes",
64− "acronym":"UGA",
65− "code":"UMR 5217"
66− },
67− {
68− "id":"180089013",
69− "label":"Centre national de la recherche scientifique",
70− "acronym":"CNRS",
71− "code":"UMR 5217"
72− },
73− {
74− "id":"180089047",
75− "label":"Institut national de recherche en informatique et en automatique",
76− "acronym":"Inria",
77− "code":"UMR 5217"
78− }
79− ],
80− "highlights":[
81− {
82− "type":"projects",
83− "value":"linguicielles d\xe9velopp\xe9s jusqu'ici par le GETALP\
84− du <strong>LIG</strong> en tant que prototypes op\xe9rationnels.\
85−\\r\\nDans le contexte"
86− },
87− {
88− "type":"acronym",
89− "value":"<strong>LIG</strong>"
90− },
91− {
92− "type":"websiteContents",
93− "value":"S\xe9lection\\nListe structures\\nD\xe9tail\\n\
94− Accueil\\n200711886U : <strong>LIG</strong>\
95− Laboratoire d'Informatique de Grenoble Unit\xe9 de recherche"},
96− {
97− "type":"publications",
98− "value":"de noms. Nous avons d'abord d\xe9velopp\xe9 LOOV \
99− (pour <strong>Lig</strong> Overlaid OCR in Vid\xe9o), \
100− un outil d'extraction des"
101− }
102− ]
103− },
104− {
105− "id":"199511665F",
106− "label":"Laboratoire Bordelais de Recherche en Informatique",
107− "kind":"RNSR",
108− "publicEntity":true,
109− "address":{"city":"Talence","departement":"33"},
110− "logo":"/static/logos/199511665F.png",
111− "acronym":"LaBRI",
112− "type":{"code":"UR","label":"Unit\xe9 de recherche"},
113− "level":2,
114− "institutions":[
115− {
116− "id":"130006356",
117− "label":"Institut polytechnique de Bordeaux",
118− "acronym":"IPB",
119− "code":"UMR 5800"
120− },
121− {
122− "id":"130018351",
123− "label":"Universit\xe9 de Bordeaux",
124− "acronym":null,
125− "code":"UMR 5800"
126− },
127− {
128− "id":"180089013",
129− "label":"Centre national de la recherche scientifique",
130− "acronym":"CNRS",
131− "code":"UMR 5800"
132− },
133− {
134− "id":"180089047",
135− "label":"Institut national de recherche en informatique et en automatique",
136− "acronym":"Inria",
137− "code":"UMR 5800"
138− }
139− ],
140− "highlights":[
141− {
142− "type":"websiteContents",
143− "value":"Samia Kerdjoudj\\n2016-07-05\\nDouble-exponential\
144− and <strong>triple</strong>-exponential bounds for\
145− choosability problems parameterized"
146− },
147− {
148− "type":"publications",
149− "value":"de cam\xe9ras install\xe9es dans les lieux publiques \
150− a <strong>tripl\xe9</strong> en 2009, passant de 20 000 \
151− \xe0 60 000. Malgr\xe9 le"
152− }
153− ]
154− }
155− ]
156− }
157− """
158− response = mock.Mock(text=json)
159− results = scanr_structures.response(response)
160− self.assertEqual(type(results), list)
161− self.assertEqual(len(results), 2)
162− self.assertEqual(results[0]['title'], u"Laboratoire d'Informatique de Grenoble")
163− self.assertEqual(results[0]['url'], 'https://scanr.enseignementsup-recherche.gouv.fr/structure/200711886U')
164− self.assertEqual(results[0]['content'],
165− u"linguicielles d\xe9velopp\xe9s jusqu'ici par le GETALP "
166− u"du LIG en tant que prototypes "
167− u"op\xe9rationnels. Dans le contexte")
168− self.assertEqual(results[1]['img_src'],
169− 'https://scanr.enseignementsup-recherche.gouv.fr//static/logos/199511665F.png')
170− self.assertEqual(results[1]['content'],
171− "Samia Kerdjoudj 2016-07-05 Double-exponential and"
172− " triple-exponential bounds for "
173− "choosability problems parameterized")
174− self.assertEqual(results[1]['url'], 'https://scanr.enseignementsup-recherche.gouv.fr/structure/199511665F')
175− self.assertEqual(results[1]['title'], u"Laboratoire Bordelais de Recherche en Informatique")
tests/unit/engines/test_searchcode_code.pydeleted−75
@@ -1,75 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import searchcode_code
4−from searx.testing import SearxTestCase
5−
6−
7−class TestSearchcodeCodeEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = searchcode_code.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16− self.assertIn('searchcode.com', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, searchcode_code.response, None)
20− self.assertRaises(AttributeError, searchcode_code.response, [])
21− self.assertRaises(AttributeError, searchcode_code.response, '')
22− self.assertRaises(AttributeError, searchcode_code.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(searchcode_code.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(searchcode_code.response(response), [])
29−
30− json = """
31− {
32− "matchterm": "test",
33− "previouspage": null,
34− "searchterm": "test",
35− "query": "test",
36− "total": 1000,
37− "page": 0,
38− "nextpage": 1,
39− "results": [
40− {
41− "repo": "https://repo",
42− "linescount": 1044,
43− "location": "/tests",
44− "name": "Name",
45− "url": "https://url",
46− "md5hash": "ecac6e479edd2b9406c9e08603cec655",
47− "lines": {
48− "1": "// Test 011",
49− "2": "// Source: "
50− },
51− "id": 51223527,
52− "filename": "File.CPP"
53− }
54− ]
55− }
56− """
57− response = mock.Mock(text=json)
58− results = searchcode_code.response(response)
59− self.assertEqual(type(results), list)
60− self.assertEqual(len(results), 1)
61− self.assertEqual(results[0]['title'], 'Name - File.CPP')
62− self.assertEqual(results[0]['url'], 'https://url')
63− self.assertEqual(results[0]['repository'], 'https://repo')
64− self.assertEqual(results[0]['code_language'], 'cpp')
65−
66− json = r"""
67− {"toto":[
68− {"id":200,"name":"Artist Name",
69− "link":"http:\/\/www.searchcode_code.com\/artist\/1217","type":"artist"}
70− ]}
71− """
72− response = mock.Mock(text=json)
73− results = searchcode_code.response(response)
74− self.assertEqual(type(results), list)
75− self.assertEqual(len(results), 0)
tests/unit/engines/test_searchcode_doc.pydeleted−70
@@ -1,70 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import searchcode_doc
4−from searx.testing import SearxTestCase
5−
6−
7−class TestSearchcodeDocEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = searchcode_doc.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16− self.assertIn('searchcode.com', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, searchcode_doc.response, None)
20− self.assertRaises(AttributeError, searchcode_doc.response, [])
21− self.assertRaises(AttributeError, searchcode_doc.response, '')
22− self.assertRaises(AttributeError, searchcode_doc.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(searchcode_doc.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(searchcode_doc.response(response), [])
29−
30− json = """
31− {
32− "matchterm": "test",
33− "previouspage": null,
34− "searchterm": "test",
35− "query": "test",
36− "total": 60,
37− "page": 0,
38− "nextpage": 1,
39− "results": [
40− {
41− "synopsis": "Synopsis",
42− "displayname": null,
43− "name": "test",
44− "url": "http://url",
45− "type": "Type",
46− "icon": null,
47− "namespace": "Namespace",
48− "description": "Description"
49− }
50− ]
51− }
52− """
53− response = mock.Mock(text=json)
54− results = searchcode_doc.response(response)
55− self.assertEqual(type(results), list)
56− self.assertEqual(len(results), 1)
57− self.assertEqual(results[0]['title'], '[Type] Namespace test')
58− self.assertEqual(results[0]['url'], 'http://url')
59− self.assertIn('Description', results[0]['content'])
60−
61− json = r"""
62− {"toto":[
63− {"id":200,"name":"Artist Name",
64− "link":"http:\/\/www.searchcode_doc.com\/artist\/1217","type":"artist"}
65− ]}
66− """
67− response = mock.Mock(text=json)
68− results = searchcode_doc.response(response)
69− self.assertEqual(type(results), list)
70− self.assertEqual(len(results), 0)
tests/unit/engines/test_seedpeer.pydeleted−66
@@ -1,66 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import seedpeer
5−from searx.testing import SearxTestCase
6−
7−
8−class TestBtdiggEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = seedpeer.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('seedpeer', params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, seedpeer.response, None)
21− self.assertRaises(AttributeError, seedpeer.response, [])
22− self.assertRaises(AttributeError, seedpeer.response, '')
23− self.assertRaises(AttributeError, seedpeer.response, '[]')
24−
25− response = mock.Mock(text='<html></html>')
26− self.assertEqual(seedpeer.response(response), [])
27−
28− html = u"""
29− <html>
30− <head>
31− <script></script>
32− <script type="text/javascript" src="not_here.js"></script>
33− <script type="text/javascript">
34− window.initialData=
35− {"data": {"list": [{"name": "Title", "seeds": "10", "peers": "20", "size": "1024", "hash": "abc123"}]}}
36− </script>
37− </head>
38− <body>
39− <table></table>
40− <table>
41− <thead><tr></tr></thead>
42− <tbody>
43− <tr>
44− <td><a href="link">Title</a></td>
45− <td>1 year</td>
46− <td>1 KB</td>
47− <td>10</td>
48− <td>20</td>
49− <td></td>
50− </tr>
51− </tbody>
52− </table>
53− </body>
54− </html>
55− """
56− response = mock.Mock(text=html)
57− results = seedpeer.response(response)
58− self.assertEqual(type(results), list)
59− self.assertEqual(len(results), 1)
60− self.assertEqual(results[0]['title'], 'Title')
61− self.assertEqual(results[0]['url'], 'https://seedpeer.me/link')
62− self.assertEqual(results[0]['seed'], 10)
63− self.assertEqual(results[0]['leech'], 20)
64− self.assertEqual(results[0]['filesize'], 1024)
65− self.assertEqual(results[0]['torrentfile'], 'https://seedpeer.me/torrent/abc123')
66− self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:abc123')
tests/unit/engines/test_soundcloud.pydeleted−192
@@ -1,192 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import soundcloud
4−from searx.testing import SearxTestCase
5−from searx.url_utils import quote_plus
6−
7−
8−class TestSoundcloudEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− params = soundcloud.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('soundcloud.com', params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, soundcloud.response, None)
21− self.assertRaises(AttributeError, soundcloud.response, [])
22− self.assertRaises(AttributeError, soundcloud.response, '')
23− self.assertRaises(AttributeError, soundcloud.response, '[]')
24−
25− response = mock.Mock(text='{}')
26− self.assertEqual(soundcloud.response(response), [])
27−
28− response = mock.Mock(text='{"data": []}')
29− self.assertEqual(soundcloud.response(response), [])
30−
31− json = """
32− {
33− "collection": [
34− {
35− "kind": "track",
36− "id": 159723640,
37− "created_at": "2014/07/22 00:51:21 +0000",
38− "user_id": 2976616,
39− "duration": 303780,
40− "commentable": true,
41− "state": "finished",
42− "original_content_size": 13236349,
43− "last_modified": "2015/01/31 15:14:50 +0000",
44− "sharing": "public",
45− "tag_list": "seekae flume",
46− "permalink": "seekae-test-recognise-flume-re-work",
47− "streamable": true,
48− "embeddable_by": "all",
49− "downloadable": true,
50− "purchase_url": "http://www.facebook.com/seekaemusic",
51− "label_id": null,
52− "purchase_title": "Seekae",
53− "genre": "freedownload",
54− "title": "This is the title",
55− "description": "This is the content",
56− "label_name": "Future Classic",
57− "release": "",
58− "track_type": "remix",
59− "key_signature": "",
60− "isrc": "",
61− "video_url": null,
62− "bpm": null,
63− "release_year": 2014,
64− "release_month": 7,
65− "release_day": 22,
66− "original_format": "mp3",
67− "license": "all-rights-reserved",
68− "uri": "https://api.soundcloud.com/tracks/159723640",
69− "user": {
70− "id": 2976616,
71− "kind": "user",
72− "permalink": "flume",
73− "username": "Flume",
74− "last_modified": "2014/11/24 19:21:29 +0000",
75− "uri": "https://api.soundcloud.com/users/2976616",
76− "permalink_url": "http://soundcloud.com/flume",
77− "avatar_url": "https://i1.sndcdn.com/avatars-000044475439-4zi7ii-large.jpg"
78− },
79− "permalink_url": "http://soundcloud.com/this.is.the.url",
80− "artwork_url": "https://i1.sndcdn.com/artworks-000085857162-xdxy5c-large.jpg",
81− "waveform_url": "https://w1.sndcdn.com/DWrL1lAN8BkP_m.png",
82− "stream_url": "https://api.soundcloud.com/tracks/159723640/stream",
83− "download_url": "https://api.soundcloud.com/tracks/159723640/download",
84− "playback_count": 2190687,
85− "download_count": 54856,
86− "favoritings_count": 49061,
87− "comment_count": 826,
88− "likes_count": 49061,
89− "reposts_count": 15910,
90− "attachments_uri": "https://api.soundcloud.com/tracks/159723640/attachments",
91− "policy": "ALLOW"
92− }
93− ],
94− "total_results": 375750,
95− "next_href": "https://api.soundcloud.com/search?&q=test",
96− "tx_id": ""
97− }
98− """
99− response = mock.Mock(text=json)
100− results = soundcloud.response(response)
101− self.assertEqual(type(results), list)
102− self.assertEqual(len(results), 1)
103− self.assertEqual(results[0]['title'], 'This is the title')
104− self.assertEqual(results[0]['url'], 'http://soundcloud.com/this.is.the.url')
105− self.assertEqual(results[0]['content'], 'This is the content')
106− self.assertIn(quote_plus('https://api.soundcloud.com/tracks/159723640'), results[0]['embedded'])
107−
108− json = """
109− {
110− "collection": [
111− {
112− "kind": "user",
113− "id": 159723640,
114− "created_at": "2014/07/22 00:51:21 +0000",
115− "user_id": 2976616,
116− "duration": 303780,
117− "commentable": true,
118− "state": "finished",
119− "original_content_size": 13236349,
120− "last_modified": "2015/01/31 15:14:50 +0000",
121− "sharing": "public",
122− "tag_list": "seekae flume",
123− "permalink": "seekae-test-recognise-flume-re-work",
124− "streamable": true,
125− "embeddable_by": "all",
126− "downloadable": true,
127− "purchase_url": "http://www.facebook.com/seekaemusic",
128− "label_id": null,
129− "purchase_title": "Seekae",
130− "genre": "freedownload",
131− "title": "This is the title",
132− "description": "This is the content",
133− "label_name": "Future Classic",
134− "release": "",
135− "track_type": "remix",
136− "key_signature": "",
137− "isrc": "",
138− "video_url": null,
139− "bpm": null,
140− "release_year": 2014,
141− "release_month": 7,
142− "release_day": 22,
143− "original_format": "mp3",
144− "license": "all-rights-reserved",
145− "uri": "https://api.soundcloud.com/tracks/159723640",
146− "user": {
147− "id": 2976616,
148− "kind": "user",
149− "permalink": "flume",
150− "username": "Flume",
151− "last_modified": "2014/11/24 19:21:29 +0000",
152− "uri": "https://api.soundcloud.com/users/2976616",
153− "permalink_url": "http://soundcloud.com/flume",
154− "avatar_url": "https://i1.sndcdn.com/avatars-000044475439-4zi7ii-large.jpg"
155− },
156− "permalink_url": "http://soundcloud.com/this.is.the.url",
157− "artwork_url": "https://i1.sndcdn.com/artworks-000085857162-xdxy5c-large.jpg",
158− "waveform_url": "https://w1.sndcdn.com/DWrL1lAN8BkP_m.png",
159− "stream_url": "https://api.soundcloud.com/tracks/159723640/stream",
160− "download_url": "https://api.soundcloud.com/tracks/159723640/download",
161− "playback_count": 2190687,
162− "download_count": 54856,
163− "favoritings_count": 49061,
164− "comment_count": 826,
165− "likes_count": 49061,
166− "reposts_count": 15910,
167− "attachments_uri": "https://api.soundcloud.com/tracks/159723640/attachments",
168− "policy": "ALLOW"
169− }
170− ],
171− "total_results": 375750,
172− "next_href": "https://api.soundcloud.com/search?&q=test",
173− "tx_id": ""
174− }
175− """
176− response = mock.Mock(text=json)
177− results = soundcloud.response(response)
178− self.assertEqual(type(results), list)
179− self.assertEqual(len(results), 0)
180−
181− json = """
182− {
183− "collection": [],
184− "total_results": 375750,
185− "next_href": "https://api.soundcloud.com/search?&q=test",
186− "tx_id": ""
187− }
188− """
189− response = mock.Mock(text=json)
190− results = soundcloud.response(response)
191− self.assertEqual(type(results), list)
192− self.assertEqual(len(results), 0)
tests/unit/engines/test_spotify.pydeleted−124
@@ -1,124 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import spotify
4−from searx.testing import SearxTestCase
5−
6−
7−class TestSpotifyEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = spotify.request(query, dicto)
14− self.assertIn('url', params)
15− self.assertIn(query, params['url'])
16− self.assertIn('spotify.com', params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, spotify.response, None)
20− self.assertRaises(AttributeError, spotify.response, [])
21− self.assertRaises(AttributeError, spotify.response, '')
22− self.assertRaises(AttributeError, spotify.response, '[]')
23−
24− response = mock.Mock(text='{}')
25− self.assertEqual(spotify.response(response), [])
26−
27− response = mock.Mock(text='{"data": []}')
28− self.assertEqual(spotify.response(response), [])
29−
30− json = """
31− {
32− "tracks": {
33− "href": "https://api.spotify.com/v1/search?query=nosfell&offset=0&limit=20&type=track",
34− "items": [
35− {
36− "album": {
37− "album_type": "album",
38− "external_urls": {
39− "spotify": "https://open.spotify.com/album/5c9ap1PBkSGLxT3J73toxA"
40− },
41− "href": "https://api.spotify.com/v1/albums/5c9ap1PBkSGLxT3J73toxA",
42− "id": "5c9ap1PBkSGLxT3J73toxA",
43− "name": "Album Title",
44− "type": "album",
45− "uri": "spotify:album:5c9ap1PBkSGLxT3J73toxA"
46− },
47− "artists": [
48− {
49− "external_urls": {
50− "spotify": "https://open.spotify.com/artist/0bMc6b75FfZEpQHG1jifKu"
51− },
52− "href": "https://api.spotify.com/v1/artists/0bMc6b75FfZEpQHG1jifKu",
53− "id": "0bMc6b75FfZEpQHG1jifKu",
54− "name": "Artist Name",
55− "type": "artist",
56− "uri": "spotify:artist:0bMc6b75FfZEpQHG1jifKu"
57− }
58− ],
59− "disc_number": 1,
60− "duration_ms": 202386,
61− "explicit": false,
62− "external_ids": {
63− "isrc": "FRV640600067"
64− },
65− "external_urls": {
66− "spotify": "https://open.spotify.com/track/2GzvFiedqW8hgqUpWcASZa"
67− },
68− "href": "https://api.spotify.com/v1/tracks/2GzvFiedqW8hgqUpWcASZa",
69− "id": "1000",
70− "is_playable": true,
71− "name": "Title of track",
72− "popularity": 6,
73− "preview_url": "https://p.scdn.co/mp3-preview/7b8ecda580965a066b768c2647f877e43f7b1a0a",
74− "track_number": 3,
75− "type": "track",
76− "uri": "spotify:track:2GzvFiedqW8hgqUpWcASZa"
77− }
78− ],
79− "limit": 20,
80− "next": "https://api.spotify.com/v1/search?query=nosfell&offset=20&limit=20&type=track",
81− "offset": 0,
82− "previous": null,
83− "total": 107
84− }
85− }
86− """
87− response = mock.Mock(text=json)
88− results = spotify.response(response)
89− self.assertEqual(type(results), list)
90− self.assertEqual(len(results), 1)
91− self.assertEqual(results[0]['title'], 'Title of track')
92− self.assertEqual(results[0]['url'], 'https://open.spotify.com/track/2GzvFiedqW8hgqUpWcASZa')
93− self.assertEqual(results[0]['content'], 'Artist Name - Album Title - Title of track')
94− self.assertIn('1000', results[0]['embedded'])
95−
96− json = """
97− {
98− "tracks": {
99− "href": "https://api.spotify.com/v1/search?query=nosfell&offset=0&limit=20&type=track",
100− "items": [
101− {
102− "href": "https://api.spotify.com/v1/tracks/2GzvFiedqW8hgqUpWcASZa",
103− "id": "1000",
104− "is_playable": true,
105− "name": "Title of track",
106− "popularity": 6,
107− "preview_url": "https://p.scdn.co/mp3-preview/7b8ecda580965a066b768c2647f877e43f7b1a0a",
108− "track_number": 3,
109− "type": "album",
110− "uri": "spotify:track:2GzvFiedqW8hgqUpWcASZa"
111− }
112− ],
113− "limit": 20,
114− "next": "https://api.spotify.com/v1/search?query=nosfell&offset=20&limit=20&type=track",
115− "offset": 0,
116− "previous": null,
117− "total": 107
118− }
119− }
120− """
121− response = mock.Mock(text=json)
122− results = spotify.response(response)
123− self.assertEqual(type(results), list)
124− self.assertEqual(len(results), 0)
tests/unit/engines/test_stackoverflow.pydeleted−106
@@ -1,106 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import stackoverflow
4−from searx.testing import SearxTestCase
5−
6−
7−class TestStackoverflowEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− params = stackoverflow.request(query, dicto)
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16− self.assertTrue('stackoverflow.com' in params['url'])
17−
18− def test_response(self):
19− self.assertRaises(AttributeError, stackoverflow.response, None)
20− self.assertRaises(AttributeError, stackoverflow.response, [])
21− self.assertRaises(AttributeError, stackoverflow.response, '')
22− self.assertRaises(AttributeError, stackoverflow.response, '[]')
23−
24− response = mock.Mock(text='<html></html>')
25− self.assertEqual(stackoverflow.response(response), [])
26−
27− html = """
28− <div class="question-summary search-result" id="answer-id-1783426">
29− <div class="statscontainer">
30− <div class="statsarrow"></div>
31− <div class="stats">
32− <div class="vote">
33− <div class="votes answered">
34− <span class="vote-count-post "><strong>2583</strong></span>
35− <div class="viewcount">votes</div>
36− </div>
37− </div>
38− </div>
39− </div>
40− <div class="summary">
41− <div class="result-link">
42− <span>
43− <a href="/questions/this.is.the.url"
44− data-searchsession="/questions"
45− title="Checkout remote Git branch">
46− This is the title
47− </a>
48− </span>
49− </div>
50− <div class="excerpt">
51− This is the content
52− </div>
53− <div class="tags user-tags t-git t-git-checkout t-remote-branch">
54− </div>
55− <div class="started fr">
56− answered <span title="2009-11-23 14:26:08Z" class="relativetime">nov 23 '09</span> by
57− <a href="/users/214090/hallski">hallski</a>
58− </div>
59− </div>
60− </div>
61− """
62− response = mock.Mock(text=html)
63− results = stackoverflow.response(response)
64− self.assertEqual(type(results), list)
65− self.assertEqual(len(results), 1)
66− self.assertEqual(results[0]['title'], 'This is the title')
67− self.assertEqual(results[0]['url'], 'https://stackoverflow.com/questions/this.is.the.url')
68− self.assertEqual(results[0]['content'], 'This is the content')
69−
70− html = """
71− <div class="statscontainer">
72− <div class="statsarrow"></div>
73− <div class="stats">
74− <div class="vote">
75− <div class="votes answered">
76− <span class="vote-count-post "><strong>2583</strong></span>
77− <div class="viewcount">votes</div>
78− </div>
79− </div>
80− </div>
81− </div>
82− <div class="summary">
83− <div class="result-link">
84− <span>
85− <a href="/questions/this.is.the.url"
86− data-searchsession="/questions"
87− title="Checkout remote Git branch">
88− This is the title
89− </a>
90− </span>
91− </div>
92− <div class="excerpt">
93− This is the content
94− </div>
95− <div class="tags user-tags t-git t-git-checkout t-remote-branch">
96− </div>
97− <div class="started fr">
98− answered <span title="2009-11-23 14:26:08Z" class="relativetime">nov 23 '09</span> by
99− <a href="/users/214090/hallski">hallski</a>
100− </div>
101− </div>
102− """
103− response = mock.Mock(text=html)
104− results = stackoverflow.response(response)
105− self.assertEqual(type(results), list)
106− self.assertEqual(len(results), 0)
tests/unit/engines/test_startpage.pydeleted−67
@@ -1,67 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import startpage
5−from searx.testing import SearxTestCase
6−
7−
8−class TestStartpageEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 1
14− dicto['language'] = 'fr_FR'
15− params = startpage.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn('startpage.com', params['url'])
18− self.assertIn('data', params)
19− self.assertIn('query', params['data'])
20− self.assertIn(query, params['data']['query'])
21−
22− dicto['language'] = 'all'
23− params = startpage.request(query, dicto)
24−
25− def test_response(self):
26− self.assertRaises(AttributeError, startpage.response, None)
27− self.assertRaises(AttributeError, startpage.response, [])
28− self.assertRaises(AttributeError, startpage.response, '')
29− self.assertRaises(AttributeError, startpage.response, '[]')
30−
31− response = mock.Mock(text='<html></html>')
32− self.assertEqual(startpage.response(response), [])
33−
34− html = """
35−<div class="w-gl__result">
36− <a
37− class="w-gl__result-title"
38− href="http://this.should.be.the.link/"
39− data-onw="1"
40− rel="noopener noreferrer"
41− target="_blank">
42−
43− <h3>This should be the title</h3>
44− </a>
45− <div class="w-gl__result-second-line-container">
46− <div class="w-gl__result-url-container">
47− <a
48− class="w-gl__result-url"
49− href="http://this.should.be.the.link/"
50− rel="noopener noreferrer"
51− target="_blank">https://www.cnbc.com/2019/10/12/dj-zedd-banned-in-china-for-liking-a-south-park-tweet.html</a>
52− </div>
53− <a
54− class="w-gl__anonymous-view-url"
55− href="https://eu-browse.startpage.com/do/proxy?ep=556b554d576b6f5054554546423167764b5445616455554d5342675441774659495246304848774f5267385453304941486b5949546c63704e33774f526b705544565647516d4a61554246304847674f4a556f6957415a4f436b455042426b6b4f7a64535a52784a56514a4f45307743446c567250445a4f4c52514e5677554e46776b4b545563704c7931554c5167465467644f42464d4f4255426f4d693152624634525741305845526c595746636b626d67494e42705743466c515252634f4267456e597a7346596b7856435134465345634f564249794b5752785643315863546769515773764a5163494c5877505246315865456f5141426b4f41774167596d6c5a4e30395758773442465251495677596c624770665a6b786344466b4151455663425249794d6a78525a55554157516f4342556766526b51314b57514e&amp;ek=4q58686o5047786n6343527259445247576p6o38&amp;ekdata=84abd523dc13cba5c65164d04d7d7263"
56− target="_blank">Anonymous View</a>
57− </div>
58− <p class="w-gl__description">This should be the content.</p>
59− </div>
60− """ # noqa
61− response = mock.Mock(text=html.encode('utf-8'))
62− results = startpage.response(response)
63− self.assertEqual(type(results), list)
64− self.assertEqual(len(results), 1)
65− self.assertEqual(results[0]['title'], 'This should be the title')
66− self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
67− self.assertEqual(results[0]['content'], 'This should be the content.')
tests/unit/engines/test_tokyotoshokan.pydeleted−110
@@ -1,110 +0,0 @@
1−import mock
2−from collections import defaultdict
3−from searx.engines import tokyotoshokan
4−from searx.testing import SearxTestCase
5−from datetime import datetime
6−
7−
8−class TestTokyotoshokanEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dic = defaultdict(dict)
13− dic['pageno'] = 1
14− params = tokyotoshokan.request(query, dic)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('tokyotosho.info' in params['url'])
18−
19− def test_response(self):
20− resp = mock.Mock(text='<html></html>')
21− self.assertEqual(tokyotoshokan.response(resp), [])
22−
23− html = """
24− <table class="listing">
25− <tbody>
26− <tr class="shade category_0">
27− <td rowspan="2">
28− <a href="/?cat=7"><span class="sprite_cat-raw"></span></a>
29− </td>
30− <td class="desc-top">
31− <a href="magnet:?xt=urn:btih:4c19eb46b5113685fbd2288ed2531b0b">
32− <span class="sprite_magnet"></span>
33− </a>
34− <a rel="nofollow" type="application/x-bittorrent" href="http://www.nyaa.se/f">
35− Koyomimonogatari
36− </a>
37− </td>
38− <td class="web"><a rel="nofollow" href="details.php?id=975700">Details</a></td>
39− </tr>
40− <tr class="shade category_0">
41− <td class="desc-bot">
42− Authorized: <span class="auth_ok">Yes</span>
43− Submitter: <a href="?username=Ohys">Ohys</a> |
44− Size: 10.5MB |
45− Date: 2016-03-26 16:41 UTC |
46− Comment: sample comment
47− </td>
48− <td style="color: #BBB; font-family: monospace" class="stats" align="right">
49− S: <span style="color: red">53</span>
50− L: <span style="color: red">18</span>
51− C: <span style="color: red">0</span>
52− ID: 975700
53− </td>
54− </tr>
55−
56− <tr class="category_0">
57− <td rowspan="2">
58− <a href="/?cat=7"><span class="sprite_cat-raw"></span></a>
59− </td>
60− <td class="desc-top">
61− <a rel="nofollow" type="application/x-bittorrent" href="http://google.com/q">
62− Owarimonogatari
63− </a>
64− </td>
65− <td class="web"><a rel="nofollow" href="details.php?id=975700">Details</a></td>
66− </tr>
67− <tr class="category_0">
68− <td class="desc-bot">
69− Submitter: <a href="?username=Ohys">Ohys</a> |
70− Size: 932.84EB |
71− Date: QWERTY-03-26 16:41 UTC
72− </td>
73− <td style="color: #BBB; font-family: monospace" class="stats" align="right">
74− S: <span style="color: red">0</span>
75− </td>
76− </tr>
77− </tbody>
78− </table>
79− """
80−
81− resp = mock.Mock(text=html)
82− results = tokyotoshokan.response(resp)
83−
84− self.assertEqual(type(results), list)
85− self.assertEqual(len(results), 2)
86−
87− # testing the first result, which has correct format
88− # and should have all information fields filled
89− r = results[0]
90− self.assertEqual(r['url'], 'http://www.nyaa.se/f')
91− self.assertEqual(r['title'], 'Koyomimonogatari')
92− self.assertEqual(r['magnetlink'], 'magnet:?xt=urn:btih:4c19eb46b5113685fbd2288ed2531b0b')
93− self.assertEqual(r['filesize'], int(1024 * 1024 * 10.5))
94− self.assertEqual(r['publishedDate'], datetime(2016, 3, 26, 16, 41))
95− self.assertEqual(r['content'], 'Comment: sample comment')
96− self.assertEqual(r['seed'], 53)
97− self.assertEqual(r['leech'], 18)
98−
99− # testing the second result, which does not include magnet link,
100− # seed & leech info, and has incorrect size & creation date
101− r = results[1]
102− self.assertEqual(r['url'], 'http://google.com/q')
103− self.assertEqual(r['title'], 'Owarimonogatari')
104−
105− self.assertFalse('magnetlink' in r)
106− self.assertFalse('filesize' in r)
107− self.assertFalse('content' in r)
108− self.assertFalse('publishedDate' in r)
109− self.assertFalse('seed' in r)
110− self.assertFalse('leech' in r)
tests/unit/engines/test_torrentz.pydeleted−87
@@ -1,87 +0,0 @@
1−import mock
2−from collections import defaultdict
3−from searx.engines import torrentz
4−from searx.testing import SearxTestCase
5−from datetime import datetime
6−
7−
8−class TestTorrentzEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dic = defaultdict(dict)
13− dic['pageno'] = 1
14− params = torrentz.request(query, dic)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('torrentz2.eu' in params['url'])
18−
19− def test_response(self):
20− resp = mock.Mock(text='<html></html>')
21− self.assertEqual(torrentz.response(resp), [])
22−
23− html = """
24− <div class="results">
25− <dl>
26− <dt>
27− <a href="/4362e08b1d80e1820fb2550b752f9f3126fe76d6">
28− Completely valid info
29− </a>
30− books ebooks
31− </dt>
32− <dd>
33− <span>1</span>
34− <span title="1503595924">5 hours</span>
35− <span>30 MB</span>
36− <span>14</span>
37− <span>1</span>
38− </dd>
39− </dl>
40−
41− <dl>
42− <dt>
43− <a href="/poaskdpokaspod">
44− Invalid hash and date and filesize
45− </a>
46− books ebooks
47− </dt>
48− <dd>
49− <span>1</span>
50− <span title="1503595924 aaa">5 hours</span>
51− <span>30MB</span>
52− <span>5,555</span>
53− <span>1,234,567</span>
54− </dd>
55− </dl>
56− </div>
57− """
58−
59− resp = mock.Mock(text=html)
60− results = torrentz.response(resp)
61−
62− self.assertEqual(type(results), list)
63− self.assertEqual(len(results), 2)
64−
65− # testing against the first result
66− r = results[0]
67− self.assertEqual(r['url'], 'https://torrentz2.eu/4362e08b1d80e1820fb2550b752f9f3126fe76d6')
68− self.assertEqual(r['title'], 'Completely valid info books ebooks')
69− # 22 Nov 2015 03:01:42
70− self.assertEqual(r['publishedDate'], datetime.fromtimestamp(1503595924))
71− self.assertEqual(r['seed'], 14)
72− self.assertEqual(r['leech'], 1)
73− self.assertEqual(r['filesize'], 30 * 1024 * 1024)
74− self.assertEqual(r['magnetlink'], 'magnet:?xt=urn:btih:4362e08b1d80e1820fb2550b752f9f3126fe76d6')
75−
76− # testing against the second result
77− r = results[1]
78− self.assertEqual(r['url'], 'https://torrentz2.eu/poaskdpokaspod')
79− self.assertEqual(r['title'], 'Invalid hash and date and filesize books ebooks')
80− self.assertEqual(r['seed'], 5555)
81− self.assertEqual(r['leech'], 1234567)
82−
83− # in the second result we have invalid hash, creation date & torrent size,
84− # so these tests should fail
85− self.assertFalse('magnetlink' in r)
86− self.assertFalse('filesize' in r)
87− self.assertFalse('publishedDate' in r)
tests/unit/engines/test_twitter.pydeleted−502
@@ -1,502 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import twitter
5−from searx.testing import SearxTestCase
6−
7−
8−class TestTwitterEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 0
14− dicto['language'] = 'fr_FR'
15− params = twitter.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18− self.assertIn('twitter.com', params['url'])
19− self.assertIn('cookies', params)
20− self.assertIn('lang', params['cookies'])
21− self.assertIn('fr', params['cookies']['lang'])
22−
23− dicto['language'] = 'all'
24− params = twitter.request(query, dicto)
25− self.assertIn('cookies', params)
26− self.assertIn('lang', params['cookies'])
27− self.assertIn('en', params['cookies']['lang'])
28−
29− def test_response(self):
30− self.assertRaises(AttributeError, twitter.response, None)
31− self.assertRaises(AttributeError, twitter.response, [])
32− self.assertRaises(AttributeError, twitter.response, '')
33− self.assertRaises(AttributeError, twitter.response, '[]')
34−
35− response = mock.Mock(text='<html></html>')
36− self.assertEqual(twitter.response(response), [])
37−
38− html = """
39− <li class="js-stream-item stream-item stream-item expanding-stream-item" data-item-id="563005573290287105"
40− id="stream-item-tweet-563005573290287105" data-item-type="tweet">
41− <div class="tweet original-tweet js-stream-tweet js-actionable-tweet js-profile-popup-actionable
42− js-original-tweet has-cards has-native-media" data-tweet-id="563005573290287105" data-disclosure-type=""
43− data-item-id="563005573290287105" data-screen-name="Jalopnik" data-name="Jalopnik"
44− data-user-id="3060631" data-has-native-media="true" data-has-cards="true" data-card-type="photo"
45− data-expanded-footer="&lt;div class=&quot;js-tweet-details-fixer
46− tweet-details-fixer&quot;&gt;&#10;&#10;&#10;
47− &lt;div class=&quot;cards-media-container js-media-container&quot;&gt;&lt;div
48− data-card-url=&quot;//twitter.com/Jalopnik/status/563005573290287105/photo/1&quot; data-card-type=&quot;
49− photo&quot; class=&quot;cards-base cards-multimedia&quot; data-element-context=&quot;platform_photo_card
50− &quot;&gt;&#10;&#10;&#10; &lt;a class=&quot;media media-thumbnail twitter-timeline-link is-preview
51− &quot; data-url=&quot;https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large&quot;
52− data-resolved-url-large=&quot;https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large&quot;
53− href=&quot;//twitter.com/Jalopnik/status/563005573290287105/photo/1&quot;&gt;&#10;
54− &lt;div class=&quot;&quot;&gt;&#10; &lt;img src=&quot;
55− https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg&quot;
56− alt=&quot;Embedded image permalink&quot; width=&quot;636&quot; height=&quot;309&quot;&gt;&#10;
57− &lt;/div&gt;&#10;&#10; &lt;/a&gt;&#10;&#10; &lt;div class=&quot;cards-content&quot;&gt;&#10;
58− &lt;div class=&quot;byline&quot;&gt;&#10; &#10; &lt;/div&gt;&#10; &#10; &lt;/div&gt;&#10;
59− &#10;&lt;/div&gt;&#10;&#10;&#10;&#10;&#10;&lt;/div&gt;&#10;&#10;&#10;&#10; &lt;div
60− class=&quot;js-machine-translated-tweet-container&quot;&gt;&lt;/div&gt;&#10; &lt;div
61− class=&quot;js-tweet-stats-container tweet-stats-container &quot;&gt;&#10; &lt;/div&gt;&#10;&#10;
62− &lt;div class=&quot;client-and-actions&quot;&gt;&#10; &lt;span class=&quot;metadata&quot;&gt;&#10;
63− &lt;span&gt;5:06 PM - 4 Feb 2015&lt;/span&gt;&#10;&#10; &amp;middot; &lt;a
64− class=&quot;permalink-link js-permalink js-nav&quot; href=&quot;/Jalopnik/status/563005573290287105
65− &quot;tabindex=&quot;-1&quot;&gt;Details&lt;/a&gt;&#10; &#10;&#10; &#10; &#10;
66− &#10;&#10; &lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&#10;&lt;/div&gt;&#10;" data-you-follow="false"
67− data-you-block="false">
68− <div class="context">
69− </div>
70− <div class="content">
71− <div class="stream-item-header">
72− <a class="account-group js-account-group js-action-profile js-user-profile-link js-nav"
73− href="/Jalopnik" data-user-id="3060631">
74− <img class="avatar js-action-profile-avatar"
75− src="https://pbs.twimg.com/profile_images/2976430168/5cd4a59_bigger.jpeg" alt="">
76− <strong class="fullname js-action-profile-name show-popup-with-id" data-aria-label-part>
77− Jalopnik
78− </strong>
79− <span>&rlm;</span>
80− <span class="username js-action-profile-name" data-aria-label-part>
81− <s>@</s><b>TitleName</b>
82− </span>
83− </a>
84− <small class="time">
85− <a href="/this.is.the.url"
86− class="tweet-timestamp js-permalink js-nav js-tooltip" title="5:06 PM - 4 Feb 2015" >
87− <span class="u-hiddenVisually" data-aria-label-part="last">17 minutes ago</span>
88− </a>
89− </small>
90− </div>
91− <p class="js-tweet-text tweet-text" lang="en" data-aria-label-part="0">
92− This is the content étude à€
93− <a href="http://t.co/nRWsqQAwBL" rel="nofollow" dir="ltr"
94− data-expanded-url="http://jalo.ps/ReMENu4" class="twitter-timeline-link"
95− target="_blank" title="http://jalo.ps/ReMENu4" >
96− <span class="tco-ellipsis">
97− </span>
98− <span class="invisible">http://</span><span class="js-display-url">link.in.tweet</span>
99− <span class="invisible"></span>
100− <span class="tco-ellipsis">
101− <span class="invisible">&nbsp;</span>
102− </span>
103− </a>
104− <a href="http://t.co/rbFsfeE0l3" class="twitter-timeline-link u-hidden"
105− data-pre-embedded="true" dir="ltr">
106− pic.twitter.com/rbFsfeE0l3
107− </a>
108− </p>
109− <div class="expanded-content js-tweet-details-dropdown">
110− </div>
111− <div class="stream-item-footer">
112− <a class="details with-icn js-details" href="/Jalopnik/status/563005573290287105">
113− <span class="Icon Icon--photo">
114− </span>
115− <b>
116− <span class="expand-stream-item js-view-details">
117− View photo
118− </span>
119− <span class="collapse-stream-item js-hide-details">
120− Hide photo
121− </span>
122− </b>
123− </a>
124− <span class="ProfileTweet-action--reply u-hiddenVisually">
125− <span class="ProfileTweet-actionCount" aria-hidden="true" data-tweet-stat-count="0">
126− <span class="ProfileTweet-actionCountForAria" >0 replies</span>
127− </span>
128− </span>
129− <span class="ProfileTweet-action--retweet u-hiddenVisually">
130− <span class="ProfileTweet-actionCount" data-tweet-stat-count="8">
131− <span class="ProfileTweet-actionCountForAria" data-aria-label-part>8 retweets</span>
132− </span>
133− </span>
134− <span class="ProfileTweet-action--favorite u-hiddenVisually">
135− <span class="ProfileTweet-actionCount" data-tweet-stat-count="14">
136− <span class="ProfileTweet-actionCountForAria" data-aria-label-part>14 favorites</span>
137− </span>
138− </span>
139− <div role="group" aria-label="Tweet actions" class="ProfileTweet-actionList u-cf js-actions">
140− <div class="ProfileTweet-action ProfileTweet-action--reply">
141− <button class="ProfileTweet-actionButton u-textUserColorHover js-actionButton
142− js-actionReply" data-modal="ProfileTweet-reply" type="button" title="Reply">
143− <span class="Icon Icon--reply">
144− </span>
145− <span class="u-hiddenVisually">Reply</span>
146− <span class="ProfileTweet-actionCount u-textUserColorHover
147− ProfileTweet-actionCount--isZero">
148− <span class="ProfileTweet-actionCountForPresentation" aria-hidden="true">
149− </span>
150− </span>
151− </button>
152− </div>
153− <div class="ProfileTweet-action ProfileTweet-action--retweet js-toggleState js-toggleRt">
154− <button class="ProfileTweet-actionButton js-actionButton js-actionRetweet js-tooltip"
155− title="Retweet" data-modal="ProfileTweet-retweet" type="button">
156− <span class="Icon Icon--retweet">
157− </span>
158− <span class="u-hiddenVisually">Retweet</span>
159− <span class="ProfileTweet-actionCount">
160− <span class="ProfileTweet-actionCountForPresentation">8</span>
161− </span>
162− </button>
163− <button class="ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet"
164− data-modal="ProfileTweet-retweet" title="Undo retweet" type="button">
165− <span class="Icon Icon--retweet">
166− </span>
167− <span class="u-hiddenVisually">Retweeted</span>
168− <span class="ProfileTweet-actionCount">
169− <span class="ProfileTweet-actionCountForPresentation">8</span>
170− </span>
171− </button>
172− </div>
173− <div class="ProfileTweet-action ProfileTweet-action--favorite js-toggleState">
174− <button class="ProfileTweet-actionButton js-actionButton js-actionFavorite js-tooltip"
175− title="Favorite" type="button">
176− <span class="Icon Icon--favorite">
177− </span>
178− <span class="u-hiddenVisually">Favorite</span>
179− <span class="ProfileTweet-actionCount">
180− <span class="ProfileTweet-actionCountForPresentation">14</span>
181− </span>
182− </button>
183− <button class="ProfileTweet-actionButtonUndo u-linkClean js-actionButton
184− js-actionFavorite" title="Undo favorite" type="button">
185− <span class="Icon Icon--favorite">
186− </span>
187− <span class="u-hiddenVisually">Favorited</span>
188− <span class="ProfileTweet-actionCount">
189− <span class="ProfileTweet-actionCountForPresentation">
190− 14
191− </span>
192− </span>
193− </button>
194− </div>
195− <div class="ProfileTweet-action ProfileTweet-action--more js-more-ProfileTweet-actions">
196− <div class="dropdown">
197− <button class="ProfileTweet-actionButton u-textUserColorHover dropdown-toggle
198− js-tooltip js-dropdown-toggle" type="button" title="More">
199− <span class="Icon Icon--dots">
200− </span>
201− <span class="u-hiddenVisually">More</span>
202− </button>
203− <div class="dropdown-menu">
204− <div class="dropdown-caret">
205− <div class="caret-outer">
206− </div>
207− <div class="caret-inner">
208− </div>
209− </div>
210− <ul>
211− <li class="share-via-dm js-actionShareViaDM" data-nav="share_tweet_dm">
212− <button type="button" class="dropdown-link">
213− Share via Direct Message
214− </button>
215− </li>
216− <li class="embed-link js-actionEmbedTweet" data-nav="embed_tweet">
217− <button type="button" class="dropdown-link">
218− Embed Tweet
219− </button>
220− </li>
221− <li class="mute-user-item pretty-link">
222− <button type="button" class="dropdown-link">
223− Mute
224− </button>
225− </li>
226− <li class="unmute-user-item pretty-link">
227− <button type="button" class="dropdown-link">
228− Unmute
229− </button>
230− </li>
231− <li class="block-or-report-link js-actionBlockOrReport"
232− data-nav="block_or_report">
233− <button type="button" class="dropdown-link">
234− Block or report
235− </button>
236− </li>
237− </ul>
238− </div>
239− </div>
240− </div>
241− </div>
242− </div>
243− </div>
244− </div>
245− </li>
246− """
247− response = mock.Mock(text=html)
248− results = twitter.response(response)
249− self.assertEqual(type(results), list)
250− self.assertEqual(len(results), 1)
251− self.assertEqual(results[0]['title'], '@TitleName')
252− self.assertEqual(results[0]['url'], 'https://twitter.com/this.is.the.url')
253− self.assertIn(u'This is the content', results[0]['content'])
254− # self.assertIn(u'This is the content étude à€', results[0]['content'])
255−
256− html = """
257− <li class="js-stream-item stream-item stream-item expanding-stream-item" data-item-id="563005573290287105"
258− id="stream-item-tweet-563005573290287105" data-item-type="tweet">
259− <div class="tweet original-tweet js-stream-tweet js-actionable-tweet js-profile-popup-actionable
260− js-original-tweet has-cards has-native-media" data-tweet-id="563005573290287105" data-disclosure-type=""
261− data-item-id="563005573290287105" data-screen-name="Jalopnik" data-name="Jalopnik"
262− data-user-id="3060631" data-has-native-media="true" data-has-cards="true" data-card-type="photo"
263− data-expanded-footer="&lt;div class=&quot;js-tweet-details-fixer
264− tweet-details-fixer&quot;&gt;&#10;&#10;&#10;
265− &lt;div class=&quot;cards-media-container js-media-container&quot;&gt;&lt;div
266− data-card-url=&quot;//twitter.com/Jalopnik/status/563005573290287105/photo/1&quot; data-card-type=&quot;
267− photo&quot; class=&quot;cards-base cards-multimedia&quot; data-element-context=&quot;platform_photo_card
268− &quot;&gt;&#10;&#10;&#10; &lt;a class=&quot;media media-thumbnail twitter-timeline-link is-preview
269− &quot; data-url=&quot;https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large&quot;
270− data-resolved-url-large=&quot;https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large&quot;
271− href=&quot;//twitter.com/Jalopnik/status/563005573290287105/photo/1&quot;&gt;&#10;
272− &lt;div class=&quot;&quot;&gt;&#10; &lt;img src=&quot;
273− https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg&quot;
274− alt=&quot;Embedded image permalink&quot; width=&quot;636&quot; height=&quot;309&quot;&gt;&#10;
275− &lt;/div&gt;&#10;&#10; &lt;/a&gt;&#10;&#10; &lt;div class=&quot;cards-content&quot;&gt;&#10;
276− &lt;div class=&quot;byline&quot;&gt;&#10; &#10; &lt;/div&gt;&#10; &#10; &lt;/div&gt;&#10;
277− &#10;&lt;/div&gt;&#10;&#10;&#10;&#10;&#10;&lt;/div&gt;&#10;&#10;&#10;&#10; &lt;div
278− class=&quot;js-machine-translated-tweet-container&quot;&gt;&lt;/div&gt;&#10; &lt;div
279− class=&quot;js-tweet-stats-container tweet-stats-container &quot;&gt;&#10; &lt;/div&gt;&#10;&#10;
280− &lt;div class=&quot;client-and-actions&quot;&gt;&#10; &lt;span class=&quot;metadata&quot;&gt;&#10;
281− &lt;span&gt;5:06 PM - 4 Feb 2015&lt;/span&gt;&#10;&#10; &amp;middot; &lt;a
282− class=&quot;permalink-link js-permalink js-nav&quot; href=&quot;/Jalopnik/status/563005573290287105
283− &quot;tabindex=&quot;-1&quot;&gt;Details&lt;/a&gt;&#10; &#10;&#10; &#10; &#10;
284− &#10;&#10; &lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&#10;&lt;/div&gt;&#10;" data-you-follow="false"
285− data-you-block="false">
286− <div class="context">
287− </div>
288− <div class="content">
289− <div class="stream-item-header">
290− <a class="account-group js-account-group js-action-profile js-user-profile-link js-nav"
291− href="/Jalopnik" data-user-id="3060631">
292− <img class="avatar js-action-profile-avatar"
293− src="https://pbs.twimg.com/profile_images/2976430168/5cd4a59_bigger.jpeg" alt="">
294− <strong class="fullname js-action-profile-name show-popup-with-id" data-aria-label-part>
295− Jalopnik
296− </strong>
297− <span>&rlm;</span>
298− <span class="username js-action-profile-name" data-aria-label-part>
299− <s>@</s><b>TitleName</b>
300− </span>
301− </a>
302− <small class="time">
303− <a href="/this.is.the.url"
304− class="tweet-timestamp js-permalink js-nav js-tooltip" title="5:06 PM - 4 Feb 2015" >
305− <span class="_timestamp js-short-timestamp js-relative-timestamp" data-time="1423065963"
306− data-time-ms="1423065963000" data-long-form="true" aria-hidden="true">
307− 17m
308− </span>
309− <span class="u-hiddenVisually" data-aria-label-part="last">17 minutes ago</span>
310− </a>
311− </small>
312− </div>
313− <p class="js-tweet-text tweet-text" lang="en" data-aria-label-part="0">
314− This is the content étude à€
315− <a href="http://t.co/nRWsqQAwBL" rel="nofollow" dir="ltr"
316− data-expanded-url="http://jalo.ps/ReMENu4" class="twitter-timeline-link"
317− target="_blank" title="http://jalo.ps/ReMENu4" >
318− <span class="tco-ellipsis">
319− </span>
320− <span class="invisible">http://</span><span class="js-display-url">link.in.tweet</span>
321− <span class="invisible"></span>
322− <span class="tco-ellipsis">
323− <span class="invisible">&nbsp;</span>
324− </span>
325− </a>
326− <a href="http://t.co/rbFsfeE0l3" class="twitter-timeline-link u-hidden"
327− data-pre-embedded="true" dir="ltr">
328− pic.twitter.com/rbFsfeE0l3
329− </a>
330− </p>
331− <div class="expanded-content js-tweet-details-dropdown">
332− </div>
333− <div class="stream-item-footer">
334− <a class="details with-icn js-details" href="/Jalopnik/status/563005573290287105">
335− <span class="Icon Icon--photo">
336− </span>
337− <b>
338− <span class="expand-stream-item js-view-details">
339− View photo
340− </span>
341− <span class="collapse-stream-item js-hide-details">
342− Hide photo
343− </span>
344− </b>
345− </a>
346− <span class="ProfileTweet-action--reply u-hiddenVisually">
347− <span class="ProfileTweet-actionCount" aria-hidden="true" data-tweet-stat-count="0">
348− <span class="ProfileTweet-actionCountForAria" >0 replies</span>
349− </span>
350− </span>
351− <span class="ProfileTweet-action--retweet u-hiddenVisually">
352− <span class="ProfileTweet-actionCount" data-tweet-stat-count="8">
353− <span class="ProfileTweet-actionCountForAria" data-aria-label-part>8 retweets</span>
354− </span>
355− </span>
356− <span class="ProfileTweet-action--favorite u-hiddenVisually">
357− <span class="ProfileTweet-actionCount" data-tweet-stat-count="14">
358− <span class="ProfileTweet-actionCountForAria" data-aria-label-part>14 favorites</span>
359− </span>
360− </span>
361− <div role="group" aria-label="Tweet actions" class="ProfileTweet-actionList u-cf js-actions">
362− <div class="ProfileTweet-action ProfileTweet-action--reply">
363− <button class="ProfileTweet-actionButton u-textUserColorHover js-actionButton
364− js-actionReply" data-modal="ProfileTweet-reply" type="button" title="Reply">
365− <span class="Icon Icon--reply">
366− </span>
367− <span class="u-hiddenVisually">Reply</span>
368− <span class="ProfileTweet-actionCount u-textUserColorHover
369− ProfileTweet-actionCount--isZero">
370− <span class="ProfileTweet-actionCountForPresentation" aria-hidden="true">
371− </span>
372− </span>
373− </button>
374− </div>
375− <div class="ProfileTweet-action ProfileTweet-action--retweet js-toggleState js-toggleRt">
376− <button class="ProfileTweet-actionButton js-actionButton js-actionRetweet js-tooltip"
377− title="Retweet" data-modal="ProfileTweet-retweet" type="button">
378− <span class="Icon Icon--retweet">
379− </span>
380− <span class="u-hiddenVisually">Retweet</span>
381− <span class="ProfileTweet-actionCount">
382− <span class="ProfileTweet-actionCountForPresentation">8</span>
383− </span>
384− </button>
385− <button class="ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet"
386− data-modal="ProfileTweet-retweet" title="Undo retweet" type="button">
387− <span class="Icon Icon--retweet">
388− </span>
389− <span class="u-hiddenVisually">Retweeted</span>
390− <span class="ProfileTweet-actionCount">
391− <span class="ProfileTweet-actionCountForPresentation">8</span>
392− </span>
393− </button>
394− </div>
395− <div class="ProfileTweet-action ProfileTweet-action--favorite js-toggleState">
396− <button class="ProfileTweet-actionButton js-actionButton js-actionFavorite js-tooltip"
397− title="Favorite" type="button">
398− <span class="Icon Icon--favorite">
399− </span>
400− <span class="u-hiddenVisually">Favorite</span>
401− <span class="ProfileTweet-actionCount">
402− <span class="ProfileTweet-actionCountForPresentation">14</span>
403− </span>
404− </button>
405− <button class="ProfileTweet-actionButtonUndo u-linkClean js-actionButton
406− js-actionFavorite" title="Undo favorite" type="button">
407− <span class="Icon Icon--favorite">
408− </span>
409− <span class="u-hiddenVisually">Favorited</span>
410− <span class="ProfileTweet-actionCount">
411− <span class="ProfileTweet-actionCountForPresentation">
412− 14
413− </span>
414− </span>
415− </button>
416− </div>
417− <div class="ProfileTweet-action ProfileTweet-action--more js-more-ProfileTweet-actions">
418− <div class="dropdown">
419− <button class="ProfileTweet-actionButton u-textUserColorHover dropdown-toggle
420− js-tooltip js-dropdown-toggle" type="button" title="More">
421− <span class="Icon Icon--dots">
422− </span>
423− <span class="u-hiddenVisually">More</span>
424− </button>
425− <div class="dropdown-menu">
426− <div class="dropdown-caret">
427− <div class="caret-outer">
428− </div>
429− <div class="caret-inner">
430− </div>
431− </div>
432− <ul>
433− <li class="share-via-dm js-actionShareViaDM" data-nav="share_tweet_dm">
434− <button type="button" class="dropdown-link">
435− Share via Direct Message
436− </button>
437− </li>
438− <li class="embed-link js-actionEmbedTweet" data-nav="embed_tweet">
439− <button type="button" class="dropdown-link">
440− Embed Tweet
441− </button>
442− </li>
443− <li class="mute-user-item pretty-link">
444− <button type="button" class="dropdown-link">
445− Mute
446− </button>
447− </li>
448− <li class="unmute-user-item pretty-link">
449− <button type="button" class="dropdown-link">
450− Unmute
451− </button>
452− </li>
453− <li class="block-or-report-link js-actionBlockOrReport"
454− data-nav="block_or_report">
455− <button type="button" class="dropdown-link">
456− Block or report
457− </button>
458− </li>
459− </ul>
460− </div>
461− </div>
462− </div>
463− </div>
464− </div>
465− </div>
466− </div>
467− </li>
468− """
469− response = mock.Mock(text=html)
470− results = twitter.response(response)
471− self.assertEqual(type(results), list)
472− self.assertEqual(len(results), 1)
473− self.assertEqual(results[0]['title'], '@TitleName')
474− self.assertEqual(results[0]['url'], 'https://twitter.com/this.is.the.url')
475− self.assertIn(u'This is the content', results[0]['content'])
476−
477− html = """
478− <li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
479− <div Class="sa_mc">
480− <div class="sb_tlst">
481− <h2>
482− <a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
483− <strong>This</strong> should be the title</a>
484− </h2>
485− </div>
486− <div class="sb_meta">
487− <cite>
488− <strong>this</strong>.meta.com</cite>
489− <span class="c_tlbxTrg">
490− <span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
491− </span>
492− </span>
493− </div>
494− <p>
495− <strong>This</strong> should be the content.</p>
496− </div>
497− </li>
498− """
499− response = mock.Mock(text=html)
500− results = twitter.response(response)
501− self.assertEqual(type(results), list)
502− self.assertEqual(len(results), 0)
tests/unit/engines/test_unsplash.pydeleted−38
@@ -1,38 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.testing import SearxTestCase
4−from searx.engines import unsplash
5−
6−
7−class TestUnsplashEngine(SearxTestCase):
8− def test_request(self):
9− query = 'penguin'
10− _dict = defaultdict(dict)
11− _dict['pageno'] = 1
12− params = unsplash.request(query, _dict)
13−
14− self.assertTrue('url' in params)
15− self.assertTrue(query in params['url'])
16−
17− def test_response(self):
18− resp = mock.Mock(text='{}')
19− result = unsplash.response(resp)
20− self.assertEqual([], result)
21−
22− resp.text = '{"results": []}'
23− result = unsplash.response(resp)
24− self.assertEqual([], result)
25−
26− # Sourced from https://unsplash.com/napi/search/photos?query=penguin&xp=&per_page=20&page=2
27− with open('./tests/unit/engines/unsplash_fixture.json') as fixture:
28− resp.text = fixture.read()
29−
30− result = unsplash.response(resp)
31− self.assertEqual(len(result), 2)
32− self.assertEqual(result[0]['title'], 'low angle photography of swimming penguin')
33− self.assertEqual(result[0]['url'], 'https://unsplash.com/photos/FY8d721UO_4')
34− self.assertEqual(result[0]['thumbnail_src'], 'https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&q=80\
35−&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max')
36− self.assertEqual(result[0]['img_src'], 'https://images.unsplash.com/photo-1523557148507-1b77641c7e7c\
37−?ixlib=rb-0.3.5')
38− self.assertEqual(result[0]['content'], '')
tests/unit/engines/test_vimeo.pydeleted−36
@@ -1,36 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import vimeo
5−from searx.testing import SearxTestCase
6−
7−
8−class TestVimeoEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 0
14− params = vimeo.request(query, dicto)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertTrue('vimeo.com' in params['url'])
18−
19− def test_response(self):
20− self.assertRaises(AttributeError, vimeo.response, None)
21− self.assertRaises(AttributeError, vimeo.response, [])
22− self.assertRaises(AttributeError, vimeo.response, '')
23− self.assertRaises(AttributeError, vimeo.response, '[]')
24−
25− json = u"""
26−{"filtered":{"total":274641,"page":1,"per_page":18,"paging":{"next":"?sizes=590x332&page=2","previous":null,"first":"?sizes=590x332&page=1","last":"?sizes=590x332&page=15258"},"data":[{"is_staffpick":false,"is_featured":true,"type":"clip","clip":{"uri":"\\/videos\\/106557563","name":"Hot Rod Revue: The South","link":"https:\\/\\/vimeo.com\\/106557563","duration":4069,"created_time":"2014-09-19T03:38:04+00:00","privacy":{"view":"ptv"},"pictures":{"sizes":[{"width":"590","height":"332","link":"https:\\/\\/i.vimeocdn.com\\/video\\/489717884_590x332.jpg?r=pad","link_with_play_button":"https:\\/\\/i.vimeocdn.com\\/filter\\/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F489717884_590x332.jpg&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"}]},"stats":{"plays":null},"metadata":{"connections":{"comments":{"total":0},"likes":{"total":5}},"interactions":[]},"user":{"name":"Cal Thorley","link":"https:\\/\\/vimeo.com\\/calthorley","pictures":{"sizes":[{"width":30,"height":30,"link":"https:\\/\\/i.vimeocdn.com\\/portrait\\/2545308_30x30?r=pad"},{"width":75,"height":75,"link":"https:\\/\\/i.vimeocdn.com\\/portrait\\/2545308_75x75?r=pad"},{"width":100,"height":100,"link":"https:\\/\\/i.vimeocdn.com\\/portrait\\/2545308_100x100?r=pad"},{"width":300,"height":300,"link":"https:\\/\\/i.vimeocdn.com\\/portrait\\/2545308_300x300?r=pad"}]}}}}]}};
27−
28−""" # noqa
29− response = mock.Mock(text=json)
30− results = vimeo.response(response)
31− self.assertEqual(type(results), list)
32− self.assertEqual(len(results), 1)
33− self.assertEqual(results[0]['title'], u'Hot Rod Revue: The South')
34− self.assertEqual(results[0]['url'], 'https://vimeo.com/106557563')
35− self.assertEqual(results[0]['content'], '')
36− self.assertEqual(results[0]['thumbnail'], 'https://i.vimeocdn.com/video/489717884_590x332.jpg?r=pad')
tests/unit/engines/test_wikidata.pydeleted−514
@@ -1,514 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from lxml.html import fromstring
3−from lxml import etree
4−from collections import defaultdict
5−import mock
6−from searx.engines import wikidata
7−from searx.testing import SearxTestCase
8−
9−
10−class TestWikidataEngine(SearxTestCase):
11−
12− def test_request(self):
13− query = 'test_query'
14− dicto = defaultdict(dict)
15− dicto['language'] = 'all'
16− params = wikidata.request(query, dicto)
17− self.assertIn('url', params)
18− self.assertIn(query, params['url'])
19− self.assertIn('wikidata.org', params['url'])
20−
21− dicto['language'] = 'es_ES'
22− params = wikidata.request(query, dicto)
23− self.assertIn(query, params['url'])
24−
25− # successful cases are not tested here to avoid sending additional requests
26− def test_response(self):
27− self.assertRaises(AttributeError, wikidata.response, None)
28− self.assertRaises(AttributeError, wikidata.response, [])
29− self.assertRaises(AttributeError, wikidata.response, '')
30− self.assertRaises(AttributeError, wikidata.response, '[]')
31−
32− wikidata.supported_languages = ['en', 'es']
33− wikidata.language_aliases = {}
34− response = mock.Mock(content='<html></html>'.encode("utf-8"), search_params={"language": "en"})
35− self.assertEqual(wikidata.response(response), [])
36−
37− def test_getDetail(self):
38− response = {}
39− results = wikidata.getDetail(response, "Q123", "en", "en-US", etree.HTMLParser())
40− self.assertEqual(results, [])
41−
42− title_html = '<div><div class="wikibase-title-label">Test</div></div>'
43− html = """
44− <div>
45− <div class="wikibase-entitytermsview-heading-description">
46− </div>
47− <div>
48− <ul class="wikibase-sitelinklistview-listview">
49− <li data-wb-siteid="enwiki"><a href="http://en.wikipedia.org/wiki/Test">Test</a></li>
50− </ul>
51− </div>
52− </div>
53− """
54− response = {"parse": {"displaytitle": title_html, "text": html}}
55−
56− results = wikidata.getDetail(response, "Q123", "en", "en-US", etree.HTMLParser())
57− self.assertEqual(len(results), 1)
58− self.assertEqual(results[0]['url'], 'https://en.wikipedia.org/wiki/Test')
59−
60− title_html = """
61− <div>
62− <div class="wikibase-title-label">
63− <span lang="en">Test</span>
64− <sup class="wb-language-fallback-indicator">English</sup>
65− </div>
66− </div>
67− """
68− html = """
69− <div>
70− <div class="wikibase-entitytermsview-heading-description">
71− <span lang="en">Description</span>
72− <sup class="wb-language-fallback-indicator">English</sup>
73− </div>
74− <div id="P856">
75− <div class="wikibase-statementgroupview-property-label">
76− <a href="/wiki/Property:P856">
77− <span lang="en">official website</span>
78− <sup class="wb-language-fallback-indicator">English</sup>
79− </a>
80− </div>
81− <div class="wikibase-statementview-mainsnak">
82− <a class="external free" href="https://officialsite.com">
83− https://officialsite.com
84− </a>
85− </div>
86− </div>
87− <div>
88− <ul class="wikibase-sitelinklistview-listview">
89− <li data-wb-siteid="enwiki"><a href="http://en.wikipedia.org/wiki/Test">Test</a></li>
90− </ul>
91− </div>
92− </div>
93− """
94− response = {"parse": {"displaytitle": title_html, "text": html}}
95−
96− results = wikidata.getDetail(response, "Q123", "yua", "yua_MX", etree.HTMLParser())
97− self.assertEqual(len(results), 2)
98− self.assertEqual(results[0]['title'], 'Official website')
99− self.assertEqual(results[0]['url'], 'https://officialsite.com')
100−
101− self.assertEqual(results[1]['infobox'], 'Test')
102− self.assertEqual(results[1]['id'], None)
103− self.assertEqual(results[1]['content'], 'Description')
104− self.assertEqual(results[1]['attributes'], [])
105− self.assertEqual(results[1]['urls'][0]['title'], 'Official website')
106− self.assertEqual(results[1]['urls'][0]['url'], 'https://officialsite.com')
107− self.assertEqual(results[1]['urls'][1]['title'], 'Wikipedia (en)')
108− self.assertEqual(results[1]['urls'][1]['url'], 'https://en.wikipedia.org/wiki/Test')
109−
110− def test_add_image(self):
111− image_src = wikidata.add_image(fromstring("<div></div>"))
112− self.assertEqual(image_src, None)
113−
114− html = u"""
115− <div>
116− <div id="P18">
117− <div class="wikibase-statementgroupview-property-label">
118− <a href="/wiki/Property:P18">
119− image
120− </a>
121− </div>
122− <div class="wikibase-statementlistview">
123− <div class="wikibase-statementview listview-item">
124− <div class="wikibase-statementview-rankselector">
125− <span class="wikibase-rankselector-normal"></span>
126− </div>
127− <div class="wikibase-statementview-mainsnak">
128− <div>
129− <div class="wikibase-snakview-value">
130− <div class="commons-media-caption">
131− <a href="https://commons.wikimedia.org/wiki/File:image.png">image.png</a>
132− <br/>2,687 &#215; 3,356; 1.22 MB
133− </div>
134− </div>
135− </div>
136− </div>
137− </div>
138− </div>
139− </div>
140− </div>
141− """
142− html_etree = fromstring(html)
143− id_cache = wikidata.get_id_cache(html_etree)
144− image_src = wikidata.add_image(id_cache)
145− self.assertEqual(image_src,
146− "https://commons.wikimedia.org/wiki/Special:FilePath/image.png?width=500&height=400")
147−
148− html = u"""
149− <div>
150− <div id="P2910">
151− <div class="wikibase-statementgroupview-property-label">
152− <a href="/wiki/Property:P2910">
153− icon
154− </a>
155− </div>
156− <div class="wikibase-statementlistview">
157− <div class="wikibase-statementview listview-item">
158− <div class="wikibase-statementview-rankselector">
159− <span class="wikibase-rankselector-normal"></span>
160− </div>
161− <div class="wikibase-statementview-mainsnak">
162− <div>
163− <div class="wikibase-snakview-value">
164− <div class="commons-media-caption">
165− <a href="https://commons.wikimedia.org/wiki/File:icon.png">icon.png</a>
166− <br/>671 &#215; 671; 18 KB</div>
167− </div>
168− </div>
169− </div>
170− </div>
171− </div>
172− </div>
173− </div>
174− <div id="P154">
175− <div class="wikibase-statementgroupview-property-label">
176− <a href="/wiki/Property:P154">
177− logo
178− </a>
179− </div>
180− <div class="wikibase-statementlistview">
181− <div class="wikibase-statementview listview-item">
182− <div class="wikibase-statementview-rankselector">
183− <span class="wikibase-rankselector-normal"></span>
184− </div>
185− <div class="wikibase-statementview-mainsnak">
186− <div>
187− <div class="wikibase-snakview-value">
188− <div class="commons-media-caption">
189− <a href="https://commons.wikimedia.org/wiki/File:logo.png">logo.png</a>
190− <br/>170 &#215; 170; 1 KB
191− </div>
192− </div>
193− </div>
194− </div>
195− </div>
196− </div>
197− </div>
198− </div>
199− """
200− html_etree = fromstring(html)
201− id_cache = wikidata.get_id_cache(html_etree)
202−
203− image_src = wikidata.add_image(id_cache)
204− self.assertEqual(image_src,
205− "https://commons.wikimedia.org/wiki/Special:FilePath/logo.png?width=500&height=400")
206−
207− def test_add_attribute(self):
208− html = u"""
209− <div>
210− <div id="P27">
211− <div class="wikibase-statementgroupview-property-label">
212− <a href="/wiki/Property:P27">
213− country of citizenship
214− </a>
215− </div>
216− <div class="wikibase-statementlistview">
217− <div class="wikibase-statementview listview-item">
218− <div class="wikibase-statementview-rankselector">
219− <span class="wikibase-rankselector-normal"></span>
220− </div>
221− <div class="wikibase-statementview-mainsnak">
222− <div>
223− <div class="wikibase-snakview-value">
224− <a href="/wiki/Q145">
225− United Kingdom
226− </a>
227− </div>
228− </div>
229− </div>
230− </div>
231− </div>
232− </div>
233− </div>
234− """
235− attributes = []
236− html_etree = fromstring(html)
237− id_cache = wikidata.get_id_cache(html_etree)
238−
239− wikidata.add_attribute(attributes, id_cache, "Fail")
240− self.assertEqual(attributes, [])
241−
242− wikidata.add_attribute(attributes, id_cache, "P27")
243− self.assertEqual(len(attributes), 1)
244− self.assertEqual(attributes[0]["label"], "Country of citizenship")
245− self.assertEqual(attributes[0]["value"], "United Kingdom")
246−
247− html = u"""
248− <div>
249− <div id="P569">
250− <div class="wikibase-statementgroupview-property-label">
251− <a href="/wiki/Property:P569">
252− date of birth
253− </a>
254− </div>
255− <div class="wikibase-statementlistview">
256− <div class="wikibase-statementview listview-item">
257− <div class="wikibase-statementview-rankselector">
258− <span class="wikibase-rankselector-normal"></span>
259− </div>
260− <div class="wikibase-statementview-mainsnak">
261− <div>
262− <div class="wikibase-snakview-value">
263− 27 January 1832
264− <sup class="wb-calendar-name">
265− Gregorian
266− </sup>
267− </div>
268− </div>
269− </div>
270− </div>
271− </div>
272− </div>
273− </div>
274− """
275− attributes = []
276− html_etree = fromstring(html)
277− id_cache = wikidata.get_id_cache(html_etree)
278− wikidata.add_attribute(attributes, id_cache, "P569", date=True)
279− self.assertEqual(len(attributes), 1)
280− self.assertEqual(attributes[0]["label"], "Date of birth")
281− self.assertEqual(attributes[0]["value"], "27 January 1832")
282−
283− html = u"""
284− <div>
285− <div id="P6">
286− <div class="wikibase-statementgroupview-property-label">
287− <a href="/wiki/Property:P27">
288− head of government
289− </a>
290− </div>
291− <div class="wikibase-statementlistview">
292− <div class="wikibase-statementview listview-item">
293− <div class="wikibase-statementview-rankselector">
294− <span class="wikibase-rankselector-normal"></span>
295− </div>
296− <div class="wikibase-statementview-mainsnak">
297− <div>
298− <div class="wikibase-snakview-value">
299− <a href="/wiki/Q206">
300− Old Prime Minister
301− </a>
302− </div>
303− </div>
304− </div>
305− </div>
306− <div class="wikibase-statementview listview-item">
307− <div class="wikibase-statementview-rankselector">
308− <span class="wikibase-rankselector-preferred"></span>
309− </div>
310− <div class="wikibase-statementview-mainsnak">
311− <div>
312− <div class="wikibase-snakview-value">
313− <a href="/wiki/Q3099714">
314− Actual Prime Minister
315− </a>
316− </div>
317− </div>
318− </div>
319− </div>
320− </div>
321− </div>
322− </div>
323− """
324− attributes = []
325− html_etree = fromstring(html)
326− id_cache = wikidata.get_id_cache(html_etree)
327− wikidata.add_attribute(attributes, id_cache, "P6")
328− self.assertEqual(len(attributes), 1)
329− self.assertEqual(attributes[0]["label"], "Head of government")
330− self.assertEqual(attributes[0]["value"], "Old Prime Minister, Actual Prime Minister")
331−
332− attributes = []
333− html_etree = fromstring(html)
334− id_cache = wikidata.get_id_cache(html_etree)
335− wikidata.add_attribute(attributes, id_cache, "P6", trim=True)
336− self.assertEqual(len(attributes), 1)
337− self.assertEqual(attributes[0]["value"], "Actual Prime Minister")
338−
339− def test_add_url(self):
340− html = u"""
341− <div>
342− <div id="P856">
343− <div class="wikibase-statementgroupview-property-label">
344− <a href="/wiki/Property:P856">
345− official website
346− </a>
347− </div>
348− <div class="wikibase-statementlistview">
349− <div class="wikibase-statementview listview-item">
350− <div class="wikibase-statementview-mainsnak">
351− <div>
352− <div class="wikibase-snakview-value">
353− <a class="external free" href="https://searx.me">
354− https://searx.me/
355− </a>
356− </div>
357− </div>
358− </div>
359− </div>
360− </div>
361− </div>
362− </div>
363− """
364− urls = []
365− html_etree = fromstring(html)
366− id_cache = wikidata.get_id_cache(html_etree)
367− wikidata.add_url(urls, html_etree, id_cache, 'P856')
368− self.assertEquals(len(urls), 1)
369− self.assertIn({'title': 'Official website', 'url': 'https://searx.me/'}, urls)
370− urls = []
371− results = []
372− wikidata.add_url(urls, html_etree, id_cache, 'P856', 'custom label', results=results)
373− self.assertEquals(len(urls), 1)
374− self.assertEquals(len(results), 1)
375− self.assertIn({'title': 'custom label', 'url': 'https://searx.me/'}, urls)
376− self.assertIn({'title': 'custom label', 'url': 'https://searx.me/'}, results)
377−
378− html = u"""
379− <div>
380− <div id="P856">
381− <div class="wikibase-statementgroupview-property-label">
382− <a href="/wiki/Property:P856">
383− official website
384− </a>
385− </div>
386− <div class="wikibase-statementlistview">
387− <div class="wikibase-statementview listview-item">
388− <div class="wikibase-statementview-mainsnak">
389− <div>
390− <div class="wikibase-snakview-value">
391− <a class="external free" href="http://www.worldofwarcraft.com">
392− http://www.worldofwarcraft.com
393− </a>
394− </div>
395− </div>
396− </div>
397− </div>
398− <div class="wikibase-statementview listview-item">
399− <div class="wikibase-statementview-mainsnak">
400− <div>
401− <div class="wikibase-snakview-value">
402− <a class="external free" href="http://eu.battle.net/wow/en/">
403− http://eu.battle.net/wow/en/
404− </a>
405− </div>
406− </div>
407− </div>
408− </div>
409− </div>
410− </div>
411− </div>
412− """
413− urls = []
414− html_etree = fromstring(html)
415− id_cache = wikidata.get_id_cache(html_etree)
416− wikidata.add_url(urls, html_etree, id_cache, 'P856')
417− self.assertEquals(len(urls), 2)
418− self.assertIn({'title': 'Official website', 'url': 'http://www.worldofwarcraft.com'}, urls)
419− self.assertIn({'title': 'Official website', 'url': 'http://eu.battle.net/wow/en/'}, urls)
420−
421− def test_get_imdblink(self):
422− html = u"""
423− <div>
424− <div class="wikibase-statementview-mainsnak">
425− <div>
426− <div class="wikibase-snakview-value">
427− <a class="wb-external-id" href="http://www.imdb.com/tt0433664">
428− tt0433664
429− </a>
430− </div>
431− </div>
432− </div>
433− </div>
434− """
435− html_etree = fromstring(html)
436− imdblink = wikidata.get_imdblink(html_etree, 'https://www.imdb.com/')
437−
438− html = u"""
439− <div>
440− <div class="wikibase-statementview-mainsnak">
441− <div>
442− <div class="wikibase-snakview-value">
443− <a class="wb-external-id"
444− href="href="http://tools.wmflabs.org/...http://www.imdb.com/&id=nm4915994"">
445− nm4915994
446− </a>
447− </div>
448− </div>
449− </div>
450− </div>
451− """
452− html_etree = fromstring(html)
453− imdblink = wikidata.get_imdblink(html_etree, 'https://www.imdb.com/')
454− self.assertIn('https://www.imdb.com/name/nm4915994', imdblink)
455−
456− def test_get_geolink(self):
457− html = u"""
458− <div>
459− <div class="wikibase-statementview-mainsnak">
460− <div>
461− <div class="wikibase-snakview-value">
462− 60°N, 40°E
463− </div>
464− </div>
465− </div>
466− </div>
467− """
468− html_etree = fromstring(html)
469− geolink = wikidata.get_geolink(html_etree)
470− self.assertIn('https://www.openstreetmap.org/', geolink)
471− self.assertIn('lat=60&lon=40', geolink)
472−
473− html = u"""
474− <div>
475− <div class="wikibase-statementview-mainsnak">
476− <div>
477− <div class="wikibase-snakview-value">
478− 34°35'59"S, 58°22'55"W
479− </div>
480− </div>
481− </div>
482− </div>
483− """
484− html_etree = fromstring(html)
485− geolink = wikidata.get_geolink(html_etree)
486− self.assertIn('https://www.openstreetmap.org/', geolink)
487− self.assertIn('lat=-34.59', geolink)
488− self.assertIn('lon=-58.38', geolink)
489−
490− def test_get_wikilink(self):
491− html = """
492− <div>
493− <div>
494− <ul class="wikibase-sitelinklistview-listview">
495− <li data-wb-siteid="arwiki"><a href="http://ar.wikipedia.org/wiki/Test">Test</a></li>
496− <li data-wb-siteid="enwiki"><a href="http://en.wikipedia.org/wiki/Test">Test</a></li>
497− </ul>
498− </div>
499− <div>
500− <ul class="wikibase-sitelinklistview-listview">
501− <li data-wb-siteid="enwikiquote"><a href="https://en.wikiquote.org/wiki/Test">Test</a></li>
502− </ul>
503− </div>
504− </div>
505− """
506− html_etree = fromstring(html)
507− wikilink = wikidata.get_wikilink(html_etree, 'nowiki')
508− self.assertEqual(wikilink, None)
509− wikilink = wikidata.get_wikilink(html_etree, 'enwiki')
510− self.assertEqual(wikilink, 'https://en.wikipedia.org/wiki/Test')
511− wikilink = wikidata.get_wikilink(html_etree, 'arwiki')
512− self.assertEqual(wikilink, 'https://ar.wikipedia.org/wiki/Test')
513− wikilink = wikidata.get_wikilink(html_etree, 'enwikiquote')
514− self.assertEqual(wikilink, 'https://en.wikiquote.org/wiki/Test')
tests/unit/engines/test_wikipedia.pydeleted−263
@@ -1,263 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import wikipedia
5−from searx.testing import SearxTestCase
6−
7−
8−class TestWikipediaEngine(SearxTestCase):
9−
10− def test_request(self):
11− wikipedia.supported_languages = ['fr', 'en', 'no']
12− wikipedia.language_aliases = {'nb': 'no'}
13−
14− query = 'test_query'
15− dicto = defaultdict(dict)
16− dicto['language'] = 'fr-FR'
17− params = wikipedia.request(query.encode('utf-8'), dicto)
18− self.assertIn('url', params)
19− self.assertIn(query, params['url'])
20− self.assertIn('test_query', params['url'])
21− self.assertIn('Test_Query', params['url'])
22− self.assertIn('fr.wikipedia.org', params['url'])
23−
24− query = u'Test_Query'
25− params = wikipedia.request(query.encode('utf-8'), dicto)
26− self.assertIn('Test_Query', params['url'])
27− self.assertNotIn('test_query', params['url'])
28−
29− dicto['language'] = 'nb'
30− params = wikipedia.request(query, dicto)
31− self.assertIn('no.wikipedia.org', params['url'])
32− dicto['language'] = 'all'
33− params = wikipedia.request(query, dicto)
34− self.assertIn('en', params['url'])
35−
36− dicto['language'] = 'xx'
37− params = wikipedia.request(query, dicto)
38− self.assertIn('en.wikipedia.org', params['url'])
39−
40− def test_response(self):
41− dicto = defaultdict(dict)
42− dicto['language'] = 'fr'
43−
44− self.assertRaises(AttributeError, wikipedia.response, None)
45− self.assertRaises(AttributeError, wikipedia.response, [])
46− self.assertRaises(AttributeError, wikipedia.response, '')
47− self.assertRaises(AttributeError, wikipedia.response, '[]')
48−
49− # page not found
50− json = """
51− {
52− "batchcomplete": "",
53− "query": {
54− "normalized": [],
55− "pages": {
56− "-1": {
57− "ns": 0,
58− "title": "",
59− "missing": ""
60− }
61− }
62− }
63− }"""
64− response = mock.Mock(text=json, search_params=dicto)
65− self.assertEqual(wikipedia.response(response), [])
66−
67− # normal case
68− json = """
69− {
70− "batchcomplete": "",
71− "query": {
72− "normalized": [],
73− "pages": {
74− "12345": {
75− "pageid": 12345,
76− "ns": 0,
77− "title": "The Title",
78− "extract": "The Title is...",
79− "thumbnail": {
80− "source": "img_src.jpg"
81− },
82− "pageimage": "img_name.jpg"
83− }
84− }
85− }
86− }"""
87− response = mock.Mock(text=json, search_params=dicto)
88− results = wikipedia.response(response)
89− self.assertEqual(type(results), list)
90− self.assertEqual(len(results), 2)
91− self.assertEqual(results[0]['title'], u'The Title')
92− self.assertIn('fr.wikipedia.org/wiki/The_Title', results[0]['url'])
93− self.assertEqual(results[1]['infobox'], u'The Title')
94− self.assertIn('fr.wikipedia.org/wiki/The_Title', results[1]['id'])
95− self.assertIn('The Title is...', results[1]['content'])
96− self.assertEqual(results[1]['img_src'], 'img_src.jpg')
97−
98− # disambiguation page
99− json = """
100− {
101− "batchcomplete": "",
102− "query": {
103− "normalized": [],
104− "pages": {
105− "12345": {
106− "pageid": 12345,
107− "ns": 0,
108− "title": "The Title",
109− "extract": "The Title can be:\\nThe Title 1\\nThe Title 2\\nThe Title 3\\nThe Title 4......................................................................................................................................." """ # noqa
110− json += """
111− }
112− }
113− }
114− }"""
115− response = mock.Mock(text=json, search_params=dicto)
116− results = wikipedia.response(response)
117− self.assertEqual(type(results), list)
118− self.assertEqual(len(results), 2)
119−
120− # no image
121− json = """
122− {
123− "batchcomplete": "",
124− "query": {
125− "normalized": [],
126− "pages": {
127− "12345": {
128− "pageid": 12345,
129− "ns": 0,
130− "title": "The Title",
131− "extract": "The Title is......................................................................................................................................................................................." """ # noqa
132− json += """
133− }
134− }
135− }
136− }"""
137− response = mock.Mock(text=json, search_params=dicto)
138− results = wikipedia.response(response)
139− self.assertEqual(type(results), list)
140− self.assertEqual(len(results), 2)
141− self.assertIn('The Title is...', results[1]['content'])
142− self.assertEqual(results[1]['img_src'], None)
143−
144− # title not in first paragraph
145− json = u"""
146− {
147− "batchcomplete": "",
148− "query": {
149− "normalized": [],
150− "pages": {
151− "12345": {
152− "pageid": 12345,
153− "ns": 0,
154− "title": "披頭四樂隊",
155− "extract": "披头士乐队....................................................................................................................................................................................................\\n披頭四樂隊...", """ # noqa
156− json += """
157− "thumbnail": {
158− "source": "img_src.jpg"
159− },
160− "pageimage": "img_name.jpg"
161− }
162− }
163− }
164− }"""
165− response = mock.Mock(text=json, search_params=dicto)
166− results = wikipedia.response(response)
167− self.assertEqual(type(results), list)
168− self.assertEqual(len(results), 2)
169− self.assertEqual(results[1]['infobox'], u'披頭四樂隊')
170− self.assertIn(u'披头士乐队...', results[1]['content'])
171−
172− def test_fetch_supported_languages(self):
173− html = u"""<html></html>"""
174− response = mock.Mock(text=html)
175− languages = wikipedia._fetch_supported_languages(response)
176− self.assertEqual(type(languages), dict)
177− self.assertEqual(len(languages), 0)
178−
179− html = u"""
180− <html>
181− <body>
182− <div>
183− <div>
184− <h3>Table header</h3>
185− <table class="sortable jquery-tablesorter">
186− <thead>
187− <tr>
188− <th>N</th>
189− <th>Language</th>
190− <th>Language (local)</th>
191− <th>Wiki</th>
192− <th>Articles</th>
193− </tr>
194− </thead>
195− <tbody>
196− <tr>
197− <td>2</td>
198− <td><a>Swedish</a></td>
199− <td><a>Svenska</a></td>
200− <td><a>sv</a></td>
201− <td><a><b>3000000</b></a></td>
202− </tr>
203− <tr>
204− <td>3</td>
205− <td><a>Cebuano</a></td>
206− <td><a>Sinugboanong Binisaya</a></td>
207− <td><a>ceb</a></td>
208− <td><a><b>3000000</b></a></td>
209− </tr>
210− </tbody>
211− </table>
212− <h3>Table header</h3>
213− <table class="sortable jquery-tablesorter">
214− <thead>
215− <tr>
216− <th>N</th>
217− <th>Language</th>
218− <th>Language (local)</th>
219− <th>Wiki</th>
220− <th>Articles</th>
221− </tr>
222− </thead>
223− <tbody>
224− <tr>
225− <td>2</td>
226− <td><a>Norwegian (Bokmål)</a></td>
227− <td><a>Norsk (Bokmål)</a></td>
228− <td><a>no</a></td>
229− <td><a><b>100000</b></a></td>
230− </tr>
231− </tbody>
232− </table>
233− </div>
234− </div>
235− </body>
236− </html>
237− """
238− response = mock.Mock(text=html)
239− languages = wikipedia._fetch_supported_languages(response)
240− self.assertEqual(type(languages), dict)
241− self.assertEqual(len(languages), 3)
242−
243− self.assertIn('sv', languages)
244− self.assertIn('ceb', languages)
245− self.assertIn('no', languages)
246−
247− self.assertEqual(type(languages['sv']), dict)
248− self.assertEqual(type(languages['ceb']), dict)
249− self.assertEqual(type(languages['no']), dict)
250−
251− self.assertIn('name', languages['sv'])
252− self.assertIn('english_name', languages['sv'])
253− self.assertIn('articles', languages['sv'])
254−
255− self.assertEqual(languages['sv']['name'], 'Svenska')
256− self.assertEqual(languages['sv']['english_name'], 'Swedish')
257− self.assertEqual(languages['sv']['articles'], 3000000)
258− self.assertEqual(languages['ceb']['name'], 'Sinugboanong Binisaya')
259− self.assertEqual(languages['ceb']['english_name'], 'Cebuano')
260− self.assertEqual(languages['ceb']['articles'], 3000000)
261− self.assertEqual(languages['no']['name'], u'Norsk (Bokmål)')
262− self.assertEqual(languages['no']['english_name'], u'Norwegian (Bokmål)')
263− self.assertEqual(languages['no']['articles'], 100000)
tests/unit/engines/test_wolframalpha_api.pydeleted−166
@@ -1,166 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from requests import Request
5−from searx.engines import wolframalpha_api
6−from searx.testing import SearxTestCase
7−
8−
9−class TestWolframAlphaAPIEngine(SearxTestCase):
10−
11− def test_request(self):
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− params = wolframalpha_api.request(query, dicto)
15−
16− # TODO: test api_key
17− self.assertIn('url', params)
18− self.assertIn('https://api.wolframalpha.com/v2/query?', params['url'])
19− self.assertIn(query, params['url'])
20− self.assertEqual('https://www.wolframalpha.com/input/?i=test_query', params['headers']['Referer'])
21−
22− def test_replace_pua_chars(self):
23− self.assertEqual('i', wolframalpha_api.replace_pua_chars(u'\uf74e'))
24−
25− def test_response(self):
26− self.assertRaises(AttributeError, wolframalpha_api.response, None)
27− self.assertRaises(AttributeError, wolframalpha_api.response, [])
28− self.assertRaises(AttributeError, wolframalpha_api.response, '')
29− self.assertRaises(AttributeError, wolframalpha_api.response, '[]')
30−
31− referer_url = 'referer_url'
32− request = Request(headers={'Referer': referer_url})
33−
34− # test failure
35− xml = '''<?xml version='1.0' encoding='UTF-8'?>
36− <queryresult success='false' error='false' />
37− '''
38− response = mock.Mock(content=xml.encode('utf-8'))
39− self.assertEqual(wolframalpha_api.response(response), [])
40−
41− # test basic case
42− xml = b"""<?xml version='1.0' encoding='UTF-8'?>
43− <queryresult success='true'
44− error='false'
45− numpods='3'
46− datatypes='Math'
47− id='queryresult_id'
48− host='http://www4c.wolframalpha.com'
49− related='related_url'
50− version='2.6'>
51− <pod title='Input'
52− scanner='Identity'
53− id='Input'
54− numsubpods='1'>
55− <subpod title=''>
56− <img src='input_img_src.gif'
57− alt='input_img_alt'
58− title='input_img_title' />
59− <plaintext>input_plaintext</plaintext>
60− </subpod>
61− </pod>
62− <pod title='Result'
63− scanner='Simplification'
64− id='Result'
65− numsubpods='1'
66− primary='true'>
67− <subpod title=''>
68− <img src='result_img_src.gif'
69− alt='result_img_alt'
70− title='result_img_title' />
71− <plaintext>result_plaintext</plaintext>
72− </subpod>
73− </pod>
74− <pod title='Manipulatives illustration'
75− scanner='Arithmetic'
76− id='Illustration'
77− numsubpods='1'>
78− <subpod title=''>
79− <img src='illustration_img_src.gif'
80− alt='illustration_img_alt' />
81− <plaintext>illustration_plaintext</plaintext>
82− </subpod>
83− </pod>
84− </queryresult>
85− """
86− response = mock.Mock(content=xml, request=request)
87− results = wolframalpha_api.response(response)
88− self.assertEqual(type(results), list)
89− self.assertEqual(len(results), 2)
90− self.assertEqual('input_plaintext', results[0]['infobox'])
91−
92− self.assertEqual(len(results[0]['attributes']), 3)
93− self.assertEqual('Input', results[0]['attributes'][0]['label'])
94− self.assertEqual('input_plaintext', results[0]['attributes'][0]['value'])
95− self.assertEqual('Result', results[0]['attributes'][1]['label'])
96− self.assertEqual('result_plaintext', results[0]['attributes'][1]['value'])
97− self.assertEqual('Manipulatives illustration', results[0]['attributes'][2]['label'])
98− self.assertEqual('illustration_img_src.gif', results[0]['attributes'][2]['image']['src'])
99− self.assertEqual('illustration_img_alt', results[0]['attributes'][2]['image']['alt'])
100−
101− self.assertEqual(len(results[0]['urls']), 1)
102−
103− self.assertEqual(referer_url, results[0]['urls'][0]['url'])
104− self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
105− self.assertEqual(referer_url, results[1]['url'])
106− self.assertEqual('Wolfram|Alpha (input_plaintext)', results[1]['title'])
107− self.assertIn('result_plaintext', results[1]['content'])
108−
109− # test calc
110− xml = b"""<?xml version='1.0' encoding='UTF-8'?>
111− <queryresult success='true'
112− error='false'
113− numpods='2'
114− datatypes=''
115− parsetimedout='false'
116− id='queryresult_id'
117− host='http://www5b.wolframalpha.com'
118− related='related_url'
119− version='2.6' >
120− <pod title='Indefinite integral'
121− scanner='Integral'
122− id='IndefiniteIntegral'
123− error='false'
124− numsubpods='1'
125− primary='true'>
126− <subpod title=''>
127− <img src='integral_image.gif'
128− alt='integral_img_alt'
129− title='integral_img_title' />
130− <plaintext>integral_plaintext</plaintext>
131− </subpod>
132− </pod>
133− <pod title='Plot of the integral'
134− scanner='Integral'
135− id='Plot'
136− error='false'
137− numsubpods='1'>
138− <subpod title=''>
139− <img src='plot.gif'
140− alt='plot_alt'
141− title='' />
142− <plaintext></plaintext>
143− </subpod>
144− </pod>
145− </queryresult>
146− """
147− response = mock.Mock(content=xml, request=request)
148− results = wolframalpha_api.response(response)
149− self.assertEqual(type(results), list)
150− self.assertEqual(len(results), 2)
151− self.assertEqual('integral_plaintext', results[0]['infobox'])
152−
153− self.assertEqual(len(results[0]['attributes']), 2)
154− self.assertEqual('Indefinite integral', results[0]['attributes'][0]['label'])
155− self.assertEqual('integral_plaintext', results[0]['attributes'][0]['value'])
156− self.assertEqual('Plot of the integral', results[0]['attributes'][1]['label'])
157− self.assertEqual('plot.gif', results[0]['attributes'][1]['image']['src'])
158− self.assertEqual('plot_alt', results[0]['attributes'][1]['image']['alt'])
159−
160− self.assertEqual(len(results[0]['urls']), 1)
161−
162− self.assertEqual(referer_url, results[0]['urls'][0]['url'])
163− self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
164− self.assertEqual(referer_url, results[1]['url'])
165− self.assertEqual('Wolfram|Alpha (integral_plaintext)', results[1]['title'])
166− self.assertIn('integral_plaintext', results[1]['content'])
tests/unit/engines/test_wolframalpha_noapi.pydeleted−224
@@ -1,224 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from requests import Request
5−from searx.engines import wolframalpha_noapi
6−from searx.testing import SearxTestCase
7−
8−
9−class TestWolframAlphaNoAPIEngine(SearxTestCase):
10−
11− def test_request(self):
12− query = 'test_query'
13− dicto = defaultdict(dict)
14− params = wolframalpha_noapi.request(query, dicto)
15−
16− self.assertIn('url', params)
17− self.assertIn('https://www.wolframalpha.com/input/json.jsp', params['url'])
18− self.assertIn(query, params['url'])
19− self.assertEqual('https://www.wolframalpha.com/input/?i=test_query', params['headers']['Referer'])
20−
21− def test_response(self):
22− self.assertRaises(AttributeError, wolframalpha_noapi.response, None)
23− self.assertRaises(AttributeError, wolframalpha_noapi.response, [])
24− self.assertRaises(AttributeError, wolframalpha_noapi.response, '')
25− self.assertRaises(AttributeError, wolframalpha_noapi.response, '[]')
26−
27− referer_url = 'referer_url'
28− request = Request(headers={'Referer': referer_url})
29−
30− # test failure
31− json = r'''
32− {"queryresult" : {
33− "success" : false,
34− "error" : false,
35− "numpods" : 0,
36− "id" : "",
37− "host" : "https:\/\/www5a.wolframalpha.com",
38− "didyoumeans" : {}
39− }}
40− '''
41− response = mock.Mock(text=json, request=request)
42− self.assertEqual(wolframalpha_noapi.response(response), [])
43−
44− # test basic case
45− json = r'''
46− {"queryresult" : {
47− "success" : true,
48− "error" : false,
49− "numpods" : 6,
50− "datatypes" : "Math",
51− "id" : "queryresult_id",
52− "host" : "https:\/\/www5b.wolframalpha.com",
53− "related" : "related_url",
54− "version" : "2.6",
55− "pods" : [
56− {
57− "title" : "Input",
58− "scanners" : [
59− "Identity"
60− ],
61− "id" : "Input",
62− "error" : false,
63− "numsubpods" : 1,
64− "subpods" : [
65− {
66− "title" : "",
67− "img" : {
68− "src" : "input_img_src.gif",
69− "alt" : "input_img_alt",
70− "title" : "input_img_title"
71− },
72− "plaintext" : "input_plaintext",
73− "minput" : "input_minput"
74− }
75− ]
76− },
77− {
78− "title" : "Result",
79− "scanners" : [
80− "Simplification"
81− ],
82− "id" : "Result",
83− "error" : false,
84− "numsubpods" : 1,
85− "primary" : true,
86− "subpods" : [
87− {
88− "title" : "",
89− "img" : {
90− "src" : "result_img_src.gif",
91− "alt" : "result_img_alt",
92− "title" : "result_img_title"
93− },
94− "plaintext" : "result_plaintext",
95− "moutput" : "result_moutput"
96− }
97− ]
98− },
99− {
100− "title" : "Manipulatives illustration",
101− "scanners" : [
102− "Arithmetic"
103− ],
104− "id" : "Illustration",
105− "error" : false,
106− "numsubpods" : 1,
107− "subpods" : [
108− {
109− "title" : "",
110− "CDFcontent" : "Resizeable",
111− "img" : {
112− "src" : "illustration_img_src.gif",
113− "alt" : "illustration_img_alt",
114− "title" : "illustration_img_title"
115− },
116− "plaintext" : "illustration_img_plaintext"
117− }
118− ]
119− }
120− ]
121− }}
122− '''
123− response = mock.Mock(text=json, request=request)
124− results = wolframalpha_noapi.response(response)
125− self.assertEqual(type(results), list)
126− self.assertEqual(len(results), 2)
127− self.assertEqual('input_plaintext', results[0]['infobox'])
128−
129− self.assertEqual(len(results[0]['attributes']), 3)
130− self.assertEqual('Input', results[0]['attributes'][0]['label'])
131− self.assertEqual('input_plaintext', results[0]['attributes'][0]['value'])
132− self.assertEqual('Result', results[0]['attributes'][1]['label'])
133− self.assertEqual('result_plaintext', results[0]['attributes'][1]['value'])
134− self.assertEqual('Manipulatives illustration', results[0]['attributes'][2]['label'])
135− self.assertEqual('illustration_img_src.gif', results[0]['attributes'][2]['image']['src'])
136− self.assertEqual('illustration_img_alt', results[0]['attributes'][2]['image']['alt'])
137−
138− self.assertEqual(len(results[0]['urls']), 1)
139−
140− self.assertEqual(referer_url, results[0]['urls'][0]['url'])
141− self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
142− self.assertEqual(referer_url, results[1]['url'])
143− self.assertEqual('Wolfram|Alpha (input_plaintext)', results[1]['title'])
144− self.assertIn('result_plaintext', results[1]['content'])
145−
146− # test calc
147− json = r"""
148− {"queryresult" : {
149− "success" : true,
150− "error" : false,
151− "numpods" : 2,
152− "datatypes" : "",
153− "id" : "queryresult_id",
154− "host" : "https:\/\/www4b.wolframalpha.com",
155− "related" : "related_url",
156− "version" : "2.6",
157− "pods" : [
158− {
159− "title" : "Indefinite integral",
160− "scanners" : [
161− "Integral"
162− ],
163− "id" : "IndefiniteIntegral",
164− "error" : false,
165− "numsubpods" : 1,
166− "primary" : true,
167− "subpods" : [
168− {
169− "title" : "",
170− "img" : {
171− "src" : "integral_img_src.gif",
172− "alt" : "integral_img_alt",
173− "title" : "integral_img_title"
174− },
175− "plaintext" : "integral_plaintext",
176− "minput" : "integral_minput",
177− "moutput" : "integral_moutput"
178− }
179− ]
180− },
181− {
182− "title" : "Plot of the integral",
183− "scanners" : [
184− "Integral"
185− ],
186− "id" : "Plot",
187− "error" : false,
188− "numsubpods" : 1,
189− "subpods" : [
190− {
191− "title" : "",
192− "img" : {
193− "src" : "plot.gif",
194− "alt" : "plot_alt",
195− "title" : "plot_title"
196− },
197− "plaintext" : "",
198− "minput" : "plot_minput"
199− }
200− ]
201− }
202− ]
203− }}
204− """
205− response = mock.Mock(text=json, request=request)
206− results = wolframalpha_noapi.response(response)
207− self.assertEqual(type(results), list)
208− self.assertEqual(len(results), 2)
209− self.assertEqual('integral_plaintext', results[0]['infobox'])
210−
211− self.assertEqual(len(results[0]['attributes']), 2)
212− self.assertEqual('Indefinite integral', results[0]['attributes'][0]['label'])
213− self.assertEqual('integral_plaintext', results[0]['attributes'][0]['value'])
214− self.assertEqual('Plot of the integral', results[0]['attributes'][1]['label'])
215− self.assertEqual('plot.gif', results[0]['attributes'][1]['image']['src'])
216− self.assertEqual('plot_alt', results[0]['attributes'][1]['image']['alt'])
217−
218− self.assertEqual(len(results[0]['urls']), 1)
219−
220− self.assertEqual(referer_url, results[0]['urls'][0]['url'])
221− self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
222− self.assertEqual(referer_url, results[1]['url'])
223− self.assertEqual('Wolfram|Alpha (integral_plaintext)', results[1]['title'])
224− self.assertIn('integral_plaintext', results[1]['content'])
tests/unit/engines/test_www1x.pydeleted−14
@@ -1,14 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import www1x
4−from searx.testing import SearxTestCase
5−
6−
7−class TestWww1xEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− params = www1x.request(query, defaultdict(dict))
12− self.assertTrue('url' in params)
13− self.assertTrue(query in params['url'])
14− self.assertTrue('1x.com' in params['url'])
tests/unit/engines/test_yacy.pydeleted−96
@@ -1,96 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import yacy
4−from searx.testing import SearxTestCase
5−
6−
7−class TestYacyEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 1
13− dicto['language'] = 'fr_FR'
14− params = yacy.request(query, dicto)
15− self.assertIn('url', params)
16− self.assertIn(query, params['url'])
17− self.assertIn('localhost', params['url'])
18− self.assertIn('fr', params['url'])
19−
20− dicto['language'] = 'all'
21− params = yacy.request(query, dicto)
22− self.assertIn('url', params)
23− self.assertNotIn('lr=lang_', params['url'])
24−
25− def test_response(self):
26− self.assertRaises(AttributeError, yacy.response, None)
27− self.assertRaises(AttributeError, yacy.response, [])
28− self.assertRaises(AttributeError, yacy.response, '')
29− self.assertRaises(AttributeError, yacy.response, '[]')
30−
31− response = mock.Mock(text='{}')
32− self.assertEqual(yacy.response(response), [])
33−
34− response = mock.Mock(text='{"data": []}')
35− self.assertEqual(yacy.response(response), [])
36−
37− json = """
38− {
39− "channels": [
40− {
41− "title": "YaCy P2P-Search for test",
42− "description": "Search for test",
43− "link": "http://search.yacy.de:7001/yacysearch.html?query=test&amp;resource=global&amp;contentdom=0",
44− "image": {
45− "url": "http://search.yacy.de:7001/env/grafics/yacy.png",
46− "title": "Search for test",
47− "link": "http://search.yacy.de:7001/yacysearch.html?query=test&amp;resource=global&amp;contentdom=0"
48− },
49− "totalResults": "249",
50− "startIndex": "0",
51− "itemsPerPage": "5",
52− "searchTerms": "test",
53− "items": [
54− {
55− "title": "This is the title",
56− "link": "http://this.is.the.url",
57− "code": "",
58− "description": "This should be the content",
59− "pubDate": "Sat, 08 Jun 2013 02:00:00 +0200",
60− "size": "44213",
61− "sizename": "43 kbyte",
62− "guid": "lzh_1T_5FP-A",
63− "faviconCode": "XTS4uQ_5FP-A",
64− "host": "www.gamestar.de",
65− "path": "/spiele/city-of-heroes-freedom/47019.html",
66− "file": "47019.html",
67− "urlhash": "lzh_1T_5FP-A",
68− "ranking": "0.20106804"
69− },
70− {
71− "title": "This is the title2",
72− "icon": "/ViewImage.png?maxwidth=96&amp;maxheight=96&amp;code=7EbAbW6BpPOA",
73− "image": "http://image.url/image.png",
74− "cache": "/ViewImage.png?quadratic=&amp;url=http://golem.ivwbox.de/cgi-bin/ivw/CP/G_INET?d=14071378",
75− "url": "http://this.is.the.url",
76− "urlhash": "7EbAbW6BpPOA",
77− "host": "www.golem.de",
78− "width": "-1",
79− "height": "-1"
80− }
81− ]
82− }
83− ]
84− }
85− """
86− response = mock.Mock(text=json)
87− results = yacy.response(response)
88− self.assertEqual(type(results), list)
89− self.assertEqual(len(results), 2)
90− self.assertEqual(results[0]['title'], 'This is the title')
91− self.assertEqual(results[0]['url'], 'http://this.is.the.url')
92− self.assertEqual(results[0]['content'], 'This should be the content')
93− self.assertEqual(results[1]['img_src'], 'http://image.url/image.png')
94− self.assertEqual(results[1]['content'], '')
95− self.assertEqual(results[1]['url'], 'http://this.is.the.url')
96− self.assertEqual(results[1]['title'], 'This is the title2')
tests/unit/engines/test_yahoo.pydeleted−190
@@ -1,190 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import yahoo
5−from searx.testing import SearxTestCase
6−
7−
8−class TestYahooEngine(SearxTestCase):
9−
10− def test_parse_url(self):
11− test_url = 'http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb' +\
12− '2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10/RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=' +\
13− 'dtcJsfP4mEeBOjnVfUQ-'
14− url = yahoo.parse_url(test_url)
15− self.assertEqual('https://this.is.the.url/', url)
16−
17− test_url = 'http://r.search.yahoo.com/_ylt=A0LElb9JUSKcAEGRXNyoA;_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb' +\
18− '2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10/RU=https%3a%2f%2fthis.is.the.url%2f/RS=' +\
19− 'dtcJsfP4mEeBOjnVfUQ-'
20− url = yahoo.parse_url(test_url)
21− self.assertEqual('https://this.is.the.url/', url)
22−
23− test_url = 'https://this.is.the.url/'
24− url = yahoo.parse_url(test_url)
25− self.assertEqual('https://this.is.the.url/', url)
26−
27− def test_request(self):
28− yahoo.supported_languages = ['en', 'fr', 'zh-CHT', 'zh-CHS']
29− query = 'test_query'
30− dicto = defaultdict(dict)
31− dicto['pageno'] = 1
32− dicto['time_range'] = ''
33− dicto['language'] = 'fr-FR'
34− params = yahoo.request(query, dicto)
35− self.assertIn('url', params)
36− self.assertIn(query, params['url'])
37− self.assertIn('search.yahoo.com', params['url'])
38− self.assertIn('fr', params['url'])
39− self.assertIn('cookies', params)
40− self.assertIn('sB', params['cookies'])
41− self.assertIn('fr', params['cookies']['sB'])
42−
43− dicto['language'] = 'zh'
44− params = yahoo.request(query, dicto)
45− self.assertIn('zh_chs', params['url'])
46− self.assertIn('zh_chs', params['cookies']['sB'])
47−
48− dicto['language'] = 'zh-TW'
49− params = yahoo.request(query, dicto)
50− self.assertIn('zh_cht', params['url'])
51− self.assertIn('zh_cht', params['cookies']['sB'])
52−
53− dicto['language'] = 'all'
54− params = yahoo.request(query, dicto)
55− self.assertIn('cookies', params)
56− self.assertIn('sB', params['cookies'])
57− self.assertIn('en', params['cookies']['sB'])
58− self.assertIn('en', params['url'])
59−
60− def test_no_url_in_request_year_time_range(self):
61− dicto = defaultdict(dict)
62− query = 'test_query'
63− dicto['time_range'] = 'year'
64− params = yahoo.request(query, dicto)
65− self.assertEqual({}, params['url'])
66−
67− def test_response(self):
68− self.assertRaises(AttributeError, yahoo.response, None)
69− self.assertRaises(AttributeError, yahoo.response, [])
70− self.assertRaises(AttributeError, yahoo.response, '')
71− self.assertRaises(AttributeError, yahoo.response, '[]')
72−
73− response = mock.Mock(text='<html></html>')
74− self.assertEqual(yahoo.response(response), [])
75−
76− html = """
77−<ol class="reg mb-15 searchCenterMiddle">
78− <li class="first">
79− <div class="dd algo fst Sr">
80− <div class="compTitle">
81− <h3 class="title"><a class=" td-u" href="http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;
82− _ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10
83− /RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=dtcJsfP4mEeBOjnVfUQ-"
84− target="_blank" data-bid="54e712e13671c">
85− <b><b>This is the title</b></b></a>
86− </h3>
87− </div>
88− <div class="compText aAbs">
89− <p class="lh-18"><b><b>This is the </b>content</b>
90− </p>
91− </div>
92− </div>
93− </li>
94− <li>
95− <div class="dd algo lst Sr">
96− <div class="compTitle">
97− </div>
98− <div class="compText aAbs">
99− <p class="lh-18">This is the second content</p>
100− </div>
101− </div>
102− </li>
103−</ol>
104−<div class="dd assist fst lst AlsoTry" data-bid="54e712e138d04">
105− <div class="compTitle mb-4 h-17">
106− <h3 class="title">Also Try</h3> </div>
107− <table class="compTable m-0 ac-1st td-u fz-ms">
108− <tbody>
109− <tr>
110− <td class="w-50p pr-28"><a href="https://search.yahoo.com/"><B>This is the </B>suggestion<B></B></a>
111− </td>
112− </tr>
113− </table>
114−</div>
115− """
116− response = mock.Mock(text=html)
117− results = yahoo.response(response)
118− self.assertEqual(type(results), list)
119− self.assertEqual(len(results), 2)
120− self.assertEqual(results[0]['title'], 'This is the title')
121− self.assertEqual(results[0]['url'], 'https://this.is.the.url/')
122− self.assertEqual(results[0]['content'], 'This is the content')
123− self.assertEqual(results[1]['suggestion'], 'This is the suggestion')
124−
125− html = """
126−<ol class="reg mb-15 searchCenterMiddle">
127− <li class="first">
128− <div class="dd algo fst Sr">
129− <div class="compTitle">
130− <h3 class="title"><a class=" td-u" href="http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;
131− _ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10
132− /RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=dtcJsfP4mEeBOjnVfUQ-"
133− target="_blank" data-bid="54e712e13671c">
134− <b><b>This is the title</b></b></a>
135− </h3>
136− </div>
137− <div class="compText aAbs">
138− <p class="lh-18"><b><b>This is the </b>content</b>
139− </p>
140− </div>
141− </div>
142− </li>
143−</ol>
144− """
145− response = mock.Mock(text=html)
146− results = yahoo.response(response)
147− self.assertEqual(type(results), list)
148− self.assertEqual(len(results), 1)
149− self.assertEqual(results[0]['title'], 'This is the title')
150− self.assertEqual(results[0]['url'], 'https://this.is.the.url/')
151− self.assertEqual(results[0]['content'], 'This is the content')
152−
153− html = """
154− <li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
155− </li>
156− """
157− response = mock.Mock(text=html)
158− results = yahoo.response(response)
159− self.assertEqual(type(results), list)
160− self.assertEqual(len(results), 0)
161−
162− def test_fetch_supported_languages(self):
163− html = """<html></html>"""
164− response = mock.Mock(text=html)
165− results = yahoo._fetch_supported_languages(response)
166− self.assertEqual(type(results), list)
167− self.assertEqual(len(results), 0)
168−
169− html = """
170− <html>
171− <div>
172− <div id="yschlang">
173− <span>
174− <label><input value="lang_ar"></input></label>
175− </span>
176− <span>
177− <label><input value="lang_zh_chs"></input></label>
178− <label><input value="lang_zh_cht"></input></label>
179− </span>
180− </div>
181− </div>
182− </html>
183− """
184− response = mock.Mock(text=html)
185− languages = yahoo._fetch_supported_languages(response)
186− self.assertEqual(type(languages), list)
187− self.assertEqual(len(languages), 3)
188− self.assertIn('ar', languages)
189− self.assertIn('zh-CHS', languages)
190− self.assertIn('zh-CHT', languages)
tests/unit/engines/test_yahoo_news.pydeleted−150
@@ -1,150 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−from datetime import datetime
4−import mock
5−from searx.engines import yahoo_news
6−from searx.testing import SearxTestCase
7−
8−
9−class TestYahooNewsEngine(SearxTestCase):
10−
11− def test_request(self):
12− yahoo_news.supported_languages = ['en', 'fr']
13− query = 'test_query'
14− dicto = defaultdict(dict)
15− dicto['pageno'] = 1
16− dicto['language'] = 'fr-FR'
17− params = yahoo_news.request(query, dicto)
18− self.assertIn('url', params)
19− self.assertIn(query, params['url'])
20− self.assertIn('news.search.yahoo.com', params['url'])
21− self.assertIn('fr', params['url'])
22− self.assertIn('cookies', params)
23− self.assertIn('sB', params['cookies'])
24− self.assertIn('fr', params['cookies']['sB'])
25−
26− dicto['language'] = 'all'
27− params = yahoo_news.request(query, dicto)
28− self.assertIn('cookies', params)
29− self.assertIn('sB', params['cookies'])
30− self.assertIn('en', params['cookies']['sB'])
31− self.assertIn('en', params['url'])
32−
33− def test_sanitize_url(self):
34− url = "test.url"
35− self.assertEqual(url, yahoo_news.sanitize_url(url))
36−
37− url = "www.yahoo.com/;_ylt=test"
38− self.assertEqual("www.yahoo.com/", yahoo_news.sanitize_url(url))
39−
40− def test_response(self):
41− self.assertRaises(AttributeError, yahoo_news.response, None)
42− self.assertRaises(AttributeError, yahoo_news.response, [])
43− self.assertRaises(AttributeError, yahoo_news.response, '')
44− self.assertRaises(AttributeError, yahoo_news.response, '[]')
45−
46− response = mock.Mock(text='<html></html>')
47− self.assertEqual(yahoo_news.response(response), [])
48−
49− html = """
50− <ol class=" reg searchCenterMiddle">
51− <li class="first">
52− <div class="compTitle">
53− <h3>
54− <a class="yschttl spt" href="http://this.is.the.url" target="_blank">
55− This is
56− the <b>title</b>...
57− </a>
58− </h3>
59− </div>
60− <div>
61− <span class="cite">Business via Yahoo!</span>
62− <span class="tri fc-2nd ml-10">May 01 10:00 AM</span>
63− </div>
64− <div class="compText">
65− This is the content
66− </div>
67− </li>
68− <li class="first">
69− <div class="compTitle">
70− <h3>
71− <a class="yschttl spt" target="_blank">
72− </a>
73− </h3>
74− </div>
75− <div class="compText">
76− </div>
77− </li>
78− </ol>
79− """
80− response = mock.Mock(text=html)
81− results = yahoo_news.response(response)
82− self.assertEqual(type(results), list)
83− self.assertEqual(len(results), 1)
84− self.assertEqual(results[0]['title'], 'This is the title...')
85− self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
86− self.assertEqual(results[0]['content'], 'This is the content')
87−
88− html = """
89− <ol class=" reg searchCenterMiddle">
90− <li class="first">
91− <div class="compTitle">
92− <h3>
93− <a class="yschttl spt" href="http://this.is.the.url" target="_blank">
94− This is
95− the <b>title</b>...
96− </a>
97− </h3>
98− </div>
99− <div>
100− <span class="cite">Business via Yahoo!</span>
101− <span class="tri fc-2nd ml-10">2 hours, 22 minutes ago</span>
102− </div>
103− <div class="compText">
104− This is the content
105− </div>
106− </li>
107− <li>
108− <div class="compTitle">
109− <h3>
110− <a class="yschttl spt" href="http://this.is.the.url" target="_blank">
111− This is
112− the <b>title</b>...
113− </a>
114− </h3>
115− </div>
116− <div>
117− <span class="cite">Business via Yahoo!</span>
118− <span class="tri fc-2nd ml-10">22 minutes ago</span>
119− </div>
120− <div class="compText">
121− This is the content
122− </div>
123− </li>
124− <li>
125− <div class="compTitle">
126− <h3>
127− <a class="yschttl spt" href="http://this.is.the.url" target="_blank">
128− This is
129− the <b>title</b>...
130− </a>
131− </h3>
132− </div>
133− <div>
134− <span class="cite">Business via Yahoo!</span>
135− <span class="tri fc-2nd ml-10">Feb 03 09:45AM 1900</span>
136− </div>
137− <div class="compText">
138− This is the content
139− </div>
140− </li>
141− </ol>
142− """
143− response = mock.Mock(text=html)
144− results = yahoo_news.response(response)
145− self.assertEqual(type(results), list)
146− self.assertEqual(len(results), 3)
147− self.assertEqual(results[0]['title'], 'This is the title...')
148− self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
149− self.assertEqual(results[0]['content'], 'This is the content')
150− self.assertEqual(results[2]['publishedDate'].year, datetime.now().year)
tests/unit/engines/test_youtube_api.pydeleted−111
@@ -1,111 +0,0 @@
1−from collections import defaultdict
2−import mock
3−from searx.engines import youtube_api
4−from searx.testing import SearxTestCase
5−
6−
7−class TestYoutubeAPIEngine(SearxTestCase):
8−
9− def test_request(self):
10− query = 'test_query'
11− dicto = defaultdict(dict)
12− dicto['pageno'] = 0
13− dicto['language'] = 'fr_FR'
14− params = youtube_api.request(query, dicto)
15− self.assertTrue('url' in params)
16− self.assertTrue(query in params['url'])
17− self.assertIn('googleapis.com', params['url'])
18− self.assertIn('youtube', params['url'])
19− self.assertIn('fr', params['url'])
20−
21− dicto['language'] = 'all'
22− params = youtube_api.request(query, dicto)
23− self.assertFalse('fr' in params['url'])
24−
25− def test_response(self):
26− self.assertRaises(AttributeError, youtube_api.response, None)
27− self.assertRaises(AttributeError, youtube_api.response, [])
28− self.assertRaises(AttributeError, youtube_api.response, '')
29− self.assertRaises(AttributeError, youtube_api.response, '[]')
30−
31− response = mock.Mock(text='{}')
32− self.assertEqual(youtube_api.response(response), [])
33−
34− response = mock.Mock(text='{"data": []}')
35− self.assertEqual(youtube_api.response(response), [])
36−
37− json = """
38− {
39− "kind": "youtube#searchListResponse",
40− "etag": "xmg9xJZuZD438sF4hb-VcBBREXc/YJQDcTBCDcaBvl-sRZJoXdvy1ME",
41− "nextPageToken": "CAUQAA",
42− "pageInfo": {
43− "totalResults": 1000000,
44− "resultsPerPage": 20
45− },
46− "items": [
47− {
48− "kind": "youtube#searchResult",
49− "etag": "xmg9xJZuZD438sF4hb-VcBBREXc/IbLO64BMhbHIgWLwLw7MDYe7Hs4",
50− "id": {
51− "kind": "youtube#video",
52− "videoId": "DIVZCPfAOeM"
53− },
54− "snippet": {
55− "publishedAt": "2015-05-29T22:41:04.000Z",
56− "channelId": "UCNodmx1ERIjKqvcJLtdzH5Q",
57− "title": "Title",
58− "description": "Description",
59− "thumbnails": {
60− "default": {
61− "url": "https://i.ytimg.com/vi/DIVZCPfAOeM/default.jpg"
62− },
63− "medium": {
64− "url": "https://i.ytimg.com/vi/DIVZCPfAOeM/mqdefault.jpg"
65− },
66− "high": {
67− "url": "https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg"
68− }
69− },
70− "channelTitle": "MinecraftUniverse",
71− "liveBroadcastContent": "none"
72− }
73− }
74− ]
75− }
76− """
77− response = mock.Mock(text=json)
78− results = youtube_api.response(response)
79− self.assertEqual(type(results), list)
80− self.assertEqual(len(results), 1)
81− self.assertEqual(results[0]['title'], 'Title')
82− self.assertEqual(results[0]['url'], 'https://www.youtube.com/watch?v=DIVZCPfAOeM')
83− self.assertEqual(results[0]['content'], 'Description')
84− self.assertEqual(results[0]['thumbnail'], 'https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg')
85− self.assertTrue('DIVZCPfAOeM' in results[0]['embedded'])
86−
87− json = """
88− {
89− "kind": "youtube#searchListResponse",
90− "etag": "xmg9xJZuZD438sF4hb-VcBBREXc/YJQDcTBCDcaBvl-sRZJoXdvy1ME",
91− "nextPageToken": "CAUQAA",
92− "pageInfo": {
93− "totalResults": 1000000,
94− "resultsPerPage": 20
95− }
96− }
97− """
98− response = mock.Mock(text=json)
99− results = youtube_api.response(response)
100− self.assertEqual(type(results), list)
101− self.assertEqual(len(results), 0)
102−
103− json = """
104− {"toto":{"entry":[]
105− }
106− }
107− """
108− response = mock.Mock(text=json)
109− results = youtube_api.response(response)
110− self.assertEqual(type(results), list)
111− self.assertEqual(len(results), 0)
tests/unit/engines/test_youtube_noapi.pydeleted−124
@@ -1,124 +0,0 @@
1−# -*- coding: utf-8 -*-
2−from collections import defaultdict
3−import mock
4−from searx.engines import youtube_noapi
5−from searx.testing import SearxTestCase
6−
7−
8−class TestYoutubeNoAPIEngine(SearxTestCase):
9−
10− def test_request(self):
11− query = 'test_query'
12− dicto = defaultdict(dict)
13− dicto['pageno'] = 0
14− dicto['time_range'] = ''
15− params = youtube_noapi.request(query, dicto)
16− self.assertIn('url', params)
17− self.assertIn(query, params['url'])
18− self.assertIn('youtube.com', params['url'])
19−
20− def test_time_range_search(self):
21− dicto = defaultdict(dict)
22− query = 'test_query'
23− dicto['time_range'] = 'year'
24− params = youtube_noapi.request(query, dicto)
25− self.assertIn('&sp=EgIIBQ%253D%253D', params['url'])
26−
27− dicto['time_range'] = 'month'
28− params = youtube_noapi.request(query, dicto)
29− self.assertIn('&sp=EgIIBA%253D%253D', params['url'])
30−
31− dicto['time_range'] = 'week'
32− params = youtube_noapi.request(query, dicto)
33− self.assertIn('&sp=EgIIAw%253D%253D', params['url'])
34−
35− dicto['time_range'] = 'day'
36− params = youtube_noapi.request(query, dicto)
37− self.assertIn('&sp=EgIIAg%253D%253D', params['url'])
38−
39− def test_response(self):
40− self.assertRaises(AttributeError, youtube_noapi.response, None)
41− self.assertRaises(AttributeError, youtube_noapi.response, [])
42− self.assertRaises(AttributeError, youtube_noapi.response, '')
43− self.assertRaises(AttributeError, youtube_noapi.response, '[]')
44−
45− response = mock.Mock(text='<html></html>')
46− self.assertEqual(youtube_noapi.response(response), [])
47−
48− html = """
49− <div></div>
50− <script>
51− window["ytInitialData"] = {
52− "contents": {
53− "twoColumnSearchResultsRenderer": {
54− "primaryContents": {
55− "sectionListRenderer": {
56− "contents": [
57− {
58− "itemSectionRenderer": {
59− "contents": [
60− {
61− "videoRenderer": {
62− "videoId": "DIVZCPfAOeM",
63− "title": {
64− "simpleText": "Title"
65− },
66− "descriptionSnippet": {
67− "runs": [
68− {
69− "text": "Des"
70− },
71− {
72− "text": "cription"
73− }
74− ]
75− }
76− }
77− },
78− {
79− "videoRenderer": {
80− "videoId": "9C_HReR_McQ",
81− "title": {
82− "simpleText": "Title"
83− },
84− "descriptionSnippet": {
85− "simpleText": "Description"
86− }
87− }
88− }
89− ]
90− }
91− }
92− ]
93− }
94− }
95− }
96− }
97− };
98− </script>
99− """
100− response = mock.Mock(text=html)
101− results = youtube_noapi.response(response)
102− self.assertEqual(type(results), list)
103− self.assertEqual(len(results), 2)
104− self.assertEqual(results[0]['title'], 'Title')
105− self.assertEqual(results[0]['url'], 'https://www.youtube.com/watch?v=DIVZCPfAOeM')
106− self.assertEqual(results[0]['content'], 'Description')
107− self.assertEqual(results[0]['thumbnail'], 'https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg')
108− self.assertTrue('DIVZCPfAOeM' in results[0]['embedded'])
109− self.assertEqual(results[1]['title'], 'Title')
110− self.assertEqual(results[1]['url'], 'https://www.youtube.com/watch?v=9C_HReR_McQ')
111− self.assertEqual(results[1]['content'], 'Description')
112− self.assertEqual(results[1]['thumbnail'], 'https://i.ytimg.com/vi/9C_HReR_McQ/hqdefault.jpg')
113− self.assertTrue('9C_HReR_McQ' in results[1]['embedded'])
114−
115− html = """
116− <ol id="item-section-063864" class="item-section">
117− <li>
118− </li>
119− </ol>
120− """
121− response = mock.Mock(text=html)
122− results = youtube_noapi.response(response)
123− self.assertEqual(type(results), list)
124− self.assertEqual(len(results), 0)
tests/unit/engines/unsplash_fixture.jsondeleted−241
@@ -1,241 +0,0 @@
1−{
2− "total": 2,
3− "total_pages": 1,
4− "results": [
5− {
6− "id": "FY8d721UO_4",
7− "created_at": "2018-04-12T14:20:35-04:00",
8− "updated_at": "2018-08-28T20:58:33-04:00",
9− "width": 3891,
10− "height": 5829,
11− "color": "#152C33",
12− "description": "low angle photography of swimming penguin",
13− "urls": {
14− "raw": "https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=095c5fc319c5a77c705f49ad63e0f195",
15− "full": "https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjEyMDd9&s=74be977849c173d6929636d491a760c3",
16− "regular": "https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=ad65df26970bd010085f0ca25434de33",
17− "small": "https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=5d2edfd073c31eb8ee7b305222bdc5a2",
18− "thumb": "https://images.unsplash.com/photo-1523557148507-1b77641c7e7c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=a9b9e56e63efc6f4611a87ce7e9a48f8"
19− },
20− "links": {
21− "self": "https://api.unsplash.com/photos/FY8d721UO_4",
22− "html": "https://unsplash.com/photos/FY8d721UO_4",
23− "download": "https://unsplash.com/photos/FY8d721UO_4/download",
24− "download_location": "https://api.unsplash.com/photos/FY8d721UO_4/download"
25− },
26− "categories": [],
27− "sponsored": false,
28− "likes": 31,
29− "liked_by_user": false,
30− "current_user_collections": [],
31− "slug": null,
32− "user": {
33− "id": "N4gE4mrG8lE",
34− "updated_at": "2018-10-03T02:51:19-04:00",
35− "username": "gaspanik",
36− "name": "Masaaki Komori",
37− "first_name": "Masaaki",
38− "last_name": "Komori",
39− "twitter_username": "cipher",
40− "portfolio_url": "https://www.instagram.com/cipher/",
41− "bio": null,
42− "location": "Tokyo, JAPAN",
43− "links": {
44− "self": "https://api.unsplash.com/users/gaspanik",
45− "html": "https://unsplash.com/@gaspanik",
46− "photos": "https://api.unsplash.com/users/gaspanik/photos",
47− "likes": "https://api.unsplash.com/users/gaspanik/likes",
48− "portfolio": "https://api.unsplash.com/users/gaspanik/portfolio",
49− "following": "https://api.unsplash.com/users/gaspanik/following",
50− "followers": "https://api.unsplash.com/users/gaspanik/followers"
51− },
52− "profile_image": {
53− "small": "https://images.unsplash.com/profile-fb-1502270358-e7c86c1011ce.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=9fe12f6d177bd6fdbd56d233a80c01a3",
54− "medium": "https://images.unsplash.com/profile-fb-1502270358-e7c86c1011ce.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=6ad7d156b62e438ae9dc794cba712fff",
55− "large": "https://images.unsplash.com/profile-fb-1502270358-e7c86c1011ce.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=13a08a2e72e7d11632410e92bd3a9406"
56− },
57− "instagram_username": "cipher",
58− "total_collections": 0,
59− "total_likes": 406,
60− "total_photos": 196
61− },
62− "tags": [
63− {
64− "title": "animal"
65− },
66− {
67− "title": "water"
68− },
69− {
70− "title": "swim"
71− },
72− {
73− "title": "aquarium"
74− },
75− {
76− "title": "wallpaper"
77− },
78− {
79− "title": "blue"
80− },
81− {
82− "title": "sealife"
83− },
84− {
85− "title": "wildlife"
86− },
87− {
88− "title": "bird"
89− },
90− {
91− "title": "deep sea"
92− },
93− {
94− "title": "fish"
95− },
96− {
97− "title": "water life"
98− }
99− ],
100− "photo_tags": [
101− {
102− "title": "animal"
103− },
104− {
105− "title": "water"
106− },
107− {
108− "title": "swim"
109− },
110− {
111− "title": "aquarium"
112− },
113− {
114− "title": "wallpaper"
115− }
116− ]
117− },
118− {
119− "id": "ayKyc01xLWA",
120− "created_at": "2018-02-16T23:14:31-05:00",
121− "updated_at": "2018-08-28T20:48:27-04:00",
122− "width": 4928,
123− "height": 3264,
124− "color": "#161618",
125− "description": "black and white penguins on ice field",
126− "urls": {
127− "raw": "https://images.unsplash.com/photo-1518840801558-9770b4a34eeb?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4e107a2bc49ab561ba6272eea2ec725d",
128− "full": "https://images.unsplash.com/photo-1518840801558-9770b4a34eeb?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjEyMDd9&s=f9b1e4d4572ab44efb2cf3d601d2b4d9",
129− "regular": "https://images.unsplash.com/photo-1518840801558-9770b4a34eeb?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=4430cedb63841f1fe055d5005316cc96",
130− "small": "https://images.unsplash.com/photo-1518840801558-9770b4a34eeb?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=ee73c7af22ce445d408e240821ce07af",
131− "thumb": "https://images.unsplash.com/photo-1518840801558-9770b4a34eeb?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=934302390d383cad8c571905e3a80bac"
132− },
133− "links": {
134− "self": "https://api.unsplash.com/photos/ayKyc01xLWA",
135− "html": "https://unsplash.com/photos/ayKyc01xLWA",
136− "download": "https://unsplash.com/photos/ayKyc01xLWA/download",
137− "download_location": "https://api.unsplash.com/photos/ayKyc01xLWA/download"
138− },
139− "categories": [],
140− "sponsored": false,
141− "likes": 37,
142− "liked_by_user": false,
143− "current_user_collections": [],
144− "slug": null,
145− "user": {
146− "id": "tRb_KGw60Xk",
147− "updated_at": "2018-09-20T11:51:54-04:00",
148− "username": "ghost_cat",
149− "name": "Danielle Barnes",
150− "first_name": "Danielle",
151− "last_name": "Barnes",
152− "twitter_username": null,
153− "portfolio_url": null,
154− "bio": null,
155− "location": null,
156− "links": {
157− "self": "https://api.unsplash.com/users/ghost_cat",
158− "html": "https://unsplash.com/@ghost_cat",
159− "photos": "https://api.unsplash.com/users/ghost_cat/photos",
160− "likes": "https://api.unsplash.com/users/ghost_cat/likes",
161− "portfolio": "https://api.unsplash.com/users/ghost_cat/portfolio",
162− "following": "https://api.unsplash.com/users/ghost_cat/following",
163− "followers": "https://api.unsplash.com/users/ghost_cat/followers"
164− },
165− "profile_image": {
166− "small": "https://images.unsplash.com/profile-fb-1508491082-ae77f53e9ac3.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=751bf6a557763648d52ffd7e60e79436",
167− "medium": "https://images.unsplash.com/profile-fb-1508491082-ae77f53e9ac3.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=e46cd1c8713035f045130e1b093b981e",
168− "large": "https://images.unsplash.com/profile-fb-1508491082-ae77f53e9ac3.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=352eabcf107c3ce95fe51a18485f116b"
169− },
170− "instagram_username": null,
171− "total_collections": 0,
172− "total_likes": 0,
173− "total_photos": 21
174− },
175− "tags": [
176− {
177− "title": "ice"
178− },
179− {
180− "title": "bird"
181− },
182− {
183− "title": "ice field"
184− },
185− {
186− "title": "iceberg"
187− },
188− {
189− "title": "snow"
190− },
191− {
192− "title": "frozen"
193− },
194− {
195− "title": "animal"
196− },
197− {
198− "title": "wildlife"
199− },
200− {
201− "title": "wild"
202− },
203− {
204− "title": "antarctica"
205− },
206− {
207− "title": "sunshine"
208− },
209− {
210− "title": "daylight"
211− },
212− {
213− "title": "wilderness"
214− },
215− {
216− "title": "south pole"
217− },
218− {
219− "title": "flock"
220− }
221− ],
222− "photo_tags": [
223− {
224− "title": "ice"
225− },
226− {
227− "title": "bird"
228− },
229− {
230− "title": "ice field"
231− },
232− {
233− "title": "iceberg"
234− },
235− {
236− "title": "snow"
237− }
238− ]
239− }
240− ]
241−}