mirror of
https://github.com/YunoHost-Apps/searx_ynh.git
synced 2024-09-03 20:16:30 +02:00
remove upstream source files
This commit is contained in:
parent
2e36a000bd
commit
1a10fd8b7f
84 changed files with 0 additions and 9843 deletions
|
@ -1,53 +0,0 @@
|
|||
Searx was created by Adam Tauber and is maintained by Adam Tauber and Alexandre Flament.
|
||||
|
||||
Major contributing authors:
|
||||
|
||||
- Adam Tauber <asciimoo@gmail.com> `@asciimoo <https://github.com/asciimoo>`_
|
||||
- Matej Cotman
|
||||
- Thomas Pointhuber
|
||||
- Alexandre Flament `@dalf <https://github.com/dalf>`_
|
||||
- @Cqoicebordel
|
||||
|
||||
People who have submitted patches/translates, reported bugs, consulted features or
|
||||
generally made searx better:
|
||||
|
||||
- Laszlo Hammerl
|
||||
- Stefan Marsiske
|
||||
- Gabor Nagy
|
||||
- @pw3t
|
||||
- @rhapsodhy
|
||||
- András Veres-Szentkirályi
|
||||
- Benjamin Sonntag
|
||||
- @HLFH
|
||||
- @TheRadialActive
|
||||
- @Okhin
|
||||
- André Koot
|
||||
- Alejandro León Aznar
|
||||
- rike
|
||||
- dp
|
||||
- Martin Zimmermann
|
||||
- @courgette
|
||||
- @kernc
|
||||
- @Reventl0v
|
||||
- Caner Başaran
|
||||
- Benjamin Sonntag
|
||||
- @opi
|
||||
- @dimqua
|
||||
- Giorgos Logiotatidis
|
||||
- Luc Didry
|
||||
- Niklas Haas
|
||||
- @underr
|
||||
- Emmanuel Benazera
|
||||
- @GreenLunar
|
||||
- Noemi Vanyi
|
||||
- Kang-min Liu
|
||||
- Kirill Isakov
|
||||
- Guilhem Bonnefille
|
||||
- Marc Abonce Seguin
|
||||
|
||||
- @jibe-b
|
||||
- Christian Pietsch @pietsch
|
||||
- @Maxqia
|
||||
- Ashutosh Das @pyprism
|
||||
- YuLun Shih @imZack
|
||||
- Dmitry Mikhirev @mikhirev
|
|
@ -1,164 +0,0 @@
|
|||
0.9.0 2016.05.24
|
||||
================
|
||||
|
||||
- New search category: science
|
||||
- New engines
|
||||
|
||||
- Wolframalpha (science)
|
||||
- Frinkiac (images)
|
||||
- Arch Linux (it)
|
||||
- BASE - Bielefeld Academic Search Engine (science)
|
||||
- Dokuwiki (general)
|
||||
- Nyaa.se (files, images, music, video)
|
||||
- Reddit (general, images, news, social media)
|
||||
- Torrentz.eu (files, music, video)
|
||||
- Tokyo Toshokan (files, music, video)
|
||||
- F-Droid (files)
|
||||
- Erowid (general)
|
||||
- Bitbucket (it)
|
||||
- GitLab (it)
|
||||
- Geektimes (it)
|
||||
- Habrahabr (it)
|
||||
- New plugins
|
||||
|
||||
- Open links in new tab
|
||||
- Vim hotkeys for better navigation
|
||||
- Wikipedia/Mediawiki engine improvements
|
||||
- Configurable instance name
|
||||
- Configurable connection pool size
|
||||
- Fixed broken google engine
|
||||
- Better docker image
|
||||
- Images in standard results
|
||||
- Fixed and refactored user settings (Warning: backward incompatibility - you have to reset your custom engine preferences)
|
||||
- Suspending engines on errors
|
||||
- Simplified development/deployment tooling
|
||||
- Translation updates
|
||||
- Multilingual autocompleter
|
||||
- Qwant autocompleter backend
|
||||
|
||||
0.8.1 2015.12.22
|
||||
================
|
||||
|
||||
- More efficient result parsing
|
||||
- Rewritten google engine to prevent app crashes
|
||||
- Other engine fixes/tweaks
|
||||
|
||||
- Bing news
|
||||
- Btdigg
|
||||
- Gigablast
|
||||
- Google images
|
||||
- Startpage
|
||||
|
||||
|
||||
News
|
||||
~~~~
|
||||
|
||||
New documentation page is available: https://asciimoo.github.io/searx
|
||||
|
||||
|
||||
0.8.0 2015.09.08
|
||||
================
|
||||
|
||||
- New engines
|
||||
|
||||
- Blekko (image)
|
||||
- Gigablast (general)
|
||||
- Spotify (music)
|
||||
- Swisscows (general, images)
|
||||
- Qwant (general, images, news, social media)
|
||||
- Plugin system
|
||||
- New plugins
|
||||
|
||||
- HTTPS rewrite
|
||||
- Search on cagetory select
|
||||
- User information
|
||||
- Tracker url part remover
|
||||
- Multiple outgoing IP and HTTP/HTTPS proxy support
|
||||
- New autocompleter: startpage
|
||||
- New theme: pix-art
|
||||
- Settings file structure change
|
||||
- Fabfile, docker deployment
|
||||
- Optional safesearch result filter
|
||||
- Force HTTPS in engines if possible
|
||||
- Disabled HTTP referrer on outgoing links
|
||||
- Display cookie information
|
||||
- Prettier search URLs
|
||||
- Right-to-left text handling in themes
|
||||
- Translation updates (New locales: Chinese, Hebrew, Portuguese, Romanian)
|
||||
|
||||
|
||||
New dependencies
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- pyopenssl
|
||||
- ndg-httpsclient
|
||||
- pyasn1
|
||||
- pyasn1-modules
|
||||
- certifi
|
||||
|
||||
|
||||
News
|
||||
~~~~
|
||||
|
||||
@dalf joined the maintainer "team"
|
||||
|
||||
|
||||
0.7.0 2015.02.03
|
||||
================
|
||||
|
||||
- New engines
|
||||
|
||||
- Digg
|
||||
- Google Play Store
|
||||
- Deezer
|
||||
- Btdigg
|
||||
- Mixcloud
|
||||
- 1px
|
||||
- Image proxy
|
||||
- Search speed improvements
|
||||
- Autocompletition of engines, shortcuts and supported languages
|
||||
- Translation updates (New locales: Turkish, Russian)
|
||||
- Default theme changed to oscar
|
||||
- Settings option to disable engines by default
|
||||
- UI code cleanup and restructure
|
||||
- Engine tests
|
||||
- Multiple engine bug fixes and tweaks
|
||||
- Config option to set default interface locale
|
||||
- Flexible result template handling
|
||||
- Application logging and sophisticated engine exception tracebacks
|
||||
- Kickass torrent size display (oscar theme)
|
||||
|
||||
|
||||
New dependencies
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- pygments - http://pygments.org/
|
||||
|
||||
|
||||
0.6.0 - 2014.12.25
|
||||
==================
|
||||
|
||||
- Changelog added
|
||||
- New engines
|
||||
|
||||
- Flickr (api)
|
||||
- Subtitleseeker
|
||||
- photon
|
||||
- 500px
|
||||
- Searchcode
|
||||
- Searchcode doc
|
||||
- Kickass torrent
|
||||
- Precise search request timeout handling
|
||||
- Better favicon support
|
||||
- Stricter config parsing
|
||||
- Translation updates
|
||||
- Multiple ui fixes
|
||||
- Flickr (noapi) engine fix
|
||||
- Pep8 fixes
|
||||
|
||||
|
||||
News
|
||||
~~~~
|
||||
|
||||
Health status of searx instances and engines: http://stats.searx.oe5tpo.com
|
||||
(source: https://github.com/pointhi/searx_stats)
|
|
@ -1,54 +0,0 @@
|
|||
FROM alpine:3.3
|
||||
MAINTAINER searx <https://github.com/asciimoo/searx>
|
||||
LABEL description "A privacy-respecting, hackable metasearch engine."
|
||||
|
||||
ENV BASE_URL=False IMAGE_PROXY=False
|
||||
EXPOSE 8888
|
||||
WORKDIR /usr/local/searx
|
||||
CMD ["/usr/bin/tini","--","/usr/local/searx/run.sh"]
|
||||
|
||||
RUN adduser -D -h /usr/local/searx -s /bin/sh searx searx \
|
||||
&& echo '#!/bin/sh' >> run.sh \
|
||||
&& echo 'sed -i "s|base_url : False|base_url : $BASE_URL|g" searx/settings.yml' >> run.sh \
|
||||
&& echo 'sed -i "s/image_proxy : False/image_proxy : $IMAGE_PROXY/g" searx/settings.yml' >> run.sh \
|
||||
&& echo 'sed -i "s/ultrasecretkey/`openssl rand -hex 16`/g" searx/settings.yml' >> run.sh \
|
||||
&& echo 'python searx/webapp.py' >> run.sh \
|
||||
&& chmod +x run.sh
|
||||
|
||||
COPY requirements.txt ./requirements.txt
|
||||
|
||||
RUN echo "@commuedge http://nl.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
|
||||
&& apk -U add \
|
||||
build-base \
|
||||
python \
|
||||
python-dev \
|
||||
py-pip \
|
||||
libxml2 \
|
||||
libxml2-dev \
|
||||
libxslt \
|
||||
libxslt-dev \
|
||||
libffi-dev \
|
||||
openssl \
|
||||
openssl-dev \
|
||||
ca-certificates \
|
||||
tini@commuedge \
|
||||
&& pip install --no-cache -r requirements.txt \
|
||||
&& apk del \
|
||||
build-base \
|
||||
python-dev \
|
||||
py-pip\
|
||||
libffi-dev \
|
||||
openssl-dev \
|
||||
libxslt-dev \
|
||||
libxml2-dev \
|
||||
openssl-dev \
|
||||
ca-certificates \
|
||||
&& rm -f /var/cache/apk/*
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN chown -R searx:searx *
|
||||
|
||||
USER searx
|
||||
|
||||
RUN sed -i "s/127.0.0.1/0.0.0.0/g" searx/settings.yml
|
661
sources/LICENSE
661
sources/LICENSE
|
@ -1,661 +0,0 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
|
@ -1,45 +0,0 @@
|
|||
searx
|
||||
=====
|
||||
|
||||
A privacy-respecting, hackable `metasearch
|
||||
engine <https://en.wikipedia.org/wiki/Metasearch_engine>`__.
|
||||
|
||||
List of `running
|
||||
instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__.
|
||||
|
||||
See the `documentation <https://asciimoo.github.io/searx>`__ and the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
|
||||
|
||||
|Flattr searx|
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- clone source:
|
||||
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
||||
- install dependencies: ``./manage.sh update_packages``
|
||||
- edit your
|
||||
`settings.yml <https://github.com/asciimoo/searx/blob/master/searx/settings.yml>`__
|
||||
(set your ``secret_key``!)
|
||||
- run ``python searx/webapp.py`` to start the application
|
||||
|
||||
For all the details, follow this `step by step
|
||||
installation <https://github.com/asciimoo/searx/wiki/Installation>`__
|
||||
|
||||
Bugs
|
||||
~~~~
|
||||
|
||||
Bugs or suggestions? Visit the `issue
|
||||
tracker <https://github.com/asciimoo/searx/issues>`__.
|
||||
|
||||
`License <https://github.com/asciimoo/searx/blob/master/LICENSE>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
More about searx
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- `ohloh <https://www.ohloh.net/p/searx/>`__
|
||||
- `twitter <https://twitter.com/Searx_engine>`__
|
||||
- IRC: #searx @ freenode
|
||||
|
||||
.. |Flattr searx| image:: http://api.flattr.com/button/flattr-badge-large.png
|
||||
:target: https://flattr.com/submit/auto?user_id=asciimoo&url=https://github.com/asciimoo/searx&title=searx&language=&tags=github&category=software
|
|
@ -1,3 +0,0 @@
|
|||
[python: **.py]
|
||||
[jinja2: **/templates/**.html]
|
||||
extensions=jinja2.ext.autoescape,jinja2.ext.with_
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
categories = ['general'] # optional
|
||||
|
||||
def request(query, params):
|
||||
'''pre-request callback
|
||||
params<dict>:
|
||||
method : POST/GET
|
||||
headers : {}
|
||||
data : {} # if method == POST
|
||||
url : ''
|
||||
category: 'search category'
|
||||
pageno : 1 # number of the requested page
|
||||
'''
|
||||
|
||||
params['url'] = 'https://host/%s' % query
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
'''post-response callback
|
||||
resp: requests response object
|
||||
'''
|
||||
return [{'url': '', 'title': '', 'content': ''}]
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
BASE_DIR=$(dirname `readlink -f $0`)
|
||||
PYTHONPATH=$BASE_DIR
|
||||
SEARX_DIR="$BASE_DIR/searx"
|
||||
ACTION=$1
|
||||
|
||||
update_packages() {
|
||||
pip install --upgrade -r "$BASE_DIR/requirements.txt"
|
||||
}
|
||||
|
||||
update_dev_packages() {
|
||||
update_packages
|
||||
pip install --upgrade -r "$BASE_DIR/requirements-dev.txt"
|
||||
}
|
||||
|
||||
pep8_check() {
|
||||
echo '[!] Running pep8 check'
|
||||
# ignored rules:
|
||||
# E402 module level import not at top of file
|
||||
# W503 line break before binary operator
|
||||
pep8 --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
|
||||
}
|
||||
|
||||
unit_tests() {
|
||||
echo '[!] Running unit tests'
|
||||
python -m nose2 -s "$BASE_DIR/tests/unit"
|
||||
}
|
||||
|
||||
py_test_coverage() {
|
||||
echo '[!] Running python test coverage'
|
||||
PYTHONPATH=`pwd` python -m nose2 -C --coverage "$SEARX_DIR" -s "$BASE_DIR/tests/unit"
|
||||
coverage report
|
||||
coverage html
|
||||
}
|
||||
|
||||
robot_tests() {
|
||||
echo '[!] Running robot tests'
|
||||
PYTHONPATH=`pwd` python "$SEARX_DIR/testing.py" robot
|
||||
}
|
||||
|
||||
tests() {
|
||||
set -e
|
||||
pep8_check
|
||||
unit_tests
|
||||
robot_tests
|
||||
set +e
|
||||
}
|
||||
|
||||
build_style() {
|
||||
lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
|
||||
}
|
||||
|
||||
styles() {
|
||||
echo '[!] Building styles'
|
||||
build_style themes/default/less/style.less themes/default/css/style.css
|
||||
build_style themes/default/less/style-rtl.less themes/default/css/style-rtl.css
|
||||
build_style themes/courgette/less/style.less themes/courgette/css/style.css
|
||||
build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css
|
||||
build_style less/bootstrap/bootstrap.less css/bootstrap.min.css
|
||||
build_style themes/oscar/less/oscar/oscar.less themes/oscar/css/oscar.min.css
|
||||
build_style themes/pix-art/less/style.less themes/pix-art/css/style.css
|
||||
}
|
||||
|
||||
grunt_build() {
|
||||
grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
|
||||
}
|
||||
|
||||
locales() {
|
||||
pybabel compile -d "$SEARX_DIR/translations"
|
||||
}
|
||||
|
||||
help() {
|
||||
[ -z "$1" ] || printf "Error: $1\n"
|
||||
echo "Searx manage.sh help
|
||||
|
||||
Commands
|
||||
========
|
||||
grunt_build - Build js files
|
||||
help - This text
|
||||
locales - Compile locales
|
||||
pep8_check - Pep8 validation
|
||||
py_test_coverage - Unit test coverage
|
||||
robot_tests - Run selenium tests
|
||||
styles - Build less files
|
||||
tests - Run all python tests (pep8, unit, robot)
|
||||
unit_tests - Run unit tests
|
||||
update_dev_packages - Check & update development and production dependency changes
|
||||
update_packages - Check & update dependency changes
|
||||
"
|
||||
}
|
||||
|
||||
[ "$(command -V "$ACTION" | grep ' function$')" = "" ] \
|
||||
&& help "action not found" \
|
||||
|| $ACTION
|
|
@ -1,10 +0,0 @@
|
|||
babel==2.2.0
|
||||
mock==1.0.1
|
||||
nose2[coverage-plugin]
|
||||
pep8==1.7.0
|
||||
plone.testing==4.0.15
|
||||
robotframework-selenium2library==1.7.4
|
||||
robotsuite==1.7.0
|
||||
transifex-client==0.11
|
||||
unittest2==1.1.0
|
||||
zope.testrunner==4.4.10
|
|
@ -1,12 +0,0 @@
|
|||
certifi==2015.11.20.1
|
||||
flask==0.10.1
|
||||
flask-babel==0.9
|
||||
lxml==3.5.0
|
||||
ndg-httpsclient==0.4.0
|
||||
pyasn1==0.1.9
|
||||
pyasn1-modules==0.0.8
|
||||
pygments==2.0.2
|
||||
pyopenssl==0.15.1
|
||||
python-dateutil==2.4.2
|
||||
pyyaml==3.11
|
||||
requests==2.9.1
|
|
@ -1,74 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Installer for Searx package."""
|
||||
|
||||
from setuptools import setup
|
||||
from setuptools import find_packages
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# required to load VERSION_STRING constant
|
||||
sys.path.insert(0, './searx')
|
||||
from version import VERSION_STRING
|
||||
|
||||
|
||||
def read(*rnames):
|
||||
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
|
||||
|
||||
|
||||
long_description = read('README.rst')
|
||||
requirements = map(str.strip, open('requirements.txt').readlines())
|
||||
dev_requirements = map(str.strip, open('requirements-dev.txt').readlines())
|
||||
|
||||
setup(
|
||||
name='searx',
|
||||
version=VERSION_STRING,
|
||||
description="A privacy-respecting, hackable metasearch engine",
|
||||
long_description=long_description,
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Programming Language :: Python",
|
||||
"Topic :: Internet",
|
||||
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
||||
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
|
||||
'License :: OSI Approved :: GNU Affero General Public License v3'
|
||||
],
|
||||
keywords='metasearch searchengine search web http',
|
||||
author='Adam Tauber',
|
||||
author_email='asciimoo@gmail.com',
|
||||
url='https://github.com/asciimoo/searx',
|
||||
license='GNU Affero General Public License',
|
||||
packages=find_packages('.'),
|
||||
zip_safe=False,
|
||||
install_requires=requirements,
|
||||
extras_require={
|
||||
'test': dev_requirements
|
||||
},
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'searx-run = searx.webapp:run'
|
||||
]
|
||||
},
|
||||
package_data={
|
||||
'searx': [
|
||||
'settings.yml',
|
||||
'../README.rst',
|
||||
'../requirements.txt',
|
||||
'../requirements-dev.txt',
|
||||
'data/*',
|
||||
'plugins/*/*',
|
||||
'static/*.*',
|
||||
'static/*/*.*',
|
||||
'static/*/*/*.*',
|
||||
'static/*/*/*/*.*',
|
||||
'static/*/*/*/*/*.*',
|
||||
'templates/*/*.*',
|
||||
'templates/*/*/*.*',
|
||||
'tests/*',
|
||||
'tests/*/*',
|
||||
'tests/*/*/*',
|
||||
'translations/*/*/*'
|
||||
],
|
||||
},
|
||||
|
||||
)
|
|
@ -1,152 +0,0 @@
|
|||
*** Settings ***
|
||||
Library Selenium2Library timeout=10 implicit_wait=0.5
|
||||
Test Setup Open Browser http://localhost:11111/
|
||||
Test Teardown Close All Browsers
|
||||
|
||||
|
||||
*** Test Cases ***
|
||||
Front page
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
|
||||
About page
|
||||
Click Element link=about
|
||||
Page Should Contain Why use Searx?
|
||||
Page Should Contain Element link=search engines
|
||||
|
||||
Preferences page
|
||||
Click Element link=preferences
|
||||
Page Should Contain Preferences
|
||||
Page Should Contain Default categories
|
||||
Page Should Contain Currently used search engines
|
||||
Page Should Contain dummy_dummy
|
||||
Page Should Contain general_dummy
|
||||
|
||||
Switch category
|
||||
Go To http://localhost:11111/preferences
|
||||
Page Should Contain Checkbox category_general
|
||||
Page Should Contain Checkbox category_dummy
|
||||
Click Element xpath=//*[.="general"]
|
||||
Click Element xpath=//*[.="dummy"]
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Checkbox Should Not Be Selected category_general
|
||||
Checkbox Should Be Selected category_dummy
|
||||
|
||||
Change language
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
Select From List locale hu
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Page Should Contain rólunk
|
||||
Page Should Contain beállítások
|
||||
|
||||
Change method
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
Select From List method GET
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be method GET
|
||||
Select From List method POST
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be method POST
|
||||
|
||||
Change theme
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be theme default
|
||||
Select From List theme oscar
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be theme oscar
|
||||
|
||||
Change safesearch
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be safesearch None
|
||||
Select From List safesearch Strict
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be safesearch Strict
|
||||
|
||||
Change image proxy
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be image_proxy Disabled
|
||||
Select From List image_proxy Enabled
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be image_proxy Enabled
|
||||
|
||||
Change search language
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be language Automatic
|
||||
Select From List language Turkish (Turkey) - tr_TR
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be language Turkish (Turkey) - tr_TR
|
||||
|
||||
Change autocomplete
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be autocomplete -
|
||||
Select From List autocomplete google
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be autocomplete google
|
||||
|
||||
Change allowed/disabled engines
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
Page Should Contain Engine name
|
||||
Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block
|
||||
Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] Block
|
||||
Click Element xpath=//label[@class="deny"][@for='engine_general_general_dummy']
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
Page Should Contain Engine name
|
||||
Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block
|
||||
Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] \
|
||||
|
||||
Block a plugin
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be theme default
|
||||
Select From List theme oscar
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
List Selection Should Be theme oscar
|
||||
Page Should Contain Plugins
|
||||
Click Link Plugins
|
||||
Checkbox Should Not Be Selected id=plugin_HTTPS_rewrite
|
||||
Click Element xpath=//label[@for='plugin_HTTPS_rewrite']
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Go To http://localhost:11111/preferences
|
||||
Page Should Contain Plugins
|
||||
Click Link Plugins
|
||||
Checkbox Should Be Selected id=plugin_HTTPS_rewrite
|
|
@ -1,23 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import unittest2 as unittest
|
||||
from plone.testing import layered
|
||||
from robotsuite import RobotTestSuite
|
||||
from searx.testing import SEARXROBOTLAYER
|
||||
|
||||
|
||||
def test_suite():
|
||||
suite = unittest.TestSuite()
|
||||
current_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
robot_dir = os.path.join(current_dir, 'robot')
|
||||
tests = [
|
||||
os.path.join('robot', f) for f in
|
||||
os.listdir(robot_dir) if f.endswith('.robot') and
|
||||
f.startswith('test_')
|
||||
]
|
||||
for test in tests:
|
||||
suite.addTests([
|
||||
layered(RobotTestSuite(test), layer=SEARXROBOTLAYER),
|
||||
])
|
||||
return suite
|
|
@ -1,106 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import archlinux
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
domains = {
|
||||
'all': 'https://wiki.archlinux.org',
|
||||
'de': 'https://wiki.archlinux.de',
|
||||
'fr': 'https://wiki.archlinux.fr',
|
||||
'ja': 'https://wiki.archlinuxjp.org',
|
||||
'ro': 'http://wiki.archlinux.ro',
|
||||
'tr': 'http://archtr.org/wiki'
|
||||
}
|
||||
|
||||
|
||||
class TestArchLinuxEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
dic['pageno'] = 1
|
||||
dic['language'] = 'en_US'
|
||||
params = archlinux.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('wiki.archlinux.org' in params['url'])
|
||||
|
||||
for lang, domain in domains.iteritems():
|
||||
dic['language'] = lang
|
||||
params = archlinux.request(query, dic)
|
||||
self.assertTrue(domain in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
response = mock.Mock(text='<html></html>',
|
||||
search_params={'language': 'en_US'})
|
||||
self.assertEqual(archlinux.response(response), [])
|
||||
|
||||
html = """
|
||||
<ul class="mw-search-results">
|
||||
<li>
|
||||
<div class="mw-search-result-heading">
|
||||
<a href="/index.php/ATI" title="ATI">ATI</a>
|
||||
</div>
|
||||
<div class="searchresult">
|
||||
Lorem ipsum dolor sit amet
|
||||
</div>
|
||||
<div class="mw-search-result-data">
|
||||
30 KB (4,630 words) - 19:04, 17 March 2016</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="mw-search-result-heading">
|
||||
<a href="/index.php/Frequently_asked_questions" title="Frequently asked questions">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
<div class="searchresult">
|
||||
CPUs with AMDs instruction set "AMD64"
|
||||
</div>
|
||||
<div class="mw-search-result-data">
|
||||
17 KB (2,722 words) - 20:13, 21 March 2016
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="mw-search-result-heading">
|
||||
<a href="/index.php/CPU_frequency_scaling" title="CPU frequency scaling">CPU frequency scaling</a>
|
||||
</div>
|
||||
<div class="searchresult">
|
||||
ondemand for AMD and older Intel CPU
|
||||
</div>
|
||||
<div class="mw-search-result-data">
|
||||
15 KB (2,319 words) - 23:46, 16 March 2016
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
"""
|
||||
|
||||
expected = [
|
||||
{
|
||||
'title': 'ATI',
|
||||
'url': 'https://wiki.archlinux.org/index.php/ATI'
|
||||
},
|
||||
{
|
||||
'title': 'Frequently asked questions',
|
||||
'url': 'https://wiki.archlinux.org/index.php/Frequently_asked_questions'
|
||||
},
|
||||
{
|
||||
'title': 'CPU frequency scaling',
|
||||
'url': 'https://wiki.archlinux.org/index.php/CPU_frequency_scaling'
|
||||
}
|
||||
]
|
||||
|
||||
response = mock.Mock(text=html)
|
||||
response.search_params = {
|
||||
'language': 'en_US'
|
||||
}
|
||||
results = archlinux.response(response)
|
||||
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), len(expected))
|
||||
|
||||
i = 0
|
||||
for exp in expected:
|
||||
res = results[i]
|
||||
i += 1
|
||||
for key, value in exp.iteritems():
|
||||
self.assertEqual(res[key], value)
|
|
@ -1,90 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import bing
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestBingEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = bing.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('bing.com' in params['url'])
|
||||
self.assertTrue('SRCHHPGUSR' in params['cookies'])
|
||||
self.assertTrue('fr' in params['cookies']['SRCHHPGUSR'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = bing.request(query, dicto)
|
||||
self.assertTrue('SRCHHPGUSR' in params['cookies'])
|
||||
self.assertTrue('en' in params['cookies']['SRCHHPGUSR'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, bing.response, None)
|
||||
self.assertRaises(AttributeError, bing.response, [])
|
||||
self.assertRaises(AttributeError, bing.response, '')
|
||||
self.assertRaises(AttributeError, bing.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(bing.response(response), [])
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(bing.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="sa_cc" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
|
||||
<div Class="sa_mc">
|
||||
<div class="sb_tlst">
|
||||
<h3>
|
||||
<a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
|
||||
<strong>This</strong> should be the title</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="sb_meta"><cite><strong>this</strong>.meta.com</cite>
|
||||
<span class="c_tlbxTrg">
|
||||
<span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<p><strong>This</strong> should be the content.</p>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = bing.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
||||
|
||||
html = """
|
||||
<li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
|
||||
<div Class="sa_mc">
|
||||
<div class="sb_tlst">
|
||||
<h2>
|
||||
<a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
|
||||
<strong>This</strong> should be the title</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="sb_meta"><cite><strong>this</strong>.meta.com</cite>
|
||||
<span class="c_tlbxTrg">
|
||||
<span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<p><strong>This</strong> should be the content.</p>
|
||||
</div>
|
||||
</li>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = bing.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
|
@ -1,122 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import bing_images
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestBingImagesEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
dicto['safesearch'] = 1
|
||||
params = bing_images.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('bing.com' in params['url'])
|
||||
self.assertTrue('SRCHHPGUSR' in params['cookies'])
|
||||
self.assertTrue('fr' in params['cookies']['SRCHHPGUSR'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = bing_images.request(query, dicto)
|
||||
self.assertIn('SRCHHPGUSR', params['cookies'])
|
||||
self.assertIn('en', params['cookies']['SRCHHPGUSR'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, bing_images.response, None)
|
||||
self.assertRaises(AttributeError, bing_images.response, [])
|
||||
self.assertRaises(AttributeError, bing_images.response, '')
|
||||
self.assertRaises(AttributeError, bing_images.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(bing_images.response(response), [])
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(bing_images.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px"><div>
|
||||
<a href="/images/search?q=south&view=detailv2&&id=7E92863981CCFB89FBDD55205C742DFDA3290CF6&selectedIndex=9&ccid=vzvIfv5u&simid=608055786735667000&thid=OIP.Mbf3bc87efe6e0e476be8cc34bf6cd80eH0" ihk="OIP.Mbf3bc87efe6e0e476be8cc34bf6cd80eH0" t1="South Carolina" t2="747 x 589 · 29 kB · gif" t3="www.digital-topo-maps.com/county-map/south-carolina.shtml" hh="236" hw="300" m='{ns:"images",k:"5117",mid:"7E92863981CCFB89FBDD55205C742DFDA3290CF6",md5:"bf3bc87efe6e0e476be8cc34bf6cd80e",surl:"http://www.digital-topo-maps.com/county-map/south-carolina.shtml",imgurl:"http://www.digital-topo-maps.com/county-map/south-carolina-county-map.gif",tid:"OIP.Mbf3bc87efe6e0e476be8cc34bf6cd80eH0",ow:"480",docid:"608055786735667000",oh:"378",tft:"45"}' mid="7E92863981CCFB89FBDD55205C742DFDA3290CF6" h="ID=images,5117.1">
|
||||
<img class="img_hid" src2="https://tse4.mm.bing.net/th?id=OIP.Mbf3bc87efe6e0e476be8cc34bf6cd80eH0&w=210&h=154&c=7&rs=1&qlt=90&o=4&pid=1.1" style="width:210px;height:154px;" width="210" height="154">
|
||||
</a>
|
||||
|
||||
</div></div>
|
||||
""" # noqa
|
||||
html = html.replace('\r\n', '').replace('\n', '').replace('\r', '')
|
||||
response = mock.Mock(text=html)
|
||||
results = bing_images.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'South Carolina')
|
||||
self.assertEqual(results[0]['url'],
|
||||
'http://www.digital-topo-maps.com/county-map/south-carolina.shtml')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['thumbnail_src'],
|
||||
'https://www.bing.com/th?id=OIP.Mbf3bc87efe6e0e476be8cc34bf6cd80eH0')
|
||||
self.assertEqual(results[0]['img_src'],
|
||||
'http://www.digital-topo-maps.com/county-map/south-carolina-county-map.gif')
|
||||
|
||||
html = """
|
||||
<a href="#" ihk="HN.608003696942779811"
|
||||
m="{ns:"images",k:"5045",
|
||||
mid:"59EB92C317974F34517A1CCAEBEF76A578E08DEE",
|
||||
surl:"http://www.page.url/",
|
||||
imgurl:"http://test.url/Test%20Query.jpg",oh:"238",
|
||||
tft:"0",oi:"http://www.image.url/Images/Test%20Query.jpg"}"
|
||||
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
|
||||
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
|
||||
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&o=4&pid=1.7"
|
||||
style="height:144px;" width="178" height="144"/>
|
||||
</a>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = bing_images.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
html = """
|
||||
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px"><div>
|
||||
<a href="#" ihk="HN.608003696942779811"
|
||||
m="{ns:"images",k:"5045",
|
||||
mid:"659EB92C317974F34517A1CCAEBEF76A578E08DEE",
|
||||
surl:"http://www.page.url/",imgurl:"http://test.url/Test%20Query.jpg",
|
||||
oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%20Query.jpg"}"
|
||||
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
|
||||
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
|
||||
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&o=4&pid=1.7"
|
||||
style="height:144px;" width="178" height="144"/>
|
||||
</a>
|
||||
</div></div>
|
||||
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px"><div>
|
||||
<a href="#" ihk="HN.608003696942779811"
|
||||
m="{ns:"images",k:"5045",
|
||||
mid:"659EB92C317974F34517A1CCAEBEF76A578E08DEE",
|
||||
surl:"http://www.page.url/",imgurl:"http://test.url/Test%20Query.jpg",
|
||||
oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%20Query.jpg"}"
|
||||
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
|
||||
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
|
||||
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&o=4&pid=1.7"
|
||||
style="height:144px;" width="178" height="144"/>
|
||||
</a>
|
||||
</div></div>
|
||||
<div class="dg_u" style="width:178px;height:144px;left:17px;top:0px"><div>
|
||||
<a href="#" ihk="HN.608003696942779811"
|
||||
m="{ns:"images",k:"5045",
|
||||
mid:"659EB92C317974F34517A1CCAEBEF76A578E08DEE",
|
||||
surl:"http://www.page.url/",imgurl:"http://test.url/Test%20Query.jpg",
|
||||
oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%20Query.jpg"}"
|
||||
mid="59EB92C317974F34517A1CCAEBEF76A578E08DEE" onclick="return false;"
|
||||
t1="Test Query" t2="650 x 517 · 31 kB · jpeg" t3="www.short.url" h="ID=images,5045.1">
|
||||
<img src="https://tse4.mm.bing.net/th?id=HN.608003696942779811&o=4&pid=1.7"
|
||||
style="height:144px;" width="178" height="144"/>
|
||||
</a>
|
||||
</div></div>
|
||||
"""
|
||||
html = html.replace('\r\n', '').replace('\n', '').replace('\r', '')
|
||||
response = mock.Mock(text=html)
|
||||
results = bing_images.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
|
@ -1,138 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import bing_news
|
||||
from searx.testing import SearxTestCase
|
||||
import lxml
|
||||
|
||||
|
||||
class TestBingNewsEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = bing_news.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('bing.com', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = bing_news.request(query, dicto)
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, bing_news.response, None)
|
||||
self.assertRaises(AttributeError, bing_news.response, [])
|
||||
self.assertRaises(AttributeError, bing_news.response, '')
|
||||
self.assertRaises(AttributeError, bing_news.response, '[]')
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(bing_news.response(response), [])
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(bing_news.response(response), [])
|
||||
|
||||
html = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS">
|
||||
<channel>
|
||||
<title>python - Bing News</title>
|
||||
<link>https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS</link>
|
||||
<description>Search results</description>
|
||||
<image>
|
||||
<url>http://10.53.64.9/rsslogo.gif</url>
|
||||
<title>test</title>
|
||||
<link>https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS</link>
|
||||
</image>
|
||||
<copyright>Copyright</copyright>
|
||||
<item>
|
||||
<title>Title</title>
|
||||
<link>https://www.bing.com/news/apiclick.aspx?ref=FexRss&aid=&tid=c237eccc50bd4758b106a5e3c94fce09&url=http%3a%2f%2furl.of.article%2f&c=xxxxxxxxx&mkt=en-us</link>
|
||||
<description>Article Content</description>
|
||||
<pubDate>Tue, 02 Jun 2015 13:37:00 GMT</pubDate>
|
||||
<News:Source>Infoworld</News:Source>
|
||||
<News:Image>http://a1.bing4.com/th?id=ON.13371337133713371337133713371337&pid=News</News:Image>
|
||||
<News:ImageSize>w={0}&h={1}&c=7</News:ImageSize>
|
||||
<News:ImageKeepOriginalRatio></News:ImageKeepOriginalRatio>
|
||||
<News:ImageMaxWidth>620</News:ImageMaxWidth>
|
||||
<News:ImageMaxHeight>413</News:ImageMaxHeight>
|
||||
</item>
|
||||
<item>
|
||||
<title>Another Title</title>
|
||||
<link>https://www.bing.com/news/apiclick.aspx?ref=FexRss&aid=&tid=c237eccc50bd4758b106a5e3c94fce09&url=http%3a%2f%2fanother.url.of.article%2f&c=xxxxxxxxx&mkt=en-us</link>
|
||||
<description>Another Article Content</description>
|
||||
<pubDate>Tue, 02 Jun 2015 13:37:00 GMT</pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>""" # noqa
|
||||
response = mock.Mock(content=html)
|
||||
results = bing_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://url.of.article/')
|
||||
self.assertEqual(results[0]['content'], 'Article Content')
|
||||
self.assertEqual(results[0]['thumbnail'], 'https://www.bing.com/th?id=ON.13371337133713371337133713371337')
|
||||
self.assertEqual(results[1]['title'], 'Another Title')
|
||||
self.assertEqual(results[1]['url'], 'http://another.url.of.article/')
|
||||
self.assertEqual(results[1]['content'], 'Another Article Content')
|
||||
self.assertNotIn('thumbnail', results[1])
|
||||
|
||||
html = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS">
|
||||
<channel>
|
||||
<title>python - Bing News</title>
|
||||
<link>https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS</link>
|
||||
<description>Search results</description>
|
||||
<image>
|
||||
<url>http://10.53.64.9/rsslogo.gif</url>
|
||||
<title>test</title>
|
||||
<link>https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS</link>
|
||||
</image>
|
||||
<copyright>Copyright</copyright>
|
||||
<item>
|
||||
<title>Title</title>
|
||||
<link>http://another.url.of.article/</link>
|
||||
<description>Article Content</description>
|
||||
<pubDate>garbage</pubDate>
|
||||
<News:Source>Infoworld</News:Source>
|
||||
<News:Image>http://another.bing.com/image</News:Image>
|
||||
<News:ImageSize>w={0}&h={1}&c=7</News:ImageSize>
|
||||
<News:ImageKeepOriginalRatio></News:ImageKeepOriginalRatio>
|
||||
<News:ImageMaxWidth>620</News:ImageMaxWidth>
|
||||
<News:ImageMaxHeight>413</News:ImageMaxHeight>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>""" # noqa
|
||||
response = mock.Mock(content=html)
|
||||
results = bing_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://another.url.of.article/')
|
||||
self.assertEqual(results[0]['content'], 'Article Content')
|
||||
self.assertEqual(results[0]['thumbnail'], 'http://another.bing.com/image')
|
||||
|
||||
html = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0" xmlns:News="https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS">
|
||||
<channel>
|
||||
<title>python - Bing News</title>
|
||||
<link>https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS</link>
|
||||
<description>Search results</description>
|
||||
<image>
|
||||
<url>http://10.53.64.9/rsslogo.gif</url>
|
||||
<title>test</title>
|
||||
<link>https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS</link>
|
||||
</image>
|
||||
</channel>
|
||||
</rss>""" # noqa
|
||||
|
||||
response = mock.Mock(content=html)
|
||||
results = bing_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
html = """<?xml version="1.0" encoding="utf-8" ?>gabarge"""
|
||||
response = mock.Mock(content=html)
|
||||
self.assertRaises(lxml.etree.XMLSyntaxError, bing_news.response, response)
|
|
@ -1,71 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import blekko_images
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestBlekkoImagesEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['safesearch'] = 1
|
||||
params = blekko_images.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('blekko.com', params['url'])
|
||||
self.assertIn('page', params['url'])
|
||||
|
||||
dicto['pageno'] = 1
|
||||
params = blekko_images.request(query, dicto)
|
||||
self.assertNotIn('page', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, blekko_images.response, None)
|
||||
self.assertRaises(AttributeError, blekko_images.response, [])
|
||||
self.assertRaises(AttributeError, blekko_images.response, '')
|
||||
self.assertRaises(AttributeError, blekko_images.response, '[]')
|
||||
|
||||
response = mock.Mock(text='[]')
|
||||
self.assertEqual(blekko_images.response(response), [])
|
||||
|
||||
json = """
|
||||
[
|
||||
{
|
||||
"c": 1,
|
||||
"page_url": "http://result_url.html",
|
||||
"title": "Photo title",
|
||||
"tn_url": "http://ts1.mm.bing.net/th?id=HN.608050619474382748&pid=15.1",
|
||||
"url": "http://result_image.jpg"
|
||||
},
|
||||
{
|
||||
"c": 2,
|
||||
"page_url": "http://companyorange.simpsite.nl/OSM",
|
||||
"title": "OSM",
|
||||
"tn_url": "http://ts2.mm.bing.net/th?id=HN.608048068264919461&pid=15.1",
|
||||
"url": "http://simpsite.nl/userdata2/58985/Home/OSM.bmp"
|
||||
},
|
||||
{
|
||||
"c": 3,
|
||||
"page_url": "http://invincible.webklik.nl/page/osm",
|
||||
"title": "OSM",
|
||||
"tn_url": "http://ts1.mm.bing.net/th?id=HN.608024514657649476&pid=15.1",
|
||||
"url": "http://www.webklik.nl/user_files/2009_09/65324/osm.gif"
|
||||
},
|
||||
{
|
||||
"c": 4,
|
||||
"page_url": "http://www.offshorenorway.no/event/companyDetail/id/12492",
|
||||
"title": "Go to OSM Offshore AS homepage",
|
||||
"tn_url": "http://ts2.mm.bing.net/th?id=HN.608054265899847285&pid=15.1",
|
||||
"url": "http://www.offshorenorway.no/firmalogo/OSM-logo.png"
|
||||
}
|
||||
]
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = blekko_images.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 4)
|
||||
self.assertEqual(results[0]['title'], 'Photo title')
|
||||
self.assertEqual(results[0]['url'], 'http://result_url.html')
|
||||
self.assertEqual(results[0]['img_src'], 'http://result_image.jpg')
|
|
@ -1,384 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import btdigg
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestBtdiggEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = btdigg.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('btdigg.org', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, btdigg.response, None)
|
||||
self.assertRaises(AttributeError, btdigg.response, [])
|
||||
self.assertRaises(AttributeError, btdigg.response, '')
|
||||
self.assertRaises(AttributeError, btdigg.response, '[]')
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(btdigg.response(response), [])
|
||||
|
||||
html = """
|
||||
<div id="search_res">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">8 B</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">710</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">5</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = btdigg.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Should be the title')
|
||||
self.assertEqual(results[0]['url'], 'https://btdigg.org/url')
|
||||
self.assertEqual(results[0]['content'], 'Content')
|
||||
self.assertEqual(results[0]['seed'], 5)
|
||||
self.assertEqual(results[0]['leech'], 0)
|
||||
self.assertEqual(results[0]['filesize'], 8)
|
||||
self.assertEqual(results[0]['files'], 710)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:magnet&dn=Test')
|
||||
|
||||
html = """
|
||||
<div id="search_res">
|
||||
<table>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = btdigg.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
html = """
|
||||
<div id="search_res">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">1 KB</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">710</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">5</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">1 MB</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">a</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">4</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">1 GB</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">710</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">3</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">1 TB</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">710</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">2</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="idx">1</td>
|
||||
<td>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="torrent_name">
|
||||
<a href="/url">Should be the title</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="torrent_name_tbl">
|
||||
<tr>
|
||||
<td class="ttth">
|
||||
<a onclick="fclck(this.href)" href="magnet:?xt=urn:btih:magnet&dn=Test"
|
||||
title="Télécharger des liens Magnet">[magnet]</a>
|
||||
</td>
|
||||
<td class="ttth">
|
||||
<a href="https://btcloud.io/manager?cmd=add&info_hash=hash"
|
||||
target="_blank" title="Ajouter à BTCloud">[cloud]</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Taille:</span>
|
||||
<span class="attr_val">a TB</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Fichiers:</span>
|
||||
<span class="attr_val">710</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Téléchargements:</span>
|
||||
<span class="attr_val">z</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Temps:</span>
|
||||
<span class="attr_val">417.8 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Dernière mise à jour:</span>
|
||||
<span class="attr_val">5.3 jours</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="attr_name">Faux:</span>
|
||||
<span class="attr_val">Aucun</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre class="snippet">
|
||||
Content
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = btdigg.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 5)
|
||||
self.assertEqual(results[0]['title'], 'Should be the title')
|
||||
self.assertEqual(results[0]['url'], 'https://btdigg.org/url')
|
||||
self.assertEqual(results[0]['content'], 'Content')
|
||||
self.assertEqual(results[0]['seed'], 5)
|
||||
self.assertEqual(results[0]['leech'], 0)
|
||||
self.assertEqual(results[0]['files'], 710)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:magnet&dn=Test')
|
||||
self.assertEqual(results[0]['filesize'], 1024)
|
||||
self.assertEqual(results[1]['filesize'], 1048576)
|
||||
self.assertEqual(results[2]['filesize'], 1073741824)
|
||||
self.assertEqual(results[3]['filesize'], 1099511627776)
|
|
@ -1,43 +0,0 @@
|
|||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
import mock
|
||||
from searx.engines import currency_convert
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestCurrencyConvertEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = currency_convert.request(query, dicto)
|
||||
self.assertNotIn('url', params)
|
||||
|
||||
query = 'convert 10 Pound Sterlings to United States Dollars'
|
||||
params = currency_convert.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn('finance.yahoo.com', params['url'])
|
||||
self.assertIn('GBP', params['url'])
|
||||
self.assertIn('USD', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
dicto = defaultdict(dict)
|
||||
dicto['ammount'] = float(10)
|
||||
dicto['from'] = "GBP"
|
||||
dicto['to'] = "USD"
|
||||
dicto['from_name'] = "pound sterling"
|
||||
dicto['to_name'] = "United States dollar"
|
||||
response = mock.Mock(text='a,b,c,d', search_params=dicto)
|
||||
self.assertEqual(currency_convert.response(response), [])
|
||||
|
||||
csv = "2,0.5,1"
|
||||
response = mock.Mock(text=csv, search_params=dicto)
|
||||
results = currency_convert.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['answer'], '10.0 GBP = 5.0 USD, 1 GBP (pound sterling)' +
|
||||
' = 0.5 USD (United States dollar)')
|
||||
now_date = datetime.now().strftime('%Y%m%d')
|
||||
self.assertEqual(results[0]['url'], 'https://finance.yahoo.com/currency/converter-results/' +
|
||||
now_date + '/10.0-gbp-to-usd.html')
|
|
@ -1,74 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import dailymotion
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDailymotionEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = dailymotion.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('dailymotion.com' in params['url'])
|
||||
self.assertTrue('fr' in params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = dailymotion.request(query, dicto)
|
||||
self.assertTrue('en' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, dailymotion.response, None)
|
||||
self.assertRaises(AttributeError, dailymotion.response, [])
|
||||
self.assertRaises(AttributeError, dailymotion.response, '')
|
||||
self.assertRaises(AttributeError, dailymotion.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(dailymotion.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(dailymotion.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"page": 1,
|
||||
"limit": 5,
|
||||
"explicit": false,
|
||||
"total": 289487,
|
||||
"has_more": true,
|
||||
"list": [
|
||||
{
|
||||
"created_time": 1422173451,
|
||||
"title": "Title",
|
||||
"description": "Description",
|
||||
"duration": 81,
|
||||
"url": "http://www.url",
|
||||
"thumbnail_360_url": "http://thumbnail",
|
||||
"id": "x2fit7q"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = dailymotion.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://www.url')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
self.assertIn('x2fit7q', results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.dailymotion.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = dailymotion.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,57 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import deezer
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDeezerEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = deezer.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('deezer.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, deezer.response, None)
|
||||
self.assertRaises(AttributeError, deezer.response, [])
|
||||
self.assertRaises(AttributeError, deezer.response, '')
|
||||
self.assertRaises(AttributeError, deezer.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(deezer.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(deezer.response(response), [])
|
||||
|
||||
json = """
|
||||
{"data":[
|
||||
{"id":100, "title":"Title of track",
|
||||
"link":"https:\/\/www.deezer.com\/track\/1094042","duration":232,
|
||||
"artist":{"id":200,"name":"Artist Name",
|
||||
"link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"},
|
||||
"album":{"id":118106,"title":"Album Title","type":"album"},"type":"track"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = deezer.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title of track')
|
||||
self.assertEqual(results[0]['url'], 'https://www.deezer.com/track/1094042')
|
||||
self.assertEqual(results[0]['content'], 'Artist Name • Album Title • Title of track')
|
||||
self.assertTrue('100' in results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{"data":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = deezer.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,118 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import deviantart
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDeviantartEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = deviantart.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('deviantart.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, deviantart.response, None)
|
||||
self.assertRaises(AttributeError, deviantart.response, [])
|
||||
self.assertRaises(AttributeError, deviantart.response, '')
|
||||
self.assertRaises(AttributeError, deviantart.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(deviantart.response(response), [])
|
||||
|
||||
response = mock.Mock(status_code=302)
|
||||
self.assertEqual(deviantart.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="tt-a tt-fh tt-boxed" collect_rid="1:149167425"
|
||||
usericon="http://a.deviantart.net/avatars/t/e/test-0.gif" userid="233301"
|
||||
username="test-0" symbol="~" category="digitalart/animation">
|
||||
<span class="tt-w" style="width: auto; max-width: 277px;">
|
||||
<span class="tt-fh-tc" style="width: 202px;">
|
||||
<span class="tt-bb" style="width: 202px;">
|
||||
</span>
|
||||
<span class="shadow">
|
||||
<a class="thumb" href="http://url.of.result/2nd.part.of.url"
|
||||
title="Behoimi BE Animation Test by test-0, Jan 4,
|
||||
2010 in Digital Art > Animation"> <i></i>
|
||||
<img width="200" height="200" alt="Test"
|
||||
src="http://url.of.thumbnail" data-src="http://th08.deviantart.net/test.jpg">
|
||||
</a>
|
||||
</span>
|
||||
<!-- ^TTT -->
|
||||
</span>
|
||||
<span class="details">
|
||||
<a href="http://test-0.deviantart.com/art/Test" class="t"
|
||||
title="Behoimi BE Animation Test by test-0, Jan 4, 2010">
|
||||
<span class="tt-fh-oe">Title of image</span> </a>
|
||||
<small>
|
||||
<span class="category">
|
||||
<span class="age">
|
||||
5 years ago
|
||||
</span>
|
||||
in <a title="Behoimi BE Animation Test by test-0, Jan 4, 2010"
|
||||
href="http://www.deviantart.com/browse/all/digitalart/animation/">Animation</a>
|
||||
</span>
|
||||
<div class="commentcount">
|
||||
<a href="http://test-0.deviantart.com/art/Test#comments">
|
||||
<span class="iconcommentsstats"></span>9 Comments</a>
|
||||
</div>
|
||||
<a class="mlt-link" href="http://www.deviantart.com/morelikethis/149167425">
|
||||
<span class="mlt-icon"></span> <span class="mlt-text">More Like This</span> </a>
|
||||
</span>
|
||||
</small> <!-- TTT$ -->
|
||||
</span>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = deviantart.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title of image')
|
||||
self.assertEqual(results[0]['url'], 'http://url.of.result/2nd.part.of.url')
|
||||
self.assertNotIn('content', results[0])
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'https://url.of.thumbnail')
|
||||
|
||||
html = """
|
||||
<span class="tt-fh-tc" style="width: 202px;">
|
||||
<span class="tt-bb" style="width: 202px;">
|
||||
</span>
|
||||
<span class="shadow">
|
||||
<a class="thumb" href="http://url.of.result/2nd.part.of.url"
|
||||
title="Behoimi BE Animation Test by test-0, Jan 4,
|
||||
2010 in Digital Art > Animation"> <i></i>
|
||||
<img width="200" height="200" alt="Test"
|
||||
src="http://url.of.thumbnail" data-src="http://th08.deviantart.net/test.jpg">
|
||||
</a>
|
||||
</span>
|
||||
<!-- ^TTT -->
|
||||
</span>
|
||||
<span class="details">
|
||||
<a href="http://test-0.deviantart.com/art/Test" class="t"
|
||||
title="Behoimi BE Animation Test by test-0, Jan 4, 2010">
|
||||
<span class="tt-fh-oe">Title of image</span> </a>
|
||||
<small>
|
||||
<span class="category">
|
||||
<span class="age">
|
||||
5 years ago
|
||||
</span>
|
||||
in <a title="Behoimi BE Animation Test by test-0, Jan 4, 2010"
|
||||
href="http://www.deviantart.com/browse/all/digitalart/animation/">Animation</a>
|
||||
</span>
|
||||
<div class="commentcount">
|
||||
<a href="http://test-0.deviantart.com/art/Test#comments">
|
||||
<span class="iconcommentsstats"></span>9 Comments</a>
|
||||
</div>
|
||||
<a class="mlt-link" href="http://www.deviantart.com/morelikethis/149167425">
|
||||
<span class="mlt-icon"></span> <span class="mlt-text">More Like This</span> </a>
|
||||
</span>
|
||||
</small> <!-- TTT$ -->
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = deviantart.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,101 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import digg
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDiggEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = digg.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('digg.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, digg.response, None)
|
||||
self.assertRaises(AttributeError, digg.response, [])
|
||||
self.assertRaises(AttributeError, digg.response, '')
|
||||
self.assertRaises(AttributeError, digg.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(digg.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(digg.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "ok",
|
||||
"num": 10,
|
||||
"next_position": 20,
|
||||
"html": "<article itemscope itemtype=\\"http://schema.org/Article\\"
|
||||
class=\\"story-container digg-story-el hentry entry story-1sRANah col-1\\"
|
||||
data-content-id=\\"1sRANah\\" data-contenturl=\\"http://url.of.link\\"
|
||||
data-position=\\"0\\" data-diggs=\\"24\\" data-tweets=\\"69\\"
|
||||
data-digg-score=\\"1190\\"> <div class=\\"story-image story-image-thumb\\">
|
||||
<a data-position=\\"0\\" data-content-id=\\"1sRANah\\"
|
||||
class=\\"story-link\\" href=\\"http://www.thedailybeast.com/\\"
|
||||
target=\\"_blank\\"><img class=\\"story-image-img\\"
|
||||
src=\\"http://url.of.image.jpeg\\" width=\\"312\\" height=\\"170\\"
|
||||
alt=\\"\\" /> </a> </div> <div class=\\"story-content\\"><header
|
||||
class=\\"story-header\\"> <div itemprop=\\"alternativeHeadline\\"
|
||||
class=\\"story-kicker\\" >Kicker</div> <h2 itemprop=\\"headline\\"
|
||||
class=\\"story-title entry-title\\"><a class=\\"story-title-link story-link\\"
|
||||
rel=\\"bookmark\\" itemprop=\\"url\\" href=\\"http://www.thedailybeast.com/\\"
|
||||
target=\\"_blank\\">Title of article</h2> <div class=\\"story-meta\\">
|
||||
<div class=\\"story-score \\">
|
||||
<div class=\\"story-score-diggscore diggscore-1sRANah\\">1190</div>
|
||||
<div class=\\"story-score-details\\"> <div class=\\"arrow\\"></div>
|
||||
<ul class=\\"story-score-details-list\\"> <li
|
||||
class=\\"story-score-detail story-score-diggs\\"><span
|
||||
class=\\"label\\">Diggs:</span> <span class=\\"count diggs-1sRANah\\">24</span>
|
||||
</li> <li class=\\"story-score-detail story-score-twitter\\"><span
|
||||
class=\\"label\\">Tweets:</span> <span class=\\"count tweets-1sRANah\\">69</span>
|
||||
</li> <li class=\\"story-score-detail story-score-facebook\\"><span
|
||||
class=\\"label\\">Facebook Shares:</span> <span
|
||||
class=\\"count fb_shares-1sRANah\\">1097</span></li> </ul> </div> </div>
|
||||
<span class=\\"story-meta-item story-source\\"> <a
|
||||
itemprop=\\"publisher copyrightHolder sourceOrganization provider\\"
|
||||
class=\\"story-meta-item-link story-source-link\\"
|
||||
href=\\"/source/thedailybeast.com\\">The Daily Beast </a> </span>
|
||||
<span class=\\"story-meta-item story-tag first-tag\\"> <a
|
||||
itemprop=\\"keywords\\" rel=\\"tag\\"
|
||||
class=\\"story-meta-item-link story-tag-link\\" href=\\"/tag/news\\">News</a>
|
||||
</span> <abbr class=\\"published story-meta-item story-timestamp\\"
|
||||
title=\\"2014-10-18 14:53:45\\"> <time datetime=\\"2014-10-18 14:53:45\\">18 Oct 2014</time>
|
||||
</abbr> </div> </header> </div> <ul class=\\"story-actions\\"> <li
|
||||
class=\\"story-action story-action-digg btn-story-action-container\\">
|
||||
<a class=\\"target digg-1sRANah\\" href=\\"#\\">Digg</a></li> <li
|
||||
class=\\"story-action story-action-save btn-story-action-container\\">
|
||||
<a class=\\"target save-1sRANah\\" href=\\"#\\">Save</a></li> <li
|
||||
class=\\"story-action story-action-share\\"><a
|
||||
class=\\"target share-facebook\\" href=\\"https://www.facebook.com/\\">Facebook</a></li>
|
||||
<li class=\\"story-action story-action-share\\"><a class=\\"target share-twitter\\"
|
||||
href=\\"https://twitter.com/\\">Twitter</a></li> </ul> </article>"
|
||||
}
|
||||
"""
|
||||
json = json.replace('\r\n', '').replace('\n', '').replace('\r', '')
|
||||
response = mock.Mock(text=json)
|
||||
results = digg.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title of article')
|
||||
self.assertEqual(results[0]['url'], 'http://url.of.link')
|
||||
self.assertEqual(results[0]['thumbnail'], 'http://url.of.image.jpeg')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "error",
|
||||
"num": 10,
|
||||
"next_position": 20
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = digg.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,79 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import doku
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDokuEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
params = doku.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, doku.response, None)
|
||||
self.assertRaises(AttributeError, doku.response, [])
|
||||
self.assertRaises(AttributeError, doku.response, '')
|
||||
self.assertRaises(AttributeError, doku.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(doku.response(response), [])
|
||||
|
||||
html = u"""
|
||||
<div class="search_quickresult">
|
||||
<h3>Pages trouvées :</h3>
|
||||
<ul class="search_quickhits">
|
||||
<li> <a href="/xfconf-query" class="wikilink1" title="xfconf-query">xfconf-query</a></li>
|
||||
</ul>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = doku.response(response)
|
||||
expected = [{'content': '', 'title': 'xfconf-query', 'url': 'http://localhost:8090/xfconf-query'}]
|
||||
self.assertEqual(doku.response(response), expected)
|
||||
|
||||
html = u"""
|
||||
<dl class="search_results">
|
||||
<dt><a href="/xvnc?s[]=query" class="wikilink1" title="xvnc">xvnc</a>: 40 Occurrences trouvées</dt>
|
||||
<dd>er = /usr/bin/Xvnc
|
||||
server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 640x480 ... er = /usr/bin/Xvnc
|
||||
server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 800x600 ... er = /usr/bin/Xvnc
|
||||
server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 1024x768 ... er = /usr/bin/Xvnc
|
||||
server_args = -inetd -<strong class="search_hit">query</strong> localhost -geometry 1280x1024 -depth 8 -Sec</dd>
|
||||
<dt><a href="/postfix_mysql_tls_sasl_1404?s[]=query"
|
||||
class="wikilink1"
|
||||
title="postfix_mysql_tls_sasl_1404">postfix_mysql_tls_sasl_1404</a>: 14 Occurrences trouvées</dt>
|
||||
<dd>tdepasse
|
||||
hosts = 127.0.0.1
|
||||
dbname = postfix
|
||||
<strong class="search_hit">query</strong> = SELECT goto FROM alias WHERE address='%s' AND a... tdepasse
|
||||
hosts = 127.0.0.1
|
||||
dbname = postfix
|
||||
<strong class="search_hit">query</strong> = SELECT domain FROM domain WHERE domain='%s'
|
||||
#optional <strong class="search_hit">query</strong> to use when relaying for backup MX
|
||||
#<strong class="search_hit">query</strong> = SELECT domain FROM domain WHERE domain='%s' and backupmx =</dd>
|
||||
<dt><a href="/bind9?s[]=query" class="wikilink1" title="bind9">bind9</a>: 12 Occurrences trouvées</dt>
|
||||
<dd> printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: <strong class="search_hit">QUERY</strong>, status: NOERROR, id: 13427
|
||||
;; flags: qr aa rd ra; <strong class="search_hit">QUERY</strong>: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
|
||||
|
||||
[...]
|
||||
|
||||
;; <strong class="search_hit">Query</strong> time: 1 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;... par la requête (<strong class="search_hit">Query</strong> time) , entre la première et la deuxième requête.</dd>
|
||||
</dl>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = doku.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertEqual(results[0]['title'], 'xvnc')
|
||||
# FIXME self.assertEqual(results[0]['url'], u'http://this.should.be.the.link/ű')
|
||||
# FIXME self.assertEqual(results[0]['content'], 'This should be the content.')
|
|
@ -1,71 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import duckduckgo
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDuckduckgoEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = duckduckgo.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('duckduckgo.com', params['url'])
|
||||
self.assertIn('fr-fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = duckduckgo.request(query, dicto)
|
||||
self.assertIn('en-us', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, duckduckgo.response, None)
|
||||
self.assertRaises(AttributeError, duckduckgo.response, [])
|
||||
self.assertRaises(AttributeError, duckduckgo.response, '')
|
||||
self.assertRaises(AttributeError, duckduckgo.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(duckduckgo.response(response), [])
|
||||
|
||||
html = u"""
|
||||
<div class="result results_links results_links_deep web-result result--no-result">
|
||||
<div class="links_main links_deep result__body">
|
||||
<h2 class="result__title">
|
||||
</h2>
|
||||
<div class="no-results">No results</div>
|
||||
<div class="result__extras">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = duckduckgo.response(response)
|
||||
self.assertEqual(duckduckgo.response(response), [])
|
||||
|
||||
html = u"""
|
||||
<div class="result results_links results_links_deep web-result ">
|
||||
<div class="links_main links_deep result__body">
|
||||
<h2 class="result__title">
|
||||
<a rel="nofollow" class="result__a" href="http://this.should.be.the.link/ű">
|
||||
This <b>is</b> <b>the</b> title
|
||||
</a>
|
||||
</h2>
|
||||
<a class="result__snippet" href="http://this.should.be.the.link/ű">
|
||||
<b>This</b> should be the content.
|
||||
</a>
|
||||
<div class="result__extras">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = duckduckgo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], u'http://this.should.be.the.link/ű')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
|
@ -1,250 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import duckduckgo_definitions
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDDGDefinitionsEngine(SearxTestCase):
|
||||
|
||||
def test_result_to_text(self):
|
||||
url = ''
|
||||
text = 'Text'
|
||||
html_result = 'Html'
|
||||
result = duckduckgo_definitions.result_to_text(url, text, html_result)
|
||||
self.assertEqual(result, text)
|
||||
|
||||
html_result = '<a href="url">Text in link</a>'
|
||||
result = duckduckgo_definitions.result_to_text(url, text, html_result)
|
||||
self.assertEqual(result, 'Text in link')
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = duckduckgo_definitions.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('duckduckgo.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, duckduckgo_definitions.response, None)
|
||||
self.assertRaises(AttributeError, duckduckgo_definitions.response, [])
|
||||
self.assertRaises(AttributeError, duckduckgo_definitions.response, '')
|
||||
self.assertRaises(AttributeError, duckduckgo_definitions.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(duckduckgo_definitions.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(duckduckgo_definitions.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"DefinitionSource": "definition source",
|
||||
"Heading": "heading",
|
||||
"ImageWidth": 0,
|
||||
"RelatedTopics": [
|
||||
{
|
||||
"Result": "Top-level domains",
|
||||
"Icon": {
|
||||
"URL": "",
|
||||
"Height": "",
|
||||
"Width": ""
|
||||
},
|
||||
"FirstURL": "https://first.url",
|
||||
"Text": "text"
|
||||
},
|
||||
{
|
||||
"Topics": [
|
||||
{
|
||||
"Result": "result topic",
|
||||
"Icon": {
|
||||
"URL": "",
|
||||
"Height": "",
|
||||
"Width": ""
|
||||
},
|
||||
"FirstURL": "https://duckduckgo.com/?q=2%2F2",
|
||||
"Text": "result topic text"
|
||||
}
|
||||
],
|
||||
"Name": "name"
|
||||
}
|
||||
],
|
||||
"Entity": "Entity",
|
||||
"Type": "A",
|
||||
"Redirect": "",
|
||||
"DefinitionURL": "http://definition.url",
|
||||
"AbstractURL": "https://abstract.url",
|
||||
"Definition": "this is the definition",
|
||||
"AbstractSource": "abstract source",
|
||||
"Infobox": {
|
||||
"content": [
|
||||
{
|
||||
"data_type": "string",
|
||||
"value": "1999",
|
||||
"label": "Introduced",
|
||||
"wiki_order": 0
|
||||
}
|
||||
],
|
||||
"meta": [
|
||||
{
|
||||
"data_type": "string",
|
||||
"value": ".test",
|
||||
"label": "article_title"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Image": "image.png",
|
||||
"ImageIsLogo": 0,
|
||||
"Abstract": "abstract",
|
||||
"AbstractText": "abstract text",
|
||||
"AnswerType": "",
|
||||
"ImageHeight": 0,
|
||||
"Results": [{
|
||||
"Result" : "result title",
|
||||
"Icon" : {
|
||||
"URL" : "result url",
|
||||
"Height" : 16,
|
||||
"Width" : 16
|
||||
},
|
||||
"FirstURL" : "result first url",
|
||||
"Text" : "result text"
|
||||
}
|
||||
],
|
||||
"Answer": "answer"
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = duckduckgo_definitions.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 4)
|
||||
self.assertEqual(results[0]['answer'], 'answer')
|
||||
self.assertEqual(results[1]['title'], 'heading')
|
||||
self.assertEqual(results[1]['url'], 'result first url')
|
||||
self.assertEqual(results[2]['suggestion'], 'text')
|
||||
self.assertEqual(results[3]['infobox'], 'heading')
|
||||
self.assertEqual(results[3]['id'], 'https://definition.url')
|
||||
self.assertEqual(results[3]['entity'], 'Entity')
|
||||
self.assertIn('abstract', results[3]['content'])
|
||||
self.assertIn('this is the definition', results[3]['content'])
|
||||
self.assertEqual(results[3]['img_src'], 'image.png')
|
||||
self.assertIn('Introduced', results[3]['attributes'][0]['label'])
|
||||
self.assertIn('1999', results[3]['attributes'][0]['value'])
|
||||
self.assertIn({'url': 'https://abstract.url', 'title': 'abstract source'}, results[3]['urls'])
|
||||
self.assertIn({'url': 'http://definition.url', 'title': 'definition source'}, results[3]['urls'])
|
||||
self.assertIn({'name': 'name', 'suggestions': ['result topic text']}, results[3]['relatedTopics'])
|
||||
|
||||
json = """
|
||||
{
|
||||
"DefinitionSource": "definition source",
|
||||
"Heading": "heading",
|
||||
"ImageWidth": 0,
|
||||
"RelatedTopics": [],
|
||||
"Entity": "Entity",
|
||||
"Type": "A",
|
||||
"Redirect": "",
|
||||
"DefinitionURL": "",
|
||||
"AbstractURL": "https://abstract.url",
|
||||
"Definition": "",
|
||||
"AbstractSource": "abstract source",
|
||||
"Image": "",
|
||||
"ImageIsLogo": 0,
|
||||
"Abstract": "",
|
||||
"AbstractText": "abstract text",
|
||||
"AnswerType": "",
|
||||
"ImageHeight": 0,
|
||||
"Results": [],
|
||||
"Answer": ""
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = duckduckgo_definitions.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['url'], 'https://abstract.url')
|
||||
self.assertEqual(results[0]['title'], 'heading')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
|
||||
json = """
|
||||
{
|
||||
"DefinitionSource": "definition source",
|
||||
"Heading": "heading",
|
||||
"ImageWidth": 0,
|
||||
"RelatedTopics": [
|
||||
{
|
||||
"Result": "Top-level domains",
|
||||
"Icon": {
|
||||
"URL": "",
|
||||
"Height": "",
|
||||
"Width": ""
|
||||
},
|
||||
"FirstURL": "https://first.url",
|
||||
"Text": "heading"
|
||||
},
|
||||
{
|
||||
"Name": "name"
|
||||
},
|
||||
{
|
||||
"Topics": [
|
||||
{
|
||||
"Result": "result topic",
|
||||
"Icon": {
|
||||
"URL": "",
|
||||
"Height": "",
|
||||
"Width": ""
|
||||
},
|
||||
"FirstURL": "https://duckduckgo.com/?q=2%2F2",
|
||||
"Text": "heading"
|
||||
}
|
||||
],
|
||||
"Name": "name"
|
||||
}
|
||||
],
|
||||
"Entity": "Entity",
|
||||
"Type": "A",
|
||||
"Redirect": "",
|
||||
"DefinitionURL": "http://definition.url",
|
||||
"AbstractURL": "https://abstract.url",
|
||||
"Definition": "this is the definition",
|
||||
"AbstractSource": "abstract source",
|
||||
"Infobox": {
|
||||
"meta": [
|
||||
{
|
||||
"data_type": "string",
|
||||
"value": ".test",
|
||||
"label": "article_title"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Image": "image.png",
|
||||
"ImageIsLogo": 0,
|
||||
"Abstract": "abstract",
|
||||
"AbstractText": "abstract text",
|
||||
"AnswerType": "",
|
||||
"ImageHeight": 0,
|
||||
"Results": [{
|
||||
"Result" : "result title",
|
||||
"Icon" : {
|
||||
"URL" : "result url",
|
||||
"Height" : 16,
|
||||
"Width" : 16
|
||||
},
|
||||
"Text" : "result text"
|
||||
}
|
||||
],
|
||||
"Answer": ""
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = duckduckgo_definitions.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['infobox'], 'heading')
|
||||
self.assertEqual(results[0]['id'], 'https://definition.url')
|
||||
self.assertEqual(results[0]['entity'], 'Entity')
|
||||
self.assertIn('abstract', results[0]['content'])
|
||||
self.assertIn('this is the definition', results[0]['content'])
|
||||
self.assertEqual(results[0]['img_src'], 'image.png')
|
||||
self.assertIn({'url': 'https://abstract.url', 'title': 'abstract source'}, results[0]['urls'])
|
||||
self.assertIn({'url': 'http://definition.url', 'title': 'definition source'}, results[0]['urls'])
|
||||
self.assertIn({'name': 'name', 'suggestions': []}, results[0]['relatedTopics'])
|
|
@ -1,26 +0,0 @@
|
|||
from searx.engines import dummy
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestDummyEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
test_params = [
|
||||
[1, 2, 3],
|
||||
['a'],
|
||||
[],
|
||||
1
|
||||
]
|
||||
for params in test_params:
|
||||
self.assertEqual(dummy.request(None, params), params)
|
||||
|
||||
def test_response(self):
|
||||
responses = [
|
||||
None,
|
||||
[],
|
||||
True,
|
||||
dict(),
|
||||
tuple()
|
||||
]
|
||||
for response in responses:
|
||||
self.assertEqual(dummy.response(response), [])
|
|
@ -1,116 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import faroo
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestFarooEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
dicto['category'] = 'general'
|
||||
params = faroo.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('faroo.com', params['url'])
|
||||
self.assertIn('en', params['url'])
|
||||
self.assertIn('web', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = faroo.request(query, dicto)
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
dicto['language'] = 'de_DE'
|
||||
params = faroo.request(query, dicto)
|
||||
self.assertIn('de', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, faroo.response, None)
|
||||
self.assertRaises(AttributeError, faroo.response, [])
|
||||
self.assertRaises(AttributeError, faroo.response, '')
|
||||
self.assertRaises(AttributeError, faroo.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(faroo.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(faroo.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}', status_code=401)
|
||||
self.assertRaises(Exception, faroo.response, response)
|
||||
|
||||
response = mock.Mock(text='{"data": []}', status_code=429)
|
||||
self.assertRaises(Exception, faroo.response, response)
|
||||
|
||||
json = """
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"title": "This is the title",
|
||||
"kwic": "This is the content",
|
||||
"content": "",
|
||||
"url": "http://this.is.the.url/",
|
||||
"iurl": "",
|
||||
"domain": "css3test.com",
|
||||
"author": "Jim Dalrymple",
|
||||
"news": true,
|
||||
"votes": "10",
|
||||
"date": 1360622563000,
|
||||
"related": []
|
||||
},
|
||||
{
|
||||
"title": "This is the title2",
|
||||
"kwic": "This is the content2",
|
||||
"content": "",
|
||||
"url": "http://this.is.the.url2/",
|
||||
"iurl": "",
|
||||
"domain": "css3test.com",
|
||||
"author": "Jim Dalrymple",
|
||||
"news": false,
|
||||
"votes": "10",
|
||||
"related": []
|
||||
},
|
||||
{
|
||||
"title": "This is the title3",
|
||||
"kwic": "This is the content3",
|
||||
"content": "",
|
||||
"url": "http://this.is.the.url3/",
|
||||
"iurl": "http://upload.wikimedia.org/optimized.jpg",
|
||||
"domain": "css3test.com",
|
||||
"author": "Jim Dalrymple",
|
||||
"news": false,
|
||||
"votes": "10",
|
||||
"related": []
|
||||
}
|
||||
],
|
||||
"query": "test",
|
||||
"suggestions": [],
|
||||
"count": 100,
|
||||
"start": 1,
|
||||
"length": 10,
|
||||
"time": "15"
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = faroo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 4)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
self.assertEqual(results[1]['title'], 'This is the title2')
|
||||
self.assertEqual(results[1]['url'], 'http://this.is.the.url2/')
|
||||
self.assertEqual(results[1]['content'], 'This is the content2')
|
||||
self.assertEqual(results[3]['img_src'], 'http://upload.wikimedia.org/optimized.jpg')
|
||||
|
||||
json = """
|
||||
{}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = faroo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,49 +0,0 @@
|
|||
import mock
|
||||
from collections import defaultdict
|
||||
from searx.engines import fdroid
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestFdroidEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
dic['pageno'] = 1
|
||||
params = fdroid.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('f-droid.org' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
resp = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(fdroid.response(resp), [])
|
||||
|
||||
html = """
|
||||
<a href="https://google.com/qwerty">
|
||||
<div id="appheader">
|
||||
<div style="float:left;padding-right:10px;">
|
||||
<img src="http://example.com/image.png"
|
||||
style="width:48px;border:none;">
|
||||
</div>
|
||||
<div style="float:right;">
|
||||
<p>Details...</p>
|
||||
</div>
|
||||
<p style="color:#000000;">
|
||||
<span style="font-size:20px;">Sample title</span>
|
||||
<br>
|
||||
Sample content
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
"""
|
||||
|
||||
resp = mock.Mock(text=html)
|
||||
results = fdroid.response(resp)
|
||||
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['url'], 'https://google.com/qwerty')
|
||||
self.assertEqual(results[0]['title'], 'Sample title')
|
||||
self.assertEqual(results[0]['content'], 'Sample content')
|
||||
self.assertEqual(results[0]['img_src'], 'http://example.com/image.png')
|
|
@ -1,142 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import flickr
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestFlickrEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = flickr.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('flickr.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, flickr.response, None)
|
||||
self.assertRaises(AttributeError, flickr.response, [])
|
||||
self.assertRaises(AttributeError, flickr.response, '')
|
||||
self.assertRaises(AttributeError, flickr.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(flickr.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(flickr.response(response), [])
|
||||
|
||||
json = """
|
||||
{ "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
|
||||
"photo": [
|
||||
{ "id": "15751017054", "owner": "66847915@N08",
|
||||
"secret": "69c22afc40", "server": "7285", "farm": 8,
|
||||
"title": "Photo title", "ispublic": 1,
|
||||
"isfriend": 0, "isfamily": 0,
|
||||
"description": { "_content": "Description" },
|
||||
"ownername": "Owner",
|
||||
"url_o": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_9178e0f963_o.jpg",
|
||||
"height_o": "2100", "width_o": "2653",
|
||||
"url_n": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_n.jpg",
|
||||
"height_n": "253", "width_n": "320",
|
||||
"url_z": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_z.jpg",
|
||||
"height_z": "507", "width_z": "640" }
|
||||
] }, "stat": "ok" }
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Photo title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
|
||||
self.assertTrue('o.jpg' in results[0]['img_src'])
|
||||
self.assertTrue('n.jpg' in results[0]['thumbnail_src'])
|
||||
self.assertTrue('Owner' in results[0]['content'])
|
||||
self.assertTrue('Description' in results[0]['content'])
|
||||
|
||||
json = """
|
||||
{ "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
|
||||
"photo": [
|
||||
{ "id": "15751017054", "owner": "66847915@N08",
|
||||
"secret": "69c22afc40", "server": "7285", "farm": 8,
|
||||
"title": "Photo title", "ispublic": 1,
|
||||
"isfriend": 0, "isfamily": 0,
|
||||
"description": { "_content": "Description" },
|
||||
"ownername": "Owner",
|
||||
"url_z": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_z.jpg",
|
||||
"height_z": "507", "width_z": "640" }
|
||||
] }, "stat": "ok" }
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Photo title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
|
||||
self.assertTrue('z.jpg' in results[0]['img_src'])
|
||||
self.assertTrue('z.jpg' in results[0]['thumbnail_src'])
|
||||
self.assertTrue('Owner' in results[0]['content'])
|
||||
self.assertTrue('Description' in results[0]['content'])
|
||||
|
||||
json = """
|
||||
{ "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
|
||||
"photo": [
|
||||
{ "id": "15751017054", "owner": "66847915@N08",
|
||||
"secret": "69c22afc40", "server": "7285", "farm": 8,
|
||||
"title": "Photo title", "ispublic": 1,
|
||||
"isfriend": 0, "isfamily": 0,
|
||||
"description": { "_content": "Description" },
|
||||
"ownername": "Owner",
|
||||
"url_o": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_9178e0f963_o.jpg",
|
||||
"height_o": "2100", "width_o": "2653" }
|
||||
] }, "stat": "ok" }
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Photo title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/66847915@N08/15751017054')
|
||||
self.assertTrue('o.jpg' in results[0]['img_src'])
|
||||
self.assertTrue('o.jpg' in results[0]['thumbnail_src'])
|
||||
self.assertTrue('Owner' in results[0]['content'])
|
||||
self.assertTrue('Description' in results[0]['content'])
|
||||
|
||||
json = """
|
||||
{ "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
|
||||
"photo": [
|
||||
{ "id": "15751017054", "owner": "66847915@N08",
|
||||
"secret": "69c22afc40", "server": "7285", "farm": 8,
|
||||
"title": "Photo title", "ispublic": 1,
|
||||
"isfriend": 0, "isfamily": 0,
|
||||
"description": { "_content": "Description" },
|
||||
"ownername": "Owner",
|
||||
"url_n": "https:\/\/farm8.staticflickr.com\/7285\/15751017054_69c22afc40_n.jpg",
|
||||
"height_n": "253", "width_n": "320" }
|
||||
] }, "stat": "ok" }
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{ "photos": { "page": 1, "pages": "41001", "perpage": 100, "total": "4100032",
|
||||
"toto": [] }, "stat": "ok" }
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.flickr.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,328 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import flickr_noapi
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestFlickrNoapiEngine(SearxTestCase):
|
||||
|
||||
def test_build_flickr_url(self):
|
||||
url = flickr_noapi.build_flickr_url("uid", "pid")
|
||||
self.assertIn("uid", url)
|
||||
self.assertIn("pid", url)
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = flickr_noapi.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('flickr.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, flickr_noapi.response, None)
|
||||
self.assertRaises(AttributeError, flickr_noapi.response, [])
|
||||
self.assertRaises(AttributeError, flickr_noapi.response, '')
|
||||
self.assertRaises(AttributeError, flickr_noapi.response, '[]')
|
||||
|
||||
response = mock.Mock(text='"search-photos-lite-models","photos":{},"totalItems":')
|
||||
self.assertEqual(flickr_noapi.response(response), [])
|
||||
|
||||
response = mock.Mock(text='search-photos-lite-models","photos":{"data": []},"totalItems":')
|
||||
self.assertEqual(flickr_noapi.response(response), [])
|
||||
|
||||
# everthing is ok test
|
||||
json = """
|
||||
"search-photos-lite-models","photos":
|
||||
{
|
||||
"_data": [
|
||||
{
|
||||
"_flickrModelRegistry": "photo-lite-models",
|
||||
"title": "This is the title",
|
||||
"username": "Owner",
|
||||
"pathAlias": "klink692",
|
||||
"realname": "Owner",
|
||||
"license": 0,
|
||||
"ownerNsid": "59729010@N00",
|
||||
"canComment": false,
|
||||
"commentCount": 14,
|
||||
"faveCount": 21,
|
||||
"id": "14001294434",
|
||||
"sizes": {
|
||||
"c": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_c.jpg",
|
||||
"width": 541,
|
||||
"height": 800,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_c.jpg",
|
||||
"key": "c"
|
||||
},
|
||||
"h": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_761d32237a_h.jpg",
|
||||
"width": 1081,
|
||||
"height": 1600,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_761d32237a_h.jpg",
|
||||
"key": "h"
|
||||
},
|
||||
"k": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_f145a2c11a_k.jpg",
|
||||
"width": 1383,
|
||||
"height": 2048,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_f145a2c11a_k.jpg",
|
||||
"key": "k"
|
||||
},
|
||||
"l": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_b.jpg",
|
||||
"width": 692,
|
||||
"height": 1024,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_b.jpg",
|
||||
"key": "l"
|
||||
},
|
||||
"m": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777.jpg",
|
||||
"width": 338,
|
||||
"height": 500,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777.jpg",
|
||||
"key": "m"
|
||||
},
|
||||
"n": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_n.jpg",
|
||||
"width": 216,
|
||||
"height": 320,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_n.jpg",
|
||||
"key": "n"
|
||||
},
|
||||
"q": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_q.jpg",
|
||||
"width": 150,
|
||||
"height": 150,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_q.jpg",
|
||||
"key": "q"
|
||||
},
|
||||
"s": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_m.jpg",
|
||||
"width": 162,
|
||||
"height": 240,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_m.jpg",
|
||||
"key": "s"
|
||||
},
|
||||
"sq": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_s.jpg",
|
||||
"width": 75,
|
||||
"height": 75,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_s.jpg",
|
||||
"key": "sq"
|
||||
},
|
||||
"t": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_t.jpg",
|
||||
"width": 68,
|
||||
"height": 100,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_t.jpg",
|
||||
"key": "t"
|
||||
},
|
||||
"z": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_z.jpg",
|
||||
"width": 433,
|
||||
"height": 640,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_z.jpg",
|
||||
"key": "z"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
json = json.replace('\r\n', '').replace('\n', '').replace('\r', '')
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
|
||||
self.assertIn('k.jpg', results[0]['img_src'])
|
||||
self.assertIn('n.jpg', results[0]['thumbnail_src'])
|
||||
self.assertIn('Owner', results[0]['content'])
|
||||
|
||||
# no n size, only the z size
|
||||
json = """
|
||||
"search-photos-lite-models","photos":
|
||||
{
|
||||
"_data": [
|
||||
{
|
||||
"_flickrModelRegistry": "photo-lite-models",
|
||||
"title": "This is the title",
|
||||
"username": "Owner",
|
||||
"pathAlias": "klink692",
|
||||
"realname": "Owner",
|
||||
"license": 0,
|
||||
"ownerNsid": "59729010@N00",
|
||||
"canComment": false,
|
||||
"commentCount": 14,
|
||||
"faveCount": 21,
|
||||
"id": "14001294434",
|
||||
"sizes": {
|
||||
"z": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_z.jpg",
|
||||
"width": 433,
|
||||
"height": 640,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_z.jpg",
|
||||
"key": "z"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
|
||||
self.assertIn('z.jpg', results[0]['img_src'])
|
||||
self.assertIn('z.jpg', results[0]['thumbnail_src'])
|
||||
self.assertIn('Owner', results[0]['content'])
|
||||
|
||||
# no z or n size
|
||||
json = """
|
||||
"search-photos-lite-models","photos":
|
||||
{
|
||||
"_data": [
|
||||
{
|
||||
"_flickrModelRegistry": "photo-lite-models",
|
||||
"title": "This is the title",
|
||||
"username": "Owner",
|
||||
"pathAlias": "klink692",
|
||||
"realname": "Owner",
|
||||
"license": 0,
|
||||
"ownerNsid": "59729010@N00",
|
||||
"canComment": false,
|
||||
"commentCount": 14,
|
||||
"faveCount": 21,
|
||||
"id": "14001294434",
|
||||
"sizes": {
|
||||
"o": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_o.jpg",
|
||||
"width": 433,
|
||||
"height": 640,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_o.jpg",
|
||||
"key": "o"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.flickr.com/photos/59729010@N00/14001294434')
|
||||
self.assertIn('o.jpg', results[0]['img_src'])
|
||||
self.assertIn('o.jpg', results[0]['thumbnail_src'])
|
||||
self.assertIn('Owner', results[0]['content'])
|
||||
|
||||
# no image test
|
||||
json = """
|
||||
"search-photos-lite-models","photos":
|
||||
{
|
||||
"_data": [
|
||||
{
|
||||
"_flickrModelRegistry": "photo-lite-models",
|
||||
"title": "This is the title",
|
||||
"username": "Owner",
|
||||
"pathAlias": "klink692",
|
||||
"realname": "Owner",
|
||||
"license": 0,
|
||||
"ownerNsid": "59729010@N00",
|
||||
"canComment": false,
|
||||
"commentCount": 14,
|
||||
"faveCount": 21,
|
||||
"id": "14001294434",
|
||||
"sizes": {
|
||||
}
|
||||
}
|
||||
],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
# null test
|
||||
json = """
|
||||
"search-photos-models","photos":
|
||||
{
|
||||
"_data": [null],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
# no ownerNsid test
|
||||
json = """
|
||||
"search-photos-lite-models","photos":
|
||||
{
|
||||
"_data": [
|
||||
{
|
||||
"_flickrModelRegistry": "photo-lite-models",
|
||||
"title": "This is the title",
|
||||
"username": "Owner",
|
||||
"pathAlias": "klink692",
|
||||
"realname": "Owner",
|
||||
"license": 0,
|
||||
"canComment": false,
|
||||
"commentCount": 14,
|
||||
"faveCount": 21,
|
||||
"id": "14001294434",
|
||||
"sizes": {
|
||||
"o": {
|
||||
"displayUrl": "//farm8.staticflickr.com/7246/14001294434_410f653777_o.jpg",
|
||||
"width": 433,
|
||||
"height": 640,
|
||||
"url": "//c4.staticflickr.com/8/7246/14001294434_410f653777_o.jpg",
|
||||
"key": "o"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fetchedStart": true,
|
||||
"fetchedEnd": false,
|
||||
"totalItems": "4386039"
|
||||
},"totalItems":
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
# garbage test
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.flickr.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = flickr_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,49 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from json import dumps
|
||||
from searx.engines import frinkiac
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestFrinkiacEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
request_dict = defaultdict(dict)
|
||||
params = frinkiac.request(query, request_dict)
|
||||
self.assertTrue('url' in params)
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, frinkiac.response, None)
|
||||
self.assertRaises(AttributeError, frinkiac.response, [])
|
||||
self.assertRaises(AttributeError, frinkiac.response, '')
|
||||
self.assertRaises(AttributeError, frinkiac.response, '[]')
|
||||
|
||||
text = """
|
||||
[{"Id":770931,
|
||||
"Episode":"S06E18",
|
||||
"Timestamp":534616,
|
||||
"Filename":""},
|
||||
{"Id":1657080,
|
||||
"Episode":"S12E14",
|
||||
"Timestamp":910868,
|
||||
"Filename":""},
|
||||
{"Id":1943753,
|
||||
"Episode":"S14E21",
|
||||
"Timestamp":773439,
|
||||
"Filename":""},
|
||||
{"Id":107835,
|
||||
"Episode":"S02E03",
|
||||
"Timestamp":531709,
|
||||
"Filename":""}]
|
||||
"""
|
||||
|
||||
response = mock.Mock(text=text)
|
||||
results = frinkiac.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 4)
|
||||
self.assertEqual(results[0]['title'], u'S06E18')
|
||||
self.assertEqual(results[0]['url'], 'https://frinkiac.com/?p=caption&e=S06E18&t=534616')
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'https://frinkiac.com/img/S06E18/534616/medium.jpg')
|
||||
self.assertEqual(results[0]['img_src'], 'https://frinkiac.com/img/S06E18/534616.jpg')
|
|
@ -1,85 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import gigablast
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestGigablastEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'all'
|
||||
params = gigablast.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('gigablast.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, gigablast.response, None)
|
||||
self.assertRaises(AttributeError, gigablast.response, [])
|
||||
self.assertRaises(AttributeError, gigablast.response, '')
|
||||
self.assertRaises(AttributeError, gigablast.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{"results": []}')
|
||||
self.assertEqual(gigablast.response(response), [])
|
||||
|
||||
json = """{"results": [
|
||||
{
|
||||
"title":"South by Southwest 2016",
|
||||
"dmozEntry":{
|
||||
"dmozCatId":1041152,
|
||||
"directCatId":1,
|
||||
"dmozCatStr":"Top: Regional: North America: United States",
|
||||
"dmozTitle":"South by Southwest (SXSW)",
|
||||
"dmozSum":"Annual music, film, and interactive conference.",
|
||||
"dmozAnchor":""
|
||||
},
|
||||
"dmozEntry":{
|
||||
"dmozCatId":763945,
|
||||
"directCatId":1,
|
||||
"dmozCatStr":"Top: Regional: North America: United States",
|
||||
"dmozTitle":"South by Southwest (SXSW)",
|
||||
"dmozSum":"",
|
||||
"dmozAnchor":"www.sxsw.com"
|
||||
},
|
||||
"dmozEntry":{
|
||||
"dmozCatId":761446,
|
||||
"directCatId":1,
|
||||
"dmozCatStr":"Top: Regional: North America: United States",
|
||||
"dmozTitle":"South by Southwest (SXSW)",
|
||||
"dmozSum":"Music, film, and interactive conference and festival.",
|
||||
"dmozAnchor":""
|
||||
},
|
||||
"indirectDmozCatId":1041152,
|
||||
"indirectDmozCatId":763945,
|
||||
"indirectDmozCatId":761446,
|
||||
"contentType":"html",
|
||||
"sum":"This should be the content.",
|
||||
"url":"www.sxsw.com",
|
||||
"hopCount":0,
|
||||
"size":" 102k",
|
||||
"sizeInBytes":104306,
|
||||
"bytesUsedToComputeSummary":70000,
|
||||
"docId":269411794364,
|
||||
"docScore":586571136.000000,
|
||||
"summaryGenTimeMS":12,
|
||||
"summaryTagdbLookupTimeMS":0,
|
||||
"summaryTitleRecLoadTimeMS":1,
|
||||
"site":"www.sxsw.com",
|
||||
"spidered":1452203608,
|
||||
"firstIndexedDateUTC":1444167123,
|
||||
"contentHash32":2170650347,
|
||||
"language":"English",
|
||||
"langAbbr":"en"
|
||||
}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = gigablast.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'South by Southwest 2016')
|
||||
self.assertEqual(results[0]['url'], 'www.sxsw.com')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
|
@ -1,61 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import github
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestGitHubEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
params = github.request(query, defaultdict(dict))
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('github.com' in params['url'])
|
||||
self.assertEqual(params['headers']['Accept'], github.accept_header)
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, github.response, None)
|
||||
self.assertRaises(AttributeError, github.response, [])
|
||||
self.assertRaises(AttributeError, github.response, '')
|
||||
self.assertRaises(AttributeError, github.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(github.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"items": []}')
|
||||
self.assertEqual(github.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "title",
|
||||
"html_url": "url",
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = github.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'title')
|
||||
self.assertEqual(results[0]['url'], 'url')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
|
||||
json = """
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "title",
|
||||
"html_url": "url",
|
||||
"description": "desc"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = github.response(response)
|
||||
self.assertEqual(results[0]['content'], "desc")
|
|
@ -1,178 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
import lxml
|
||||
from searx.engines import google
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestGoogleEngine(SearxTestCase):
|
||||
|
||||
def mock_response(self, text):
|
||||
response = mock.Mock(text=text, url='https://www.google.com/search?q=test&start=0&gbv=1&gws_rd=cr')
|
||||
response.search_params = mock.Mock()
|
||||
response.search_params.get = mock.Mock(return_value='www.google.com')
|
||||
return response
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = google.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('google.fr', params['url'])
|
||||
self.assertIn('fr', params['headers']['Accept-Language'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = google.request(query, dicto)
|
||||
self.assertIn('google.com', params['url'])
|
||||
self.assertIn('en', params['headers']['Accept-Language'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, google.response, None)
|
||||
self.assertRaises(AttributeError, google.response, [])
|
||||
self.assertRaises(AttributeError, google.response, '')
|
||||
self.assertRaises(AttributeError, google.response, '[]')
|
||||
|
||||
response = self.mock_response('<html></html>')
|
||||
self.assertEqual(google.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="g">
|
||||
<h3 class="r">
|
||||
<a href="http://this.should.be.the.link/">
|
||||
<b>This</b> is <b>the</b> title
|
||||
</a>
|
||||
</h3>
|
||||
<div class="s">
|
||||
<div class="kv" style="margin-bottom:2px">
|
||||
<cite>
|
||||
<b>test</b>.psychologies.com/
|
||||
</cite>
|
||||
<div class="_nBb">
|
||||
<div style="display:inline" onclick="google.sham(this);" aria-expanded="false"
|
||||
aria-haspopup="true" tabindex="0" data-ved="0CBUQ7B0wAA">
|
||||
<span class="_O0">
|
||||
</span>
|
||||
</div>
|
||||
<div style="display:none" class="am-dropdown-menu" role="menu" tabindex="-1">
|
||||
<ul>
|
||||
<li class="_Ykb">
|
||||
<a class="_Zkb" href="http://www.google.fr/url?url=http://webcache.googleusercontent
|
||||
.com/search%3Fcache:R1Z_4pGXjuIJ:http://test.psychologies.com/">
|
||||
En cache
|
||||
</a>
|
||||
</li>
|
||||
<li class="_Ykb">
|
||||
<a class="_Zkb" href="/search?safe=off&q=related:test.psy.com/">
|
||||
Pages similaires
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="st">
|
||||
This should be the content.
|
||||
</span>
|
||||
<br>
|
||||
<div class="osl">
|
||||
<a href="http://www.google.fr/url?url=http://test.psychologies.com/tests/">
|
||||
Test Personnalité
|
||||
</a> -
|
||||
<a href="http://www.google.fr/url?url=http://test.psychologies.com/test/">
|
||||
Tests - Moi
|
||||
</a> -
|
||||
<a href="http://www.google.fr/url?url=http://test.psychologies.com/test/tests-couple">
|
||||
Test Couple
|
||||
</a>
|
||||
-
|
||||
<a href="http://www.google.fr/url?url=http://test.psychologies.com/tests/tests-amour">
|
||||
Test Amour
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g">
|
||||
<h3 class="r">
|
||||
<a href="http://www.google.com/images?q=toto">
|
||||
<b>This</b>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="g">
|
||||
<h3 class="r">
|
||||
<a href="http://www.google.com/search?q=toto">
|
||||
<b>This</b> is
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="g">
|
||||
<h3 class="r">
|
||||
<a href="€">
|
||||
<b>This</b> is <b>the</b>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="g">
|
||||
<h3 class="r">
|
||||
<a href="/url?q=url">
|
||||
<b>This</b> is <b>the</b>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<p class="_Bmc" style="margin:3px 8px">
|
||||
<a href="/search?num=20&safe=off&q=t&revid=1754833769&sa=X&ei=-&ved=">
|
||||
suggestion <b>title</b>
|
||||
</a>
|
||||
</p>
|
||||
"""
|
||||
response = self.mock_response(html)
|
||||
results = google.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
||||
self.assertEqual(results[1]['suggestion'], 'suggestion title')
|
||||
|
||||
html = """
|
||||
<li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
|
||||
</li>
|
||||
"""
|
||||
response = self.mock_response(html)
|
||||
results = google.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
response = mock.Mock(text='<html></html>', url='https://sorry.google.com')
|
||||
response.search_params = mock.Mock()
|
||||
response.search_params.get = mock.Mock(return_value='www.google.com')
|
||||
self.assertRaises(RuntimeWarning, google.response, response)
|
||||
|
||||
response = mock.Mock(text='<html></html>', url='https://www.google.com/sorry/IndexRedirect')
|
||||
response.search_params = mock.Mock()
|
||||
response.search_params.get = mock.Mock(return_value='www.google.com')
|
||||
self.assertRaises(RuntimeWarning, google.response, response)
|
||||
|
||||
def test_parse_images(self):
|
||||
html = """
|
||||
<li>
|
||||
<div>
|
||||
<a href="http://www.google.com/url?q=http://this.is.the.url/">
|
||||
<img style="margin:3px 0;margin-right:6px;padding:0" height="90"
|
||||
src="https://this.is.the.image/image.jpg" width="60" align="middle" alt="" border="0">
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
"""
|
||||
dom = lxml.html.fromstring(html)
|
||||
results = google.parse_images(dom, 'www.google.com')
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
|
||||
self.assertEqual(results[0]['title'], '')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['img_src'], 'https://this.is.the.image/image.jpg')
|
|
@ -1,58 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import google_images
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestGoogleImagesEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['safesearch'] = 1
|
||||
params = google_images.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('safe=active', params['url'])
|
||||
|
||||
dicto['safesearch'] = 0
|
||||
params = google_images.request(query, dicto)
|
||||
self.assertNotIn('safe', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, google_images.response, None)
|
||||
self.assertRaises(AttributeError, google_images.response, [])
|
||||
self.assertRaises(AttributeError, google_images.response, '')
|
||||
self.assertRaises(AttributeError, google_images.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<div></div>')
|
||||
self.assertEqual(google_images.response(response), [])
|
||||
|
||||
html = """
|
||||
<div style="display:none">
|
||||
<div eid="fWhnVq4Shqpp3pWo4AM" id="isr_scm_1" style="display:none"></div>
|
||||
<div data-cei="fWhnVq4Shqpp3pWo4AM" class="rg_add_chunk"><!--m-->
|
||||
<div class="rg_di rg_el ivg-i" data-ved="0ahUKEwjuxPWQts3JAhUGVRoKHd4KCjwQMwgDKAAwAA">
|
||||
<a href="/imgres?imgurl=http://www.clker.com/cliparts/H/X/l/b/0/0/south-arrow-hi.png&imgrefurl=http://www.clker.com/clipart-south-arrow.html&h=598&w=504&tbnid=bQWQ9wz9loJmjM:&docid=vlONkeBtERfDuM&ei=fWhnVq4Shqpp3pWo4AM&tbm=isch" jsaction="fire.ivg_o;mouseover:str.hmov;mouseout:str.hmou" class="rg_l"><img data-src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRsxy3gKnEX0lrwwpRxdPWyLJ8iZ--PXZ-ThbBA2_xXDG_bdQutMQ" data-sz="f" name="bQWQ9wz9loJmjM:" class="rg_i" alt="Image result for south" jsaction="load:str.tbn" onload="google.aft&&google.aft(this)">
|
||||
<div class="_aOd rg_ilm">
|
||||
<div class="rg_ilmbg"><span class="rg_ilmn"> 504 × 598 - clker.com </span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="rg_meta">
|
||||
{"id":"bQWQ9wz9loJmjM:","isu":"clker.com","ity":"png","md":"/search?tbs\u003dsbi:AMhZZit7u1mHyop9pQisu-5idR-8W_1Itvwc3afChmsjQYPx_1yYMzBvUZgtkcGoojqekKZ-6n_1rjX9ySH0OWA_1eO5OijFY6BBDw_1GApr6xxb1bXJcBcj-DiguMoXWW7cZSG7MRQbwnI5SoDZNXcv_1xGszy886I7NVb_1oRKSliTHtzqbXAxhvYreM","msu":"/search?q\u003dsouth\u0026biw\u003d1364\u0026bih\u003d235\u0026tbm\u003disch\u0026tbs\u003dsimg:CAQSEgltBZD3DP2WgiG-U42R4G0RFw","oh":598,"os":"13KB","ow":504,"pt":"South Arrow Clip Art at Clker.com - vector clip art online ...","rid":"vlONkeBtERfDuM","s":"Download this image as:","sc":1,"si":"/search?q\u003dsouth\u0026biw\u003d1364\u0026bih\u003d235\u0026tbm\u003disch\u0026tbs\u003dsimg:CAESEgltBZD3DP2WgiG-U42R4G0RFw","th":245,"tu":"https://thumbnail.url/","tw":206,"ru":"a","ou":"b"}
|
||||
</div>
|
||||
</div><!--n--><!--m-->
|
||||
</div>
|
||||
</div>
|
||||
""" # noqa
|
||||
response = mock.Mock(text=html)
|
||||
results = google_images.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], u'South Arrow Clip Art at Clker.com - vector clip art online ...')
|
||||
self.assertEqual(results[0]['url'], 'a')
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'https://thumbnail.url/')
|
||||
self.assertEqual(results[0]['img_src'], 'b')
|
||||
self.assertEqual(results[0]['content'], 'Download this image as:')
|
|
@ -1,136 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import google_news
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestGoogleNewsEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = google_news.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('googleapis.com', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = google_news.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, google_news.response, None)
|
||||
self.assertRaises(AttributeError, google_news.response, [])
|
||||
self.assertRaises(AttributeError, google_news.response, '')
|
||||
self.assertRaises(AttributeError, google_news.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(google_news.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(google_news.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"responseData": {
|
||||
"results": [
|
||||
{
|
||||
"GsearchResultClass": "GnewsSearch",
|
||||
"clusterUrl": "http://news.google.com/news/story?ncl=d2d3t1LMDpNIj2MPPhdTT0ycN4sWM&hl=fr&ned=fr",
|
||||
"content": "This is the content",
|
||||
"unescapedUrl": "http://this.is.the.url",
|
||||
"url": "http://this.is.the.url",
|
||||
"title": "This is the title",
|
||||
"titleNoFormatting": "This is the title",
|
||||
"location": "",
|
||||
"publisher": "Jeux Actu",
|
||||
"publishedDate": "Fri, 30 Jan 2015 11:00:25 -0800",
|
||||
"signedRedirectUrl": "http://news.google.com/",
|
||||
"language": "fr",
|
||||
"image": {
|
||||
"url": "http://i.jeuxactus.com/datas/jeux/d/y/dying-light/vu/dying-light-54cc080b568fb.jpg",
|
||||
"tbUrl": "http://t1.gstatic.com/images?q=tbn:ANd9GcSF4yYrs9Ycw23DGiOSAZ-5SEPXYwG3LNs",
|
||||
"originalContextUrl": "http://www.jeuxactu.com/test-dying-light-sur-ps4-97208.htm",
|
||||
"publisher": "Jeux Actu",
|
||||
"tbWidth": 80,
|
||||
"tbHeight": 30
|
||||
},
|
||||
"relatedStories": [
|
||||
{
|
||||
"unescapedUrl": "http://www.jeuxvideo.com/test/415823/dying-light.htm",
|
||||
"url": "http%3A%2F%2Fwww.jeuxvideo.com%2Ftest%2F415823%2Fdying-light.htm",
|
||||
"title": "<b>Test</b> du jeu Dying Light - jeuxvideo.com",
|
||||
"titleNoFormatting": "Test du jeu Dying Light - jeuxvideo.com",
|
||||
"location": "",
|
||||
"publisher": "JeuxVideo.com",
|
||||
"publishedDate": "Fri, 30 Jan 2015 08:52:30 -0800",
|
||||
"signedRedirectUrl": "http://news.google.com/news/url?sa=T&",
|
||||
"language": "fr"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"responseDetails": null,
|
||||
"responseStatus": 200
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = google_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
|
||||
json = """
|
||||
{
|
||||
"responseData": {
|
||||
"results": [
|
||||
{
|
||||
"GsearchResultClass": "GnewsSearch",
|
||||
"clusterUrl": "http://news.google.com/news/story?ncl=d2d3t1LMDpNIj2MPPhdTT0ycN4sWM&hl=fr&ned=fr",
|
||||
"content": "This is the content",
|
||||
"unescapedUrl": "http://this.is.the.url",
|
||||
"title": "This is the title",
|
||||
"titleNoFormatting": "This is the title",
|
||||
"location": "",
|
||||
"publisher": "Jeux Actu",
|
||||
"publishedDate": "Fri, 30 Jan 2015 11:00:25 -0800",
|
||||
"signedRedirectUrl": "http://news.google.com/news/",
|
||||
"language": "fr",
|
||||
"image": {
|
||||
"url": "http://i.jeuxactus.com/datas/jeux/d/y/dying-light/vu/dying-light-54cc080b568fb.jpg",
|
||||
"tbUrl": "http://t1.gstatic.com/images?q=tbn:b_6f-OSAZ-5SEPXYwG3LNs",
|
||||
"originalContextUrl": "http://www.jeuxactu.com/test-dying-light-sur-ps4-97208.htm",
|
||||
"publisher": "Jeux Actu",
|
||||
"tbWidth": 80,
|
||||
"tbHeight": 30
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"responseDetails": null,
|
||||
"responseStatus": 200
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = google_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"responseData": {},
|
||||
"responseDetails": null,
|
||||
"responseStatus": 200
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = google_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,397 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import kickass
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestKickassEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = kickass.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('kickass.to', params['url'])
|
||||
self.assertFalse(params['verify'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, kickass.response, None)
|
||||
self.assertRaises(AttributeError, kickass.response, [])
|
||||
self.assertRaises(AttributeError, kickass.response, '')
|
||||
self.assertRaises(AttributeError, kickass.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(kickass.response(response), [])
|
||||
|
||||
html = """
|
||||
<table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
|
||||
<tr class="firstr">
|
||||
<th class="width100perc nopad">torrent name</th>
|
||||
<th class="center">
|
||||
<a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
|
||||
</th>
|
||||
<th class="center"><span class="files">
|
||||
<a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
|
||||
</th>
|
||||
<th class="center"><span>
|
||||
<a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
|
||||
</th>
|
||||
<th class="center"><span class="seed">
|
||||
<a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
|
||||
</th>
|
||||
<th class="lasttd nobr center">
|
||||
<a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">449 <span>bytes</span></td>
|
||||
<td class="center">4</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">10</td>
|
||||
<td class="red lasttd center">1</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = kickass.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'https://kickass.to/url.html')
|
||||
self.assertEqual(results[0]['content'], 'Posted by riri in Other > Unsorted')
|
||||
self.assertEqual(results[0]['seed'], 10)
|
||||
self.assertEqual(results[0]['leech'], 1)
|
||||
self.assertEqual(results[0]['filesize'], 449)
|
||||
self.assertEqual(results[0]['files'], 4)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
|
||||
self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
|
||||
|
||||
html = """
|
||||
<table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
|
||||
<tr class="firstr">
|
||||
<th class="width100perc nopad">torrent name</th>
|
||||
<th class="center">
|
||||
<a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
|
||||
</th>
|
||||
<th class="center"><span class="files">
|
||||
<a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
|
||||
</th>
|
||||
<th class="center"><span>
|
||||
<a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
|
||||
</th>
|
||||
<th class="center"><span class="seed">
|
||||
<a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
|
||||
</th>
|
||||
<th class="lasttd nobr center">
|
||||
<a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = kickass.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
html = """
|
||||
<table cellpadding="0" cellspacing="0" class="data" style="width: 100%">
|
||||
<tr class="firstr">
|
||||
<th class="width100perc nopad">torrent name</th>
|
||||
<th class="center">
|
||||
<a href="/search/test/?field=size&sorder=desc" rel="nofollow">size</a>
|
||||
</th>
|
||||
<th class="center"><span class="files">
|
||||
<a href="/search/test/?field=files_count&sorder=desc" rel="nofollow">files</a></span>
|
||||
</th>
|
||||
<th class="center"><span>
|
||||
<a href="/search/test/?field=time_add&sorder=desc" rel="nofollow">age</a></span>
|
||||
</th>
|
||||
<th class="center"><span class="seed">
|
||||
<a href="/search/test/?field=seeders&sorder=desc" rel="nofollow">seed</a></span>
|
||||
</th>
|
||||
<th class="lasttd nobr center">
|
||||
<a href="/search/test/?field=leechers&sorder=desc" rel="nofollow">leech</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">1 <span>KB</span></td>
|
||||
<td class="center">4</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">10</td>
|
||||
<td class="red lasttd center">1</td>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">1 <span>MB</span></td>
|
||||
<td class="center">4</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">9</td>
|
||||
<td class="red lasttd center">1</td>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">1 <span>GB</span></td>
|
||||
<td class="center">4</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">8</td>
|
||||
<td class="red lasttd center">1</td>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">1 <span>TB</span></td>
|
||||
<td class="center">4</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">7</td>
|
||||
<td class="red lasttd center">1</td>
|
||||
</tr>
|
||||
<tr class="even" id="torrent_test6478745">
|
||||
<td>
|
||||
<div class="iaconbox center floatright">
|
||||
<a rel="6478745,0" class="icommentjs icon16" href="/test-t6478745.html#comment">
|
||||
<em style="font-size: 12px; margin: 0 4px 0 4px;" class="iconvalue">3</em>
|
||||
<i class="ka ka-comment"></i>
|
||||
</a>
|
||||
<a class="iverify icon16" href="/test-t6478745.html" title="Verified Torrent">
|
||||
<i class="ka ka16 ka-verify ka-green"></i>
|
||||
</a>
|
||||
<a href="#" onclick="_scq.push([]); return false;" class="partner1Button idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down partner1Button"></i>
|
||||
</a>
|
||||
<a title="Torrent magnet link"
|
||||
href="magnet:?xt=urn:btih:MAGNETURL&dn=test" class="imagnet icon16">
|
||||
<i class="ka ka16 ka-magnet"></i>
|
||||
</a>
|
||||
<a title="Download torrent file"
|
||||
href="http://torcache.net/torrent/53917.torrent?title=test" class="idownload icon16">
|
||||
<i class="ka ka16 ka-arrow-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="torrentname">
|
||||
<a href="/test-t6478745.html" class="torType txtType"></a>
|
||||
<a href="/test-t6478745.html" class="normalgrey font12px plain bold"></a>
|
||||
<div class="markeredBlock torType txtType">
|
||||
<a href="/url.html" class="cellMainLink">
|
||||
<strong class="red">This should be the title</strong>
|
||||
</a>
|
||||
<span class="font11px lightgrey block">
|
||||
Posted by <i class="ka ka-verify" style="font-size: 16px;color:orange;"></i>
|
||||
<a class="plain" href="/user/riri/">riri</a> in
|
||||
<span id="cat_6478745">
|
||||
<strong><a href="/other/">Other</a> > <a href="/unsorted/">Unsorted</a></strong>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="nobr center">z <span>bytes</span></td>
|
||||
<td class="center">r</td>
|
||||
<td class="center">2 years</td>
|
||||
<td class="green center">a</td>
|
||||
<td class="red lasttd center">t</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = kickass.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 5)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'https://kickass.to/url.html')
|
||||
self.assertEqual(results[0]['content'], 'Posted by riri in Other > Unsorted')
|
||||
self.assertEqual(results[0]['seed'], 10)
|
||||
self.assertEqual(results[0]['leech'], 1)
|
||||
self.assertEqual(results[0]['files'], 4)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
|
||||
self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
|
||||
self.assertEqual(results[0]['filesize'], 1024)
|
||||
self.assertEqual(results[1]['filesize'], 1048576)
|
||||
self.assertEqual(results[2]['filesize'], 1073741824)
|
||||
self.assertEqual(results[3]['filesize'], 1099511627776)
|
||||
self.assertEqual(results[4]['seed'], 0)
|
||||
self.assertEqual(results[4]['leech'], 0)
|
||||
self.assertEqual(results[4]['files'], None)
|
||||
self.assertEqual(results[4]['filesize'], None)
|
|
@ -1,130 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import mediawiki
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestMediawikiEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = mediawiki.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('wikipedia.org', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = mediawiki.request(query, dicto)
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
mediawiki.base_url = "http://test.url/"
|
||||
mediawiki.search_url = mediawiki.base_url +\
|
||||
'w/api.php?action=query'\
|
||||
'&list=search'\
|
||||
'&{query}'\
|
||||
'&srprop=timestamp'\
|
||||
'&format=json'\
|
||||
'&sroffset={offset}'\
|
||||
'&srlimit={limit}' # noqa
|
||||
params = mediawiki.request(query, dicto)
|
||||
self.assertIn('test.url', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
dicto = defaultdict(dict)
|
||||
dicto['language'] = 'fr'
|
||||
mediawiki.base_url = "https://{language}.wikipedia.org/"
|
||||
|
||||
self.assertRaises(AttributeError, mediawiki.response, None)
|
||||
self.assertRaises(AttributeError, mediawiki.response, [])
|
||||
self.assertRaises(AttributeError, mediawiki.response, '')
|
||||
self.assertRaises(AttributeError, mediawiki.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}', search_params=dicto)
|
||||
self.assertEqual(mediawiki.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}', search_params=dicto)
|
||||
self.assertEqual(mediawiki.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"query-continue": {
|
||||
"search": {
|
||||
"sroffset": 1
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"searchinfo": {
|
||||
"totalhits": 29721
|
||||
},
|
||||
"search": [
|
||||
{
|
||||
"ns": 0,
|
||||
"title": "This is the title étude",
|
||||
"timestamp": "2014-12-19T17:42:52Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json, search_params=dicto)
|
||||
results = mediawiki.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], u'This is the title étude')
|
||||
self.assertIn('fr.wikipedia.org', results[0]['url'])
|
||||
self.assertIn('This_is_the_title', results[0]['url'])
|
||||
self.assertIn('%C3%A9tude', results[0]['url'])
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
|
||||
json = """
|
||||
{
|
||||
"query-continue": {
|
||||
"search": {
|
||||
"sroffset": 1
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"searchinfo": {
|
||||
"totalhits": 29721
|
||||
},
|
||||
"search": [
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json, search_params=dicto)
|
||||
results = mediawiki.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"query-continue": {
|
||||
"search": {
|
||||
"sroffset": 1
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json, search_params=dicto)
|
||||
results = mediawiki.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.mediawiki.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json, search_params=dicto)
|
||||
results = mediawiki.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,67 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import mixcloud
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestMixcloudEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = mixcloud.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('mixcloud.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, mixcloud.response, None)
|
||||
self.assertRaises(AttributeError, mixcloud.response, [])
|
||||
self.assertRaises(AttributeError, mixcloud.response, '')
|
||||
self.assertRaises(AttributeError, mixcloud.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(mixcloud.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(mixcloud.response(response), [])
|
||||
|
||||
json = """
|
||||
{"data":[
|
||||
{
|
||||
"user": {
|
||||
"url": "http://www.mixcloud.com/user/",
|
||||
"username": "user",
|
||||
"name": "User",
|
||||
"key": "/user/"
|
||||
},
|
||||
"key": "/user/this-is-the-url/",
|
||||
"created_time": "2014-11-14T13:30:02Z",
|
||||
"audio_length": 3728,
|
||||
"slug": "this-is-the-url",
|
||||
"name": "Title of track",
|
||||
"url": "http://www.mixcloud.com/user/this-is-the-url/",
|
||||
"updated_time": "2014-11-14T13:14:10Z"
|
||||
}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = mixcloud.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title of track')
|
||||
self.assertEqual(results[0]['url'], 'http://www.mixcloud.com/user/this-is-the-url/')
|
||||
self.assertEqual(results[0]['content'], 'User')
|
||||
self.assertTrue('http://www.mixcloud.com/user/this-is-the-url/' in results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.mixcloud.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = mixcloud.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,66 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import nyaa
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestNyaaEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
dic['pageno'] = 1
|
||||
params = nyaa.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('nyaa.se' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
resp = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(nyaa.response(resp), [])
|
||||
|
||||
html = """
|
||||
<table class="tlist">
|
||||
<tbody>
|
||||
<tr class="trusted tlistrow">
|
||||
<td class="tlisticon">
|
||||
<a href="//www.nyaa.se" title="English-translated Anime">
|
||||
<img src="//files.nyaa.se" alt="English-translated Anime">
|
||||
</a>
|
||||
</td>
|
||||
<td class="tlistname">
|
||||
<a href="//www.nyaa.se/?page3">
|
||||
Sample torrent title
|
||||
</a>
|
||||
</td>
|
||||
<td class="tlistdownload">
|
||||
<a href="//www.nyaa.se/?page_dl" title="Download">
|
||||
<img src="//files.nyaa.se/www-dl.png" alt="DL">
|
||||
</a>
|
||||
</td>
|
||||
<td class="tlistsize">10 MiB</td>
|
||||
<td class="tlistsn">1</td>
|
||||
<td class="tlistln">3</td>
|
||||
<td class="tlistdn">666</td>
|
||||
<td class="tlistmn">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
"""
|
||||
|
||||
resp = mock.Mock(text=html)
|
||||
results = nyaa.response(resp)
|
||||
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
|
||||
r = results[0]
|
||||
self.assertTrue(r['url'].find('www.nyaa.se/?page3') >= 0)
|
||||
self.assertTrue(r['torrentfile'].find('www.nyaa.se/?page_dl') >= 0)
|
||||
self.assertTrue(r['content'].find('English-translated Anime') >= 0)
|
||||
self.assertTrue(r['content'].find('Downloaded 666 times.') >= 0)
|
||||
|
||||
self.assertEqual(r['title'], 'Sample torrent title')
|
||||
self.assertEqual(r['seed'], 1)
|
||||
self.assertEqual(r['leech'], 3)
|
||||
self.assertEqual(r['filesize'], 10 * 1024 * 1024)
|
|
@ -1,199 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import openstreetmap
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestOpenstreetmapEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = openstreetmap.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('openstreetmap.org', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, openstreetmap.response, None)
|
||||
self.assertRaises(AttributeError, openstreetmap.response, [])
|
||||
self.assertRaises(AttributeError, openstreetmap.response, '')
|
||||
self.assertRaises(AttributeError, openstreetmap.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(openstreetmap.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(openstreetmap.response(response), [])
|
||||
|
||||
json = """
|
||||
[
|
||||
{
|
||||
"place_id": "127732055",
|
||||
"licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||
"osm_type": "relation",
|
||||
"osm_id": "7444",
|
||||
"boundingbox": [
|
||||
"48.8155755",
|
||||
"48.902156",
|
||||
"2.224122",
|
||||
"2.4697602"
|
||||
],
|
||||
"lat": "48.8565056",
|
||||
"lon": "2.3521334",
|
||||
"display_name": "This is the title",
|
||||
"class": "place",
|
||||
"type": "city",
|
||||
"importance": 0.96893459932191,
|
||||
"icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
|
||||
"address": {
|
||||
"city": "Paris",
|
||||
"county": "Paris",
|
||||
"state": "Île-de-France",
|
||||
"country": "France",
|
||||
"country_code": "fr"
|
||||
},
|
||||
"geojson": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
2.224122,
|
||||
48.854199
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = openstreetmap.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://openstreetmap.org/relation/7444')
|
||||
self.assertIn('coordinates', results[0]['geojson'])
|
||||
self.assertEqual(results[0]['geojson']['coordinates'][0][0][0], 2.224122)
|
||||
self.assertEqual(results[0]['geojson']['coordinates'][0][0][1], 48.854199)
|
||||
self.assertEqual(results[0]['address'], None)
|
||||
self.assertIn('48.8155755', results[0]['boundingbox'])
|
||||
self.assertIn('48.902156', results[0]['boundingbox'])
|
||||
self.assertIn('2.224122', results[0]['boundingbox'])
|
||||
self.assertIn('2.4697602', results[0]['boundingbox'])
|
||||
|
||||
json = """
|
||||
[
|
||||
{
|
||||
"place_id": "127732055",
|
||||
"licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||
"osm_type": "relation",
|
||||
"osm_id": "7444",
|
||||
"boundingbox": [
|
||||
"48.8155755",
|
||||
"48.902156",
|
||||
"2.224122",
|
||||
"2.4697602"
|
||||
],
|
||||
"lat": "48.8565056",
|
||||
"lon": "2.3521334",
|
||||
"display_name": "This is the title",
|
||||
"class": "tourism",
|
||||
"type": "city",
|
||||
"importance": 0.96893459932191,
|
||||
"icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
|
||||
"address": {
|
||||
"city": "Paris",
|
||||
"county": "Paris",
|
||||
"state": "Île-de-France",
|
||||
"country": "France",
|
||||
"country_code": "fr",
|
||||
"address29": "Address"
|
||||
},
|
||||
"geojson": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
2.224122,
|
||||
48.854199
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"place_id": "127732055",
|
||||
"licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||
"osm_type": "relation",
|
||||
"osm_id": "7444",
|
||||
"boundingbox": [
|
||||
"48.8155755",
|
||||
"48.902156",
|
||||
"2.224122",
|
||||
"2.4697602"
|
||||
],
|
||||
"lat": "48.8565056",
|
||||
"lon": "2.3521334",
|
||||
"display_name": "This is the title",
|
||||
"class": "tourism",
|
||||
"type": "city",
|
||||
"importance": 0.96893459932191,
|
||||
"icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
|
||||
"address": {
|
||||
"city": "Paris",
|
||||
"county": "Paris",
|
||||
"state": "Île-de-France",
|
||||
"country": "France",
|
||||
"postcode": 75000,
|
||||
"country_code": "fr"
|
||||
},
|
||||
"geojson": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
2.224122,
|
||||
48.854199
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"place_id": "127732055",
|
||||
"licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
|
||||
"osm_type": "node",
|
||||
"osm_id": "7444",
|
||||
"boundingbox": [
|
||||
"48.8155755",
|
||||
"48.902156",
|
||||
"2.224122",
|
||||
"2.4697602"
|
||||
],
|
||||
"lat": "48.8565056",
|
||||
"lon": "2.3521334",
|
||||
"display_name": "This is the title",
|
||||
"class": "tourism",
|
||||
"type": "city",
|
||||
"importance": 0.96893459932191,
|
||||
"icon": "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
|
||||
"address": {
|
||||
"city": "Paris",
|
||||
"county": "Paris",
|
||||
"state": "Île-de-France",
|
||||
"country": "France",
|
||||
"country_code": "fr",
|
||||
"address29": "Address"
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = openstreetmap.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertIn('48.8565056', results[2]['geojson']['coordinates'])
|
||||
self.assertIn('2.3521334', results[2]['geojson']['coordinates'])
|
|
@ -1,166 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import photon
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestPhotonEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'all'
|
||||
params = photon.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('photon.komoot.de', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = photon.request(query, dicto)
|
||||
self.assertNotIn('lang', params['url'])
|
||||
|
||||
dicto['language'] = 'al'
|
||||
params = photon.request(query, dicto)
|
||||
self.assertNotIn('lang', params['url'])
|
||||
|
||||
dicto['language'] = 'fr'
|
||||
params = photon.request(query, dicto)
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, photon.response, None)
|
||||
self.assertRaises(AttributeError, photon.response, [])
|
||||
self.assertRaises(AttributeError, photon.response, '')
|
||||
self.assertRaises(AttributeError, photon.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(photon.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(photon.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"features": [
|
||||
{
|
||||
"properties": {
|
||||
"osm_key": "waterway",
|
||||
"extent": [
|
||||
-1.4508446,
|
||||
51.1614997,
|
||||
-1.4408036,
|
||||
51.1525635
|
||||
],
|
||||
"name": "This is the title",
|
||||
"state": "England",
|
||||
"osm_id": 114823817,
|
||||
"osm_type": "W",
|
||||
"osm_value": "river",
|
||||
"city": "Test Valley",
|
||||
"country": "United Kingdom"
|
||||
},
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
-1.4458571,
|
||||
51.1576661
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"osm_key": "place",
|
||||
"street": "Rue",
|
||||
"state": "Ile-de-France",
|
||||
"osm_id": 129211377,
|
||||
"osm_type": "R",
|
||||
"housenumber": "10",
|
||||
"postcode": "75011",
|
||||
"osm_value": "house",
|
||||
"city": "Paris",
|
||||
"country": "France"
|
||||
},
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
2.3725025,
|
||||
48.8654481
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"osm_key": "amenity",
|
||||
"street": "Allée",
|
||||
"name": "Bibliothèque",
|
||||
"state": "Ile-de-France",
|
||||
"osm_id": 1028573132,
|
||||
"osm_type": "N",
|
||||
"postcode": "75001",
|
||||
"osm_value": "library",
|
||||
"city": "Paris",
|
||||
"country": "France"
|
||||
},
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
2.3445634,
|
||||
48.862494
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"osm_key": "amenity",
|
||||
"osm_id": 1028573132,
|
||||
"osm_type": "Y",
|
||||
"postcode": "75001",
|
||||
"osm_value": "library",
|
||||
"city": "Paris",
|
||||
"country": "France"
|
||||
},
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
2.3445634,
|
||||
48.862494
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
}
|
||||
],
|
||||
"type": "FeatureCollection"
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = photon.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['longitude'], -1.4458571)
|
||||
self.assertEqual(results[0]['latitude'], 51.1576661)
|
||||
self.assertIn(-1.4508446, results[0]['boundingbox'])
|
||||
self.assertIn(51.1614997, results[0]['boundingbox'])
|
||||
self.assertIn(-1.4408036, results[0]['boundingbox'])
|
||||
self.assertIn(51.1525635, results[0]['boundingbox'])
|
||||
self.assertIn('type', results[0]['geojson'])
|
||||
self.assertEqual(results[0]['geojson']['type'], 'Point')
|
||||
self.assertEqual(results[0]['address'], None)
|
||||
self.assertEqual(results[0]['osm']['type'], 'way')
|
||||
self.assertEqual(results[0]['osm']['id'], 114823817)
|
||||
self.assertEqual(results[0]['url'], 'https://openstreetmap.org/way/114823817')
|
||||
self.assertEqual(results[1]['osm']['type'], 'relation')
|
||||
self.assertEqual(results[2]['address']['name'], u'Bibliothèque')
|
||||
self.assertEqual(results[2]['address']['house_number'], None)
|
||||
self.assertEqual(results[2]['address']['locality'], 'Paris')
|
||||
self.assertEqual(results[2]['address']['postcode'], '75001')
|
||||
self.assertEqual(results[2]['address']['country'], 'France')
|
||||
self.assertEqual(results[2]['osm']['type'], 'node')
|
|
@ -1,166 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import piratebay
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestPiratebayEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['category'] = 'Toto'
|
||||
params = piratebay.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('piratebay.se', params['url'])
|
||||
self.assertIn('0', params['url'])
|
||||
|
||||
dicto['category'] = 'music'
|
||||
params = piratebay.request(query, dicto)
|
||||
self.assertIn('100', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, piratebay.response, None)
|
||||
self.assertRaises(AttributeError, piratebay.response, [])
|
||||
self.assertRaises(AttributeError, piratebay.response, '')
|
||||
self.assertRaises(AttributeError, piratebay.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(piratebay.response(response), [])
|
||||
|
||||
html = """
|
||||
<table id="searchResult">
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vertTh">
|
||||
<center>
|
||||
<a href="#" title="More from this category">Anime</a><br/>
|
||||
(<a href="#" title="More from this category">Anime</a>)
|
||||
</center>
|
||||
</td>
|
||||
<td>
|
||||
<div class="detName">
|
||||
<a href="/this.is.the.link" class="detLink" title="Title">
|
||||
This is the title
|
||||
</a>
|
||||
</div>
|
||||
<a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
|
||||
<img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
|
||||
</a>
|
||||
<a href="http://torcache.net/torrent/TORRENTFILE.torrent" title="Download this torrent">
|
||||
<img src="/static/img/dl.gif" class="dl" alt="Download"/>
|
||||
</a>
|
||||
<a href="/user/HorribleSubs">
|
||||
<img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
|
||||
</a>
|
||||
<img src="/static/img/11x11p.png"/>
|
||||
<font class="detDesc">
|
||||
This is the content <span>and should be</span> OK
|
||||
</font>
|
||||
</td>
|
||||
<td align="right">13</td>
|
||||
<td align="right">334</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vertTh">
|
||||
<center>
|
||||
<a href="#" title="More from this category">Anime</a><br/>
|
||||
(<a href="#" title="More from this category">Anime</a>)
|
||||
</center>
|
||||
</td>
|
||||
<td>
|
||||
<div class="detName">
|
||||
<a href="/this.is.the.link" class="detLink" title="Title">
|
||||
This is the title
|
||||
</a>
|
||||
</div>
|
||||
<a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
|
||||
<img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
|
||||
</a>
|
||||
<a href="/user/HorribleSubs">
|
||||
<img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
|
||||
</a>
|
||||
<img src="/static/img/11x11p.png"/>
|
||||
<font class="detDesc">
|
||||
This is the content <span>and should be</span> OK
|
||||
</font>
|
||||
</td>
|
||||
<td align="right">13</td>
|
||||
<td align="right">334</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = piratebay.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://thepiratebay.se/this.is.the.link')
|
||||
self.assertEqual(results[0]['content'], 'This is the content and should be OK')
|
||||
self.assertEqual(results[0]['seed'], 13)
|
||||
self.assertEqual(results[0]['leech'], 334)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETLINK')
|
||||
self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/TORRENTFILE.torrent')
|
||||
|
||||
self.assertEqual(results[1]['torrentfile'], None)
|
||||
|
||||
html = """
|
||||
<table id="searchResult">
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vertTh">
|
||||
<center>
|
||||
<a href="#" title="More from this category">Anime</a><br/>
|
||||
(<a href="#" title="More from this category">Anime</a>)
|
||||
</center>
|
||||
</td>
|
||||
<td>
|
||||
<div class="detName">
|
||||
<a href="/this.is.the.link" class="detLink" title="Title">
|
||||
This is the title
|
||||
</a>
|
||||
</div>
|
||||
<a href="magnet:?xt=urn:btih:MAGNETLINK" title="Download this torrent using magnet">
|
||||
<img src="/static/img/icon-magnet.gif" alt="Magnet link"/>
|
||||
</a>
|
||||
<a href="http://torcache.net/torrent/TORRENTFILE.torrent" title="Download this torrent">
|
||||
<img src="/static/img/dl.gif" class="dl" alt="Download"/>
|
||||
</a>
|
||||
<a href="/user/HorribleSubs">
|
||||
<img src="/static/img/vip.gif" alt="VIP" title="VIP" style="width:11px;" border='0'/>
|
||||
</a>
|
||||
<img src="/static/img/11x11p.png"/>
|
||||
<font class="detDesc">
|
||||
This is the content <span>and should be</span> OK
|
||||
</font>
|
||||
</td>
|
||||
<td align="right">s</td>
|
||||
<td align="right">d</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = piratebay.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://thepiratebay.se/this.is.the.link')
|
||||
self.assertEqual(results[0]['content'], 'This is the content and should be OK')
|
||||
self.assertEqual(results[0]['seed'], 0)
|
||||
self.assertEqual(results[0]['leech'], 0)
|
||||
self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETLINK')
|
||||
self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/TORRENTFILE.torrent')
|
||||
|
||||
html = """
|
||||
<table id="searchResult">
|
||||
</table>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = piratebay.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,317 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import qwant
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestQwantEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'fr_FR'
|
||||
qwant.categories = ['']
|
||||
params = qwant.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('web', params['url'])
|
||||
self.assertIn('qwant.com', params['url'])
|
||||
self.assertIn('fr_fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
qwant.categories = ['news']
|
||||
params = qwant.request(query, dicto)
|
||||
self.assertFalse('fr' in params['url'])
|
||||
self.assertIn('news', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, qwant.response, None)
|
||||
self.assertRaises(AttributeError, qwant.response, [])
|
||||
self.assertRaises(AttributeError, qwant.response, '')
|
||||
self.assertRaises(AttributeError, qwant.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(qwant.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": {}}')
|
||||
self.assertEqual(qwant.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Title",
|
||||
"score": 9999,
|
||||
"url": "http://www.url.xyz",
|
||||
"source": "...",
|
||||
"desc": "Description",
|
||||
"date": "",
|
||||
"_id": "db0aadd62c2a8565567ffc382f5c61fa",
|
||||
"favicon": "https://s.qwant.com/fav.ico"
|
||||
}
|
||||
],
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
qwant.categories = ['general']
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://www.url.xyz')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Title",
|
||||
"score": 9999,
|
||||
"url": "http://www.url.xyz",
|
||||
"source": "...",
|
||||
"media": "http://image.jpg",
|
||||
"desc": "",
|
||||
"thumbnail": "http://thumbnail.jpg",
|
||||
"date": "",
|
||||
"_id": "db0aadd62c2a8565567ffc382f5c61fa",
|
||||
"favicon": "https://s.qwant.com/fav.ico"
|
||||
}
|
||||
],
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
qwant.categories = ['images']
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://www.url.xyz')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'http://thumbnail.jpg')
|
||||
self.assertEqual(results[0]['img_src'], 'http://image.jpg')
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Title",
|
||||
"score": 9999,
|
||||
"url": "http://www.url.xyz",
|
||||
"source": "...",
|
||||
"desc": "Description",
|
||||
"date": 1433260920,
|
||||
"_id": "db0aadd62c2a8565567ffc382f5c61fa",
|
||||
"favicon": "https://s.qwant.com/fav.ico"
|
||||
}
|
||||
],
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
qwant.categories = ['news']
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://www.url.xyz')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
self.assertIn('publishedDate', results[0])
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Title",
|
||||
"score": 9999,
|
||||
"url": "http://www.url.xyz",
|
||||
"source": "...",
|
||||
"desc": "Description",
|
||||
"date": 1433260920,
|
||||
"_id": "db0aadd62c2a8565567ffc382f5c61fa",
|
||||
"favicon": "https://s.qwant.com/fav.ico"
|
||||
}
|
||||
],
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
qwant.categories = ['social media']
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'http://www.url.xyz')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
self.assertIn('publishedDate', results[0])
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"title": "Title",
|
||||
"score": 9999,
|
||||
"url": "http://www.url.xyz",
|
||||
"source": "...",
|
||||
"desc": "Description",
|
||||
"date": 1433260920,
|
||||
"_id": "db0aadd62c2a8565567ffc382f5c61fa",
|
||||
"favicon": "https://s.qwant.com/fav.ico"
|
||||
}
|
||||
],
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
qwant.categories = ['']
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"result": {
|
||||
"filters": []
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"query": {
|
||||
"locale": "en_us",
|
||||
"query": "Test",
|
||||
"offset": 10
|
||||
},
|
||||
"cache": {
|
||||
"key": "e66aa864c00147a0e3a16ff7a5efafde",
|
||||
"created": 1433092754,
|
||||
"expiration": 259200,
|
||||
"status": "miss",
|
||||
"age": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"status": "success"
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = qwant.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,71 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import reddit
|
||||
from searx.testing import SearxTestCase
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class TestRedditEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
params = reddit.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('reddit.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
resp = mock.Mock(text='{}')
|
||||
self.assertEqual(reddit.response(resp), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"kind": "Listing",
|
||||
"data": {
|
||||
"children": [{
|
||||
"data": {
|
||||
"url": "http://google2.com/",
|
||||
"permalink": "http://google.com/",
|
||||
"title": "Title number one",
|
||||
"selftext": "Sample",
|
||||
"created_utc": 1401219957.0,
|
||||
"thumbnail": "http://image.com/picture.jpg"
|
||||
}
|
||||
}, {
|
||||
"data": {
|
||||
"url": "https://reddit2.com/",
|
||||
"permalink": "https://reddit.com/",
|
||||
"title": "Title number two",
|
||||
"selftext": "Dominus vobiscum",
|
||||
"created_utc": 1438792533.0,
|
||||
"thumbnail": "self"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
resp = mock.Mock(text=json)
|
||||
results = reddit.response(resp)
|
||||
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(type(results), list)
|
||||
|
||||
# testing first result (picture)
|
||||
r = results[0]
|
||||
self.assertEqual(r['url'], 'http://google.com/')
|
||||
self.assertEqual(r['title'], 'Title number one')
|
||||
self.assertEqual(r['template'], 'images.html')
|
||||
self.assertEqual(r['img_src'], 'http://google2.com/')
|
||||
self.assertEqual(r['thumbnail_src'], 'http://image.com/picture.jpg')
|
||||
|
||||
# testing second result (self-post)
|
||||
r = results[1]
|
||||
self.assertEqual(r['url'], 'https://reddit.com/')
|
||||
self.assertEqual(r['title'], 'Title number two')
|
||||
self.assertEqual(r['content'], 'Dominus vobiscum')
|
||||
created = datetime.fromtimestamp(1438792533.0)
|
||||
self.assertEqual(r['publishedDate'], created)
|
||||
self.assertTrue('thumbnail_src' not in r)
|
||||
self.assertTrue('img_src' not in r)
|
|
@ -1,75 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import searchcode_code
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestSearchcodeCodeEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = searchcode_code.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('searchcode.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, searchcode_code.response, None)
|
||||
self.assertRaises(AttributeError, searchcode_code.response, [])
|
||||
self.assertRaises(AttributeError, searchcode_code.response, '')
|
||||
self.assertRaises(AttributeError, searchcode_code.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(searchcode_code.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(searchcode_code.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"matchterm": "test",
|
||||
"previouspage": null,
|
||||
"searchterm": "test",
|
||||
"query": "test",
|
||||
"total": 1000,
|
||||
"page": 0,
|
||||
"nextpage": 1,
|
||||
"results": [
|
||||
{
|
||||
"repo": "https://repo",
|
||||
"linescount": 1044,
|
||||
"location": "/tests",
|
||||
"name": "Name",
|
||||
"url": "https://url",
|
||||
"md5hash": "ecac6e479edd2b9406c9e08603cec655",
|
||||
"lines": {
|
||||
"1": "// Test 011",
|
||||
"2": "// Source: "
|
||||
},
|
||||
"id": 51223527,
|
||||
"filename": "File.CPP"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = searchcode_code.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Name - File.CPP')
|
||||
self.assertEqual(results[0]['url'], 'https://url')
|
||||
self.assertEqual(results[0]['repository'], 'https://repo')
|
||||
self.assertEqual(results[0]['code_language'], 'cpp')
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.searchcode_code.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = searchcode_code.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,73 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import searchcode_doc
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestSearchcodeDocEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = searchcode_doc.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('searchcode.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, searchcode_doc.response, None)
|
||||
self.assertRaises(AttributeError, searchcode_doc.response, [])
|
||||
self.assertRaises(AttributeError, searchcode_doc.response, '')
|
||||
self.assertRaises(AttributeError, searchcode_doc.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(searchcode_doc.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(searchcode_doc.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"matchterm": "test",
|
||||
"previouspage": null,
|
||||
"searchterm": "test",
|
||||
"query": "test",
|
||||
"total": 60,
|
||||
"page": 0,
|
||||
"nextpage": 1,
|
||||
"results": [
|
||||
{
|
||||
"synopsis": "Synopsis",
|
||||
"displayname": null,
|
||||
"name": "test",
|
||||
"url": "http://url",
|
||||
"type": "Type",
|
||||
"icon": null,
|
||||
"namespace": "Namespace",
|
||||
"description": "Description"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = searchcode_doc.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], '[Type] Namespace test')
|
||||
self.assertEqual(results[0]['url'], 'http://url')
|
||||
self.assertIn('Synopsis', results[0]['content'])
|
||||
self.assertIn('Type', results[0]['content'])
|
||||
self.assertIn('test', results[0]['content'])
|
||||
self.assertIn('Description', results[0]['content'])
|
||||
|
||||
json = """
|
||||
{"toto":[
|
||||
{"id":200,"name":"Artist Name",
|
||||
"link":"http:\/\/www.searchcode_doc.com\/artist\/1217","type":"artist"}
|
||||
]}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = searchcode_doc.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,192 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import soundcloud
|
||||
from searx.testing import SearxTestCase
|
||||
from urllib import quote_plus
|
||||
|
||||
|
||||
class TestSoundcloudEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = soundcloud.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('soundcloud.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, soundcloud.response, None)
|
||||
self.assertRaises(AttributeError, soundcloud.response, [])
|
||||
self.assertRaises(AttributeError, soundcloud.response, '')
|
||||
self.assertRaises(AttributeError, soundcloud.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(soundcloud.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(soundcloud.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"collection": [
|
||||
{
|
||||
"kind": "track",
|
||||
"id": 159723640,
|
||||
"created_at": "2014/07/22 00:51:21 +0000",
|
||||
"user_id": 2976616,
|
||||
"duration": 303780,
|
||||
"commentable": true,
|
||||
"state": "finished",
|
||||
"original_content_size": 13236349,
|
||||
"last_modified": "2015/01/31 15:14:50 +0000",
|
||||
"sharing": "public",
|
||||
"tag_list": "seekae flume",
|
||||
"permalink": "seekae-test-recognise-flume-re-work",
|
||||
"streamable": true,
|
||||
"embeddable_by": "all",
|
||||
"downloadable": true,
|
||||
"purchase_url": "http://www.facebook.com/seekaemusic",
|
||||
"label_id": null,
|
||||
"purchase_title": "Seekae",
|
||||
"genre": "freedownload",
|
||||
"title": "This is the title",
|
||||
"description": "This is the content",
|
||||
"label_name": "Future Classic",
|
||||
"release": "",
|
||||
"track_type": "remix",
|
||||
"key_signature": "",
|
||||
"isrc": "",
|
||||
"video_url": null,
|
||||
"bpm": null,
|
||||
"release_year": 2014,
|
||||
"release_month": 7,
|
||||
"release_day": 22,
|
||||
"original_format": "mp3",
|
||||
"license": "all-rights-reserved",
|
||||
"uri": "https://api.soundcloud.com/tracks/159723640",
|
||||
"user": {
|
||||
"id": 2976616,
|
||||
"kind": "user",
|
||||
"permalink": "flume",
|
||||
"username": "Flume",
|
||||
"last_modified": "2014/11/24 19:21:29 +0000",
|
||||
"uri": "https://api.soundcloud.com/users/2976616",
|
||||
"permalink_url": "http://soundcloud.com/flume",
|
||||
"avatar_url": "https://i1.sndcdn.com/avatars-000044475439-4zi7ii-large.jpg"
|
||||
},
|
||||
"permalink_url": "http://soundcloud.com/this.is.the.url",
|
||||
"artwork_url": "https://i1.sndcdn.com/artworks-000085857162-xdxy5c-large.jpg",
|
||||
"waveform_url": "https://w1.sndcdn.com/DWrL1lAN8BkP_m.png",
|
||||
"stream_url": "https://api.soundcloud.com/tracks/159723640/stream",
|
||||
"download_url": "https://api.soundcloud.com/tracks/159723640/download",
|
||||
"playback_count": 2190687,
|
||||
"download_count": 54856,
|
||||
"favoritings_count": 49061,
|
||||
"comment_count": 826,
|
||||
"likes_count": 49061,
|
||||
"reposts_count": 15910,
|
||||
"attachments_uri": "https://api.soundcloud.com/tracks/159723640/attachments",
|
||||
"policy": "ALLOW"
|
||||
}
|
||||
],
|
||||
"total_results": 375750,
|
||||
"next_href": "https://api.soundcloud.com/search?&q=test",
|
||||
"tx_id": ""
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = soundcloud.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'http://soundcloud.com/this.is.the.url')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
self.assertIn(quote_plus('https://api.soundcloud.com/tracks/159723640'), results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{
|
||||
"collection": [
|
||||
{
|
||||
"kind": "user",
|
||||
"id": 159723640,
|
||||
"created_at": "2014/07/22 00:51:21 +0000",
|
||||
"user_id": 2976616,
|
||||
"duration": 303780,
|
||||
"commentable": true,
|
||||
"state": "finished",
|
||||
"original_content_size": 13236349,
|
||||
"last_modified": "2015/01/31 15:14:50 +0000",
|
||||
"sharing": "public",
|
||||
"tag_list": "seekae flume",
|
||||
"permalink": "seekae-test-recognise-flume-re-work",
|
||||
"streamable": true,
|
||||
"embeddable_by": "all",
|
||||
"downloadable": true,
|
||||
"purchase_url": "http://www.facebook.com/seekaemusic",
|
||||
"label_id": null,
|
||||
"purchase_title": "Seekae",
|
||||
"genre": "freedownload",
|
||||
"title": "This is the title",
|
||||
"description": "This is the content",
|
||||
"label_name": "Future Classic",
|
||||
"release": "",
|
||||
"track_type": "remix",
|
||||
"key_signature": "",
|
||||
"isrc": "",
|
||||
"video_url": null,
|
||||
"bpm": null,
|
||||
"release_year": 2014,
|
||||
"release_month": 7,
|
||||
"release_day": 22,
|
||||
"original_format": "mp3",
|
||||
"license": "all-rights-reserved",
|
||||
"uri": "https://api.soundcloud.com/tracks/159723640",
|
||||
"user": {
|
||||
"id": 2976616,
|
||||
"kind": "user",
|
||||
"permalink": "flume",
|
||||
"username": "Flume",
|
||||
"last_modified": "2014/11/24 19:21:29 +0000",
|
||||
"uri": "https://api.soundcloud.com/users/2976616",
|
||||
"permalink_url": "http://soundcloud.com/flume",
|
||||
"avatar_url": "https://i1.sndcdn.com/avatars-000044475439-4zi7ii-large.jpg"
|
||||
},
|
||||
"permalink_url": "http://soundcloud.com/this.is.the.url",
|
||||
"artwork_url": "https://i1.sndcdn.com/artworks-000085857162-xdxy5c-large.jpg",
|
||||
"waveform_url": "https://w1.sndcdn.com/DWrL1lAN8BkP_m.png",
|
||||
"stream_url": "https://api.soundcloud.com/tracks/159723640/stream",
|
||||
"download_url": "https://api.soundcloud.com/tracks/159723640/download",
|
||||
"playback_count": 2190687,
|
||||
"download_count": 54856,
|
||||
"favoritings_count": 49061,
|
||||
"comment_count": 826,
|
||||
"likes_count": 49061,
|
||||
"reposts_count": 15910,
|
||||
"attachments_uri": "https://api.soundcloud.com/tracks/159723640/attachments",
|
||||
"policy": "ALLOW"
|
||||
}
|
||||
],
|
||||
"total_results": 375750,
|
||||
"next_href": "https://api.soundcloud.com/search?&q=test",
|
||||
"tx_id": ""
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = soundcloud.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{
|
||||
"collection": [],
|
||||
"total_results": 375750,
|
||||
"next_href": "https://api.soundcloud.com/search?&q=test",
|
||||
"tx_id": ""
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = soundcloud.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,124 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import spotify
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestSpotifyEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = spotify.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('spotify.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, spotify.response, None)
|
||||
self.assertRaises(AttributeError, spotify.response, [])
|
||||
self.assertRaises(AttributeError, spotify.response, '')
|
||||
self.assertRaises(AttributeError, spotify.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(spotify.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(spotify.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"tracks": {
|
||||
"href": "https://api.spotify.com/v1/search?query=nosfell&offset=0&limit=20&type=track",
|
||||
"items": [
|
||||
{
|
||||
"album": {
|
||||
"album_type": "album",
|
||||
"external_urls": {
|
||||
"spotify": "https://open.spotify.com/album/5c9ap1PBkSGLxT3J73toxA"
|
||||
},
|
||||
"href": "https://api.spotify.com/v1/albums/5c9ap1PBkSGLxT3J73toxA",
|
||||
"id": "5c9ap1PBkSGLxT3J73toxA",
|
||||
"name": "Album Title",
|
||||
"type": "album",
|
||||
"uri": "spotify:album:5c9ap1PBkSGLxT3J73toxA"
|
||||
},
|
||||
"artists": [
|
||||
{
|
||||
"external_urls": {
|
||||
"spotify": "https://open.spotify.com/artist/0bMc6b75FfZEpQHG1jifKu"
|
||||
},
|
||||
"href": "https://api.spotify.com/v1/artists/0bMc6b75FfZEpQHG1jifKu",
|
||||
"id": "0bMc6b75FfZEpQHG1jifKu",
|
||||
"name": "Artist Name",
|
||||
"type": "artist",
|
||||
"uri": "spotify:artist:0bMc6b75FfZEpQHG1jifKu"
|
||||
}
|
||||
],
|
||||
"disc_number": 1,
|
||||
"duration_ms": 202386,
|
||||
"explicit": false,
|
||||
"external_ids": {
|
||||
"isrc": "FRV640600067"
|
||||
},
|
||||
"external_urls": {
|
||||
"spotify": "https://open.spotify.com/track/2GzvFiedqW8hgqUpWcASZa"
|
||||
},
|
||||
"href": "https://api.spotify.com/v1/tracks/2GzvFiedqW8hgqUpWcASZa",
|
||||
"id": "1000",
|
||||
"is_playable": true,
|
||||
"name": "Title of track",
|
||||
"popularity": 6,
|
||||
"preview_url": "https://p.scdn.co/mp3-preview/7b8ecda580965a066b768c2647f877e43f7b1a0a",
|
||||
"track_number": 3,
|
||||
"type": "track",
|
||||
"uri": "spotify:track:2GzvFiedqW8hgqUpWcASZa"
|
||||
}
|
||||
],
|
||||
"limit": 20,
|
||||
"next": "https://api.spotify.com/v1/search?query=nosfell&offset=20&limit=20&type=track",
|
||||
"offset": 0,
|
||||
"previous": null,
|
||||
"total": 107
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = spotify.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title of track')
|
||||
self.assertEqual(results[0]['url'], 'https://open.spotify.com/track/2GzvFiedqW8hgqUpWcASZa')
|
||||
self.assertEqual(results[0]['content'], 'Artist Name • Album Title • Title of track')
|
||||
self.assertIn('1000', results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{
|
||||
"tracks": {
|
||||
"href": "https://api.spotify.com/v1/search?query=nosfell&offset=0&limit=20&type=track",
|
||||
"items": [
|
||||
{
|
||||
"href": "https://api.spotify.com/v1/tracks/2GzvFiedqW8hgqUpWcASZa",
|
||||
"id": "1000",
|
||||
"is_playable": true,
|
||||
"name": "Title of track",
|
||||
"popularity": 6,
|
||||
"preview_url": "https://p.scdn.co/mp3-preview/7b8ecda580965a066b768c2647f877e43f7b1a0a",
|
||||
"track_number": 3,
|
||||
"type": "album",
|
||||
"uri": "spotify:track:2GzvFiedqW8hgqUpWcASZa"
|
||||
}
|
||||
],
|
||||
"limit": 20,
|
||||
"next": "https://api.spotify.com/v1/search?query=nosfell&offset=20&limit=20&type=track",
|
||||
"offset": 0,
|
||||
"previous": null,
|
||||
"total": 107
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = spotify.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,106 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import stackoverflow
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestStackoverflowEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = stackoverflow.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('stackoverflow.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, stackoverflow.response, None)
|
||||
self.assertRaises(AttributeError, stackoverflow.response, [])
|
||||
self.assertRaises(AttributeError, stackoverflow.response, '')
|
||||
self.assertRaises(AttributeError, stackoverflow.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(stackoverflow.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="question-summary search-result" id="answer-id-1783426">
|
||||
<div class="statscontainer">
|
||||
<div class="statsarrow"></div>
|
||||
<div class="stats">
|
||||
<div class="vote">
|
||||
<div class="votes answered">
|
||||
<span class="vote-count-post "><strong>2583</strong></span>
|
||||
<div class="viewcount">votes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<div class="result-link">
|
||||
<span>
|
||||
<a href="/questions/this.is.the.url"
|
||||
data-searchsession="/questions"
|
||||
title="Checkout remote Git branch">
|
||||
This is the title
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="excerpt">
|
||||
This is the content
|
||||
</div>
|
||||
<div class="tags user-tags t-git t-git-checkout t-remote-branch">
|
||||
</div>
|
||||
<div class="started fr">
|
||||
answered <span title="2009-11-23 14:26:08Z" class="relativetime">nov 23 '09</span> by
|
||||
<a href="/users/214090/hallski">hallski</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = stackoverflow.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://stackoverflow.com/questions/this.is.the.url')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
|
||||
html = """
|
||||
<div class="statscontainer">
|
||||
<div class="statsarrow"></div>
|
||||
<div class="stats">
|
||||
<div class="vote">
|
||||
<div class="votes answered">
|
||||
<span class="vote-count-post "><strong>2583</strong></span>
|
||||
<div class="viewcount">votes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<div class="result-link">
|
||||
<span>
|
||||
<a href="/questions/this.is.the.url"
|
||||
data-searchsession="/questions"
|
||||
title="Checkout remote Git branch">
|
||||
This is the title
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="excerpt">
|
||||
This is the content
|
||||
</div>
|
||||
<div class="tags user-tags t-git t-git-checkout t-remote-branch">
|
||||
</div>
|
||||
<div class="started fr">
|
||||
answered <span title="2009-11-23 14:26:08Z" class="relativetime">nov 23 '09</span> by
|
||||
<a href="/users/214090/hallski">hallski</a>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = stackoverflow.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,140 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import startpage
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestStartpageEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = startpage.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn('startpage.com', params['url'])
|
||||
self.assertIn('data', params)
|
||||
self.assertIn('query', params['data'])
|
||||
self.assertIn(query, params['data']['query'])
|
||||
self.assertIn('with_language', params['data'])
|
||||
self.assertIn('lang_fr', params['data']['with_language'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = startpage.request(query, dicto)
|
||||
self.assertNotIn('with_language', params['data'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, startpage.response, None)
|
||||
self.assertRaises(AttributeError, startpage.response, [])
|
||||
self.assertRaises(AttributeError, startpage.response, '')
|
||||
self.assertRaises(AttributeError, startpage.response, '[]')
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(startpage.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class='result' style=' *width : auto; *margin-right : 10%;'>
|
||||
<h3>
|
||||
<a href='http://this.should.be.the.link/' id='title_2' name='title_2' >
|
||||
This should be the title
|
||||
</a>
|
||||
<span id='title_stars_2' name='title_stars_2'> </span>
|
||||
</h3>
|
||||
<p class='desc clk'>
|
||||
This should be the content.
|
||||
</p>
|
||||
<p>
|
||||
<span class='url'>www.speed<b>test</b>.net/fr/
|
||||
</span>
|
||||
-
|
||||
<A class="proxy" id="proxy_link" HREF="https://ixquick-proxy.com/do/spg/proxy?ep=&edata=&ek=&ekdata="
|
||||
class='proxy'>
|
||||
Navigation avec Ixquick Proxy
|
||||
</A>
|
||||
-
|
||||
<A HREF="https://ixquick-proxy.com/do/spg/highlight.pl?l=francais&c=hf&cat=web&q=test&rl=NONE&rid=
|
||||
&hlq=https://startpage.com/do/search&mtabp=-1&mtcmd=process_search&mtlanguage=francais&mtengine0=
|
||||
&mtcat=web&u=http:%2F%2Fwww.speedtest.net%2Ffr%2F" class='proxy'>
|
||||
Mis en surbrillance
|
||||
</A>
|
||||
</p>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = startpage.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
||||
|
||||
html = """
|
||||
<div class='result' style=' *width : auto; *margin-right : 10%;'>
|
||||
<h3>
|
||||
<a href='http://www.google.com/aclk?sa=l&ai=C' id='title_2' name='title_2' >
|
||||
This should be the title
|
||||
</a>
|
||||
<span id='title_stars_2' name='title_stars_2'> </span>
|
||||
</h3>
|
||||
<p class='desc clk'>
|
||||
This should be the content.
|
||||
</p>
|
||||
<p>
|
||||
<span class='url'>www.speed<b>test</b>.net/fr/
|
||||
</span>
|
||||
-
|
||||
<A class="proxy" id="proxy_link" HREF="https://ixquick-proxy.com/do/spg/proxy?ep=&edata=&ek=&ekdata="
|
||||
class='proxy'>
|
||||
Navigation avec Ixquick Proxy
|
||||
</A>
|
||||
-
|
||||
<A HREF="https://ixquick-proxy.com/do/spg/highlight.pl?l=francais&c=hf&cat=web&q=test&rl=NONE&rid=
|
||||
&hlq=https://startpage.com/do/search&mtabp=-1&mtcmd=process_search&mtlanguage=francais&mtengine0=
|
||||
&mtcat=web&u=http:%2F%2Fwww.speedtest.net%2Ffr%2F" class='proxy'>
|
||||
Mis en surbrillance
|
||||
</A>
|
||||
</p>
|
||||
</div>
|
||||
<div class='result' style=' *width : auto; *margin-right : 10%;'>
|
||||
<h3>
|
||||
<span id='title_stars_2' name='title_stars_2'> </span>
|
||||
</h3>
|
||||
<p class='desc clk'>
|
||||
This should be the content.
|
||||
</p>
|
||||
<p>
|
||||
<span class='url'>www.speed<b>test</b>.net/fr/
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='result' style=' *width : auto; *margin-right : 10%;'>
|
||||
<h3>
|
||||
<a href='http://this.should.be.the.link/' id='title_2' name='title_2' >
|
||||
This should be the title
|
||||
</a>
|
||||
<span id='title_stars_2' name='title_stars_2'> </span>
|
||||
</h3>
|
||||
<p>
|
||||
<span class='url'>www.speed<b>test</b>.net/fr/
|
||||
</span>
|
||||
-
|
||||
<A class="proxy" id="proxy_link" HREF="https://ixquick-proxy.com/do/spg/proxy?ep=&edata=&ek=&ekdata="
|
||||
class='proxy'>
|
||||
Navigation avec Ixquick Proxy
|
||||
</A>
|
||||
-
|
||||
<A HREF="https://ixquick-proxy.com/do/spg/highlight.pl?l=francais&c=hf&cat=web&q=test&rl=NONE&rid=
|
||||
&hlq=https://startpage.com/do/search&mtabp=-1&mtcmd=process_search&mtlanguage=francais&mtengine0=
|
||||
&mtcat=web&u=http:%2F%2Fwww.speedtest.net%2Ffr%2F" class='proxy'>
|
||||
Mis en surbrillance
|
||||
</A>
|
||||
</p>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = startpage.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['content'], '')
|
|
@ -1,169 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import subtitleseeker
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestSubtitleseekerEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = subtitleseeker.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('subtitleseeker.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
dicto = defaultdict(dict)
|
||||
dicto['language'] = 'fr_FR'
|
||||
response = mock.Mock(search_params=dicto)
|
||||
|
||||
self.assertRaises(AttributeError, subtitleseeker.response, None)
|
||||
self.assertRaises(AttributeError, subtitleseeker.response, [])
|
||||
self.assertRaises(AttributeError, subtitleseeker.response, '')
|
||||
self.assertRaises(AttributeError, subtitleseeker.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>', search_params=dicto)
|
||||
self.assertEqual(subtitleseeker.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="boxRows">
|
||||
<div class="boxRowsInner" style="width:600px;">
|
||||
<img src="http://static.subtitleseeker.com/images/movie.gif"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
<a href="http://this.is.the.url/"
|
||||
class="blue" title="Title subtitle" >
|
||||
This is the Title
|
||||
</a>
|
||||
<br><br>
|
||||
<span class="f10b grey-dark arial" style="padding:0px 0px 5px 20px">
|
||||
"Alternative Title"
|
||||
</span>
|
||||
</div>
|
||||
<div class="boxRowsInner f12b red" style="width:70px;">
|
||||
1998
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f12" style="width:120px;">
|
||||
<img src="http://static.subtitleseeker.com/images/basket_put.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1039 Subs
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f10" style="width:130px;">
|
||||
<img src="http://static.subtitleseeker.com/images/arrow_refresh_small.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1 hours ago
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html, search_params=dicto)
|
||||
results = subtitleseeker.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the Title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/French/')
|
||||
self.assertIn('1998', results[0]['content'])
|
||||
self.assertIn('1039 Subs', results[0]['content'])
|
||||
self.assertIn('Alternative Title', results[0]['content'])
|
||||
|
||||
html = """
|
||||
<div class="boxRows">
|
||||
<div class="boxRowsInner" style="width:600px;">
|
||||
<img src="http://static.subtitleseeker.com/images/movie.gif"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
<a href="http://this.is.the.url/"
|
||||
class="blue" title="Title subtitle" >
|
||||
This is the Title
|
||||
</a>
|
||||
</div>
|
||||
<div class="boxRowsInner f12b red" style="width:70px;">
|
||||
1998
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f12" style="width:120px;">
|
||||
<img src="http://static.subtitleseeker.com/images/basket_put.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1039 Subs
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f10" style="width:130px;">
|
||||
<img src="http://static.subtitleseeker.com/images/arrow_refresh_small.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1 hours ago
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
"""
|
||||
dicto['language'] = 'all'
|
||||
response = mock.Mock(text=html, search_params=dicto)
|
||||
results = subtitleseeker.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the Title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
|
||||
self.assertIn('1998', results[0]['content'])
|
||||
self.assertIn('1039 Subs', results[0]['content'])
|
||||
|
||||
html = """
|
||||
<div class="boxRows">
|
||||
<div class="boxRowsInner" style="width:600px;">
|
||||
<img src="http://static.subtitleseeker.com/images/movie.gif"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
<a href="http://this.is.the.url/"
|
||||
class="blue" title="Title subtitle" >
|
||||
This is the Title
|
||||
</a>
|
||||
</div>
|
||||
<div class="boxRowsInner f12b red" style="width:70px;">
|
||||
1998
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f12" style="width:120px;">
|
||||
<img src="http://static.subtitleseeker.com/images/basket_put.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1039 Subs
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f10" style="width:130px;">
|
||||
<img src="http://static.subtitleseeker.com/images/arrow_refresh_small.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1 hours ago
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
"""
|
||||
subtitleseeker.language = 'English'
|
||||
response = mock.Mock(text=html, search_params=dicto)
|
||||
results = subtitleseeker.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the Title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/English/')
|
||||
self.assertIn('1998', results[0]['content'])
|
||||
self.assertIn('1039 Subs', results[0]['content'])
|
||||
|
||||
html = """
|
||||
<div class="boxRowsInner" style="width:600px;">
|
||||
<img src="http://static.subtitleseeker.com/images/movie.gif"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
<a href="http://this.is.the.url/"
|
||||
class="blue" title="Title subtitle" >
|
||||
This is the Title
|
||||
</a>
|
||||
</div>
|
||||
<div class="boxRowsInner f12b red" style="width:70px;">
|
||||
1998
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f12" style="width:120px;">
|
||||
<img src="http://static.subtitleseeker.com/images/basket_put.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1039 Subs
|
||||
</div>
|
||||
<div class="boxRowsInner grey-web f10" style="width:130px;">
|
||||
<img src="http://static.subtitleseeker.com/images/arrow_refresh_small.png"
|
||||
style="width:16px; height:16px;" class="icon">
|
||||
1 hours ago
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html, search_params=dicto)
|
||||
results = subtitleseeker.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,128 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import swisscows
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestSwisscowsEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'de_DE'
|
||||
params = swisscows.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('swisscows.ch' in params['url'])
|
||||
self.assertTrue('uiLanguage=de' in params['url'])
|
||||
self.assertTrue('region=de-DE' in params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = swisscows.request(query, dicto)
|
||||
self.assertTrue('uiLanguage=browser' in params['url'])
|
||||
self.assertTrue('region=browser' in params['url'])
|
||||
|
||||
dicto['category'] = 'images'
|
||||
params = swisscows.request(query, dicto)
|
||||
self.assertIn('image', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, swisscows.response, None)
|
||||
self.assertRaises(AttributeError, swisscows.response, [])
|
||||
self.assertRaises(AttributeError, swisscows.response, '')
|
||||
self.assertRaises(AttributeError, swisscows.response, '[]')
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(swisscows.response(response), [])
|
||||
|
||||
response = mock.Mock(content='<html></html>')
|
||||
self.assertEqual(swisscows.response(response), [])
|
||||
|
||||
html = u"""
|
||||
<script>
|
||||
App.Dispatcher.dispatch("initialize", {
|
||||
html5history: true,
|
||||
initialData: {"Request":
|
||||
{"Page":1,
|
||||
"ItemsCount":1,
|
||||
"Query":"This should ",
|
||||
"NormalizedQuery":"This should ",
|
||||
"Region":"de-AT",
|
||||
"UILanguage":"de"},
|
||||
"Results":{"items":[
|
||||
{"Title":"\uE000This should\uE001 be the title",
|
||||
"Description":"\uE000This should\uE001 be the content.",
|
||||
"Url":"http://this.should.be.the.link/",
|
||||
"DisplayUrl":"www.\uE000this.should.be.the\uE001.link",
|
||||
"Id":"782ef287-e439-451c-b380-6ebc14ba033d"},
|
||||
{"Title":"Datei:This should1.svg",
|
||||
"Url":"https://i.swisscows.ch/?link=http%3a%2f%2fts2.mm.This/should1.png",
|
||||
"SourceUrl":"http://de.wikipedia.org/wiki/Datei:This should1.svg",
|
||||
"DisplayUrl":"de.wikipedia.org/wiki/Datei:This should1.svg",
|
||||
"Width":950,
|
||||
"Height":534,
|
||||
"FileSize":92100,
|
||||
"ContentType":"image/jpeg",
|
||||
"Thumbnail":{
|
||||
"Url":"https://i.swisscows.ch/?link=http%3a%2f%2fts2.mm.This/should1.png",
|
||||
"ContentType":"image/jpeg",
|
||||
"Width":300,
|
||||
"Height":168,
|
||||
"FileSize":9134},
|
||||
"Id":"6a97a542-8f65-425f-b7f6-1178c3aba7be"
|
||||
}
|
||||
],"TotalCount":55300,
|
||||
"Query":"This should "
|
||||
},
|
||||
"Images":[{"Title":"Datei:This should.svg",
|
||||
"Url":"https://i.swisscows.ch/?link=http%3a%2f%2fts2.mm.This/should.png",
|
||||
"SourceUrl":"http://de.wikipedia.org/wiki/Datei:This should.svg",
|
||||
"DisplayUrl":"de.wikipedia.org/wiki/Datei:This should.svg",
|
||||
"Width":1280,
|
||||
"Height":677,
|
||||
"FileSize":50053,
|
||||
"ContentType":"image/png",
|
||||
"Thumbnail":{"Url":"https://i.swisscows.ch/?link=http%3a%2f%2fts2.mm.This/should.png",
|
||||
"ContentType":"image/png",
|
||||
"Width":300,
|
||||
"Height":158,
|
||||
"FileSize":8023},
|
||||
"Id":"ae230fd8-a06a-47d6-99d5-e74766d8143a"}]},
|
||||
environment: "production"
|
||||
}).then(function (options) {
|
||||
$('#Search_Form').on('submit', function (e) {
|
||||
if (!Modernizr.history) return;
|
||||
e.preventDefault();
|
||||
|
||||
var $form = $(this),
|
||||
$query = $('#Query'),
|
||||
query = $.trim($query.val()),
|
||||
path = App.Router.makePath($form.attr('action'), null, $form.serializeObject())
|
||||
|
||||
if (query.length) {
|
||||
options.html5history ?
|
||||
ReactRouter.HistoryLocation.push(path) :
|
||||
ReactRouter.RefreshLocation.push(path);
|
||||
}
|
||||
else $('#Query').trigger('blur');
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
"""
|
||||
response = mock.Mock(content=html)
|
||||
results = swisscows.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertEqual(results[0]['title'], 'This should be the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.should.be.the.link/')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content.')
|
||||
self.assertEqual(results[1]['title'], 'Datei:This should1.svg')
|
||||
self.assertEqual(results[1]['url'], 'http://de.wikipedia.org/wiki/Datei:This should1.svg')
|
||||
self.assertEqual(results[1]['img_src'], 'http://ts2.mm.This/should1.png')
|
||||
self.assertEqual(results[1]['template'], 'images.html')
|
||||
self.assertEqual(results[2]['title'], 'Datei:This should.svg')
|
||||
self.assertEqual(results[2]['url'], 'http://de.wikipedia.org/wiki/Datei:This should.svg')
|
||||
self.assertEqual(results[2]['img_src'], 'http://ts2.mm.This/should.png')
|
||||
self.assertEqual(results[2]['template'], 'images.html')
|
|
@ -1,110 +0,0 @@
|
|||
import mock
|
||||
from collections import defaultdict
|
||||
from searx.engines import tokyotoshokan
|
||||
from searx.testing import SearxTestCase
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class TestTokyotoshokanEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
dic['pageno'] = 1
|
||||
params = tokyotoshokan.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('tokyotosho.info' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
resp = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(tokyotoshokan.response(resp), [])
|
||||
|
||||
html = """
|
||||
<table class="listing">
|
||||
<tbody>
|
||||
<tr class="shade category_0">
|
||||
<td rowspan="2">
|
||||
<a href="/?cat=7"><span class="sprite_cat-raw"></span></a>
|
||||
</td>
|
||||
<td class="desc-top">
|
||||
<a href="magnet:?xt=urn:btih:4c19eb46b5113685fbd2288ed2531b0b">
|
||||
<span class="sprite_magnet"></span>
|
||||
</a>
|
||||
<a rel="nofollow" type="application/x-bittorrent" href="http://www.nyaa.se/f">
|
||||
Koyomimonogatari
|
||||
</a>
|
||||
</td>
|
||||
<td class="web"><a rel="nofollow" href="details.php?id=975700">Details</a></td>
|
||||
</tr>
|
||||
<tr class="shade category_0">
|
||||
<td class="desc-bot">
|
||||
Authorized: <span class="auth_ok">Yes</span>
|
||||
Submitter: <a href="?username=Ohys">Ohys</a> |
|
||||
Size: 10.5MB |
|
||||
Date: 2016-03-26 16:41 UTC |
|
||||
Comment: sample comment
|
||||
</td>
|
||||
<td style="color: #BBB; font-family: monospace" class="stats" align="right">
|
||||
S: <span style="color: red">53</span>
|
||||
L: <span style="color: red">18</span>
|
||||
C: <span style="color: red">0</span>
|
||||
ID: 975700
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="category_0">
|
||||
<td rowspan="2">
|
||||
<a href="/?cat=7"><span class="sprite_cat-raw"></span></a>
|
||||
</td>
|
||||
<td class="desc-top">
|
||||
<a rel="nofollow" type="application/x-bittorrent" href="http://google.com/q">
|
||||
Owarimonogatari
|
||||
</a>
|
||||
</td>
|
||||
<td class="web"><a rel="nofollow" href="details.php?id=975700">Details</a></td>
|
||||
</tr>
|
||||
<tr class="category_0">
|
||||
<td class="desc-bot">
|
||||
Submitter: <a href="?username=Ohys">Ohys</a> |
|
||||
Size: 932.84EB |
|
||||
Date: QWERTY-03-26 16:41 UTC
|
||||
</td>
|
||||
<td style="color: #BBB; font-family: monospace" class="stats" align="right">
|
||||
S: <span style="color: red">0</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
"""
|
||||
|
||||
resp = mock.Mock(text=html)
|
||||
results = tokyotoshokan.response(resp)
|
||||
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
|
||||
# testing the first result, which has correct format
|
||||
# and should have all information fields filled
|
||||
r = results[0]
|
||||
self.assertEqual(r['url'], 'http://www.nyaa.se/f')
|
||||
self.assertEqual(r['title'], 'Koyomimonogatari')
|
||||
self.assertEqual(r['magnetlink'], 'magnet:?xt=urn:btih:4c19eb46b5113685fbd2288ed2531b0b')
|
||||
self.assertEqual(r['filesize'], int(1024 * 1024 * 10.5))
|
||||
self.assertEqual(r['publishedDate'], datetime(2016, 03, 26, 16, 41))
|
||||
self.assertEqual(r['content'], 'Comment: sample comment')
|
||||
self.assertEqual(r['seed'], 53)
|
||||
self.assertEqual(r['leech'], 18)
|
||||
|
||||
# testing the second result, which does not include magnet link,
|
||||
# seed & leech info, and has incorrect size & creation date
|
||||
r = results[1]
|
||||
self.assertEqual(r['url'], 'http://google.com/q')
|
||||
self.assertEqual(r['title'], 'Owarimonogatari')
|
||||
|
||||
self.assertFalse('magnetlink' in r)
|
||||
self.assertFalse('filesize' in r)
|
||||
self.assertFalse('content' in r)
|
||||
self.assertFalse('publishedDate' in r)
|
||||
self.assertFalse('seed' in r)
|
||||
self.assertFalse('leech' in r)
|
|
@ -1,91 +0,0 @@
|
|||
import mock
|
||||
from collections import defaultdict
|
||||
from searx.engines import torrentz
|
||||
from searx.testing import SearxTestCase
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class TestTorrentzEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dic = defaultdict(dict)
|
||||
dic['pageno'] = 1
|
||||
params = torrentz.request(query, dic)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('torrentz.eu' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
resp = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(torrentz.response(resp), [])
|
||||
|
||||
html = """
|
||||
<div class="results">
|
||||
<dl>
|
||||
<dt>
|
||||
<a href="/4362e08b1d80e1820fb2550b752f9f3126fe76d6">
|
||||
Completely valid info
|
||||
</a>
|
||||
books ebooks
|
||||
</dt>
|
||||
<dd>
|
||||
<span class="v">1</span>
|
||||
<span class="a">
|
||||
<span title="Sun, 22 Nov 2015 03:01:42">4 months</span>
|
||||
</span>
|
||||
<span class="s">30 MB</span>
|
||||
<span class="u">14</span>
|
||||
<span class="d">1</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<a href="/poaskdpokaspod">
|
||||
Invalid hash and date and filesize
|
||||
</a>
|
||||
books ebooks
|
||||
</dt>
|
||||
<dd>
|
||||
<span class="v">1</span>
|
||||
<span class="a">
|
||||
<span title="Sun, 2124091j0j190gm42">4 months</span>
|
||||
</span>
|
||||
<span class="s">30MB</span>
|
||||
<span class="u">5,555</span>
|
||||
<span class="d">1,234,567</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
"""
|
||||
|
||||
resp = mock.Mock(text=html)
|
||||
results = torrentz.response(resp)
|
||||
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
|
||||
# testing against the first result
|
||||
r = results[0]
|
||||
self.assertEqual(r['url'], 'https://torrentz.eu/4362e08b1d80e1820fb2550b752f9f3126fe76d6')
|
||||
self.assertEqual(r['title'], 'Completely valid info books ebooks')
|
||||
# 22 Nov 2015 03:01:42
|
||||
self.assertEqual(r['publishedDate'], datetime(2015, 11, 22, 3, 1, 42))
|
||||
self.assertEqual(r['seed'], 14)
|
||||
self.assertEqual(r['leech'], 1)
|
||||
self.assertEqual(r['filesize'], 30 * 1024 * 1024)
|
||||
self.assertEqual(r['magnetlink'], 'magnet:?xt=urn:btih:4362e08b1d80e1820fb2550b752f9f3126fe76d6')
|
||||
|
||||
# testing against the second result
|
||||
r = results[1]
|
||||
self.assertEqual(r['url'], 'https://torrentz.eu/poaskdpokaspod')
|
||||
self.assertEqual(r['title'], 'Invalid hash and date and filesize books ebooks')
|
||||
self.assertEqual(r['seed'], 5555)
|
||||
self.assertEqual(r['leech'], 1234567)
|
||||
|
||||
# in the second result we have invalid hash, creation date & torrent size,
|
||||
# so these tests should fail
|
||||
self.assertFalse('magnetlink' in r)
|
||||
self.assertFalse('filesize' in r)
|
||||
self.assertFalse('publishedDate' in r)
|
|
@ -1,502 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import twitter
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestTwitterEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = twitter.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('twitter.com', params['url'])
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('lang', params['cookies'])
|
||||
self.assertIn('fr', params['cookies']['lang'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = twitter.request(query, dicto)
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('lang', params['cookies'])
|
||||
self.assertIn('en', params['cookies']['lang'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, twitter.response, None)
|
||||
self.assertRaises(AttributeError, twitter.response, [])
|
||||
self.assertRaises(AttributeError, twitter.response, '')
|
||||
self.assertRaises(AttributeError, twitter.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(twitter.response(response), [])
|
||||
|
||||
html = """
|
||||
<li class="js-stream-item stream-item stream-item expanding-stream-item" data-item-id="563005573290287105"
|
||||
id="stream-item-tweet-563005573290287105" data-item-type="tweet">
|
||||
<div class="tweet original-tweet js-stream-tweet js-actionable-tweet js-profile-popup-actionable
|
||||
js-original-tweet has-cards has-native-media" data-tweet-id="563005573290287105" data-disclosure-type=""
|
||||
data-item-id="563005573290287105" data-screen-name="Jalopnik" data-name="Jalopnik"
|
||||
data-user-id="3060631" data-has-native-media="true" data-has-cards="true" data-card-type="photo"
|
||||
data-expanded-footer="<div class="js-tweet-details-fixer
|
||||
tweet-details-fixer">
|
||||
<div class="cards-media-container js-media-container"><div
|
||||
data-card-url="//twitter.com/Jalopnik/status/563005573290287105/photo/1" data-card-type="
|
||||
photo" class="cards-base cards-multimedia" data-element-context="platform_photo_card
|
||||
"> <a class="media media-thumbnail twitter-timeline-link is-preview
|
||||
" data-url="https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large"
|
||||
data-resolved-url-large="https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large"
|
||||
href="//twitter.com/Jalopnik/status/563005573290287105/photo/1">
|
||||
<div class=""> <img src="
|
||||
https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg"
|
||||
alt="Embedded image permalink" width="636" height="309">
|
||||
</div> </a> <div class="cards-content">
|
||||
<div class="byline"> </div> </div>
|
||||
</div> </div> <div
|
||||
class="js-machine-translated-tweet-container"></div> <div
|
||||
class="js-tweet-stats-container tweet-stats-container "> </div>
|
||||
<div class="client-and-actions"> <span class="metadata">
|
||||
<span>5:06 PM - 4 Feb 2015</span> &middot; <a
|
||||
class="permalink-link js-permalink js-nav" href="/Jalopnik/status/563005573290287105
|
||||
"tabindex="-1">Details</a>
|
||||
</span> </div> </div> " data-you-follow="false"
|
||||
data-you-block="false">
|
||||
<div class="context">
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="stream-item-header">
|
||||
<a class="account-group js-account-group js-action-profile js-user-profile-link js-nav"
|
||||
href="/Jalopnik" data-user-id="3060631">
|
||||
<img class="avatar js-action-profile-avatar"
|
||||
src="https://pbs.twimg.com/profile_images/2976430168/5cd4a59_bigger.jpeg" alt="">
|
||||
<strong class="fullname js-action-profile-name show-popup-with-id" data-aria-label-part>
|
||||
Jalopnik
|
||||
</strong>
|
||||
<span>‏</span>
|
||||
<span class="username js-action-profile-name" data-aria-label-part>
|
||||
<s>@</s><b>TitleName</b>
|
||||
</span>
|
||||
</a>
|
||||
<small class="time">
|
||||
<a href="/this.is.the.url"
|
||||
class="tweet-timestamp js-permalink js-nav js-tooltip" title="5:06 PM - 4 Feb 2015" >
|
||||
<span class="u-hiddenVisually" data-aria-label-part="last">17 minutes ago</span>
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
<p class="js-tweet-text tweet-text" lang="en" data-aria-label-part="0">
|
||||
This is the content étude à€
|
||||
<a href="http://t.co/nRWsqQAwBL" rel="nofollow" dir="ltr"
|
||||
data-expanded-url="http://jalo.ps/ReMENu4" class="twitter-timeline-link"
|
||||
target="_blank" title="http://jalo.ps/ReMENu4" >
|
||||
<span class="tco-ellipsis">
|
||||
</span>
|
||||
<span class="invisible">http://</span><span class="js-display-url">link.in.tweet</span>
|
||||
<span class="invisible"></span>
|
||||
<span class="tco-ellipsis">
|
||||
<span class="invisible"> </span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="http://t.co/rbFsfeE0l3" class="twitter-timeline-link u-hidden"
|
||||
data-pre-embedded="true" dir="ltr">
|
||||
pic.twitter.com/rbFsfeE0l3
|
||||
</a>
|
||||
</p>
|
||||
<div class="expanded-content js-tweet-details-dropdown">
|
||||
</div>
|
||||
<div class="stream-item-footer">
|
||||
<a class="details with-icn js-details" href="/Jalopnik/status/563005573290287105">
|
||||
<span class="Icon Icon--photo">
|
||||
</span>
|
||||
<b>
|
||||
<span class="expand-stream-item js-view-details">
|
||||
View photo
|
||||
</span>
|
||||
<span class="collapse-stream-item js-hide-details">
|
||||
Hide photo
|
||||
</span>
|
||||
</b>
|
||||
</a>
|
||||
<span class="ProfileTweet-action--reply u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" aria-hidden="true" data-tweet-stat-count="0">
|
||||
<span class="ProfileTweet-actionCountForAria" >0 replies</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="ProfileTweet-action--retweet u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" data-tweet-stat-count="8">
|
||||
<span class="ProfileTweet-actionCountForAria" data-aria-label-part>8 retweets</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="ProfileTweet-action--favorite u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" data-tweet-stat-count="14">
|
||||
<span class="ProfileTweet-actionCountForAria" data-aria-label-part>14 favorites</span>
|
||||
</span>
|
||||
</span>
|
||||
<div role="group" aria-label="Tweet actions" class="ProfileTweet-actionList u-cf js-actions">
|
||||
<div class="ProfileTweet-action ProfileTweet-action--reply">
|
||||
<button class="ProfileTweet-actionButton u-textUserColorHover js-actionButton
|
||||
js-actionReply" data-modal="ProfileTweet-reply" type="button" title="Reply">
|
||||
<span class="Icon Icon--reply">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Reply</span>
|
||||
<span class="ProfileTweet-actionCount u-textUserColorHover
|
||||
ProfileTweet-actionCount--isZero">
|
||||
<span class="ProfileTweet-actionCountForPresentation" aria-hidden="true">
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--retweet js-toggleState js-toggleRt">
|
||||
<button class="ProfileTweet-actionButton js-actionButton js-actionRetweet js-tooltip"
|
||||
title="Retweet" data-modal="ProfileTweet-retweet" type="button">
|
||||
<span class="Icon Icon--retweet">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Retweet</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">8</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet"
|
||||
data-modal="ProfileTweet-retweet" title="Undo retweet" type="button">
|
||||
<span class="Icon Icon--retweet">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Retweeted</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">8</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--favorite js-toggleState">
|
||||
<button class="ProfileTweet-actionButton js-actionButton js-actionFavorite js-tooltip"
|
||||
title="Favorite" type="button">
|
||||
<span class="Icon Icon--favorite">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Favorite</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">14</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="ProfileTweet-actionButtonUndo u-linkClean js-actionButton
|
||||
js-actionFavorite" title="Undo favorite" type="button">
|
||||
<span class="Icon Icon--favorite">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Favorited</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">
|
||||
14
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--more js-more-ProfileTweet-actions">
|
||||
<div class="dropdown">
|
||||
<button class="ProfileTweet-actionButton u-textUserColorHover dropdown-toggle
|
||||
js-tooltip js-dropdown-toggle" type="button" title="More">
|
||||
<span class="Icon Icon--dots">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">More</span>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<div class="dropdown-caret">
|
||||
<div class="caret-outer">
|
||||
</div>
|
||||
<div class="caret-inner">
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="share-via-dm js-actionShareViaDM" data-nav="share_tweet_dm">
|
||||
<button type="button" class="dropdown-link">
|
||||
Share via Direct Message
|
||||
</button>
|
||||
</li>
|
||||
<li class="embed-link js-actionEmbedTweet" data-nav="embed_tweet">
|
||||
<button type="button" class="dropdown-link">
|
||||
Embed Tweet
|
||||
</button>
|
||||
</li>
|
||||
<li class="mute-user-item pretty-link">
|
||||
<button type="button" class="dropdown-link">
|
||||
Mute
|
||||
</button>
|
||||
</li>
|
||||
<li class="unmute-user-item pretty-link">
|
||||
<button type="button" class="dropdown-link">
|
||||
Unmute
|
||||
</button>
|
||||
</li>
|
||||
<li class="block-or-report-link js-actionBlockOrReport"
|
||||
data-nav="block_or_report">
|
||||
<button type="button" class="dropdown-link">
|
||||
Block or report
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = twitter.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], '@TitleName')
|
||||
self.assertEqual(results[0]['url'], 'https://twitter.com/this.is.the.url')
|
||||
self.assertIn(u'This is the content', results[0]['content'])
|
||||
# self.assertIn(u'This is the content étude à€', results[0]['content'])
|
||||
|
||||
html = """
|
||||
<li class="js-stream-item stream-item stream-item expanding-stream-item" data-item-id="563005573290287105"
|
||||
id="stream-item-tweet-563005573290287105" data-item-type="tweet">
|
||||
<div class="tweet original-tweet js-stream-tweet js-actionable-tweet js-profile-popup-actionable
|
||||
js-original-tweet has-cards has-native-media" data-tweet-id="563005573290287105" data-disclosure-type=""
|
||||
data-item-id="563005573290287105" data-screen-name="Jalopnik" data-name="Jalopnik"
|
||||
data-user-id="3060631" data-has-native-media="true" data-has-cards="true" data-card-type="photo"
|
||||
data-expanded-footer="<div class="js-tweet-details-fixer
|
||||
tweet-details-fixer">
|
||||
<div class="cards-media-container js-media-container"><div
|
||||
data-card-url="//twitter.com/Jalopnik/status/563005573290287105/photo/1" data-card-type="
|
||||
photo" class="cards-base cards-multimedia" data-element-context="platform_photo_card
|
||||
"> <a class="media media-thumbnail twitter-timeline-link is-preview
|
||||
" data-url="https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large"
|
||||
data-resolved-url-large="https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg:large"
|
||||
href="//twitter.com/Jalopnik/status/563005573290287105/photo/1">
|
||||
<div class=""> <img src="
|
||||
https://pbs.twimg.com/media/B9Aylf5IMAAuziP.jpg"
|
||||
alt="Embedded image permalink" width="636" height="309">
|
||||
</div> </a> <div class="cards-content">
|
||||
<div class="byline"> </div> </div>
|
||||
</div> </div> <div
|
||||
class="js-machine-translated-tweet-container"></div> <div
|
||||
class="js-tweet-stats-container tweet-stats-container "> </div>
|
||||
<div class="client-and-actions"> <span class="metadata">
|
||||
<span>5:06 PM - 4 Feb 2015</span> &middot; <a
|
||||
class="permalink-link js-permalink js-nav" href="/Jalopnik/status/563005573290287105
|
||||
"tabindex="-1">Details</a>
|
||||
</span> </div> </div> " data-you-follow="false"
|
||||
data-you-block="false">
|
||||
<div class="context">
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="stream-item-header">
|
||||
<a class="account-group js-account-group js-action-profile js-user-profile-link js-nav"
|
||||
href="/Jalopnik" data-user-id="3060631">
|
||||
<img class="avatar js-action-profile-avatar"
|
||||
src="https://pbs.twimg.com/profile_images/2976430168/5cd4a59_bigger.jpeg" alt="">
|
||||
<strong class="fullname js-action-profile-name show-popup-with-id" data-aria-label-part>
|
||||
Jalopnik
|
||||
</strong>
|
||||
<span>‏</span>
|
||||
<span class="username js-action-profile-name" data-aria-label-part>
|
||||
<s>@</s><b>TitleName</b>
|
||||
</span>
|
||||
</a>
|
||||
<small class="time">
|
||||
<a href="/this.is.the.url"
|
||||
class="tweet-timestamp js-permalink js-nav js-tooltip" title="5:06 PM - 4 Feb 2015" >
|
||||
<span class="_timestamp js-short-timestamp js-relative-timestamp" data-time="1423065963"
|
||||
data-time-ms="1423065963000" data-long-form="true" aria-hidden="true">
|
||||
17m
|
||||
</span>
|
||||
<span class="u-hiddenVisually" data-aria-label-part="last">17 minutes ago</span>
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
<p class="js-tweet-text tweet-text" lang="en" data-aria-label-part="0">
|
||||
This is the content étude à€
|
||||
<a href="http://t.co/nRWsqQAwBL" rel="nofollow" dir="ltr"
|
||||
data-expanded-url="http://jalo.ps/ReMENu4" class="twitter-timeline-link"
|
||||
target="_blank" title="http://jalo.ps/ReMENu4" >
|
||||
<span class="tco-ellipsis">
|
||||
</span>
|
||||
<span class="invisible">http://</span><span class="js-display-url">link.in.tweet</span>
|
||||
<span class="invisible"></span>
|
||||
<span class="tco-ellipsis">
|
||||
<span class="invisible"> </span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="http://t.co/rbFsfeE0l3" class="twitter-timeline-link u-hidden"
|
||||
data-pre-embedded="true" dir="ltr">
|
||||
pic.twitter.com/rbFsfeE0l3
|
||||
</a>
|
||||
</p>
|
||||
<div class="expanded-content js-tweet-details-dropdown">
|
||||
</div>
|
||||
<div class="stream-item-footer">
|
||||
<a class="details with-icn js-details" href="/Jalopnik/status/563005573290287105">
|
||||
<span class="Icon Icon--photo">
|
||||
</span>
|
||||
<b>
|
||||
<span class="expand-stream-item js-view-details">
|
||||
View photo
|
||||
</span>
|
||||
<span class="collapse-stream-item js-hide-details">
|
||||
Hide photo
|
||||
</span>
|
||||
</b>
|
||||
</a>
|
||||
<span class="ProfileTweet-action--reply u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" aria-hidden="true" data-tweet-stat-count="0">
|
||||
<span class="ProfileTweet-actionCountForAria" >0 replies</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="ProfileTweet-action--retweet u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" data-tweet-stat-count="8">
|
||||
<span class="ProfileTweet-actionCountForAria" data-aria-label-part>8 retweets</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="ProfileTweet-action--favorite u-hiddenVisually">
|
||||
<span class="ProfileTweet-actionCount" data-tweet-stat-count="14">
|
||||
<span class="ProfileTweet-actionCountForAria" data-aria-label-part>14 favorites</span>
|
||||
</span>
|
||||
</span>
|
||||
<div role="group" aria-label="Tweet actions" class="ProfileTweet-actionList u-cf js-actions">
|
||||
<div class="ProfileTweet-action ProfileTweet-action--reply">
|
||||
<button class="ProfileTweet-actionButton u-textUserColorHover js-actionButton
|
||||
js-actionReply" data-modal="ProfileTweet-reply" type="button" title="Reply">
|
||||
<span class="Icon Icon--reply">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Reply</span>
|
||||
<span class="ProfileTweet-actionCount u-textUserColorHover
|
||||
ProfileTweet-actionCount--isZero">
|
||||
<span class="ProfileTweet-actionCountForPresentation" aria-hidden="true">
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--retweet js-toggleState js-toggleRt">
|
||||
<button class="ProfileTweet-actionButton js-actionButton js-actionRetweet js-tooltip"
|
||||
title="Retweet" data-modal="ProfileTweet-retweet" type="button">
|
||||
<span class="Icon Icon--retweet">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Retweet</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">8</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="ProfileTweet-actionButtonUndo js-actionButton js-actionRetweet"
|
||||
data-modal="ProfileTweet-retweet" title="Undo retweet" type="button">
|
||||
<span class="Icon Icon--retweet">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Retweeted</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">8</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--favorite js-toggleState">
|
||||
<button class="ProfileTweet-actionButton js-actionButton js-actionFavorite js-tooltip"
|
||||
title="Favorite" type="button">
|
||||
<span class="Icon Icon--favorite">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Favorite</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">14</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="ProfileTweet-actionButtonUndo u-linkClean js-actionButton
|
||||
js-actionFavorite" title="Undo favorite" type="button">
|
||||
<span class="Icon Icon--favorite">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">Favorited</span>
|
||||
<span class="ProfileTweet-actionCount">
|
||||
<span class="ProfileTweet-actionCountForPresentation">
|
||||
14
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ProfileTweet-action ProfileTweet-action--more js-more-ProfileTweet-actions">
|
||||
<div class="dropdown">
|
||||
<button class="ProfileTweet-actionButton u-textUserColorHover dropdown-toggle
|
||||
js-tooltip js-dropdown-toggle" type="button" title="More">
|
||||
<span class="Icon Icon--dots">
|
||||
</span>
|
||||
<span class="u-hiddenVisually">More</span>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<div class="dropdown-caret">
|
||||
<div class="caret-outer">
|
||||
</div>
|
||||
<div class="caret-inner">
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="share-via-dm js-actionShareViaDM" data-nav="share_tweet_dm">
|
||||
<button type="button" class="dropdown-link">
|
||||
Share via Direct Message
|
||||
</button>
|
||||
</li>
|
||||
<li class="embed-link js-actionEmbedTweet" data-nav="embed_tweet">
|
||||
<button type="button" class="dropdown-link">
|
||||
Embed Tweet
|
||||
</button>
|
||||
</li>
|
||||
<li class="mute-user-item pretty-link">
|
||||
<button type="button" class="dropdown-link">
|
||||
Mute
|
||||
</button>
|
||||
</li>
|
||||
<li class="unmute-user-item pretty-link">
|
||||
<button type="button" class="dropdown-link">
|
||||
Unmute
|
||||
</button>
|
||||
</li>
|
||||
<li class="block-or-report-link js-actionBlockOrReport"
|
||||
data-nav="block_or_report">
|
||||
<button type="button" class="dropdown-link">
|
||||
Block or report
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = twitter.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], '@TitleName')
|
||||
self.assertEqual(results[0]['url'], 'https://twitter.com/this.is.the.url')
|
||||
self.assertIn(u'This is the content', results[0]['content'])
|
||||
|
||||
html = """
|
||||
<li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
|
||||
<div Class="sa_mc">
|
||||
<div class="sb_tlst">
|
||||
<h2>
|
||||
<a href="http://this.should.be.the.link/" h="ID=SERP,5124.1">
|
||||
<strong>This</strong> should be the title</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="sb_meta">
|
||||
<cite>
|
||||
<strong>this</strong>.meta.com</cite>
|
||||
<span class="c_tlbxTrg">
|
||||
<span class="c_tlbxH" H="BASE:CACHEDPAGEDEFAULT" K="SERP,5125.1">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<p>
|
||||
<strong>This</strong> should be the content.</p>
|
||||
</div>
|
||||
</li>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = twitter.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,101 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import vimeo
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestVimeoEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = vimeo.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('vimeo.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, vimeo.response, None)
|
||||
self.assertRaises(AttributeError, vimeo.response, [])
|
||||
self.assertRaises(AttributeError, vimeo.response, '')
|
||||
self.assertRaises(AttributeError, vimeo.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(vimeo.response(response), [])
|
||||
|
||||
html = """
|
||||
<div id="browse_content" class="results_grid" data-search-id="696d5f8366914ec4ffec33cf7652de384976d4f4">
|
||||
<ul class="js-browse_list clearfix browse browse_videos browse_videos_thumbnails kane"
|
||||
data-stream="c2VhcmNoOjo6ZGVzYzp7InF1ZXJ5IjoidGVzdCJ9">
|
||||
<li data-position="7" data-result-id="clip_79600943">
|
||||
<div class="clip_thumbnail">
|
||||
<a href="/videoid" class="js-result_url">
|
||||
<div class="thumbnail_wrapper">
|
||||
<img src="http://image.url.webp" class="js-clip_thumbnail_image">
|
||||
<div class="overlay overlay_clip_meta">
|
||||
<div class="meta_data_footer">
|
||||
<span class="clip_upload_date">
|
||||
<time datetime="2013-11-17T08:49:09-05:00"
|
||||
title="dimanche 17 novembre 2013 08:49">Il y a 1 an</time>
|
||||
</span>
|
||||
<span class="clip_likes">
|
||||
<img src="https://f.vimeocdn.com/images_v6/svg/heart-icon.svg">2 215
|
||||
</span>
|
||||
<span class="clip_comments">
|
||||
<img src="https://f.vimeocdn.com/images_v6/svg/comment-icon.svg">75
|
||||
</span>
|
||||
<span class="overlay meta_data_footer clip_duration">01:12</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="title">This is the title</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="clip_thumbnail_attribution">
|
||||
<a href="/fedorshmidt">
|
||||
<img src="https://i.vimeocdn.com/portrait/6628061_100x100.jpg" class="avatar">
|
||||
<span class="display_name">Fedor Shmidt</span>
|
||||
</a>
|
||||
<span class="plays">2,1M lectures</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = vimeo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://vimeo.com/videoid')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['thumbnail'], 'http://image.url.webp')
|
||||
self.assertIn('/videoid', results[0]['embedded'])
|
||||
|
||||
html = """
|
||||
<ol class="js-browse_list clearfix browse browse_videos browse_videos_thumbnails kane"
|
||||
data-stream="c2VhcmNoOjo6ZGVzYzp7InF1ZXJ5IjoidGVzdCJ9">
|
||||
<li id="clip_100785455" data-start-page="/search/page:1/sort:relevant/" data-position="1">
|
||||
<a href="/videoid" title="Futurama 3d (test shot)">
|
||||
<img src="http://image.url.webp"
|
||||
srcset="http://i.vimeocdn.com/video/482375085_590x332.webp 2x" alt=""
|
||||
class="thumbnail thumbnail_lg_wide">
|
||||
<div class="data">
|
||||
<p class="title">
|
||||
This is the title
|
||||
</p>
|
||||
<p class="meta">
|
||||
<time datetime="2014-07-15T04:16:27-04:00"
|
||||
title="mardi 15 juillet 2014 04:16">Il y a 6 mois</time>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = vimeo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,160 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import wikipedia
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestWikipediaEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = wikipedia.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('test_query', params['url'])
|
||||
self.assertIn('Test_Query', params['url'])
|
||||
self.assertIn('fr.wikipedia.org', params['url'])
|
||||
|
||||
query = 'Test_Query'
|
||||
params = wikipedia.request(query, dicto)
|
||||
self.assertIn('Test_Query', params['url'])
|
||||
self.assertNotIn('test_query', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = wikipedia.request(query, dicto)
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
dicto = defaultdict(dict)
|
||||
dicto['language'] = 'fr'
|
||||
|
||||
self.assertRaises(AttributeError, wikipedia.response, None)
|
||||
self.assertRaises(AttributeError, wikipedia.response, [])
|
||||
self.assertRaises(AttributeError, wikipedia.response, '')
|
||||
self.assertRaises(AttributeError, wikipedia.response, '[]')
|
||||
|
||||
# page not found
|
||||
json = """
|
||||
{
|
||||
"batchcomplete": "",
|
||||
"query": {
|
||||
"normalized": [],
|
||||
"pages": {
|
||||
"-1": {
|
||||
"ns": 0,
|
||||
"title": "",
|
||||
"missing": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
response = mock.Mock(content=json, search_params=dicto)
|
||||
self.assertEqual(wikipedia.response(response), [])
|
||||
|
||||
# normal case
|
||||
json = """
|
||||
{
|
||||
"batchcomplete": "",
|
||||
"query": {
|
||||
"normalized": [],
|
||||
"pages": {
|
||||
"12345": {
|
||||
"pageid": 12345,
|
||||
"ns": 0,
|
||||
"title": "The Title",
|
||||
"extract": "The Title is...",
|
||||
"thumbnail": {
|
||||
"source": "img_src.jpg"
|
||||
},
|
||||
"pageimage": "img_name.jpg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
response = mock.Mock(content=json, search_params=dicto)
|
||||
results = wikipedia.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], u'The Title')
|
||||
self.assertIn('fr.wikipedia.org/wiki/The_Title', results[0]['url'])
|
||||
self.assertEqual(results[1]['infobox'], u'The Title')
|
||||
self.assertIn('fr.wikipedia.org/wiki/The_Title', results[1]['id'])
|
||||
self.assertIn('The Title is...', results[1]['content'])
|
||||
self.assertEqual(results[1]['img_src'], 'img_src.jpg')
|
||||
|
||||
# disambiguation page
|
||||
json = """
|
||||
{
|
||||
"batchcomplete": "",
|
||||
"query": {
|
||||
"normalized": [],
|
||||
"pages": {
|
||||
"12345": {
|
||||
"pageid": 12345,
|
||||
"ns": 0,
|
||||
"title": "The Title",
|
||||
"extract": "The Title can be:\\nThe Title 1\\nThe Title 2\\nThe Title 3\\nThe Title 4......................................................................................................................................." """ # noqa
|
||||
json += """
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
response = mock.Mock(content=json, search_params=dicto)
|
||||
results = wikipedia.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
# no image
|
||||
json = """
|
||||
{
|
||||
"batchcomplete": "",
|
||||
"query": {
|
||||
"normalized": [],
|
||||
"pages": {
|
||||
"12345": {
|
||||
"pageid": 12345,
|
||||
"ns": 0,
|
||||
"title": "The Title",
|
||||
"extract": "The Title is......................................................................................................................................................................................." """ # noqa
|
||||
json += """
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
response = mock.Mock(content=json, search_params=dicto)
|
||||
results = wikipedia.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertIn('The Title is...', results[1]['content'])
|
||||
self.assertEqual(results[1]['img_src'], None)
|
||||
|
||||
# title not in first paragraph
|
||||
json = u"""
|
||||
{
|
||||
"batchcomplete": "",
|
||||
"query": {
|
||||
"normalized": [],
|
||||
"pages": {
|
||||
"12345": {
|
||||
"pageid": 12345,
|
||||
"ns": 0,
|
||||
"title": "披頭四樂隊",
|
||||
"extract": "披头士乐队....................................................................................................................................................................................................\\n披頭四樂隊...", """ # noqa
|
||||
json += """
|
||||
"thumbnail": {
|
||||
"source": "img_src.jpg"
|
||||
},
|
||||
"pageimage": "img_name.jpg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
response = mock.Mock(content=json, search_params=dicto)
|
||||
results = wikipedia.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[1]['infobox'], u'披頭四樂隊')
|
||||
self.assertIn(u'披头士乐队...', results[1]['content'])
|
|
@ -1,164 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from requests import Request
|
||||
from searx.engines import wolframalpha_api
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestWolframAlphaAPIEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
params = wolframalpha_api.request(query, dicto)
|
||||
|
||||
# TODO: test api_key
|
||||
self.assertIn('url', params)
|
||||
self.assertIn('https://api.wolframalpha.com/v2/query?', params['url'])
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertEqual('https://www.wolframalpha.com/input/?i=test_query', params['headers']['Referer'])
|
||||
|
||||
def test_replace_pua_chars(self):
|
||||
self.assertEqual('i', wolframalpha_api.replace_pua_chars(u'\uf74e'))
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, wolframalpha_api.response, None)
|
||||
self.assertRaises(AttributeError, wolframalpha_api.response, [])
|
||||
self.assertRaises(AttributeError, wolframalpha_api.response, '')
|
||||
self.assertRaises(AttributeError, wolframalpha_api.response, '[]')
|
||||
|
||||
referer_url = 'referer_url'
|
||||
request = Request(headers={'Referer': referer_url})
|
||||
|
||||
# test failure
|
||||
xml = '''<?xml version='1.0' encoding='UTF-8'?>
|
||||
<queryresult success='false' error='false' />
|
||||
'''
|
||||
response = mock.Mock(content=xml)
|
||||
self.assertEqual(wolframalpha_api.response(response), [])
|
||||
|
||||
# test basic case
|
||||
xml = """<?xml version='1.0' encoding='UTF-8'?>
|
||||
<queryresult success='true'
|
||||
error='false'
|
||||
numpods='3'
|
||||
datatypes='Math'
|
||||
id='queryresult_id'
|
||||
host='http://www4c.wolframalpha.com'
|
||||
related='related_url'
|
||||
version='2.6'>
|
||||
<pod title='Input'
|
||||
scanner='Identity'
|
||||
id='Input'
|
||||
numsubpods='1'>
|
||||
<subpod title=''>
|
||||
<img src='input_img_src.gif'
|
||||
alt='input_img_alt'
|
||||
title='input_img_title' />
|
||||
<plaintext>input_plaintext</plaintext>
|
||||
</subpod>
|
||||
</pod>
|
||||
<pod title='Result'
|
||||
scanner='Simplification'
|
||||
id='Result'
|
||||
numsubpods='1'
|
||||
primary='true'>
|
||||
<subpod title=''>
|
||||
<img src='result_img_src.gif'
|
||||
alt='result_img_alt'
|
||||
title='result_img_title' />
|
||||
<plaintext>result_plaintext</plaintext>
|
||||
</subpod>
|
||||
</pod>
|
||||
<pod title='Manipulatives illustration'
|
||||
scanner='Arithmetic'
|
||||
id='Illustration'
|
||||
numsubpods='1'>
|
||||
<subpod title=''>
|
||||
<img src='illustration_img_src.gif'
|
||||
alt='illustration_img_alt' />
|
||||
<plaintext>illustration_plaintext</plaintext>
|
||||
</subpod>
|
||||
</pod>
|
||||
</queryresult>
|
||||
"""
|
||||
response = mock.Mock(content=xml, request=request)
|
||||
results = wolframalpha_api.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual('input_plaintext', results[0]['infobox'])
|
||||
|
||||
self.assertEqual(len(results[0]['attributes']), 3)
|
||||
self.assertEqual('Input', results[0]['attributes'][0]['label'])
|
||||
self.assertEqual('input_plaintext', results[0]['attributes'][0]['value'])
|
||||
self.assertEqual('Result', results[0]['attributes'][1]['label'])
|
||||
self.assertEqual('result_plaintext', results[0]['attributes'][1]['value'])
|
||||
self.assertEqual('Manipulatives illustration', results[0]['attributes'][2]['label'])
|
||||
self.assertEqual('illustration_img_src.gif', results[0]['attributes'][2]['image']['src'])
|
||||
self.assertEqual('illustration_img_alt', results[0]['attributes'][2]['image']['alt'])
|
||||
|
||||
self.assertEqual(len(results[0]['urls']), 1)
|
||||
|
||||
self.assertEqual(referer_url, results[0]['urls'][0]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
|
||||
self.assertEqual(referer_url, results[1]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[1]['title'])
|
||||
|
||||
# test calc
|
||||
xml = """<?xml version='1.0' encoding='UTF-8'?>
|
||||
<queryresult success='true'
|
||||
error='false'
|
||||
numpods='2'
|
||||
datatypes=''
|
||||
parsetimedout='false'
|
||||
id='queryresult_id'
|
||||
host='http://www5b.wolframalpha.com'
|
||||
related='related_url'
|
||||
version='2.6' >
|
||||
<pod title='Indefinite integral'
|
||||
scanner='Integral'
|
||||
id='IndefiniteIntegral'
|
||||
error='false'
|
||||
numsubpods='1'
|
||||
primary='true'>
|
||||
<subpod title=''>
|
||||
<img src='integral_image.gif'
|
||||
alt='integral_img_alt'
|
||||
title='integral_img_title' />
|
||||
<plaintext>integral_plaintext</plaintext>
|
||||
</subpod>
|
||||
</pod>
|
||||
<pod title='Plot of the integral'
|
||||
scanner='Integral'
|
||||
id='Plot'
|
||||
error='false'
|
||||
numsubpods='1'>
|
||||
<subpod title=''>
|
||||
<img src='plot.gif'
|
||||
alt='plot_alt'
|
||||
title='' />
|
||||
<plaintext></plaintext>
|
||||
</subpod>
|
||||
</pod>
|
||||
</queryresult>
|
||||
"""
|
||||
response = mock.Mock(content=xml, request=request)
|
||||
results = wolframalpha_api.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual('integral_plaintext', results[0]['infobox'])
|
||||
|
||||
self.assertEqual(len(results[0]['attributes']), 2)
|
||||
self.assertEqual('Indefinite integral', results[0]['attributes'][0]['label'])
|
||||
self.assertEqual('integral_plaintext', results[0]['attributes'][0]['value'])
|
||||
self.assertEqual('Plot of the integral', results[0]['attributes'][1]['label'])
|
||||
self.assertEqual('plot.gif', results[0]['attributes'][1]['image']['src'])
|
||||
self.assertEqual('plot_alt', results[0]['attributes'][1]['image']['alt'])
|
||||
|
||||
self.assertEqual(len(results[0]['urls']), 1)
|
||||
|
||||
self.assertEqual(referer_url, results[0]['urls'][0]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
|
||||
self.assertEqual(referer_url, results[1]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[1]['title'])
|
|
@ -1,222 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from requests import Request
|
||||
from searx.engines import wolframalpha_noapi
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestWolframAlphaNoAPIEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
params = wolframalpha_noapi.request(query, dicto)
|
||||
|
||||
self.assertIn('url', params)
|
||||
self.assertIn('https://www.wolframalpha.com/input/json.jsp', params['url'])
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertEqual('https://www.wolframalpha.com/input/?i=test_query', params['headers']['Referer'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, wolframalpha_noapi.response, None)
|
||||
self.assertRaises(AttributeError, wolframalpha_noapi.response, [])
|
||||
self.assertRaises(AttributeError, wolframalpha_noapi.response, '')
|
||||
self.assertRaises(AttributeError, wolframalpha_noapi.response, '[]')
|
||||
|
||||
referer_url = 'referer_url'
|
||||
request = Request(headers={'Referer': referer_url})
|
||||
|
||||
# test failure
|
||||
json = '''
|
||||
{"queryresult" : {
|
||||
"success" : false,
|
||||
"error" : false,
|
||||
"numpods" : 0,
|
||||
"id" : "",
|
||||
"host" : "https:\/\/www5a.wolframalpha.com",
|
||||
"didyoumeans" : {}
|
||||
}}
|
||||
'''
|
||||
response = mock.Mock(text=json, request=request)
|
||||
self.assertEqual(wolframalpha_noapi.response(response), [])
|
||||
|
||||
# test basic case
|
||||
json = '''
|
||||
{"queryresult" : {
|
||||
"success" : true,
|
||||
"error" : false,
|
||||
"numpods" : 6,
|
||||
"datatypes" : "Math",
|
||||
"id" : "queryresult_id",
|
||||
"host" : "https:\/\/www5b.wolframalpha.com",
|
||||
"related" : "related_url",
|
||||
"version" : "2.6",
|
||||
"pods" : [
|
||||
{
|
||||
"title" : "Input",
|
||||
"scanners" : [
|
||||
"Identity"
|
||||
],
|
||||
"id" : "Input",
|
||||
"error" : false,
|
||||
"numsubpods" : 1,
|
||||
"subpods" : [
|
||||
{
|
||||
"title" : "",
|
||||
"img" : {
|
||||
"src" : "input_img_src.gif",
|
||||
"alt" : "input_img_alt",
|
||||
"title" : "input_img_title"
|
||||
},
|
||||
"plaintext" : "input_plaintext",
|
||||
"minput" : "input_minput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Result",
|
||||
"scanners" : [
|
||||
"Simplification"
|
||||
],
|
||||
"id" : "Result",
|
||||
"error" : false,
|
||||
"numsubpods" : 1,
|
||||
"primary" : true,
|
||||
"subpods" : [
|
||||
{
|
||||
"title" : "",
|
||||
"img" : {
|
||||
"src" : "result_img_src.gif",
|
||||
"alt" : "result_img_alt",
|
||||
"title" : "result_img_title"
|
||||
},
|
||||
"plaintext" : "result_plaintext",
|
||||
"moutput" : "result_moutput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Manipulatives illustration",
|
||||
"scanners" : [
|
||||
"Arithmetic"
|
||||
],
|
||||
"id" : "Illustration",
|
||||
"error" : false,
|
||||
"numsubpods" : 1,
|
||||
"subpods" : [
|
||||
{
|
||||
"title" : "",
|
||||
"CDFcontent" : "Resizeable",
|
||||
"img" : {
|
||||
"src" : "illustration_img_src.gif",
|
||||
"alt" : "illustration_img_alt",
|
||||
"title" : "illustration_img_title"
|
||||
},
|
||||
"plaintext" : "illustration_img_plaintext"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}}
|
||||
'''
|
||||
response = mock.Mock(text=json, request=request)
|
||||
results = wolframalpha_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual('input_plaintext', results[0]['infobox'])
|
||||
|
||||
self.assertEqual(len(results[0]['attributes']), 3)
|
||||
self.assertEqual('Input', results[0]['attributes'][0]['label'])
|
||||
self.assertEqual('input_plaintext', results[0]['attributes'][0]['value'])
|
||||
self.assertEqual('Result', results[0]['attributes'][1]['label'])
|
||||
self.assertEqual('result_plaintext', results[0]['attributes'][1]['value'])
|
||||
self.assertEqual('Manipulatives illustration', results[0]['attributes'][2]['label'])
|
||||
self.assertEqual('illustration_img_src.gif', results[0]['attributes'][2]['image']['src'])
|
||||
self.assertEqual('illustration_img_alt', results[0]['attributes'][2]['image']['alt'])
|
||||
|
||||
self.assertEqual(len(results[0]['urls']), 1)
|
||||
|
||||
self.assertEqual(referer_url, results[0]['urls'][0]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
|
||||
self.assertEqual(referer_url, results[1]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[1]['title'])
|
||||
|
||||
# test calc
|
||||
json = """
|
||||
{"queryresult" : {
|
||||
"success" : true,
|
||||
"error" : false,
|
||||
"numpods" : 2,
|
||||
"datatypes" : "",
|
||||
"id" : "queryresult_id",
|
||||
"host" : "https:\/\/www4b.wolframalpha.com",
|
||||
"related" : "related_url",
|
||||
"version" : "2.6",
|
||||
"pods" : [
|
||||
{
|
||||
"title" : "Indefinite integral",
|
||||
"scanners" : [
|
||||
"Integral"
|
||||
],
|
||||
"id" : "IndefiniteIntegral",
|
||||
"error" : false,
|
||||
"numsubpods" : 1,
|
||||
"primary" : true,
|
||||
"subpods" : [
|
||||
{
|
||||
"title" : "",
|
||||
"img" : {
|
||||
"src" : "integral_img_src.gif",
|
||||
"alt" : "integral_img_alt",
|
||||
"title" : "integral_img_title"
|
||||
},
|
||||
"plaintext" : "integral_plaintext",
|
||||
"minput" : "integral_minput",
|
||||
"moutput" : "integral_moutput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Plot of the integral",
|
||||
"scanners" : [
|
||||
"Integral"
|
||||
],
|
||||
"id" : "Plot",
|
||||
"error" : false,
|
||||
"numsubpods" : 1,
|
||||
"subpods" : [
|
||||
{
|
||||
"title" : "",
|
||||
"img" : {
|
||||
"src" : "plot.gif",
|
||||
"alt" : "plot_alt",
|
||||
"title" : "plot_title"
|
||||
},
|
||||
"plaintext" : "",
|
||||
"minput" : "plot_minput"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}}
|
||||
"""
|
||||
response = mock.Mock(text=json, request=request)
|
||||
results = wolframalpha_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual('integral_plaintext', results[0]['infobox'])
|
||||
|
||||
self.assertEqual(len(results[0]['attributes']), 2)
|
||||
self.assertEqual('Indefinite integral', results[0]['attributes'][0]['label'])
|
||||
self.assertEqual('integral_plaintext', results[0]['attributes'][0]['value'])
|
||||
self.assertEqual('Plot of the integral', results[0]['attributes'][1]['label'])
|
||||
self.assertEqual('plot.gif', results[0]['attributes'][1]['image']['src'])
|
||||
self.assertEqual('plot_alt', results[0]['attributes'][1]['image']['alt'])
|
||||
|
||||
self.assertEqual(len(results[0]['urls']), 1)
|
||||
|
||||
self.assertEqual(referer_url, results[0]['urls'][0]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[0]['urls'][0]['title'])
|
||||
self.assertEqual(referer_url, results[1]['url'])
|
||||
self.assertEqual('Wolfram|Alpha', results[1]['title'])
|
|
@ -1,57 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import www1x
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestWww1xEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
params = www1x.request(query, defaultdict(dict))
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('1x.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, www1x.response, None)
|
||||
self.assertRaises(AttributeError, www1x.response, [])
|
||||
self.assertRaises(AttributeError, www1x.response, '')
|
||||
self.assertRaises(AttributeError, www1x.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(www1x.response(response), [])
|
||||
html = """
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE characters
|
||||
[
|
||||
<!ELEMENT characters (character*) >
|
||||
<!ELEMENT character (#PCDATA ) >
|
||||
|
||||
<!ENTITY iexcl "¡" >
|
||||
<!ENTITY cent "¢" >
|
||||
<!ENTITY pound "£" >
|
||||
]
|
||||
><root><searchresult><![CDATA[<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td style="min-width: 220px;" valign="top">
|
||||
<div style="font-size: 30px; margin: 0px 0px 20px 0px;">Photos</div>
|
||||
<div>
|
||||
<a href="/photo/123456" class="dynamiclink">
|
||||
<img border="0" class="searchresult" src="/images/user/testimage-123456.jpg" style="width: 125px; height: 120px;">
|
||||
</a>
|
||||
<a title="sjoerd lammers street photography" href="/member/sjoerdlammers" class="dynamiclink">
|
||||
<img border="0" class="searchresult" src="/images/profile/60c48b394c677d2fa4d9e7d263aabf44-square.jpg">
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</table>
|
||||
]]></searchresult></root>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = www1x.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['url'], 'https://1x.com/photo/123456')
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'https://1x.com/images/user/testimage-123456.jpg')
|
||||
self.assertEqual(results[0]['content'], '')
|
||||
self.assertEqual(results[0]['template'], 'images.html')
|
|
@ -1,83 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import www500px
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestWww500pxImagesEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
params = www500px.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertTrue('500px.com' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, www500px.response, None)
|
||||
self.assertRaises(AttributeError, www500px.response, [])
|
||||
self.assertRaises(AttributeError, www500px.response, '')
|
||||
self.assertRaises(AttributeError, www500px.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(www500px.response(response), [])
|
||||
|
||||
html = """
|
||||
<div class="photo">
|
||||
<a href="/this.should.be.the.url" data-ga-category="Photo Thumbnail" data-ga-action="Title">
|
||||
<img src="https://image.url/3.jpg?v=0" />
|
||||
</a>
|
||||
<div class="details">
|
||||
<div class="inside">
|
||||
<div class="title">
|
||||
<a href="/photo/64312705/branch-out-by-oliver-turpin?feature=">
|
||||
This is the title
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<a href="/ChronicleUK" data-ga-action="Image" data-ga-category="Photo Thumbnail">
|
||||
This is the content
|
||||
</a>
|
||||
</div>
|
||||
<div class="rating">44.8</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = www500px.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://500px.com/this.should.be.the.url')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
self.assertEqual(results[0]['thumbnail_src'], 'https://image.url/3.jpg?v=0')
|
||||
self.assertEqual(results[0]['img_src'], 'https://image.url/2048.jpg')
|
||||
|
||||
html = """
|
||||
<a href="/this.should.be.the.url" data-ga-category="Photo Thumbnail" data-ga-action="Title">
|
||||
<img src="https://image.url/3.jpg?v=0" />
|
||||
</a>
|
||||
<div class="details">
|
||||
<div class="inside">
|
||||
<div class="title">
|
||||
<a href="/photo/64312705/branch-out-by-oliver-turpin?feature=">
|
||||
This is the title
|
||||
</a>
|
||||
</div>
|
||||
<div class="info">
|
||||
<a href="/ChronicleUK" data-ga-action="Image" data-ga-category="Photo Thumbnail">
|
||||
Oliver Turpin
|
||||
</a>
|
||||
</div>
|
||||
<div class="rating">44.8</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = www500px.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,96 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import yacy
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestYacyEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = yacy.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('localhost', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = yacy.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertNotIn('lr=lang_', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, yacy.response, None)
|
||||
self.assertRaises(AttributeError, yacy.response, [])
|
||||
self.assertRaises(AttributeError, yacy.response, '')
|
||||
self.assertRaises(AttributeError, yacy.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(yacy.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(yacy.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"channels": [
|
||||
{
|
||||
"title": "YaCy P2P-Search for test",
|
||||
"description": "Search for test",
|
||||
"link": "http://search.yacy.de:7001/yacysearch.html?query=test&resource=global&contentdom=0",
|
||||
"image": {
|
||||
"url": "http://search.yacy.de:7001/env/grafics/yacy.png",
|
||||
"title": "Search for test",
|
||||
"link": "http://search.yacy.de:7001/yacysearch.html?query=test&resource=global&contentdom=0"
|
||||
},
|
||||
"totalResults": "249",
|
||||
"startIndex": "0",
|
||||
"itemsPerPage": "5",
|
||||
"searchTerms": "test",
|
||||
"items": [
|
||||
{
|
||||
"title": "This is the title",
|
||||
"link": "http://this.is.the.url",
|
||||
"code": "",
|
||||
"description": "This should be the content",
|
||||
"pubDate": "Sat, 08 Jun 2013 02:00:00 +0200",
|
||||
"size": "44213",
|
||||
"sizename": "43 kbyte",
|
||||
"guid": "lzh_1T_5FP-A",
|
||||
"faviconCode": "XTS4uQ_5FP-A",
|
||||
"host": "www.gamestar.de",
|
||||
"path": "/spiele/city-of-heroes-freedom/47019.html",
|
||||
"file": "47019.html",
|
||||
"urlhash": "lzh_1T_5FP-A",
|
||||
"ranking": "0.20106804"
|
||||
},
|
||||
{
|
||||
"title": "This is the title2",
|
||||
"icon": "/ViewImage.png?maxwidth=96&maxheight=96&code=7EbAbW6BpPOA",
|
||||
"image": "http://image.url/image.png",
|
||||
"cache": "/ViewImage.png?quadratic=&url=http://golem.ivwbox.de/cgi-bin/ivw/CP/G_INET?d=14071378",
|
||||
"url": "http://this.is.the.url",
|
||||
"urlhash": "7EbAbW6BpPOA",
|
||||
"host": "www.golem.de",
|
||||
"width": "-1",
|
||||
"height": "-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = yacy.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url')
|
||||
self.assertEqual(results[0]['content'], 'This should be the content')
|
||||
self.assertEqual(results[1]['img_src'], 'http://image.url/image.png')
|
||||
self.assertEqual(results[1]['content'], '')
|
||||
self.assertEqual(results[1]['url'], 'http://this.is.the.url')
|
||||
self.assertEqual(results[1]['title'], 'This is the title2')
|
|
@ -1,141 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import yahoo
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestYahooEngine(SearxTestCase):
|
||||
|
||||
def test_parse_url(self):
|
||||
test_url = 'http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb' +\
|
||||
'2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10/RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=' +\
|
||||
'dtcJsfP4mEeBOjnVfUQ-'
|
||||
url = yahoo.parse_url(test_url)
|
||||
self.assertEqual('https://this.is.the.url/', url)
|
||||
|
||||
test_url = 'http://r.search.yahoo.com/_ylt=A0LElb9JUSKcAEGRXNyoA;_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb' +\
|
||||
'2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10/RU=https%3a%2f%2fthis.is.the.url%2f/RS=' +\
|
||||
'dtcJsfP4mEeBOjnVfUQ-'
|
||||
url = yahoo.parse_url(test_url)
|
||||
self.assertEqual('https://this.is.the.url/', url)
|
||||
|
||||
test_url = 'https://this.is.the.url/'
|
||||
url = yahoo.parse_url(test_url)
|
||||
self.assertEqual('https://this.is.the.url/', url)
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = yahoo.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('search.yahoo.com', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('sB', params['cookies'])
|
||||
self.assertIn('fr', params['cookies']['sB'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = yahoo.request(query, dicto)
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('sB', params['cookies'])
|
||||
self.assertIn('en', params['cookies']['sB'])
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, yahoo.response, None)
|
||||
self.assertRaises(AttributeError, yahoo.response, [])
|
||||
self.assertRaises(AttributeError, yahoo.response, '')
|
||||
self.assertRaises(AttributeError, yahoo.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(yahoo.response(response), [])
|
||||
|
||||
html = """
|
||||
<ol class="reg mb-15 searchCenterMiddle">
|
||||
<li class="first">
|
||||
<div class="dd algo fst Sr">
|
||||
<div class="compTitle">
|
||||
<h3 class="title"><a class=" td-u" href="http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;
|
||||
_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10
|
||||
/RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=dtcJsfP4mEeBOjnVfUQ-"
|
||||
target="_blank" data-bid="54e712e13671c">
|
||||
<b><b>This is the title</b></b></a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="compText aAbs">
|
||||
<p class="lh-18"><b><b>This is the </b>content</b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="dd algo lst Sr">
|
||||
<div class="compTitle">
|
||||
</div>
|
||||
<div class="compText aAbs">
|
||||
<p class="lh-18">This is the second content</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="dd assist fst lst AlsoTry" data-bid="54e712e138d04">
|
||||
<div class="compTitle mb-4 h-17">
|
||||
<h3 class="title">Also Try</h3> </div>
|
||||
<table class="compTable m-0 ac-1st td-u fz-ms">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="w-50p pr-28"><a href="https://search.yahoo.com/"><B>This is the </B>suggestion<B></B></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = yahoo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://this.is.the.url/')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
self.assertEqual(results[1]['suggestion'], 'This is the suggestion')
|
||||
|
||||
html = """
|
||||
<ol class="reg mb-15 searchCenterMiddle">
|
||||
<li class="first">
|
||||
<div class="dd algo fst Sr">
|
||||
<div class="compTitle">
|
||||
<h3 class="title"><a class=" td-u" href="http://r.search.yahoo.com/_ylt=A0LEb9JUSKcAEGRXNyoA;
|
||||
_ylu=X3oDMTEzZm1qazYwBHNlYwNzcgRwb3MDMQRjb2xvA2Jm2dGlkA1NNRTcwM18x/RV=2/RE=1423106085/RO=10
|
||||
/RU=https%3a%2f%2fthis.is.the.url%2f/RK=0/RS=dtcJsfP4mEeBOjnVfUQ-"
|
||||
target="_blank" data-bid="54e712e13671c">
|
||||
<b><b>This is the title</b></b></a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="compText aAbs">
|
||||
<p class="lh-18"><b><b>This is the </b>content</b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = yahoo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title')
|
||||
self.assertEqual(results[0]['url'], 'https://this.is.the.url/')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
|
||||
html = """
|
||||
<li class="b_algo" u="0|5109|4755453613245655|UAGjXgIrPH5yh-o5oNHRx_3Zta87f_QO">
|
||||
</li>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = yahoo.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,149 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
import mock
|
||||
from searx.engines import yahoo_news
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestYahooNewsEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 1
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = yahoo_news.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('news.search.yahoo.com', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('sB', params['cookies'])
|
||||
self.assertIn('fr', params['cookies']['sB'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = yahoo_news.request(query, dicto)
|
||||
self.assertIn('cookies', params)
|
||||
self.assertIn('sB', params['cookies'])
|
||||
self.assertIn('en', params['cookies']['sB'])
|
||||
self.assertIn('en', params['url'])
|
||||
|
||||
def test_sanitize_url(self):
|
||||
url = "test.url"
|
||||
self.assertEqual(url, yahoo_news.sanitize_url(url))
|
||||
|
||||
url = "www.yahoo.com/;_ylt=test"
|
||||
self.assertEqual("www.yahoo.com/", yahoo_news.sanitize_url(url))
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, yahoo_news.response, None)
|
||||
self.assertRaises(AttributeError, yahoo_news.response, [])
|
||||
self.assertRaises(AttributeError, yahoo_news.response, '')
|
||||
self.assertRaises(AttributeError, yahoo_news.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(yahoo_news.response(response), [])
|
||||
|
||||
html = """
|
||||
<ol class=" reg searchCenterMiddle">
|
||||
<li class="first">
|
||||
<div class="compTitle">
|
||||
<h3>
|
||||
<a class="yschttl spt" href="http://this.is.the.url" target="_blank">
|
||||
This is
|
||||
the <b>title</b>...
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<span class="cite">Business via Yahoo!</span>
|
||||
<span class="tri fc-2nd ml-10">May 01 10:00 AM</span>
|
||||
</div>
|
||||
<div class="compText">
|
||||
This is the content
|
||||
</div>
|
||||
</li>
|
||||
<li class="first">
|
||||
<div class="compTitle">
|
||||
<h3>
|
||||
<a class="yschttl spt" target="_blank">
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="compText">
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = yahoo_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'This is the title...')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
|
||||
html = """
|
||||
<ol class=" reg searchCenterMiddle">
|
||||
<li class="first">
|
||||
<div class="compTitle">
|
||||
<h3>
|
||||
<a class="yschttl spt" href="http://this.is.the.url" target="_blank">
|
||||
This is
|
||||
the <b>title</b>...
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<span class="cite">Business via Yahoo!</span>
|
||||
<span class="tri fc-2nd ml-10">2 hours, 22 minutes ago</span>
|
||||
</div>
|
||||
<div class="compText">
|
||||
This is the content
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="compTitle">
|
||||
<h3>
|
||||
<a class="yschttl spt" href="http://this.is.the.url" target="_blank">
|
||||
This is
|
||||
the <b>title</b>...
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<span class="cite">Business via Yahoo!</span>
|
||||
<span class="tri fc-2nd ml-10">22 minutes ago</span>
|
||||
</div>
|
||||
<div class="compText">
|
||||
This is the content
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="compTitle">
|
||||
<h3>
|
||||
<a class="yschttl spt" href="http://this.is.the.url" target="_blank">
|
||||
This is
|
||||
the <b>title</b>...
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<span class="cite">Business via Yahoo!</span>
|
||||
<span class="tri fc-2nd ml-10">Feb 03 09:45AM 1900</span>
|
||||
</div>
|
||||
<div class="compText">
|
||||
This is the content
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = yahoo_news.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertEqual(results[0]['title'], 'This is the title...')
|
||||
self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
|
||||
self.assertEqual(results[0]['content'], 'This is the content')
|
||||
self.assertEqual(results[2]['publishedDate'].year, datetime.now().year)
|
|
@ -1,111 +0,0 @@
|
|||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import youtube_api
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestYoutubeAPIEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
dicto['language'] = 'fr_FR'
|
||||
params = youtube_api.request(query, dicto)
|
||||
self.assertTrue('url' in params)
|
||||
self.assertTrue(query in params['url'])
|
||||
self.assertIn('googleapis.com', params['url'])
|
||||
self.assertIn('youtube', params['url'])
|
||||
self.assertIn('fr', params['url'])
|
||||
|
||||
dicto['language'] = 'all'
|
||||
params = youtube_api.request(query, dicto)
|
||||
self.assertFalse('fr' in params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, youtube_api.response, None)
|
||||
self.assertRaises(AttributeError, youtube_api.response, [])
|
||||
self.assertRaises(AttributeError, youtube_api.response, '')
|
||||
self.assertRaises(AttributeError, youtube_api.response, '[]')
|
||||
|
||||
response = mock.Mock(text='{}')
|
||||
self.assertEqual(youtube_api.response(response), [])
|
||||
|
||||
response = mock.Mock(text='{"data": []}')
|
||||
self.assertEqual(youtube_api.response(response), [])
|
||||
|
||||
json = """
|
||||
{
|
||||
"kind": "youtube#searchListResponse",
|
||||
"etag": "xmg9xJZuZD438sF4hb-VcBBREXc/YJQDcTBCDcaBvl-sRZJoXdvy1ME",
|
||||
"nextPageToken": "CAUQAA",
|
||||
"pageInfo": {
|
||||
"totalResults": 1000000,
|
||||
"resultsPerPage": 20
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "youtube#searchResult",
|
||||
"etag": "xmg9xJZuZD438sF4hb-VcBBREXc/IbLO64BMhbHIgWLwLw7MDYe7Hs4",
|
||||
"id": {
|
||||
"kind": "youtube#video",
|
||||
"videoId": "DIVZCPfAOeM"
|
||||
},
|
||||
"snippet": {
|
||||
"publishedAt": "2015-05-29T22:41:04.000Z",
|
||||
"channelId": "UCNodmx1ERIjKqvcJLtdzH5Q",
|
||||
"title": "Title",
|
||||
"description": "Description",
|
||||
"thumbnails": {
|
||||
"default": {
|
||||
"url": "https://i.ytimg.com/vi/DIVZCPfAOeM/default.jpg"
|
||||
},
|
||||
"medium": {
|
||||
"url": "https://i.ytimg.com/vi/DIVZCPfAOeM/mqdefault.jpg"
|
||||
},
|
||||
"high": {
|
||||
"url": "https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg"
|
||||
}
|
||||
},
|
||||
"channelTitle": "MinecraftUniverse",
|
||||
"liveBroadcastContent": "none"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = youtube_api.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.youtube.com/watch?v=DIVZCPfAOeM')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
self.assertEqual(results[0]['thumbnail'], 'https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg')
|
||||
self.assertTrue('DIVZCPfAOeM' in results[0]['embedded'])
|
||||
|
||||
json = """
|
||||
{
|
||||
"kind": "youtube#searchListResponse",
|
||||
"etag": "xmg9xJZuZD438sF4hb-VcBBREXc/YJQDcTBCDcaBvl-sRZJoXdvy1ME",
|
||||
"nextPageToken": "CAUQAA",
|
||||
"pageInfo": {
|
||||
"totalResults": 1000000,
|
||||
"resultsPerPage": 20
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = youtube_api.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
json = """
|
||||
{"toto":{"entry":[]
|
||||
}
|
||||
}
|
||||
"""
|
||||
response = mock.Mock(text=json)
|
||||
results = youtube_api.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,154 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
import mock
|
||||
from searx.engines import youtube_noapi
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class TestYoutubeNoAPIEngine(SearxTestCase):
|
||||
|
||||
def test_request(self):
|
||||
query = 'test_query'
|
||||
dicto = defaultdict(dict)
|
||||
dicto['pageno'] = 0
|
||||
params = youtube_noapi.request(query, dicto)
|
||||
self.assertIn('url', params)
|
||||
self.assertIn(query, params['url'])
|
||||
self.assertIn('youtube.com', params['url'])
|
||||
|
||||
def test_response(self):
|
||||
self.assertRaises(AttributeError, youtube_noapi.response, None)
|
||||
self.assertRaises(AttributeError, youtube_noapi.response, [])
|
||||
self.assertRaises(AttributeError, youtube_noapi.response, '')
|
||||
self.assertRaises(AttributeError, youtube_noapi.response, '[]')
|
||||
|
||||
response = mock.Mock(text='<html></html>')
|
||||
self.assertEqual(youtube_noapi.response(response), [])
|
||||
|
||||
html = """
|
||||
<ol id="item-section-063864" class="item-section">
|
||||
<li>
|
||||
<div class="yt-lockup yt-lockup-tile yt-lockup-video vve-check clearfix yt-uix-tile"
|
||||
data-context-item-id="DIVZCPfAOeM"
|
||||
data-visibility-tracking="CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JECx_-GK5uqMpcIB">
|
||||
<div class="yt-lockup-dismissable"><div class="yt-lockup-thumbnail contains-addto">
|
||||
<a aria-hidden="true" href="/watch?v=DIVZCPfAOeM" class=" yt-uix-sessionlink pf-link"
|
||||
data-sessionlink="itct=CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JFIEdGVzdA">
|
||||
<div class="yt-thumb video-thumb"><img src="//i.ytimg.com/vi/DIVZCPfAOeM/mqdefault.jpg"
|
||||
width="196" height="110"/></div><span class="video-time" aria-hidden="true">11:35</span></a>
|
||||
<span class="thumb-menu dark-overflow-action-menu video-actions">
|
||||
</span>
|
||||
</div>
|
||||
<div class="yt-lockup-content">
|
||||
<h3 class="yt-lockup-title">
|
||||
<a href="/watch?v=DIVZCPfAOeM"
|
||||
class="yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link"
|
||||
data-sessionlink="itct=CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JFIEdGVzdA"
|
||||
title="Top Speed Test Kawasaki Ninja H2 (Thailand) By. MEHAY SUPERBIKE"
|
||||
aria-describedby="description-id-259079" rel="spf-prefetch" dir="ltr">
|
||||
Title
|
||||
</a>
|
||||
<span class="accessible-description" id="description-id-259079"> - Durée : 11:35.</span>
|
||||
</h3>
|
||||
<div class="yt-lockup-byline">de
|
||||
<a href="/user/mheejapan" class=" yt-uix-sessionlink spf-link g-hovercard"
|
||||
data-sessionlink="itct=CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JA" data-ytid="UCzEesu54Hjs0uRKmpy66qeA"
|
||||
data-name="">MEHAY SUPERBIKE</a></div><div class="yt-lockup-meta">
|
||||
<ul class="yt-lockup-meta-info">
|
||||
<li>il y a 20 heures</li>
|
||||
<li>8 424 vues</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="yt-lockup-description yt-ui-ellipsis yt-ui-ellipsis-2" dir="ltr">
|
||||
Description
|
||||
</div>
|
||||
<div class="yt-lockup-badges">
|
||||
<ul class="yt-badge-list ">
|
||||
<li class="yt-badge-item" >
|
||||
<span class="yt-badge">Nouveauté</span>
|
||||
</li>
|
||||
<li class="yt-badge-item" ><span class="yt-badge " >HD</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="yt-lockup-action-menu yt-uix-menu-container">
|
||||
<div class="yt-uix-menu yt-uix-videoactionmenu hide-until-delayloaded"
|
||||
data-video-id="DIVZCPfAOeM" data-menu-content-id="yt-uix-videoactionmenu-menu">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = youtube_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]['title'], 'Title')
|
||||
self.assertEqual(results[0]['url'], 'https://www.youtube.com/watch?v=DIVZCPfAOeM')
|
||||
self.assertEqual(results[0]['content'], 'Description')
|
||||
self.assertEqual(results[0]['thumbnail'], 'https://i.ytimg.com/vi/DIVZCPfAOeM/hqdefault.jpg')
|
||||
self.assertTrue('DIVZCPfAOeM' in results[0]['embedded'])
|
||||
|
||||
html = """
|
||||
<ol id="item-section-063864" class="item-section">
|
||||
<li>
|
||||
<div class="yt-lockup yt-lockup-tile yt-lockup-video vve-check clearfix yt-uix-tile"
|
||||
data-context-item-id="DIVZCPfAOeM"
|
||||
data-visibility-tracking="CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JECx_-GK5uqMpcIB">
|
||||
<div class="yt-lockup-dismissable"><div class="yt-lockup-thumbnail contains-addto">
|
||||
<a aria-hidden="true" href="/watch?v=DIVZCPfAOeM" class=" yt-uix-sessionlink pf-link"
|
||||
data-sessionlink="itct=CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JFIEdGVzdA">
|
||||
<div class="yt-thumb video-thumb"><img src="//i.ytimg.com/vi/DIVZCPfAOeM/mqdefault.jpg"
|
||||
width="196" height="110"/></div><span class="video-time" aria-hidden="true">11:35</span></a>
|
||||
<span class="thumb-menu dark-overflow-action-menu video-actions">
|
||||
</span>
|
||||
</div>
|
||||
<div class="yt-lockup-content">
|
||||
<h3 class="yt-lockup-title">
|
||||
<span class="accessible-description" id="description-id-259079"> - Durée : 11:35.</span>
|
||||
</h3>
|
||||
<div class="yt-lockup-byline">de
|
||||
<a href="/user/mheejapan" class=" yt-uix-sessionlink spf-link g-hovercard"
|
||||
data-sessionlink="itct=CBgQ3DAYACITCPGXnYau6sUCFZEIHAod-VQASCj0JA" data-ytid="UCzEesu54Hjs0uRKmpy66qeA"
|
||||
data-name="">MEHAY SUPERBIKE</a></div><div class="yt-lockup-meta">
|
||||
<ul class="yt-lockup-meta-info">
|
||||
<li>il y a 20 heures</li>
|
||||
<li>8 424 vues</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="yt-lockup-badges">
|
||||
<ul class="yt-badge-list ">
|
||||
<li class="yt-badge-item" >
|
||||
<span class="yt-badge">Nouveauté</span>
|
||||
</li>
|
||||
<li class="yt-badge-item" ><span class="yt-badge " >HD</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="yt-lockup-action-menu yt-uix-menu-container">
|
||||
<div class="yt-uix-menu yt-uix-videoactionmenu hide-until-delayloaded"
|
||||
data-video-id="DIVZCPfAOeM" data-menu-content-id="yt-uix-videoactionmenu-menu">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = youtube_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 1)
|
||||
|
||||
html = """
|
||||
<ol id="item-section-063864" class="item-section">
|
||||
<li>
|
||||
</li>
|
||||
</ol>
|
||||
"""
|
||||
response = mock.Mock(text=html)
|
||||
results = youtube_noapi.response(response)
|
||||
self.assertEqual(type(results), list)
|
||||
self.assertEqual(len(results), 0)
|
|
@ -1,74 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from searx.testing import SearxTestCase
|
||||
from searx import plugins
|
||||
from mock import Mock
|
||||
|
||||
|
||||
def get_search_mock(query, **kwargs):
|
||||
return {'search': Mock(query=query,
|
||||
result_container=Mock(answers=set()),
|
||||
**kwargs)}
|
||||
|
||||
|
||||
class PluginStoreTest(SearxTestCase):
|
||||
|
||||
def test_PluginStore_init(self):
|
||||
store = plugins.PluginStore()
|
||||
self.assertTrue(isinstance(store.plugins, list) and len(store.plugins) == 0)
|
||||
|
||||
def test_PluginStore_register(self):
|
||||
store = plugins.PluginStore()
|
||||
testplugin = plugins.Plugin()
|
||||
store.register(testplugin)
|
||||
|
||||
self.assertTrue(len(store.plugins) == 1)
|
||||
|
||||
def test_PluginStore_call(self):
|
||||
store = plugins.PluginStore()
|
||||
testplugin = plugins.Plugin()
|
||||
store.register(testplugin)
|
||||
setattr(testplugin, 'asdf', Mock())
|
||||
request = Mock(user_plugins=[])
|
||||
store.call('asdf', request, Mock())
|
||||
|
||||
self.assertFalse(testplugin.asdf.called)
|
||||
|
||||
request.user_plugins.append(testplugin)
|
||||
store.call('asdf', request, Mock())
|
||||
|
||||
self.assertTrue(testplugin.asdf.called)
|
||||
|
||||
|
||||
class SelfIPTest(SearxTestCase):
|
||||
|
||||
def test_PluginStore_init(self):
|
||||
store = plugins.PluginStore()
|
||||
store.register(plugins.self_info)
|
||||
|
||||
self.assertTrue(len(store.plugins) == 1)
|
||||
|
||||
# IP test
|
||||
request = Mock(user_plugins=store.plugins,
|
||||
remote_addr='127.0.0.1')
|
||||
request.headers.getlist.return_value = []
|
||||
ctx = get_search_mock(query='ip')
|
||||
store.call('post_search', request, ctx)
|
||||
self.assertTrue('127.0.0.1' in ctx['search'].result_container.answers)
|
||||
|
||||
# User agent test
|
||||
request = Mock(user_plugins=store.plugins,
|
||||
user_agent='Mock')
|
||||
request.headers.getlist.return_value = []
|
||||
|
||||
ctx = get_search_mock(query='user-agent')
|
||||
store.call('post_search', request, ctx)
|
||||
self.assertTrue('Mock' in ctx['search'].result_container.answers)
|
||||
|
||||
ctx = get_search_mock(query='user-agent')
|
||||
store.call('post_search', request, ctx)
|
||||
self.assertTrue('Mock' in ctx['search'].result_container.answers)
|
||||
|
||||
ctx = get_search_mock(query='What is my User-Agent?')
|
||||
store.call('post_search', request, ctx)
|
||||
self.assertTrue('Mock' in ctx['search'].result_container.answers)
|
|
@ -1,101 +0,0 @@
|
|||
from searx.preferences import (EnumStringSetting, MapSetting, MissingArgumentException,
|
||||
MultipleChoiceSetting, PluginsSetting, ValidationException)
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class PluginStub(object):
|
||||
def __init__(self, id, default_on):
|
||||
self.id = id
|
||||
self.default_on = default_on
|
||||
|
||||
|
||||
class TestSettings(SearxTestCase):
|
||||
# map settings
|
||||
def test_map_setting_invalid_initialization(self):
|
||||
with self.assertRaises(MissingArgumentException):
|
||||
setting = MapSetting(3, wrong_argument={'0': 0})
|
||||
|
||||
def test_map_setting_invalid_default_value(self):
|
||||
with self.assertRaises(ValidationException):
|
||||
setting = MapSetting(3, map={'dog': 1, 'bat': 2})
|
||||
|
||||
def test_map_setting_invalid_choice(self):
|
||||
setting = MapSetting(2, map={'dog': 1, 'bat': 2})
|
||||
with self.assertRaises(ValidationException):
|
||||
setting.parse('cat')
|
||||
|
||||
def test_map_setting_valid_default(self):
|
||||
setting = MapSetting(3, map={'dog': 1, 'bat': 2, 'cat': 3})
|
||||
self.assertEquals(setting.get_value(), 3)
|
||||
|
||||
def test_map_setting_valid_choice(self):
|
||||
setting = MapSetting(3, map={'dog': 1, 'bat': 2, 'cat': 3})
|
||||
self.assertEquals(setting.get_value(), 3)
|
||||
setting.parse('bat')
|
||||
self.assertEquals(setting.get_value(), 2)
|
||||
|
||||
def test_enum_setting_invalid_initialization(self):
|
||||
with self.assertRaises(MissingArgumentException):
|
||||
setting = EnumStringSetting('cat', wrong_argument=[0, 1, 2])
|
||||
|
||||
# enum settings
|
||||
def test_enum_setting_invalid_initialization(self):
|
||||
with self.assertRaises(MissingArgumentException):
|
||||
setting = EnumStringSetting('cat', wrong_argument=[0, 1, 2])
|
||||
|
||||
def test_enum_setting_invalid_default_value(self):
|
||||
with self.assertRaises(ValidationException):
|
||||
setting = EnumStringSetting(3, choices=[0, 1, 2])
|
||||
|
||||
def test_enum_setting_invalid_choice(self):
|
||||
setting = EnumStringSetting(0, choices=[0, 1, 2])
|
||||
with self.assertRaises(ValidationException):
|
||||
setting.parse(3)
|
||||
|
||||
def test_enum_setting_valid_default(self):
|
||||
setting = EnumStringSetting(3, choices=[1, 2, 3])
|
||||
self.assertEquals(setting.get_value(), 3)
|
||||
|
||||
def test_enum_setting_valid_choice(self):
|
||||
setting = EnumStringSetting(3, choices=[1, 2, 3])
|
||||
self.assertEquals(setting.get_value(), 3)
|
||||
setting.parse(2)
|
||||
self.assertEquals(setting.get_value(), 2)
|
||||
|
||||
# multiple choice settings
|
||||
def test_multiple_setting_invalid_initialization(self):
|
||||
with self.assertRaises(MissingArgumentException):
|
||||
setting = MultipleChoiceSetting(['2'], wrong_argument=['0', '1', '2'])
|
||||
|
||||
def test_multiple_setting_invalid_default_value(self):
|
||||
with self.assertRaises(ValidationException):
|
||||
setting = MultipleChoiceSetting(['3', '4'], choices=['0', '1', '2'])
|
||||
|
||||
def test_multiple_setting_invalid_choice(self):
|
||||
setting = MultipleChoiceSetting(['1', '2'], choices=['0', '1', '2'])
|
||||
with self.assertRaises(ValidationException):
|
||||
setting.parse('4, 3')
|
||||
|
||||
def test_multiple_setting_valid_default(self):
|
||||
setting = MultipleChoiceSetting(['3'], choices=['1', '2', '3'])
|
||||
self.assertEquals(setting.get_value(), ['3'])
|
||||
|
||||
def test_multiple_setting_valid_choice(self):
|
||||
setting = MultipleChoiceSetting(['3'], choices=['1', '2', '3'])
|
||||
self.assertEquals(setting.get_value(), ['3'])
|
||||
setting.parse('2')
|
||||
self.assertEquals(setting.get_value(), ['2'])
|
||||
|
||||
# plugins settings
|
||||
def test_plugins_setting_all_default_enabled(self):
|
||||
plugin1 = PluginStub('plugin1', True)
|
||||
plugin2 = PluginStub('plugin2', True)
|
||||
setting = PluginsSetting(['3'], choices=[plugin1, plugin2])
|
||||
self.assertEquals(setting.get_enabled(), set(['plugin1', 'plugin2']))
|
||||
|
||||
def test_plugins_setting_few_default_enabled(self):
|
||||
plugin1 = PluginStub('plugin1', True)
|
||||
plugin2 = PluginStub('plugin2', False)
|
||||
plugin3 = PluginStub('plugin3', True)
|
||||
setting = PluginsSetting('name', choices=[plugin1, plugin2, plugin3])
|
||||
self.assertEquals(setting.get_enabled(), set(['plugin1', 'plugin3']))
|
|
@ -1,41 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from searx.results import ResultContainer
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
def fake_result(url='https://aa.bb/cc?dd=ee#ff',
|
||||
title='aaa',
|
||||
content='bbb',
|
||||
engine='wikipedia', **kwargs):
|
||||
result = {'url': url,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'engine': engine}
|
||||
result.update(kwargs)
|
||||
return result
|
||||
|
||||
|
||||
# TODO
|
||||
class ResultContainerTestCase(SearxTestCase):
|
||||
|
||||
def test_empty(self):
|
||||
c = ResultContainer()
|
||||
self.assertEqual(c.get_ordered_results(), [])
|
||||
|
||||
def test_one_result(self):
|
||||
c = ResultContainer()
|
||||
c.extend('wikipedia', [fake_result()])
|
||||
self.assertEqual(c.results_length(), 1)
|
||||
|
||||
def test_one_suggestion(self):
|
||||
c = ResultContainer()
|
||||
c.extend('wikipedia', [fake_result(suggestion=True)])
|
||||
self.assertEqual(len(c.suggestions), 1)
|
||||
self.assertEqual(c.results_length(), 0)
|
||||
|
||||
def test_result_merge(self):
|
||||
c = ResultContainer()
|
||||
c.extend('wikipedia', [fake_result()])
|
||||
c.extend('wikidata', [fake_result(), fake_result(url='https://example.com/')])
|
||||
self.assertEqual(c.results_length(), 2)
|
|
@ -1,10 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
# TODO
|
||||
class SearchTestCase(SearxTestCase):
|
||||
|
||||
def test_(self):
|
||||
pass
|
|
@ -1,101 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import mock
|
||||
from searx.testing import SearxTestCase
|
||||
from searx import utils
|
||||
|
||||
|
||||
class TestUtils(SearxTestCase):
|
||||
|
||||
def test_gen_useragent(self):
|
||||
self.assertIsInstance(utils.gen_useragent(), str)
|
||||
self.assertIsNotNone(utils.gen_useragent())
|
||||
self.assertTrue(utils.gen_useragent().startswith('Mozilla'))
|
||||
|
||||
def test_searx_useragent(self):
|
||||
self.assertIsInstance(utils.searx_useragent(), str)
|
||||
self.assertIsNotNone(utils.searx_useragent())
|
||||
self.assertTrue(utils.searx_useragent().startswith('searx'))
|
||||
|
||||
def test_highlight_content(self):
|
||||
self.assertEqual(utils.highlight_content(0, None), None)
|
||||
self.assertEqual(utils.highlight_content(None, None), None)
|
||||
self.assertEqual(utils.highlight_content('', None), None)
|
||||
self.assertEqual(utils.highlight_content(False, None), None)
|
||||
|
||||
contents = [
|
||||
'<html></html>'
|
||||
'not<'
|
||||
]
|
||||
for content in contents:
|
||||
self.assertEqual(utils.highlight_content(content, None), content)
|
||||
|
||||
content = 'a'
|
||||
query = 'test'
|
||||
self.assertEqual(utils.highlight_content(content, query), content)
|
||||
query = 'a test'
|
||||
self.assertEqual(utils.highlight_content(content, query), content)
|
||||
|
||||
def test_html_to_text(self):
|
||||
html = """
|
||||
<a href="/testlink" class="link_access_account">
|
||||
<span class="toto">
|
||||
<span>
|
||||
<img src="test.jpg" />
|
||||
</span>
|
||||
</span>
|
||||
<span class="titi">
|
||||
Test text
|
||||
</span>
|
||||
</a>
|
||||
"""
|
||||
self.assertIsInstance(utils.html_to_text(html), unicode)
|
||||
self.assertIsNotNone(utils.html_to_text(html))
|
||||
self.assertEqual(utils.html_to_text(html), "Test text")
|
||||
|
||||
def test_prettify_url(self):
|
||||
data = (('https://searx.me/', 'https://searx.me/'),
|
||||
(u'https://searx.me/ű', u'https://searx.me/ű'),
|
||||
('https://searx.me/' + (100 * 'a'), 'https://searx.me/[...]aaaaaaaaaaaaaaaaa'),
|
||||
(u'https://searx.me/' + (100 * u'ű'), u'https://searx.me/[...]űűűűűűűűűűűűűűűűű'))
|
||||
|
||||
for test_url, expected in data:
|
||||
self.assertEqual(utils.prettify_url(test_url, max_length=32), expected)
|
||||
|
||||
|
||||
class TestHTMLTextExtractor(SearxTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.html_text_extractor = utils.HTMLTextExtractor()
|
||||
|
||||
def test__init__(self):
|
||||
self.assertEqual(self.html_text_extractor.result, [])
|
||||
|
||||
def test_handle_charref(self):
|
||||
self.html_text_extractor.handle_charref('xF')
|
||||
self.assertIn(u'\x0f', self.html_text_extractor.result)
|
||||
self.html_text_extractor.handle_charref('XF')
|
||||
self.assertIn(u'\x0f', self.html_text_extractor.result)
|
||||
|
||||
self.html_text_extractor.handle_charref('97')
|
||||
self.assertIn(u'a', self.html_text_extractor.result)
|
||||
|
||||
def test_handle_entityref(self):
|
||||
entity = 'test'
|
||||
self.html_text_extractor.handle_entityref(entity)
|
||||
self.assertIn(entity, self.html_text_extractor.result)
|
||||
|
||||
|
||||
class TestUnicodeWriter(SearxTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.unicode_writer = utils.UnicodeWriter(mock.MagicMock())
|
||||
|
||||
def test_write_row(self):
|
||||
row = [1, 2, 3]
|
||||
self.assertEqual(self.unicode_writer.writerow(row), None)
|
||||
|
||||
def test_write_rows(self):
|
||||
self.unicode_writer.writerow = mock.MagicMock()
|
||||
rows = [1, 2, 3]
|
||||
self.unicode_writer.writerows(rows)
|
||||
self.assertEqual(self.unicode_writer.writerow.call_count, len(rows))
|
|
@ -1,155 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from mock import Mock
|
||||
from urlparse import ParseResult
|
||||
from searx import webapp
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class ViewsTestCase(SearxTestCase):
|
||||
|
||||
def setUp(self):
|
||||
webapp.app.config['TESTING'] = True # to get better error messages
|
||||
self.app = webapp.app.test_client()
|
||||
|
||||
# set some defaults
|
||||
self.test_results = [
|
||||
{
|
||||
'content': 'first test content',
|
||||
'title': 'First Test',
|
||||
'url': 'http://first.test.xyz',
|
||||
'engines': ['youtube', 'startpage'],
|
||||
'engine': 'startpage',
|
||||
'parsed_url': ParseResult(scheme='http', netloc='first.test.xyz', path='/', params='', query='', fragment=''), # noqa
|
||||
}, {
|
||||
'content': 'second test content',
|
||||
'title': 'Second Test',
|
||||
'url': 'http://second.test.xyz',
|
||||
'engines': ['youtube', 'startpage'],
|
||||
'engine': 'youtube',
|
||||
'parsed_url': ParseResult(scheme='http', netloc='second.test.xyz', path='/', params='', query='', fragment=''), # noqa
|
||||
},
|
||||
]
|
||||
|
||||
def search_mock(search_self, *args):
|
||||
search_self.result_container = Mock(get_ordered_results=lambda: self.test_results,
|
||||
answers=set(),
|
||||
suggestions=set(),
|
||||
infoboxes=[],
|
||||
results=self.test_results,
|
||||
results_length=lambda: len(self.test_results))
|
||||
|
||||
webapp.Search.search = search_mock
|
||||
|
||||
def get_current_theme_name_mock(override=None):
|
||||
return 'default'
|
||||
|
||||
webapp.get_current_theme_name = get_current_theme_name_mock
|
||||
|
||||
self.maxDiff = None # to see full diffs
|
||||
|
||||
def test_index_empty(self):
|
||||
result = self.app.post('/')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<div class="title"><h1>searx</h1></div>', result.data)
|
||||
|
||||
def test_index_html(self):
|
||||
result = self.app.post('/', data={'q': 'test'})
|
||||
self.assertIn(
|
||||
'<h3 class="result_title"><img width="14" height="14" class="favicon" src="/static/themes/default/img/icons/icon_youtube.ico" alt="youtube" /><a href="http://second.test.xyz" rel="noreferrer">Second <span class="highlight">Test</span></a></h3>', # noqa
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<p class="content">first <span class="highlight">test</span> content<br class="last"/></p>', # noqa
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_index_json(self):
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'json'})
|
||||
|
||||
result_dict = json.loads(result.data)
|
||||
|
||||
self.assertEqual('test', result_dict['query'])
|
||||
self.assertEqual(
|
||||
result_dict['results'][0]['content'], 'first test content')
|
||||
self.assertEqual(
|
||||
result_dict['results'][0]['url'], 'http://first.test.xyz')
|
||||
|
||||
def test_index_csv(self):
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'csv'})
|
||||
|
||||
self.assertEqual(
|
||||
'title,url,content,host,engine,score\r\n'
|
||||
'First Test,http://first.test.xyz,first test content,first.test.xyz,startpage,\r\n' # noqa
|
||||
'Second Test,http://second.test.xyz,second test content,second.test.xyz,youtube,\r\n', # noqa
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_index_rss(self):
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'rss'})
|
||||
|
||||
self.assertIn(
|
||||
'<description>Search results for "test" - searx</description>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<opensearch:totalResults>2</opensearch:totalResults>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<title>First Test</title>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<link>http://first.test.xyz</link>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<description>first test content</description>',
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_about(self):
|
||||
result = self.app.get('/about')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<h1>About <a href="/">searx</a></h1>', result.data)
|
||||
|
||||
def test_preferences(self):
|
||||
result = self.app.get('/preferences')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn(
|
||||
'<form method="post" action="/preferences" id="search_form">',
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<legend>Default categories</legend>',
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<legend>Interface language</legend>',
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_stats(self):
|
||||
result = self.app.get('/stats')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<h2>Engine stats</h2>', result.data)
|
||||
|
||||
def test_robots_txt(self):
|
||||
result = self.app.get('/robots.txt')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('Allow: /', result.data)
|
||||
|
||||
def test_opensearch_xml(self):
|
||||
result = self.app.get('/opensearch.xml')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<Description>a privacy-respecting, hackable metasearch engine</Description>', result.data)
|
||||
|
||||
def test_favicon(self):
|
||||
result = self.app.get('/favicon.ico')
|
||||
self.assertEqual(result.status_code, 200)
|
|
@ -1,2 +0,0 @@
|
|||
[flake8]
|
||||
max-line-length = 120
|
117
sources/utils/fabfile.py
vendored
117
sources/utils/fabfile.py
vendored
|
@ -1,117 +0,0 @@
|
|||
from fabric.api import cd, run, sudo, put
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
||||
base_dir = '/usr/local'
|
||||
hostname = 'searx.me'
|
||||
searx_dir = base_dir + '/searx'
|
||||
searx_ve_dir = searx_dir + '/searx-ve'
|
||||
current_user = run('whoami').stdout.strip()
|
||||
|
||||
uwsgi_file = '''
|
||||
[uwsgi]
|
||||
# Who will run the code
|
||||
uid = {user}
|
||||
gid = {user}
|
||||
|
||||
# Number of workers
|
||||
workers = 8
|
||||
|
||||
# The right granted on the created socket
|
||||
chmod-socket = 666
|
||||
|
||||
# Plugin to use and interpretor config
|
||||
single-interpreter = true
|
||||
master = true
|
||||
plugin = python
|
||||
|
||||
# Module to import
|
||||
module = searx.webapp
|
||||
|
||||
# Virtualenv and python path
|
||||
virtualenv = {searx_ve_dir}
|
||||
pythonpath = {searx_dir}
|
||||
chdir = {searx_dir}/searx
|
||||
'''.format(user=current_user,
|
||||
searx_dir=searx_dir,
|
||||
searx_ve_dir=searx_ve_dir)
|
||||
|
||||
nginx_config = '''
|
||||
server {{
|
||||
listen 80;
|
||||
server_name {hostname};
|
||||
server_name www.{hostname};
|
||||
root /usr/local/searx;
|
||||
|
||||
location / {{
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:/run/uwsgi/app/searx/socket;
|
||||
}}
|
||||
}}
|
||||
'''.format(hostname=hostname)
|
||||
|
||||
|
||||
def stop():
|
||||
sudo('/etc/init.d/uwsgi stop')
|
||||
|
||||
|
||||
def start():
|
||||
sudo('/etc/init.d/uwsgi start')
|
||||
|
||||
|
||||
def restart():
|
||||
sudo('/etc/init.d/uwsgi restart')
|
||||
|
||||
|
||||
def init():
|
||||
if not run('test -d ' + searx_dir, warn_only=True).failed:
|
||||
return
|
||||
|
||||
sudo('apt-get update')
|
||||
|
||||
sudo('apt-get install git'
|
||||
' build-essential'
|
||||
' libxslt-dev'
|
||||
' python-dev'
|
||||
' python-virtualenv'
|
||||
' python-pybabel'
|
||||
' zlib1g-dev'
|
||||
' uwsgi'
|
||||
' uwsgi-plugin-python'
|
||||
' nginx')
|
||||
|
||||
sudo('mkdir -p ' + base_dir)
|
||||
|
||||
put(StringIO(nginx_config), '/etc/nginx/sites-enabled/searx', use_sudo=True)
|
||||
sudo('/etc/init.d/nginx restart')
|
||||
|
||||
with cd(base_dir):
|
||||
sudo('git clone https://github.com/asciimoo/searx')
|
||||
|
||||
sudo('chown -R {user}:{user} {searx_dir}'.format(user=current_user, searx_dir=searx_dir))
|
||||
put(StringIO(uwsgi_file), searx_dir+'/uwsgi.ini')
|
||||
sudo('ln -s {0}/uwsgi.ini /etc/uwsgi/apps-enabled/searx.ini'.format(searx_dir))
|
||||
|
||||
run('virtualenv {0}'.format(searx_ve_dir))
|
||||
|
||||
with cd(searx_dir):
|
||||
run('source {0}/bin/activate && pip install -r requirements.txt'.format(searx_ve_dir))
|
||||
|
||||
start()
|
||||
|
||||
|
||||
def deploy():
|
||||
init()
|
||||
|
||||
with cd(searx_dir):
|
||||
run("git stash", warn_only=True)
|
||||
run("git pull origin master")
|
||||
run("git stash pop", warn_only=True)
|
||||
|
||||
restart()
|
||||
|
||||
|
||||
def clean():
|
||||
sudo('rm -rf {searx_dir}'.format(searx_dir=searx_dir), warn_only=True)
|
||||
sudo('rm /etc/uwsgi/apps-enabled/searx.ini', warn_only=True)
|
||||
sudo('rm /etc/nginx/sites-enabled/searx', warn_only=True)
|
|
@ -1,161 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import re
|
||||
import unicodedata
|
||||
import string
|
||||
from urllib import urlencode
|
||||
from requests import get
|
||||
|
||||
languages = {'de', 'en', 'es', 'fr', 'hu', 'it', 'nl', 'jp'}
|
||||
|
||||
url_template = 'https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&{query}&props=labels%7Cdatatype%7Cclaims%7Caliases&languages=' + '|'.join(languages)
|
||||
url_wmflabs_template = 'http://wdq.wmflabs.org/api?q='
|
||||
url_wikidata_search_template='http://www.wikidata.org/w/api.php?action=query&list=search&format=json&srnamespace=0&srprop=sectiontitle&{query}'
|
||||
|
||||
wmflabs_queries = [
|
||||
'CLAIM[31:8142]', # all devise
|
||||
]
|
||||
|
||||
db = {
|
||||
'iso4217' : {
|
||||
},
|
||||
'names' : {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def remove_accents(data):
|
||||
return unicodedata.normalize('NFKD', data).lower()
|
||||
|
||||
|
||||
def normalize_name(name):
|
||||
return re.sub(' +',' ', remove_accents(name.lower()).replace('-', ' '))
|
||||
|
||||
|
||||
def add_currency_name(name, iso4217):
|
||||
global db
|
||||
|
||||
db_names = db['names']
|
||||
|
||||
|
||||
if not isinstance(iso4217, basestring):
|
||||
print "problem", name, iso4217
|
||||
return
|
||||
|
||||
name = normalize_name(name)
|
||||
|
||||
if name == '':
|
||||
print "name empty", iso4217
|
||||
return
|
||||
|
||||
iso4217_set = db_names.get(name, None)
|
||||
if iso4217_set is not None and iso4217 not in iso4217_set:
|
||||
db_names[name].append(iso4217)
|
||||
else:
|
||||
db_names[name] = [ iso4217 ]
|
||||
|
||||
|
||||
def add_currency_label(label, iso4217, language):
|
||||
global db
|
||||
|
||||
db['iso4217'][iso4217] = db['iso4217'].get(iso4217, {})
|
||||
db['iso4217'][iso4217][language] = label
|
||||
|
||||
|
||||
def get_property_value(data, name):
|
||||
prop = data.get('claims', {}).get(name, {})
|
||||
if len(prop) == 0:
|
||||
return None
|
||||
|
||||
value = prop[0].get('mainsnak', {}).get('datavalue', {}).get('value', '')
|
||||
if value == '':
|
||||
return None
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def parse_currency(data):
|
||||
iso4217 = get_property_value(data, 'P498')
|
||||
|
||||
if iso4217 is not None:
|
||||
unit = get_property_value(data, 'P558')
|
||||
if unit is not None:
|
||||
add_currency_name(unit, iso4217)
|
||||
|
||||
labels = data.get('labels', {})
|
||||
for language in languages:
|
||||
name = labels.get(language, {}).get('value', None)
|
||||
if name != None:
|
||||
add_currency_name(name, iso4217)
|
||||
add_currency_label(name, iso4217, language)
|
||||
|
||||
aliases = data.get('aliases', {})
|
||||
for language in aliases:
|
||||
for i in range(0, len(aliases[language])):
|
||||
alias = aliases[language][i].get('value', None)
|
||||
add_currency_name(alias, iso4217)
|
||||
|
||||
|
||||
def fetch_data(wikidata_ids):
|
||||
url = url_template.format(query=urlencode({'ids' : '|'.join(wikidata_ids)}))
|
||||
htmlresponse = get(url)
|
||||
jsonresponse = json.loads(htmlresponse.content)
|
||||
entities = jsonresponse.get('entities', {})
|
||||
|
||||
for pname in entities:
|
||||
pvalue = entities.get(pname)
|
||||
parse_currency(pvalue)
|
||||
|
||||
|
||||
def add_q(i):
|
||||
return "Q" + str(i)
|
||||
|
||||
|
||||
def fetch_data_batch(wikidata_ids):
|
||||
while len(wikidata_ids) > 0:
|
||||
if len(wikidata_ids) > 50:
|
||||
fetch_data(wikidata_ids[0:49])
|
||||
wikidata_ids = wikidata_ids[50:]
|
||||
else:
|
||||
fetch_data(wikidata_ids)
|
||||
wikidata_ids = []
|
||||
|
||||
|
||||
def wdq_query(query):
|
||||
url = url_wmflabs_template + query
|
||||
htmlresponse = get(url)
|
||||
jsonresponse = json.loads(htmlresponse.content)
|
||||
qlist = map(add_q, jsonresponse.get('items', {}))
|
||||
error = jsonresponse.get('status', {}).get('error', None)
|
||||
if error != None and error != 'OK':
|
||||
print "error for query '" + query + "' :" + error
|
||||
|
||||
fetch_data_batch(qlist)
|
||||
|
||||
|
||||
def wd_query(query, offset=0):
|
||||
qlist = []
|
||||
|
||||
url = url_wikidata_search_template.format(query=urlencode({'srsearch': query, 'srlimit': 50, 'sroffset': offset}))
|
||||
htmlresponse = get(url)
|
||||
jsonresponse = json.loads(htmlresponse.content)
|
||||
for r in jsonresponse.get('query', {}).get('search', {}):
|
||||
qlist.append(r.get('title', ''))
|
||||
fetch_data_batch(qlist)
|
||||
|
||||
## fetch ##
|
||||
for q in wmflabs_queries:
|
||||
wdq_query(q)
|
||||
|
||||
# static
|
||||
add_currency_name(u"euro", 'EUR')
|
||||
add_currency_name(u"euros", 'EUR')
|
||||
add_currency_name(u"dollar", 'USD')
|
||||
add_currency_name(u"dollars", 'USD')
|
||||
add_currency_name(u"peso", 'MXN')
|
||||
add_currency_name(u"pesos", 'MXN')
|
||||
|
||||
# write
|
||||
f = open("currencies.json", "wb")
|
||||
json.dump(db, f, indent=4, encoding="utf-8")
|
||||
f.close()
|
|
@ -1,36 +0,0 @@
|
|||
from sys import argv, exit
|
||||
|
||||
if not len(argv) > 1:
|
||||
print('search query required')
|
||||
exit(1)
|
||||
|
||||
import requests
|
||||
from json import dumps
|
||||
from searx.engines import google
|
||||
from searx.search import default_request_params
|
||||
|
||||
request_params = default_request_params()
|
||||
# Possible params
|
||||
# request_params['headers']['User-Agent'] = ''
|
||||
# request_params['category'] = ''
|
||||
# request_params['started'] = ''
|
||||
|
||||
request_params['pageno'] = 1
|
||||
request_params['language'] = 'en_us'
|
||||
|
||||
params = google.request(argv[1], request_params)
|
||||
|
||||
request_args = dict(
|
||||
headers=request_params['headers'],
|
||||
cookies=request_params['cookies'],
|
||||
)
|
||||
|
||||
if request_params['method'] == 'GET':
|
||||
req = requests.get
|
||||
else:
|
||||
req = requests.post
|
||||
request_args['data'] = request_params['data']
|
||||
|
||||
resp = req(request_params['url'], **request_args)
|
||||
|
||||
print(dumps(google.response(resp)))
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# script to easily update translation language files
|
||||
|
||||
# add new language:
|
||||
# pybabel init -i messages.pot -d searx/translations -l en
|
||||
|
||||
SEARX_DIR='searx'
|
||||
|
||||
pybabel extract -F babel.cfg -o messages.pot $SEARX_DIR
|
||||
for f in `ls $SEARX_DIR'/translations/'`; do
|
||||
pybabel update -N -i messages.pot -d $SEARX_DIR'/translations/' -l $f
|
||||
done
|
||||
|
||||
echo '[!] update done, edit .po files if required and run pybabel compile -d searx/translations/'
|
Loading…
Add table
Reference in a new issue