swiftype 0.0.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +1 -1
- data/README.md +202 -283
- data/lib/data/ca-bundle.crt +3554 -0
- data/lib/swiftype.rb +7 -31
- data/lib/swiftype/client.rb +439 -11
- data/lib/swiftype/configuration.rb +29 -4
- data/lib/swiftype/exceptions.rb +2 -0
- data/lib/swiftype/ext/backport-uri.rb +33 -0
- data/lib/swiftype/request.rb +88 -20
- data/lib/swiftype/result_set.rb +43 -6
- data/lib/swiftype/sso.rb +20 -0
- data/lib/swiftype/version.rb +1 -1
- data/spec/client_spec.rb +576 -0
- data/spec/configuration_spec.rb +36 -0
- data/spec/deprecated_spec.rb +20 -0
- data/spec/fixtures/vcr/analytics_autoselects.yml +55 -0
- data/spec/fixtures/vcr/analytics_autoselects_with_document_type.yml +55 -0
- data/spec/fixtures/vcr/analytics_autoselects_with_document_type_and_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_autoselects_with_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_clicks.yml +55 -0
- data/spec/fixtures/vcr/analytics_clicks_with_document_type.yml +55 -0
- data/spec/fixtures/vcr/analytics_clicks_with_document_type_and_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_clicks_with_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_searches.yml +55 -0
- data/spec/fixtures/vcr/analytics_searches_with_document_type_and_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_searches_with_time_range.yml +55 -0
- data/spec/fixtures/vcr/analytics_searchs_with_document_type.yml +55 -0
- data/spec/fixtures/vcr/analytics_top_no_result_queries.yml +55 -0
- data/spec/fixtures/vcr/analytics_top_no_result_queries_paginated.yml +55 -0
- data/spec/fixtures/vcr/analytics_top_queries.yml +55 -0
- data/spec/fixtures/vcr/analytics_top_queries_paginated.yml +55 -0
- data/spec/fixtures/vcr/analytics_top_queries_too_large.yml +51 -0
- data/spec/fixtures/vcr/bulk_create_documents.yml +49 -0
- data/spec/fixtures/vcr/bulk_create_or_update_documents_failure.yml +45 -0
- data/spec/fixtures/vcr/bulk_create_or_update_documents_success.yml +49 -0
- data/spec/fixtures/vcr/bulk_destroy_documents.yml +45 -0
- data/spec/fixtures/vcr/crawl_url.yml +45 -0
- data/spec/fixtures/vcr/create_document.yml +48 -0
- data/spec/fixtures/vcr/create_document_type.yml +45 -0
- data/spec/fixtures/vcr/create_domain.yml +45 -0
- data/spec/fixtures/vcr/create_engine.yml +45 -0
- data/spec/fixtures/vcr/create_or_update_document_create.yml +47 -0
- data/spec/fixtures/vcr/create_or_update_document_update.yml +47 -0
- data/spec/fixtures/vcr/create_user.yml +45 -0
- data/spec/fixtures/vcr/destroy_document.yml +41 -0
- data/spec/fixtures/vcr/destroy_document_type.yml +41 -0
- data/spec/fixtures/vcr/destroy_domain.yml +41 -0
- data/spec/fixtures/vcr/destroy_engine.yml +41 -0
- data/spec/fixtures/vcr/destroy_non_existent_document_type.yml +43 -0
- data/spec/fixtures/vcr/document_type_search.yml +60 -0
- data/spec/fixtures/vcr/document_type_search_pagination.yml +45 -0
- data/spec/fixtures/vcr/document_type_suggest.yml +50 -0
- data/spec/fixtures/vcr/document_type_suggest_pagination.yml +45 -0
- data/spec/fixtures/vcr/engine_search.yml +64 -0
- data/spec/fixtures/vcr/engine_search_facets.yml +162 -0
- data/spec/fixtures/vcr/engine_search_pagination.yml +45 -0
- data/spec/fixtures/vcr/engine_suggest.yml +52 -0
- data/spec/fixtures/vcr/engine_suggest_pagination.yml +45 -0
- data/spec/fixtures/vcr/find_document.yml +47 -0
- data/spec/fixtures/vcr/find_document_type.yml +45 -0
- data/spec/fixtures/vcr/find_domain.yml +45 -0
- data/spec/fixtures/vcr/find_domain_failure.yml +43 -0
- data/spec/fixtures/vcr/find_engine.yml +45 -0
- data/spec/fixtures/vcr/list_document_type.yml +45 -0
- data/spec/fixtures/vcr/list_documents.yml +68 -0
- data/spec/fixtures/vcr/list_documents_with_pagination.yml +68 -0
- data/spec/fixtures/vcr/list_domains.yml +45 -0
- data/spec/fixtures/vcr/list_engines.yml +46 -0
- data/spec/fixtures/vcr/list_users.yml +45 -0
- data/spec/fixtures/vcr/list_users_with_pagination.yml +45 -0
- data/spec/fixtures/vcr/log_clickthrough_failure.yml +43 -0
- data/spec/fixtures/vcr/log_clickthrough_success.yml +45 -0
- data/spec/fixtures/vcr/recrawl_domain_failure.yml +44 -0
- data/spec/fixtures/vcr/recrawl_domain_success.yml +45 -0
- data/spec/fixtures/vcr/show_user.yml +45 -0
- data/spec/fixtures/vcr/update_document.yml +47 -0
- data/spec/fixtures/vcr/update_document_unknown_field_failure.yml +45 -0
- data/spec/fixtures/vcr/update_documents_failure_non_existent_document.yml +45 -0
- data/spec/fixtures/vcr/update_documents_success.yml +45 -0
- data/spec/fixtures/vcr/users_client_secret_incorrect.yml +42 -0
- data/spec/fixtures/vcr/users_no_api_key.yml +42 -0
- data/spec/fixtures/vcr/users_no_client_id_or_secret.yml +43 -0
- data/spec/platform_spec.rb +95 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/ssl_spec.rb +34 -0
- data/spec/sso_spec.rb +24 -0
- data/swiftype.gemspec +10 -11
- metadata +183 -52
- data/lib/swiftype/base_model.rb +0 -89
- data/lib/swiftype/connection.rb +0 -47
- data/lib/swiftype/document.rb +0 -17
- data/lib/swiftype/document_type.rb +0 -69
- data/lib/swiftype/easy.rb +0 -77
- data/lib/swiftype/engine.rb +0 -33
- data/lib/swiftype/search.rb +0 -23
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'uri'
|
|
1
2
|
require 'swiftype/version'
|
|
2
3
|
|
|
3
4
|
module Swiftype
|
|
@@ -6,10 +7,10 @@ module Swiftype
|
|
|
6
7
|
DEFAULT_USER_AGENT = "Swiftype-Ruby/#{Swiftype::VERSION}"
|
|
7
8
|
|
|
8
9
|
VALID_OPTIONS_KEYS = [
|
|
9
|
-
:username,
|
|
10
|
-
:password,
|
|
11
10
|
:api_key,
|
|
12
11
|
:user_agent,
|
|
12
|
+
:platform_client_id,
|
|
13
|
+
:platform_client_secret,
|
|
13
14
|
:endpoint
|
|
14
15
|
]
|
|
15
16
|
|
|
@@ -19,24 +20,48 @@ module Swiftype
|
|
|
19
20
|
base.reset
|
|
20
21
|
end
|
|
21
22
|
|
|
23
|
+
# Reset configuration to default values.
|
|
22
24
|
def reset
|
|
23
|
-
self.username = nil
|
|
24
|
-
self.password = nil
|
|
25
25
|
self.api_key = nil
|
|
26
26
|
self.endpoint = DEFAULT_ENDPOINT
|
|
27
27
|
self.user_agent = DEFAULT_USER_AGENT
|
|
28
|
+
self.platform_client_id = nil
|
|
29
|
+
self.platform_client_secret = nil
|
|
28
30
|
self
|
|
29
31
|
end
|
|
30
32
|
|
|
33
|
+
# Yields the Swiftype::Configuration module which can be used to set configuration options.
|
|
34
|
+
#
|
|
35
|
+
# @return self
|
|
31
36
|
def configure
|
|
32
37
|
yield self
|
|
33
38
|
self
|
|
34
39
|
end
|
|
35
40
|
|
|
41
|
+
# Return a hash of the configured options.
|
|
36
42
|
def options
|
|
37
43
|
options = {}
|
|
38
44
|
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
|
|
39
45
|
options
|
|
40
46
|
end
|
|
47
|
+
|
|
48
|
+
# Set api_key and endpoint based on a URL with HTTP authentication.
|
|
49
|
+
# Useful if you're using the Swiftype Heroku add-on.
|
|
50
|
+
def authenticated_url=(url)
|
|
51
|
+
uri = URI(url)
|
|
52
|
+
self.api_key = uri.user
|
|
53
|
+
uri.user = nil
|
|
54
|
+
uri.password = nil
|
|
55
|
+
self.endpoint = uri.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# setter for endpoint that ensures it always ends in '/'
|
|
59
|
+
def endpoint=(endpoint)
|
|
60
|
+
if endpoint.end_with?('/')
|
|
61
|
+
@endpoint = endpoint
|
|
62
|
+
else
|
|
63
|
+
@endpoint = "#{endpoint}/"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
41
66
|
end
|
|
42
67
|
end
|
data/lib/swiftype/exceptions.rb
CHANGED
|
@@ -3,5 +3,7 @@ module Swiftype
|
|
|
3
3
|
class NonExistentRecord < ClientException; end
|
|
4
4
|
class RecordAlreadyExists < ClientException; end
|
|
5
5
|
class InvalidCredentials < ClientException; end
|
|
6
|
+
class BadRequest < ClientException; end
|
|
7
|
+
class Forbidden < ClientException; end
|
|
6
8
|
class UnexpectedHTTPException < ClientException; end
|
|
7
9
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# :stopdoc:
|
|
2
|
+
|
|
3
|
+
# Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
|
|
4
|
+
#
|
|
5
|
+
# https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
|
|
6
|
+
#
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
module URI
|
|
10
|
+
def self.encode_www_form(enum)
|
|
11
|
+
enum.map do |k,v|
|
|
12
|
+
if v.nil?
|
|
13
|
+
encode_www_form_component(k)
|
|
14
|
+
elsif v.respond_to?(:to_ary)
|
|
15
|
+
v.to_ary.map do |w|
|
|
16
|
+
str = encode_www_form_component(k)
|
|
17
|
+
unless w.nil?
|
|
18
|
+
str << '='
|
|
19
|
+
str << encode_www_form_component(w)
|
|
20
|
+
end
|
|
21
|
+
end.join('&')
|
|
22
|
+
else
|
|
23
|
+
str = encode_www_form_component(k)
|
|
24
|
+
str << '='
|
|
25
|
+
str << encode_www_form_component(v)
|
|
26
|
+
end
|
|
27
|
+
end.join('&')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.encode_www_form_component(str)
|
|
31
|
+
str.to_s.gsub(/[^*\-.0-9A-Z_a-z]/) { |chr| TBLENCWWWCOMP_[chr] }
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/swiftype/request.rb
CHANGED
|
@@ -1,34 +1,102 @@
|
|
|
1
|
+
require 'net/https'
|
|
2
|
+
if RUBY_VERSION < "1.9"
|
|
3
|
+
require 'swiftype/ext/backport-uri'
|
|
4
|
+
else
|
|
5
|
+
require 'uri'
|
|
6
|
+
end
|
|
7
|
+
require 'json'
|
|
8
|
+
require 'swiftype/exceptions'
|
|
9
|
+
require 'openssl'
|
|
10
|
+
|
|
1
11
|
module Swiftype
|
|
2
12
|
module Request
|
|
3
|
-
def get(path, params={}
|
|
4
|
-
request(:get, path, params
|
|
13
|
+
def get(path, params={})
|
|
14
|
+
request(:get, path, params)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def post(path, params={})
|
|
18
|
+
request(:post, path, params)
|
|
5
19
|
end
|
|
6
20
|
|
|
7
|
-
def
|
|
8
|
-
request(:
|
|
21
|
+
def put(path, params={})
|
|
22
|
+
request(:put, path, params)
|
|
9
23
|
end
|
|
10
24
|
|
|
11
|
-
def
|
|
12
|
-
request(:
|
|
25
|
+
def delete(path, params={})
|
|
26
|
+
request(:delete, path, params)
|
|
13
27
|
end
|
|
14
28
|
|
|
15
|
-
def
|
|
16
|
-
|
|
29
|
+
def request(method, path, params={})
|
|
30
|
+
uri = URI.parse("#{Swiftype.endpoint}#{path}")
|
|
31
|
+
|
|
32
|
+
request = build_request(method, uri, params)
|
|
33
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
34
|
+
|
|
35
|
+
if uri.scheme == 'https'
|
|
36
|
+
http.use_ssl = true
|
|
37
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
38
|
+
http.ca_file = File.join(__FILE__, '..', 'data', 'ca-bundle.crt')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
response = http.request(request)
|
|
42
|
+
|
|
43
|
+
handle_errors(response)
|
|
44
|
+
|
|
45
|
+
JSON.parse(response.body) if response.body && response.body.strip != ''
|
|
17
46
|
end
|
|
18
47
|
|
|
19
48
|
private
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
response
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
49
|
+
|
|
50
|
+
def handle_errors(response)
|
|
51
|
+
case response
|
|
52
|
+
when Net::HTTPSuccess
|
|
53
|
+
response
|
|
54
|
+
when Net::HTTPUnauthorized
|
|
55
|
+
raise Swiftype::InvalidCredentials
|
|
56
|
+
when Net::HTTPNotFound
|
|
57
|
+
raise Swiftype::NonExistentRecord
|
|
58
|
+
when Net::HTTPConflict
|
|
59
|
+
raise Swiftype::RecordAlreadyExists
|
|
60
|
+
when Net::HTTPBadRequest
|
|
61
|
+
raise Swiftype::BadRequest
|
|
62
|
+
when Net::HTTPForbidden
|
|
63
|
+
raise Swiftype::Forbidden
|
|
64
|
+
else
|
|
65
|
+
raise Swiftype::UnexpectedHTTPException, "#{response.code} #{response.body}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_request(method, uri, params)
|
|
70
|
+
klass = case method
|
|
71
|
+
when :get
|
|
72
|
+
Net::HTTP::Get
|
|
73
|
+
when :post
|
|
74
|
+
Net::HTTP::Post
|
|
75
|
+
when :put
|
|
76
|
+
Net::HTTP::Put
|
|
77
|
+
when :delete
|
|
78
|
+
Net::HTTP::Delete
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
case method
|
|
82
|
+
when :get, :delete
|
|
83
|
+
uri.query = URI.encode_www_form(params) if params && !params.empty?
|
|
84
|
+
req = klass.new(uri.request_uri)
|
|
85
|
+
when :post, :put
|
|
86
|
+
req = klass.new(uri.request_uri)
|
|
87
|
+
req.body = JSON.generate(params) unless params.length == 0
|
|
30
88
|
end
|
|
31
|
-
|
|
89
|
+
|
|
90
|
+
req['User-Agent'] = Swiftype.user_agent
|
|
91
|
+
req['Content-Type'] = 'application/json'
|
|
92
|
+
|
|
93
|
+
if platform_access_token
|
|
94
|
+
req['Authorization'] = "Bearer #{platform_access_token}"
|
|
95
|
+
elsif api_key
|
|
96
|
+
req.basic_auth api_key, ''
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
req
|
|
32
100
|
end
|
|
33
101
|
end
|
|
34
|
-
end
|
|
102
|
+
end
|
data/lib/swiftype/result_set.rb
CHANGED
|
@@ -1,31 +1,66 @@
|
|
|
1
1
|
module Swiftype
|
|
2
|
+
# The Swiftype::ResultSet class represents a {search}[https://swiftype.com/documentation/searching]
|
|
3
|
+
# or {suggest result}[https://swiftype.com/documentation/autocomplete] returned by the Swiftype API.
|
|
2
4
|
class ResultSet
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
# @attribute errors [r]
|
|
6
|
+
# a hash of errors for the search (for example filtering on a missing attribute) keyed by DocumentType slug
|
|
7
|
+
attr_reader :errors
|
|
8
|
+
|
|
9
|
+
# @attribute records [r]
|
|
10
|
+
# a hash of results for the search keyed by DocumentType slug. Use `[]` to access results more easily.
|
|
11
|
+
attr_reader :records
|
|
12
|
+
|
|
13
|
+
# @attribute info [r]
|
|
14
|
+
# a hash of extra query info (for example, facets and number of results) keyed by DocumentType slug.
|
|
15
|
+
# Use the convenience methods of this class for easier access.
|
|
16
|
+
attr_reader :info
|
|
17
|
+
|
|
18
|
+
# Create a Swiftype::ResultSet from deserialized JSON.
|
|
5
19
|
def initialize(results)
|
|
6
|
-
@records =
|
|
7
|
-
results['records'].each do |document_type, documents|
|
|
8
|
-
@records[document_type] = documents.map { |d| Swiftype::Document.new(d) }
|
|
9
|
-
end
|
|
20
|
+
@records = results['records']
|
|
10
21
|
@info = results['info']
|
|
22
|
+
@errors = results['errors']
|
|
11
23
|
end
|
|
12
24
|
|
|
25
|
+
# Get results for the provided DocumentType
|
|
26
|
+
#
|
|
27
|
+
# @param [String] document_type the DocumentType slug to get results for
|
|
13
28
|
def [](document_type)
|
|
14
29
|
records[document_type]
|
|
15
30
|
end
|
|
16
31
|
|
|
32
|
+
# Return a list of DocumentType slugs represented in the ResultSet.
|
|
33
|
+
def document_types
|
|
34
|
+
records.keys
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Return the search facets for the provided DocumentType. Will be
|
|
38
|
+
# empty unless a facets parameter was provided when calling the
|
|
39
|
+
# search API.
|
|
40
|
+
#
|
|
41
|
+
# @param [String] document_type the DocumentType slug to get facets for
|
|
17
42
|
def facets(document_type)
|
|
18
43
|
info[document_type]['facets']
|
|
19
44
|
end
|
|
20
45
|
|
|
46
|
+
# Return the page of results for this ResultSet
|
|
21
47
|
def current_page
|
|
22
48
|
info[info.keys.first]['current_page']
|
|
23
49
|
end
|
|
24
50
|
|
|
51
|
+
# Return the number of results per page.
|
|
25
52
|
def per_page
|
|
26
53
|
info[info.keys.first]['per_page']
|
|
27
54
|
end
|
|
28
55
|
|
|
56
|
+
# Return the number of pages. Since a search can cover multiple
|
|
57
|
+
# DocumentTypes with different numbers of results, the number of
|
|
58
|
+
# pages can vary between DocumentTypes. With no argument, it
|
|
59
|
+
# returns the maximum num_pages for all DocumentTypes in this
|
|
60
|
+
# ResultSet. With a DocumentType slug, it returns the number of
|
|
61
|
+
# pages for that DocumentType.
|
|
62
|
+
#
|
|
63
|
+
# @param [String] document_type the DocumentType slug to return the number of pages for
|
|
29
64
|
def num_pages(document_type=nil)
|
|
30
65
|
if document_type
|
|
31
66
|
info[document_type]['num_pages']
|
|
@@ -34,10 +69,12 @@ module Swiftype
|
|
|
34
69
|
end
|
|
35
70
|
end
|
|
36
71
|
|
|
72
|
+
# Return the total number of results for the query
|
|
37
73
|
def total_result_count(document_type)
|
|
38
74
|
info[document_type]['total_result_count']
|
|
39
75
|
end
|
|
40
76
|
|
|
77
|
+
# Return the query used for this search
|
|
41
78
|
def query
|
|
42
79
|
info[info.keys.first]['query']
|
|
43
80
|
end
|
data/lib/swiftype/sso.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'digest/sha1'
|
|
2
|
+
|
|
3
|
+
module Swiftype
|
|
4
|
+
# Single sign-on for the Swiftype Dashboard.
|
|
5
|
+
module SSO
|
|
6
|
+
BASE_URL = 'https://swiftype.com/sso'
|
|
7
|
+
|
|
8
|
+
# Generate a URL that a user can click on to be logged into the Swiftype Dashboard.
|
|
9
|
+
# This requires the +platform_client_id+ and +platform_client_secret+ configuration options be set.
|
|
10
|
+
def self.url(user_id)
|
|
11
|
+
timestamp = Time.now.to_i
|
|
12
|
+
|
|
13
|
+
"#{BASE_URL}?user_id=#{user_id}&client_id=#{Swiftype.platform_client_id}×tamp=#{timestamp}&token=#{token(user_id, timestamp)}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.token(user_id, timestamp)
|
|
17
|
+
Digest::SHA1.hexdigest("#{user_id}:#{Swiftype.platform_client_secret}:#{timestamp}")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/swiftype/version.rb
CHANGED
data/spec/client_spec.rb
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Swiftype::Client do
|
|
4
|
+
let(:engine_slug) { 'swiftype-api-example' }
|
|
5
|
+
let(:client) { Swiftype::Client.new }
|
|
6
|
+
|
|
7
|
+
before :each do
|
|
8
|
+
Swiftype.api_key = 'hello'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context 'Search' do
|
|
12
|
+
context '#search' do
|
|
13
|
+
it 'searches all DocumentTypes in the engine' do
|
|
14
|
+
VCR.use_cassette(:engine_search) do
|
|
15
|
+
results = client.search(engine_slug, 'cat')
|
|
16
|
+
results.document_types.size.should == 2
|
|
17
|
+
results['videos'].size.should == 2
|
|
18
|
+
results['channels'].size.should == 1
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'searches the engine with options' do
|
|
23
|
+
VCR.use_cassette(:engine_search_pagination) do
|
|
24
|
+
results = client.search(engine_slug, 'cat', {:page => 2})
|
|
25
|
+
results.document_types.size.should == 2
|
|
26
|
+
results['videos'].size.should == 0
|
|
27
|
+
results['channels'].size.should == 0
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'includes facets when requested' do
|
|
32
|
+
VCR.use_cassette(:engine_search_facets) do
|
|
33
|
+
results = client.search(engine_slug, nil, {:facets => {:videos => ['category_id']}})
|
|
34
|
+
results.document_types.size.should == 2
|
|
35
|
+
results.facets('channels').should be_empty
|
|
36
|
+
results.facets('videos')['category_id'].should == {
|
|
37
|
+
"23" => 4,
|
|
38
|
+
"28" => 2,
|
|
39
|
+
"15" => 2,
|
|
40
|
+
"25" => 1,
|
|
41
|
+
"22" => 1,
|
|
42
|
+
"2" => 1,
|
|
43
|
+
"10" => 1
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context '#search_document_type' do
|
|
50
|
+
let(:document_type_slug) { 'videos' }
|
|
51
|
+
|
|
52
|
+
it 'searches only the provided DocumentType' do
|
|
53
|
+
VCR.use_cassette(:document_type_search) do
|
|
54
|
+
results = client.search_document_type(engine_slug, document_type_slug, 'cat')
|
|
55
|
+
results.document_types.should == ['videos']
|
|
56
|
+
results['videos'].size.should == 2
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'searches the DocumentType with options' do
|
|
61
|
+
VCR.use_cassette(:document_type_search_pagination) do
|
|
62
|
+
results = client.search_document_type(engine_slug, document_type_slug, 'cat', {:page => 2})
|
|
63
|
+
results.document_types.should == ['videos']
|
|
64
|
+
results[document_type_slug].size.should == 0
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'Suggest' do
|
|
71
|
+
context '#suggest' do
|
|
72
|
+
it 'does prefix searches for all DocumentTypes in the engine' do
|
|
73
|
+
VCR.use_cassette(:engine_suggest) do
|
|
74
|
+
results = client.suggest(engine_slug, 'goo')
|
|
75
|
+
results.document_types.size.should == 2
|
|
76
|
+
results['videos'].size.should == 1
|
|
77
|
+
results['channels'].size.should == 1
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'suggests for an engine with options' do
|
|
82
|
+
VCR.use_cassette(:engine_suggest_pagination) do
|
|
83
|
+
results = client.suggest(engine_slug, 'goo', {:page => 2})
|
|
84
|
+
results.document_types.size.should == 2
|
|
85
|
+
results['videos'].size.should == 0
|
|
86
|
+
results['channels'].size.should == 0
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context '#suggest_document_type' do
|
|
92
|
+
let(:document_type_slug) { 'videos' }
|
|
93
|
+
|
|
94
|
+
it 'does a prefix search on the provided DocumentType' do
|
|
95
|
+
VCR.use_cassette(:document_type_suggest) do
|
|
96
|
+
results = client.suggest_document_type(engine_slug, document_type_slug, 'goo')
|
|
97
|
+
results.document_types.should == ['videos']
|
|
98
|
+
results['videos'].size.should == 1
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'suggests for a document types with options' do
|
|
103
|
+
VCR.use_cassette(:document_type_suggest_pagination) do
|
|
104
|
+
results = client.suggest_document_type(engine_slug, document_type_slug, 'goo', {:page => 2})
|
|
105
|
+
results.document_types.should == ['videos']
|
|
106
|
+
results[document_type_slug].size.should == 0
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
context 'Engine' do
|
|
114
|
+
it 'gets all engines' do
|
|
115
|
+
VCR.use_cassette(:list_engines) do
|
|
116
|
+
engines = client.engines
|
|
117
|
+
engines.size.should == 6
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'gets an engine' do
|
|
122
|
+
VCR.use_cassette(:find_engine) do
|
|
123
|
+
engine = client.engine(engine_slug)
|
|
124
|
+
engine['slug'].should == engine_slug
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'creates engines' do
|
|
129
|
+
VCR.use_cassette(:create_engine) do
|
|
130
|
+
engine = client.create_engine('new engine from spec')
|
|
131
|
+
engine['slug'].should == 'new-engine-from-spec'
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'destroys engines' do
|
|
136
|
+
VCR.use_cassette(:destroy_engine) do
|
|
137
|
+
response = client.destroy_engine('new-engine-from-spec')
|
|
138
|
+
response.should be_nil
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'DocumentType' do
|
|
144
|
+
let(:document_type_slug) { 'videos' }
|
|
145
|
+
|
|
146
|
+
it 'gets all document types' do
|
|
147
|
+
VCR.use_cassette(:list_document_type) do
|
|
148
|
+
document_types = client.document_types(engine_slug)
|
|
149
|
+
document_types.size.should == 2
|
|
150
|
+
document_types.map { |dt| dt['name'] }.sort.should == ['channels', 'videos']
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'gets a document type' do
|
|
155
|
+
VCR.use_cassette(:find_document_type) do
|
|
156
|
+
document_type = client.document_type(engine_slug, document_type_slug)
|
|
157
|
+
document_type['slug'].should == document_type_slug
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'creates a document type' do
|
|
162
|
+
VCR.use_cassette(:create_document_type) do
|
|
163
|
+
name = document_type_slug
|
|
164
|
+
document_type = client.create_document_type(engine_slug, 'new_doc_type')
|
|
165
|
+
document_type['name'].should == 'new_doc_type'
|
|
166
|
+
document_type['slug'].should == 'new-doc-type'
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'destroys document types' do
|
|
171
|
+
VCR.use_cassette(:destroy_document_type) do
|
|
172
|
+
response = client.destroy_document_type(engine_slug, 'new-doc-type')
|
|
173
|
+
response.should be_nil
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'raises an error if deleting a non-existent DocumentType' do
|
|
178
|
+
VCR.use_cassette(:destroy_non_existent_document_type) do
|
|
179
|
+
expect do
|
|
180
|
+
response = client.destroy_document_type(engine_slug, 'not_there')
|
|
181
|
+
end.to raise_error
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context 'Document' do
|
|
187
|
+
let(:document_type_slug) { 'videos' }
|
|
188
|
+
let(:document_id) { 'FtX8nswnUKU'}
|
|
189
|
+
let(:documents) do
|
|
190
|
+
[{'external_id'=>'INscMGmhmX4',
|
|
191
|
+
'fields' => [{'name'=>'url', 'value'=>'http://www.youtube.com/watch?v=v1uyQZNg2vE', 'type'=>'enum'},
|
|
192
|
+
{'name'=>'thumbnail_url', 'value'=>'https://i.ytimg.com/vi/INscMGmhmX4/mqdefault.jpg', 'type'=>'enum'},
|
|
193
|
+
{'name'=>'channel_id', 'value'=>'UCTzVrd9ExsI3Zgnlh3_btLg', 'type'=>'enum'},
|
|
194
|
+
{'name'=>'title', 'value'=>'The Original Grumpy Cat', 'type'=>'string'},
|
|
195
|
+
{'name'=>'category_name', 'value'=>'Pets & Animals', 'type'=>'string'}]},
|
|
196
|
+
{'external_id'=>'XfY9Dsg_DZk',
|
|
197
|
+
'fields' => [{'name'=>'url', 'value'=>'http://www.youtube.com/watch?v=XfY9Dsg_DZk', 'type'=>'enum'},
|
|
198
|
+
{'name'=>'thumbnail_url', 'value'=>'https://i.ytimg.com/vi/XfY9Dsg_DZk/mqdefault.jpg', 'type'=>'enum'},
|
|
199
|
+
{'name'=>'channel_id', 'value'=>'UC5VA5j05FjETg-iLekcyiBw', 'type'=>'enum'},
|
|
200
|
+
{'name'=>'title', 'value'=>'Corgi talks to cat', 'type'=>'string'},
|
|
201
|
+
{'name'=>'category_name', 'value'=>'Pets & Animals', 'type'=>'string'}]}]
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'lists documents in a document type' do
|
|
205
|
+
VCR.use_cassette(:list_documents) do
|
|
206
|
+
documents = client.documents(engine_slug, document_type_slug)
|
|
207
|
+
documents.size.should == 2
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'lists documents with pagination' do
|
|
212
|
+
VCR.use_cassette(:list_documents_with_pagination) do
|
|
213
|
+
documents = client.documents(engine_slug, document_type_slug, 2, 2)
|
|
214
|
+
documents.size.should == 2
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'find a document' do
|
|
219
|
+
VCR.use_cassette(:find_document) do
|
|
220
|
+
document = client.document(engine_slug, document_type_slug, document_id)
|
|
221
|
+
document['external_id'].should == document_id
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'creates a document' do
|
|
226
|
+
VCR.use_cassette(:create_document) do
|
|
227
|
+
document = client.create_document(engine_slug, document_type_slug, documents.first)
|
|
228
|
+
document['external_id'].should == 'INscMGmhmX4'
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'bulk create multiple documents' do
|
|
233
|
+
VCR.use_cassette(:bulk_create_documents) do
|
|
234
|
+
response = client.create_documents(engine_slug, document_type_slug, documents)
|
|
235
|
+
response.should == [true, true]
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'destroys a document' do
|
|
240
|
+
VCR.use_cassette(:destroy_document) do
|
|
241
|
+
response = client.destroy_document(engine_slug, document_type_slug, 'INscMGmhmX4')
|
|
242
|
+
response.should be_nil
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it 'destroys multiple documents' do
|
|
247
|
+
VCR.use_cassette(:bulk_destroy_documents) do
|
|
248
|
+
response = client.destroy_documents(engine_slug, document_type_slug, ['INscMGmhmX4', 'XfY9Dsg_DZk'])
|
|
249
|
+
response.should == [true, true]
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
context '#create_or_update_document' do
|
|
254
|
+
it 'creates a document' do
|
|
255
|
+
VCR.use_cassette(:create_or_update_document_create) do
|
|
256
|
+
response = client.create_or_update_document(engine_slug, document_type_slug, {:external_id => 'foobar', :fields => [{:type => :string, :name => 'title', :value => 'new document'}]})
|
|
257
|
+
response['external_id'].should == 'foobar'
|
|
258
|
+
response['title'].should == 'new document'
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'updates an existing document' do
|
|
263
|
+
VCR.use_cassette(:create_or_update_document_update) do
|
|
264
|
+
response = client.create_or_update_document(engine_slug, document_type_slug, {:external_id => document_id, :fields => [{:type => :string, :name => 'title', :value => 'new title'}]})
|
|
265
|
+
response['external_id'].should == document_id
|
|
266
|
+
response['title'].should == 'new title'
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
context '#bulk_create_or_update_documents' do
|
|
272
|
+
it 'returns true for all documents successfully created or updated' do
|
|
273
|
+
VCR.use_cassette(:bulk_create_or_update_documents_success) do
|
|
274
|
+
response = client.create_or_update_documents(engine_slug, document_type_slug, documents)
|
|
275
|
+
response.should == [true, true]
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'returns false if a document cannot be created or updated due to an error' do
|
|
280
|
+
documents = [{:external_id => 'failed_doc', :fields => [{:type => :string, :name => :title}]}] # missing value
|
|
281
|
+
|
|
282
|
+
VCR.use_cassette(:bulk_create_or_update_documents_failure) do
|
|
283
|
+
response = client.create_or_update_documents(engine_slug, document_type_slug, documents)
|
|
284
|
+
response.should == [false]
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
context '#update_document' do
|
|
290
|
+
it 'updates a document given its id and fields to update' do
|
|
291
|
+
fields = {:title => 'awesome new title', :channel_id => 'UC5VA5j05FjETg-iLekcyiBw'}
|
|
292
|
+
VCR.use_cassette(:update_document) do
|
|
293
|
+
response = client.update_document(engine_slug, document_type_slug, document_id, fields)
|
|
294
|
+
response['external_id'].should == document_id
|
|
295
|
+
response['title'].should == 'awesome new title'
|
|
296
|
+
response['channel_id'].should == 'UC5VA5j05FjETg-iLekcyiBw'
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'raises an error if a unknown field is included' do
|
|
301
|
+
fields = {:not_a_field => 'not a field'}
|
|
302
|
+
|
|
303
|
+
VCR.use_cassette(:update_document_unknown_field_failure) do
|
|
304
|
+
expect do
|
|
305
|
+
response = client.update_document(engine_slug, document_type_slug, document_id, fields)
|
|
306
|
+
end.to raise_error
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context "#update_documents" do
|
|
312
|
+
it 'returns true for each document successfully updated' do
|
|
313
|
+
documents = [{:external_id => 'INscMGmhmX4', :fields => {:title => 'hi'}}, {:external_id => 'XfY9Dsg_DZk', :fields => {:title => 'bye'}}]
|
|
314
|
+
|
|
315
|
+
VCR.use_cassette(:update_documents_success) do
|
|
316
|
+
response = client.update_documents(engine_slug, document_type_slug, documents)
|
|
317
|
+
response.should == [true, true]
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it 'returns false if document is not successfully updated' do
|
|
322
|
+
documents = [{:external_id => 'not_there', :fields => [{:name => :title, :value => 'hi', :type => :string}]}]
|
|
323
|
+
|
|
324
|
+
VCR.use_cassette(:update_documents_failure_non_existent_document) do
|
|
325
|
+
response = client.update_documents(engine_slug, document_type_slug, documents)
|
|
326
|
+
response.should == [false]
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
context 'Analytics' do
|
|
333
|
+
let(:engine_slug) { 'recursion' }
|
|
334
|
+
|
|
335
|
+
context '#analytics_searches' do
|
|
336
|
+
it 'returns search counts for the default time frame' do
|
|
337
|
+
VCR.use_cassette(:analytics_searches) do
|
|
338
|
+
searches = client.analytics_searches(engine_slug)
|
|
339
|
+
searches.size.should == 15 # FIXME: is this a bug in the API?
|
|
340
|
+
searches.first.should == ['2013-09-13', 0]
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it 'returns search counts for a specified time range' do
|
|
345
|
+
VCR.use_cassette(:analytics_searches_with_time_range) do
|
|
346
|
+
searches = client.analytics_searches(engine_slug, :start_date => '2013-01-01', :end_date => '2013-01-07')
|
|
347
|
+
searches.size.should == 7
|
|
348
|
+
searches.first.should == ['2013-01-07', 0]
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it 'returns search counts for a specified DocumentType' do
|
|
353
|
+
VCR.use_cassette(:analytics_searchs_with_document_type) do
|
|
354
|
+
searches = client.analytics_searches(engine_slug, :document_type_id => 'page')
|
|
355
|
+
searches.size.should == 15
|
|
356
|
+
searches.first.should == ['2013-09-16', 0]
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it 'returns search counts for a specified DocumentType and time range' do
|
|
361
|
+
VCR.use_cassette(:analytics_searches_with_document_type_and_time_range) do
|
|
362
|
+
searches = client.analytics_autoselects(engine_slug, :document_type_id => 'page', :start_date => '2013-07-01', :end_date => '2013-07-07')
|
|
363
|
+
searches.size.should == 7
|
|
364
|
+
searches.first.should == ['2013-07-07', 0]
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
context '#analytics_autoselects' do
|
|
370
|
+
it 'returns autoselect counts for the default time frame' do
|
|
371
|
+
VCR.use_cassette(:analytics_autoselects) do
|
|
372
|
+
autoselects = client.analytics_autoselects(engine_slug)
|
|
373
|
+
autoselects.size.should == 15
|
|
374
|
+
autoselects.first.should == ['2013-09-13', 0]
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it 'returns autoselects counts for a specified time range' do
|
|
379
|
+
VCR.use_cassette(:analytics_autoselects_with_time_range) do
|
|
380
|
+
autoselects = client.analytics_autoselects(engine_slug, :start_date => '2013-07-01', :end_date => '2013-07-07')
|
|
381
|
+
autoselects.size.should == 7
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it 'returns autoselect counts for a specified DocumentType' do
|
|
386
|
+
VCR.use_cassette(:analytics_autoselects_with_document_type) do
|
|
387
|
+
autoselects = client.analytics_autoselects(engine_slug, :document_type_id => 'page')
|
|
388
|
+
autoselects.size.should == 15
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it 'returns autoselect counts for a specified DocumentType and time range' do
|
|
393
|
+
VCR.use_cassette(:analytics_autoselects_with_document_type_and_time_range) do
|
|
394
|
+
autoselects = client.analytics_autoselects(engine_slug, :document_type_id => 'page', :start_date => '2013-07-01', :end_date => '2013-07-07')
|
|
395
|
+
autoselects.size.should == 7
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
context '#analytics_clicks' do
|
|
401
|
+
it 'returns click counts for the default time frame' do
|
|
402
|
+
VCR.use_cassette(:analytics_clicks) do
|
|
403
|
+
clicks = client.analytics_clicks(engine_slug)
|
|
404
|
+
clicks.size.should == 15
|
|
405
|
+
clicks.first.should == ['2013-09-17', 0]
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
it 'returns clicks counts for a specified time range' do
|
|
410
|
+
VCR.use_cassette(:analytics_clicks_with_time_range) do
|
|
411
|
+
clicks = client.analytics_clicks(engine_slug, :start_date => '2013-07-01', :end_date => '2013-07-07')
|
|
412
|
+
clicks.size.should == 7
|
|
413
|
+
clicks.first.should == ['2013-07-07', 0]
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
it 'returns click counts for a specified DocumentType' do
|
|
418
|
+
VCR.use_cassette(:analytics_clicks_with_document_type) do
|
|
419
|
+
clicks = client.analytics_clicks(engine_slug, :document_type_id => 'page')
|
|
420
|
+
clicks.size.should == 15
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it 'returns click counts for a specified DocumentType and time range' do
|
|
425
|
+
VCR.use_cassette(:analytics_clicks_with_document_type_and_time_range) do
|
|
426
|
+
clicks = client.analytics_clicks(engine_slug, :document_type_id => 'page', :start_date => '2013-07-01', :end_date => '2013-07-07')
|
|
427
|
+
clicks.size.should == 7
|
|
428
|
+
clicks.first.should == ['2013-07-07', 0]
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context '#analytics_top_queries' do
|
|
434
|
+
it 'returns top queries' do
|
|
435
|
+
VCR.use_cassette(:analytics_top_queries) do
|
|
436
|
+
top_queries = client.analytics_top_queries(engine_slug)
|
|
437
|
+
top_queries.size.should == 3
|
|
438
|
+
top_queries.first.should == ['"fire watch"', 1]
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it 'returns top queries with pagination' do
|
|
443
|
+
VCR.use_cassette(:analytics_top_queries_paginated) do
|
|
444
|
+
top_queries = client.analytics_top_queries(engine_slug, :start_date => '2013-08-01', :end_date => '2013-08-30', :per_page => 5, :page => 2)
|
|
445
|
+
top_queries.size.should == 5
|
|
446
|
+
top_queries.first.should == ['no simple victory', 1]
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it 'raises an error if the timeframe is to large' do
|
|
451
|
+
VCR.use_cassette(:analytics_top_queries_too_large) do
|
|
452
|
+
expect do
|
|
453
|
+
top_queries = client.analytics_top_queries(engine_slug, :start_date => '2013-01-01', :end_date => '2013-05-01')
|
|
454
|
+
end.to raise_error(Swiftype::BadRequest)
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
context 'analytics_top_no_result_queries' do
|
|
460
|
+
it 'returns top queries with no results for the default time range' do
|
|
461
|
+
VCR.use_cassette(:analytics_top_no_result_queries) do
|
|
462
|
+
top_no_result_queries = client.analytics_top_no_result_queries(engine_slug)
|
|
463
|
+
top_no_result_queries.size.should == 2
|
|
464
|
+
top_no_result_queries.first.should == ['no results', 10]
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it 'has top no result queries in date ranges' do
|
|
469
|
+
VCR.use_cassette(:analytics_top_no_result_queries_paginated) do
|
|
470
|
+
top_no_result_queries = client.analytics_top_no_result_queries(engine_slug, :start_date => '2013-08-01', :end_date => '2013-08-30', :per_page => 5, :page => 2)
|
|
471
|
+
top_no_result_queries.size.should == 1
|
|
472
|
+
top_no_result_queries.first.should == ['no result again', 2]
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
context 'Domain' do
|
|
479
|
+
let(:engine_slug) { 'crawler-demo-site' }
|
|
480
|
+
let(:domain_id) { '51534c6e2ed960cc79000001' }
|
|
481
|
+
|
|
482
|
+
it 'gets all domains' do
|
|
483
|
+
VCR.use_cassette(:list_domains) do
|
|
484
|
+
domains = client.domains(engine_slug)
|
|
485
|
+
domains.size.should == 1
|
|
486
|
+
domains.first['id'].should == domain_id
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
context '#domain' do
|
|
491
|
+
it 'shows a domain if it exists' do
|
|
492
|
+
VCR.use_cassette(:find_domain) do
|
|
493
|
+
domain = client.domain(engine_slug, domain_id)
|
|
494
|
+
domain['id'].should == domain_id
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
it 'raises an error if the domain does not exist' do
|
|
499
|
+
VCR.use_cassette(:find_domain_failure) do
|
|
500
|
+
expect do
|
|
501
|
+
domain = client.domain(engine_slug, 'bogus')
|
|
502
|
+
end.to raise_error(Swiftype::NonExistentRecord)
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
context '#create_domain' do
|
|
508
|
+
it 'creates a domain' do
|
|
509
|
+
VCR.use_cassette(:create_domain) do
|
|
510
|
+
url = 'http://www.zombo.com/'
|
|
511
|
+
domain = client.create_domain(engine_slug, url)
|
|
512
|
+
domain['submitted_url'].should == url
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it 'destroys a domain' do
|
|
518
|
+
VCR.use_cassette(:destroy_domain) do
|
|
519
|
+
response = client.destroy_domain(engine_slug, '52324b132ed960589800004a')
|
|
520
|
+
response.should be_nil
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
context '#recrawl_domain' do
|
|
525
|
+
it 'enqueues a request to recrawl a domain' do
|
|
526
|
+
VCR.use_cassette(:recrawl_domain_success) do
|
|
527
|
+
domain = client.recrawl_domain(engine_slug, domain_id)
|
|
528
|
+
domain['id'].should == domain_id
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it 'raises an exception if domain recrawl is not allowed' do
|
|
533
|
+
VCR.use_cassette(:recrawl_domain_failure) do
|
|
534
|
+
expect do
|
|
535
|
+
domain = client.recrawl_domain(engine_slug, domain_id)
|
|
536
|
+
end.to raise_error(Swiftype::Forbidden)
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
context '#crawl_url' do
|
|
542
|
+
it 'enqueues a request to crawl a URL on a domain' do
|
|
543
|
+
VCR.use_cassette(:crawl_url) do
|
|
544
|
+
url = 'http://crawler-demo-site.herokuapp.com/2012/01/01/first-post.html'
|
|
545
|
+
crawled_url = client.crawl_url(engine_slug, domain_id, url)
|
|
546
|
+
crawled_url['url'].should == url
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
context 'Clickthrough' do
|
|
553
|
+
let(:query) { 'foo' }
|
|
554
|
+
let(:document_type_slug) { 'videos' }
|
|
555
|
+
let(:external_id) { 'FtX8nswnUKU'}
|
|
556
|
+
|
|
557
|
+
context "#log_clickthough" do
|
|
558
|
+
# Not thrilled with this test, but since nothing is returned all we
|
|
559
|
+
# can reasonably check is that an error isn't raised
|
|
560
|
+
it 'returns nil' do
|
|
561
|
+
VCR.use_cassette(:log_clickthrough_success) do
|
|
562
|
+
response = client.log_clickthrough(engine_slug, document_type_slug, query, external_id)
|
|
563
|
+
response.should == nil
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it 'raises an error when missing params' do
|
|
568
|
+
VCR.use_cassette(:log_clickthrough_failure) do
|
|
569
|
+
expect do
|
|
570
|
+
client.log_clickthrough(engine_slug, document_type_slug, nil, external_id)
|
|
571
|
+
end.to raise_error(Swiftype::BadRequest)
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
end
|