clarify 1.1.1 → 2.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -16
- data/.rspec +2 -0
- data/.simplecov +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +4 -0
- data/Dockerfile +11 -0
- data/Gemfile +2 -2
- data/LICENSE +1 -1
- data/README.md +202 -47
- data/Rakefile +62 -4
- data/clarify.gemspec +10 -7
- data/cucumber.yml +1 -0
- data/features/create-bundles.feature +10 -0
- data/features/delete-bundle.feature +7 -0
- data/features/identity-steps.feature +6 -0
- data/features/list-bundles.feature +13 -0
- data/features/search-bundles.feature +10 -0
- data/features/step_definitions/curied_url_steps.rb +6 -0
- data/features/step_definitions/error_steps.rb +4 -0
- data/features/step_definitions/http_verification_step.rb +4 -0
- data/features/step_definitions/identity_steps.rb +12 -0
- data/features/step_definitions/list_steps.rb +76 -0
- data/features/support/env.rb +36 -0
- data/features/support/lib/curies.rb +19 -0
- data/features/support/lib/customer.rb +41 -0
- data/features/support/lib/exceptions.rb +27 -0
- data/features/support/lib/names.rb +16 -0
- data/lib/clarify.rb +16 -14
- data/lib/clarify/bundle_repository.rb +26 -0
- data/lib/clarify/client.rb +51 -0
- data/lib/clarify/collection_iterator.rb +27 -0
- data/lib/clarify/configuration.rb +29 -7
- data/lib/clarify/errors.rb +22 -0
- data/lib/clarify/response.rb +29 -0
- data/lib/clarify/response_factory.rb +34 -0
- data/lib/clarify/responses/bundle.rb +11 -0
- data/lib/clarify/responses/collection.rb +31 -0
- data/lib/clarify/responses/no_body.rb +13 -0
- data/lib/clarify/responses/search_collection.rb +18 -0
- data/lib/clarify/responses/tracks.rb +15 -0
- data/lib/clarify/rest_client.rb +129 -0
- data/lib/clarify/version.rb +3 -1
- data/spec/clarify/bundle_repository_spec.rb +37 -0
- data/spec/clarify/client_spec.rb +93 -0
- data/spec/clarify/collection_iterator_spec.rb +86 -0
- data/spec/clarify/configuration_spec.rb +77 -0
- data/spec/clarify/errors_spec.rb +15 -0
- data/spec/clarify/response_factory_spec.rb +51 -0
- data/spec/clarify/response_spec.rb +69 -0
- data/spec/clarify/responses/bundle_spec.rb +8 -0
- data/spec/clarify/responses/collection_spec.rb +58 -0
- data/spec/clarify/responses/search_collection_spec.rb +40 -0
- data/spec/clarify/responses/tracks_spec.rb +18 -0
- data/spec/clarify/rest_client_spec.rb +222 -0
- data/spec/spec_helper.rb +4 -9
- data/src_readme/README_no_output.md +186 -0
- data/src_readme/examples/bundle_create.rb +11 -0
- data/src_readme/examples/bundle_fetch.rb +9 -0
- data/src_readme/examples/bundles_list_fetch.rb +11 -0
- data/src_readme/examples/bundles_paged_over.rb +8 -0
- data/src_readme/examples/bundles_search.rb +20 -0
- data/src_readme/examples/list_bundles.rb +6 -0
- data/src_readme/examples/searches_paged_over.rb +10 -0
- data/src_readme/examples/setup.rb +5 -0
- data/src_readme/make.rb +56 -0
- data/src_readme/readme.md.erb +55 -0
- metadata +127 -62
- data/LICENSE.txt +0 -24
- data/examples/create.rb +0 -14
- data/examples/delete.rb +0 -12
- data/examples/list.rb +0 -14
- data/examples/search.rb +0 -26
- data/examples/test.rb +0 -15
- data/lib/clarify/bundle.rb +0 -40
- data/lib/clarify/metadata.rb +0 -26
- data/lib/clarify/request.rb +0 -37
- data/lib/clarify/search.rb +0 -10
- data/lib/clarify/track.rb +0 -40
- data/spec/lib/clarify/bundle_spec.rb +0 -43
- data/spec/lib/clarify/configuration_spec.rb +0 -19
- data/spec/lib/clarify/metadata_spec.rb +0 -36
- data/spec/lib/clarify/search_spec.rb +0 -22
- data/spec/lib/clarify/track_spec.rb +0 -81
data/clarify.gemspec
CHANGED
@@ -6,8 +6,8 @@ require 'clarify/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'clarify'
|
8
8
|
spec.version = Clarify::VERSION
|
9
|
-
spec.authors = ['
|
10
|
-
spec.email = ['
|
9
|
+
spec.authors = ['Clarify Inc.']
|
10
|
+
spec.email = ['support@clarify.io']
|
11
11
|
spec.summary = 'Search audio and video in a few lines of code'
|
12
12
|
spec.description = 'Use the Clarify API to make your audio and video files searchable in just a few lines of code.'
|
13
13
|
spec.homepage = 'http://www.clarify.io'
|
@@ -18,9 +18,12 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency 'rspec',
|
25
|
-
spec.add_development_dependency '
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'cucumber', '~> 1.3.0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
spec.add_development_dependency 'rspec-expectations', '~> 3.2.0'
|
26
|
+
spec.add_development_dependency 'rubocop', '~> 0.29.0'
|
27
|
+
spec.add_development_dependency 'simplecov', '~> 0.9.0'
|
26
28
|
end
|
29
|
+
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --color
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: As a user of the API, I am able to create a bundle.
|
2
|
+
Scenario: A user has added a new media file for processing.
|
3
|
+
Given I am using the environment's API key
|
4
|
+
And I know the following urls referenced as:
|
5
|
+
| name | URL |
|
6
|
+
| media:dorothy | http://media.clarify.io/audio/books/dorothyandthewizardinoz_01_baum_64kb.mp3 |
|
7
|
+
When I create a bundle named "Wizard of Oz" with the media url "[media:dorothy]"
|
8
|
+
When I request a list of bundles
|
9
|
+
Then I should get the HTTP status code 200
|
10
|
+
And my results should incude a bundle named "Wizard of Oz"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Feature: As a user of the API, I am able to delete a bundle.
|
2
|
+
Scenario: A user has added a new media file for processing.
|
3
|
+
Given I am using the environment's API key
|
4
|
+
And I have a bundle named "K.C."
|
5
|
+
When I delete my bundle
|
6
|
+
Then the server should not list my bundle
|
7
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Feature: As an unauthenticated user, I get an exception that I can handle.
|
2
|
+
Scenario: I have not entered an API key, but attempt to connect anyway.
|
3
|
+
Given I am not using an API key
|
4
|
+
When I request a list of bundles without authentication
|
5
|
+
Then the response should be rejected with a 401 Unauthorized status code
|
6
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: As a user of the API, I am able to list my submitted bundles.
|
2
|
+
Scenario: I am building an index page to my bundle collection.
|
3
|
+
Given I am using the documentation API key
|
4
|
+
And I know the following urls referenced as:
|
5
|
+
| name | URL |
|
6
|
+
| media:future-of-women-flying | http://archive.org/download/Greatest_Speeches_of_the_20th_Century/TheFutureofWomeninFlying_64kb.mp3 |
|
7
|
+
| media:watergate-tapes | http://ia700200.us.archive.org/18/items/Greatest_Speeches_of_the_20th_Century/OnReleasingtheWatergateTapes_64kb.mp3 |
|
8
|
+
| media:resignation-address | http://ia600200.us.archive.org/18/items/Greatest_Speeches_of_the_20th_Century/ResignationAddress-1974_64kb.mp3 |
|
9
|
+
When I request a list of bundles
|
10
|
+
Then I should get the HTTP status code 200
|
11
|
+
And my results should include a track with the URL "[media:future-of-women-flying]"
|
12
|
+
And my results should include a track with the URL "[media:watergate-tapes]"
|
13
|
+
And my results should include a track with the URL "[media:resignation-address]"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
Feature: As a user of the API, I am able to search for bundles based on the content.
|
3
|
+
Scenario: I am building a search functionality into my application.
|
4
|
+
Given I am using the documentation API key
|
5
|
+
And I know the following urls referenced as:
|
6
|
+
| name | URL |
|
7
|
+
| media:future-of-women-flying | http://archive.org/download/Greatest_Speeches_of_the_20th_Century/TheFutureofWomeninFlying_64kb.mp3 |
|
8
|
+
When I search my bundles for the text "women"
|
9
|
+
Then I should get the HTTP status code 200
|
10
|
+
And my results should include a track with the URL "[media:future-of-women-flying]"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
Given(/^I am using the documentation API key$/) do
|
3
|
+
customer.log_in_as_docs
|
4
|
+
end
|
5
|
+
|
6
|
+
Given(/^I am not using an API key$/) do
|
7
|
+
customer.clear_api_key
|
8
|
+
end
|
9
|
+
|
10
|
+
Given(/^I am using the environment's API key$/) do
|
11
|
+
customer.log_in_via_environment
|
12
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
When(/^I request a list of bundles without authentication$/) do
|
3
|
+
begin
|
4
|
+
@result = customer.bundle_repository.fetch
|
5
|
+
rescue Clarify::StandardError => err
|
6
|
+
exceptions.caught = err
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
When(/^I request a list of bundles$/) do
|
11
|
+
@result = customer.bundle_repository.fetch
|
12
|
+
end
|
13
|
+
|
14
|
+
When(/^I search my bundles for the text "(.*?)"$/) do |query_string|
|
15
|
+
@result = customer.bundle_repository.search(query_string)
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^my results should include a track with the URL "(.*?)"$/) do |url|
|
19
|
+
if @result.is_a? Clarify::Responses::SearchCollection
|
20
|
+
urls = @result.map { |_, bundle_url| bundle_url }
|
21
|
+
else
|
22
|
+
urls = @result.to_a
|
23
|
+
end
|
24
|
+
|
25
|
+
bundles = urls.map { |bundle_url| customer.restclient.get(bundle_url) }
|
26
|
+
|
27
|
+
tracks = bundles.map do |bundle|
|
28
|
+
customer.restclient.get(bundle.relation('clarify:tracks'))
|
29
|
+
end
|
30
|
+
media_urls = tracks.map do |tracks_resource|
|
31
|
+
tracks_resource.map { |track| track['media_url'] }
|
32
|
+
end.flatten
|
33
|
+
|
34
|
+
expect(media_urls).to include(curies.resolve(url))
|
35
|
+
end
|
36
|
+
|
37
|
+
# rubocop:disable Metrics/LineLength
|
38
|
+
When(/^I create a bundle named "(.*?)" with the media url "(.*?)"$/) do |name, url|
|
39
|
+
# rubocop:enable Metrics/LineLength
|
40
|
+
bundle = {
|
41
|
+
name: names.translate(name),
|
42
|
+
media_url: curies.resolve(url)
|
43
|
+
}
|
44
|
+
customer.bundle_repository.create!(bundle)
|
45
|
+
end
|
46
|
+
|
47
|
+
Then(/^my results should incude a bundle named "(.*?)"$/) do |name|
|
48
|
+
all_results = Clarify::CollectionIterator.new(customer.restclient, @result)
|
49
|
+
bundles = all_results.map do |item|
|
50
|
+
customer.restclient.get(item)
|
51
|
+
end
|
52
|
+
bundle_names = bundles.map(&:name)
|
53
|
+
|
54
|
+
expect(bundle_names).to include(names.translate(name))
|
55
|
+
end
|
56
|
+
|
57
|
+
Given(/^I have a bundle named "(.*?)"$/) do |name|
|
58
|
+
bundle = {
|
59
|
+
name: names.translate(name)
|
60
|
+
}
|
61
|
+
@my_bundle = customer.bundle_repository.create!(bundle)
|
62
|
+
end
|
63
|
+
|
64
|
+
When(/^I delete my bundle$/) do
|
65
|
+
customer.bundle_repository.delete!(@my_bundle)
|
66
|
+
end
|
67
|
+
|
68
|
+
Then(/^the server should not list my bundle$/) do
|
69
|
+
result = customer.bundle_repository.fetch
|
70
|
+
all_results = Clarify::CollectionIterator.new(customer.restclient, result)
|
71
|
+
bundle_urls = all_results.map do |item|
|
72
|
+
item['href']
|
73
|
+
end
|
74
|
+
|
75
|
+
expect(bundle_urls).to_not include(@my_bundle.relation('self'))
|
76
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + '/lib/'
|
3
|
+
$LOAD_PATH << File.dirname(__FILE__) + '/../../lib/'
|
4
|
+
|
5
|
+
require 'simplecov'
|
6
|
+
require 'clarify'
|
7
|
+
require 'customer'
|
8
|
+
require 'exceptions'
|
9
|
+
require 'curies'
|
10
|
+
|
11
|
+
# EnvHelpers is
|
12
|
+
class EnvHelpers
|
13
|
+
def customer
|
14
|
+
@customer ||= ClarifyTests::Customer.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def exceptions
|
18
|
+
@exceptions ||= ClarifyTests::Exceptions.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def curies
|
22
|
+
@curies ||= ClarifyTests::Curies.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def names
|
26
|
+
@names ||= ClarifyTests::Names.new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
World do
|
31
|
+
EnvHelpers.new
|
32
|
+
end
|
33
|
+
|
34
|
+
After do
|
35
|
+
exceptions.raise_pending!
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module ClarifyTests
|
3
|
+
# The Curies class helps improve readability in URL-based tests by
|
4
|
+
# introducing a replacable reference.
|
5
|
+
class Curies
|
6
|
+
def initialize
|
7
|
+
@curies = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def []=(name, value)
|
11
|
+
@curies["[#{name}]"] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve(url)
|
15
|
+
return url unless url[0] == '['
|
16
|
+
@curies.fetch(url)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module ClarifyTests
|
3
|
+
# The Customer represents a user of the API. The Customer might do things like
|
4
|
+
# log in with particular keys, or create RestClients, Configurations, etc.
|
5
|
+
class Customer
|
6
|
+
attr_reader :api_key
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
end
|
10
|
+
|
11
|
+
def log_in_as_docs
|
12
|
+
self.api_key = 'docs-api-key'
|
13
|
+
end
|
14
|
+
|
15
|
+
def log_in_via_environment
|
16
|
+
self.api_key = ENV.fetch('CLARIFY_API_KEY')
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear_api_key
|
20
|
+
self.api_key = ''
|
21
|
+
end
|
22
|
+
|
23
|
+
def api_key=(val)
|
24
|
+
@api_key = val
|
25
|
+
|
26
|
+
@client = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def bundle_repository
|
30
|
+
client.bundle_repository
|
31
|
+
end
|
32
|
+
|
33
|
+
def restclient
|
34
|
+
client.restclient
|
35
|
+
end
|
36
|
+
|
37
|
+
def client
|
38
|
+
@client ||= Clarify::Client.new(api_key: api_key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module ClarifyTests
|
3
|
+
# Used for catching and re-throwing exceptions used in tests. Guarantees that
|
4
|
+
# an exception won't be swalloawed when integrated with After commands.
|
5
|
+
class Exceptions
|
6
|
+
attr_writer :caught
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@caught = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def caught
|
13
|
+
exception = @caught
|
14
|
+
@caught = nil
|
15
|
+
|
16
|
+
exception
|
17
|
+
end
|
18
|
+
|
19
|
+
def raise_pending!
|
20
|
+
fail @caught if exception?
|
21
|
+
end
|
22
|
+
|
23
|
+
def exception?
|
24
|
+
!@caught.nil?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module ClarifyTests
|
5
|
+
# Take names you use in a test and make them unique, guaranteeing two tests
|
6
|
+
# can't trample on the same account.
|
7
|
+
class Names
|
8
|
+
def translate(name)
|
9
|
+
"#{uuid}{#{name}}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def uuid
|
13
|
+
@uuid ||= SecureRandom.uuid
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/clarify.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
-
require "clarify/version"
|
2
|
-
require "clarify/configuration"
|
3
|
-
require "clarify/bundle"
|
4
|
-
require "clarify/request"
|
5
|
-
require "clarify/metadata"
|
6
|
-
require "clarify/track"
|
7
|
-
require "clarify/search"
|
8
1
|
|
2
|
+
# The Clarify API SDK
|
9
3
|
module Clarify
|
10
|
-
class << self
|
11
|
-
attr_accessor :configuration
|
12
|
-
end
|
13
|
-
def self.configure
|
14
|
-
self.configuration ||= Configuration.new
|
15
|
-
yield(configuration)
|
16
|
-
end
|
17
4
|
end
|
5
|
+
|
6
|
+
require 'clarify/bundle_repository'
|
7
|
+
require 'clarify/rest_client'
|
8
|
+
require 'clarify/configuration'
|
9
|
+
require 'clarify/errors'
|
10
|
+
require 'clarify/client'
|
11
|
+
require 'clarify/response'
|
12
|
+
require 'clarify/response_factory'
|
13
|
+
require 'clarify/responses/bundle'
|
14
|
+
require 'clarify/responses/collection'
|
15
|
+
require 'clarify/responses/search_collection'
|
16
|
+
require 'clarify/responses/no_body'
|
17
|
+
require 'clarify/collection_iterator'
|
18
|
+
require 'clarify/responses/tracks'
|
19
|
+
require 'clarify/version'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
# A simple entrypoint to the API. Exposes access to search and CRUD
|
4
|
+
# operations on Bundles.
|
5
|
+
class BundleRepository
|
6
|
+
def initialize(restclient)
|
7
|
+
@restclient = restclient
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch
|
11
|
+
@restclient.get('/v1/bundles')
|
12
|
+
end
|
13
|
+
|
14
|
+
def search(query_string)
|
15
|
+
@restclient.get('/v1/search', query: query_string)
|
16
|
+
end
|
17
|
+
|
18
|
+
def create!(about)
|
19
|
+
@restclient.post('/v1/bundles', about)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete!(bundle)
|
23
|
+
@restclient.delete(bundle.relation!('self'))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
# The Client simplifies the configuration and bootstrapping of the restclient
|
4
|
+
# and bundle repository.
|
5
|
+
class Client
|
6
|
+
def initialize(config, opts = {})
|
7
|
+
@config = config
|
8
|
+
@klass_restclient = opts.fetch(:rest_client, Clarify::RestClient)
|
9
|
+
@klass_configuration = opts.fetch(:configuration, Clarify::Configuration)
|
10
|
+
@klass_bundle_repository = opts.fetch(:bundle_repository,
|
11
|
+
Clarify::BundleRepository)
|
12
|
+
@klass_iterator = opts.fetch(:iterator, Clarify::CollectionIterator)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get(url, params = {})
|
16
|
+
restclient.get(url, params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def put(url, params = {})
|
20
|
+
restclient.put(url, params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(url, params = {})
|
24
|
+
restclient.post(url, params)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete(url, params = {})
|
28
|
+
restclient.delete(url, params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pager(collection)
|
32
|
+
@klass_iterator.new(restclient, collection)
|
33
|
+
end
|
34
|
+
|
35
|
+
def bundles
|
36
|
+
bundle_repository
|
37
|
+
end
|
38
|
+
|
39
|
+
def bundle_repository
|
40
|
+
@bundle_repository ||= @klass_bundle_repository.new(restclient)
|
41
|
+
end
|
42
|
+
|
43
|
+
def restclient
|
44
|
+
@restclient ||= @klass_restclient.new(configuration)
|
45
|
+
end
|
46
|
+
|
47
|
+
def configuration
|
48
|
+
@configuration ||= @klass_configuration.new(@config)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|