viki 0.0.1

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 ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ *.DS_Store
5
+ pkg/*
6
+ *.swp
7
+ *.un~
8
+ .idea/
9
+ fixtures/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.3-p125@viki-gem --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in viki.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ A Viki wrapper gem for the Viki V3 API. This gem is currently under active development.
2
+
3
+ Full documentation for API V3 may be found at [dev.viki.com](http://dev.viki.com/api "Viki API V3 Docs")
4
+
5
+
6
+ Endpoints
7
+ ----------
8
+
9
+ Here are a full list of functions available.
10
+
11
+ ```
12
+ client.movies(params)
13
+ client.movies(id, params)
14
+ client.movie(id).subtitles(lang)
15
+ client.movie(id).hardsubs
16
+
17
+ client.series(params)
18
+ client.series(id, params)
19
+ client.series(id).episodes(params)
20
+ client.series(id).episodes(id)
21
+ client.series(id).episodes(id).subtitles(lang)
22
+ client.series(id).episodes(id).hardsubs
23
+
24
+ client.music_videos(params)
25
+ client.music_videos(id, params)
26
+ client.music_videos(id).subtitles(lang)
27
+ client.music_videos(id).hardsubs * implementation waiting on valid examples
28
+
29
+ client.newscasts(params)
30
+ client.newscasts(id, params)
31
+ client.newscasts(id).newsclips
32
+
33
+
34
+ client.newsclips
35
+ client.newsclips(id)
36
+ client.newsclips(id).subtitles(lang)
37
+ client.newsclips(id).hardsubs(lang)
38
+
39
+
40
+ client.artists(params)
41
+ client.artist(id, params)
42
+ client.artists(id).music_videos(params)
43
+
44
+ client.featured(params)
45
+
46
+ client.coming_soon
47
+ client.coming_soon.movies
48
+ client.coming_soon.series
49
+ ```
50
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,41 @@
1
+ require 'multi_json'
2
+ require 'viki/utilities'
3
+
4
+ module Viki
5
+ class APIObject
6
+ include Viki::Utilities
7
+
8
+ def initialize(json, access_token)
9
+ hash = MultiJson.load(json)
10
+ @content = hash["response"] ? hash["response"] : hash
11
+ @count = hash["count"] ? hash["count"].to_i : 1
12
+
13
+ pagination = hash["pagination"]
14
+
15
+ if pagination
16
+ @next_url = pagination["next"] if not pagination["next"].empty?
17
+ @previous_url = pagination["previous"] if not pagination["previous"].empty?
18
+ end
19
+
20
+ @access_token = access_token
21
+ end
22
+
23
+ attr_reader :content, :count
24
+
25
+ def next
26
+ @next_url ? direct_request(@next_url) : nil
27
+ end
28
+
29
+ def prev
30
+ @previous_url ? direct_request(@next_url) : nil
31
+ end
32
+
33
+ private
34
+
35
+ def direct_request(url)
36
+ response = HTTParty.get(url, :query => { access_token: @access_token })
37
+ capture response
38
+ APIObject.new(response.body, @access_token)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,51 @@
1
+ require 'httparty'
2
+ require 'viki/api_object'
3
+ require 'viki/request'
4
+ require 'multi_json'
5
+
6
+ module Viki
7
+ class Client
8
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each { |f| require f }
9
+ URL_NAMESPACES = [:movies, :series, :episodes, :music_videos, :newscasts, :newsclips,
10
+ :artists, :featured, :coming_soon, :subtitles, :hardsubs]
11
+
12
+ def initialize(client_id, client_secret)
13
+ @client_id = client_id
14
+ @client_secret = client_secret
15
+ @access_token = auth_request(client_id, client_secret)
16
+ end
17
+
18
+ attr_reader :access_token
19
+
20
+ include Viki::Request
21
+
22
+ def get
23
+ request(@call_chain)
24
+ end
25
+
26
+ def reset_access_token
27
+ @access_token = auth_request(@client_id, @client_secret)
28
+ end
29
+
30
+ private
31
+ def method_missing(name, *args, &block)
32
+ @call_chain ||= []
33
+ raise NoMethodError if not URL_NAMESPACES.include? name
34
+
35
+ curr_call = { name: name }
36
+
37
+ first_arg, second_arg = args[0], args[1]
38
+
39
+ if args.length == 1
40
+ first_arg.is_a?(Hash) ? curr_call.merge!({ params: first_arg }) : curr_call.merge!({ resource: first_arg })
41
+ elsif args.length == 2
42
+ curr_call.merge!({ resource: first_arg })
43
+ curr_call.merge!({ params: second_arg })
44
+ end
45
+
46
+ @call_chain.push(curr_call)
47
+ self
48
+ end
49
+
50
+ end
51
+ end
data/lib/viki/error.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Viki
2
+ class Error < StandardError
3
+ attr_accessor :status, :message
4
+
5
+ def initialize(status, msg=nil)
6
+ self.status = status
7
+ self.message = msg
8
+ super(msg||"#{self.status}: #{self.message}")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ require 'uri'
2
+ require 'httparty'
3
+ require 'multi_json'
4
+ require 'viki/utilities'
5
+
6
+ module Viki
7
+ module Request
8
+ include Viki::Utilities
9
+
10
+ private
11
+ HOST = "http://www.viki.com/api/v3/"
12
+
13
+ def auth_request(client_id, client_secret)
14
+ params = {
15
+ :grant_type => 'client_credentials',
16
+ :client_id => client_id,
17
+ :client_secret => client_secret
18
+ }
19
+ response = HTTParty.post('http://viki.com/oauth/token', query: params)
20
+ json = MultiJson.load(response.body)
21
+ raise Viki::Error.new(response.header.code, json["error_description"]) if response.header.code != "200"
22
+ json["access_token"]
23
+ end
24
+
25
+ def request(call_chain)
26
+ path, params = build_url(call_chain)
27
+ request_url = HOST + path.chop + ".json"
28
+
29
+ response = HTTParty.get(request_url, :query => params)
30
+
31
+ if response.header.code == "401"
32
+ self.reset_access_token
33
+ params.merge!({ access_token: self.access_token })
34
+ response = HTTParty.get(request_url, :query => params)
35
+ end
36
+
37
+ capture response
38
+
39
+ APIObject.new(response.body, self.access_token)
40
+ end
41
+
42
+ private
43
+
44
+ def build_url(call_chain)
45
+ path = ""
46
+ params = { access_token: self.access_token }
47
+
48
+ call_chain.each do |c|
49
+ path += "#{c[:name]}/"
50
+ path += "#{c[:resource]}/" if c.has_key?(:resource)
51
+ params.merge!(c[:params]) if c.has_key?(:params)
52
+ end
53
+
54
+ return path, params
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ module Viki
2
+ module Utilities
3
+ private
4
+
5
+ def capture(response)
6
+ if response.header.code != "200"
7
+ response_hash = MultiJson.load(response.body)
8
+ raise Viki::Error.new(response.header.code, response_hash["message"]) if response.header.code != "200"
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Viki
2
+ VERSION = "0.0.1"
3
+ end
data/lib/viki.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'viki/version'
2
+ require 'viki/client'
3
+ require 'viki/error'
4
+ require 'viki/utilities'
5
+
6
+ # Adapted from the Grackle Twitter gem.
7
+ module Viki
8
+
9
+ # Alias for viki::Client.new
10
+ #
11
+ # @return {viki::Client})
12
+ def self.new(client_id, client_secret)
13
+ Viki::Client.new(client_id, client_secret)
14
+ end
15
+
16
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Viki::Client do
4
+
5
+ describe "#get" do
6
+ before { Viki::Client.any_instance.stub(:auth_request) }
7
+ subject { Viki::Client.new('chickenrice', 'soronerychickenrice') }
8
+
9
+ it "should perform a request to the right url given a call chain" do
10
+ subject.movies(1234).subtitles('en')
11
+ subject.should_receive(:request).with([{ :name => :movies, :resource => 1234 },
12
+ { :name => :subtitles, :resource => "en" }])
13
+ subject.get
14
+ end
15
+
16
+ it "should perform a request with the right params given a call chain" do
17
+ subject.movies(1234, {genre: 2})
18
+ subject.should_receive(:request).with([{ :name => :movies, :resource => 1234, :params => {genre: 2}}])
19
+ subject.get
20
+ end
21
+
22
+ it "should raise NoMethodError error if part of the call chain is not part of the URL_NAMESPACES list" do
23
+ expect { subject.methodwrong.subtitles('en') }.to raise_error(NoMethodError)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Viki::Error do
4
+ before { @error = Viki::Error.new(404, "Resource 'blah' not found.")}
5
+
6
+ subject { @error }
7
+
8
+ it { should respond_to(:status) }
9
+ it { should respond_to(:message) }
10
+
11
+ it { subject.to_s.should == "Resource 'blah' not found."}
12
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for "API with parameter filters" do
4
+ context "when filtering with genre" do
5
+ let(:query_options) { { :genre => 2 } }
6
+ it "should return a genre-filtered list of Viki::Movie objects when given genre params" do
7
+ VCR.use_cassette "#{type}/genre_filter" do
8
+ results.each do |m|
9
+ m.genres.each do |g|
10
+ g["id"].should == 2
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ context "when filtering with subtitle_language" do
18
+ let(:query_options) { { :subtitle_language => 'fr' } }
19
+ it "should return movies with requested subtitle > 90% completion, when given a subtitle_language parameter" do
20
+ VCR.use_cassette "#{type}/subtitle_language_filter" do
21
+ results.each do |m|
22
+ m.subtitles["fr"].should > 90
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ context "when filtering with watchable_in" do
29
+ let(:query_options) { { :watchable_in => 'sg' } }
30
+ it "should return movies watchable_in selected country when given a watchable_in parameter" do
31
+ VCR.use_cassette "#{type}/watchable_in_filter" do
32
+ results.should_not be_empty
33
+ end
34
+ end
35
+ end
36
+
37
+ context "when filtering with origin_country" do
38
+ let(:query_options) { { :origin_country => 'kr' } }
39
+ it "should return movies from a specific country when given a origin_country parameter" do
40
+ VCR.use_cassette "#{type}/origin_country_filter" do
41
+ results.each do |m|
42
+ m.origin_country.should == 'Korea'
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ context "when filtering with platform" do
50
+ let(:query_options) { { :platform => 'mobile' } }
51
+ it "should return movies available in selected platform when given watchable_in and platform parameters" do
52
+ query_options.merge!({ :watchable_in => 'sg' })
53
+ VCR.use_cassette "#{type}/platform_filter" do
54
+ results.should_not be_empty
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'filter_shared_examples_spec'
5
+
6
+ describe "Viki" do
7
+ let(:client_id) { '4bd5edd4ba26ac2f3ad9d204dc6359ea8a3ebe2c95b6bc1a9195c0ce5c57d392' }
8
+ let(:client_secret) { 'f3b796a1eb6e06458a502a89171a494a9160775ed4f4e9e0008c638f7e7e7d38' }
9
+
10
+ describe "Auth" do
11
+ it "should retrieve an access token when the Viki object is configured and initialized" do
12
+ VCR.use_cassette "auth" do
13
+ client = Viki.new(client_id, client_secret)
14
+ client.access_token.should == '1b080a6b3a94ed4503e04e252500ca87f6e7dc55061cec92b627ef1fbec44c70'
15
+ end
16
+ end
17
+
18
+ it "should return an error when the client_secret or client_id is incorrect" do
19
+ VCR.use_cassette "auth_error" do
20
+ lambda { Viki.new('12345', '54321') }.should raise_error(Viki::Error,
21
+ 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.')
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "API Interactions" do
27
+ let(:query_options) { { } }
28
+ let(:client) do
29
+ VCR.use_cassette "auth" do
30
+ Viki.new(client_id, client_secret)
31
+ end
32
+ end
33
+
34
+ describe "Movies" do
35
+ let(:results) { client.movies(query_options).get }
36
+ let(:type) { :movie }
37
+
38
+ describe "/movies" do
39
+ it "should return a list Viki::Movie objects" do
40
+ VCR.use_cassette "movies/list" do
41
+ results.content.each do |movie|
42
+ movie.should be_instance_of(Hash)
43
+ end
44
+ end
45
+ end
46
+
47
+ it "should raise an error when platform parameter is given without watchable_in" do
48
+ VCR.use_cassette "movie/platform_filter_error" do
49
+ query_options.merge!({ :platform => 'mobile' })
50
+ lambda { results }.should raise_error(Viki::Error,
51
+ "Require watchable_in parameter when given platform parameter")
52
+ end
53
+ end
54
+
55
+ #it_behaves_like "API with parameter filters"
56
+ end
57
+
58
+ describe "/movies/:id" do
59
+ it "should return a Viki::Movie object" do
60
+ VCR.use_cassette "movie_show" do
61
+ response = client.movies(70436).get
62
+ movie = response.content
63
+
64
+ #overtesting
65
+ movie["id"].should == 70436
66
+ movie["title"].should == "Muoi: The Legend of a Portrait"
67
+ movie["description"].should_not be_empty
68
+ movie["created_at"].should_not be_empty
69
+ movie["uri"].should_not be_empty
70
+ movie["origin_country"].should_not be_empty
71
+ movie["image"].should_not be_empty
72
+ movie["formats"].should_not be_empty
73
+ movie["subtitles"].should_not be_empty
74
+ movie["genres"].should_not be_empty
75
+ end
76
+ end
77
+
78
+ it "should return a Viki::Error object when resource not found" do
79
+ VCR.use_cassette "movie_error" do
80
+ lambda { client.movies(50).get }.should raise_error(Viki::Error, "The resource couldn't be found")
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "/movies/:id/subtitles/:lang" do
86
+ it "should return a subtitle JSON string" do
87
+ VCR.use_cassette "movies/subtitles" do
88
+ response = client.movies(21713).subtitles('en').get
89
+ response.count.should == 1
90
+ subtitles = response.content
91
+ subtitles["language_code"].should == "en"
92
+ subtitles["subtitles"].should_not be_empty
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "movies/:id/hardsubs" do
98
+ it "should return a list of video qualities with links to hardsubbed videos" do
99
+ VCR.use_cassette "movies/hardsubs" do
100
+ response = client.movies(64135).hardsubs.get
101
+ response.count.should == 1
102
+ hardsubs = response.content
103
+ hardsubs["res-240p"].should_not be_empty
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "APIObject pagination" do
109
+ it "returns an APIObject for APIObject containing movies when it has a next page" do
110
+ VCR.use_cassette "APIObject/pagination" do
111
+ response = client.movies.get
112
+ result = response.next
113
+ result.count.should > 1
114
+ result.content.should_not be_empty
115
+ result.should be_instance_of(Viki::APIObject)
116
+ end
117
+ end
118
+
119
+ it "returns nil if there is movies listing has no next page" do
120
+ VCR.use_cassette "APIObject/pagination_fail" do
121
+ response = client.movies({ page: 6 }).get
122
+ result = response.next
123
+ result.should be_nil
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "Renew Expired Access Token" do
130
+ it "should request a new access token when an endpoint returns 401 and client currently has an access_token" do
131
+ VCR.use_cassette "auth/expired_access_token" do
132
+ client.access_token.should_not be_empty
133
+ client.instance_variable_set(:@access_token, "rubbishaccesstoken")
134
+ response = client.movies.get
135
+ response.content.should_not be_empty
136
+ end
137
+ end
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rspec'
5
+ require 'viki'
6
+ require 'vcr'
7
+
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ VCR.configure do |c|
2
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
3
+ c.allow_http_connections_when_no_cassette = true
4
+ c.hook_into :webmock
5
+ end
6
+
data/viki.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "viki/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "viki"
7
+ s.version = Viki::VERSION
8
+ s.authors = ["Joost van Amersfoort", "Cedric Chin", "Tommi Lew"]
9
+ s.email = ["engineering@viki.com"]
10
+ s.homepage = "http://dev.viki.com"
11
+ s.summary = "A thin wrapper around the Viki V3 API"
12
+ s.description = "Viki-gem is an official wrapper gem for the Viki V3 API."
13
+
14
+ s.rubyforge_project = "viki"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec", "~> 2.10.0"
23
+ s.add_development_dependency "vcr", "~> 2.2.2"
24
+ s.add_development_dependency "webmock", "~> 1.8.7"
25
+ s.add_development_dependency "excon", "~> 0.9.6"
26
+ s.add_runtime_dependency "httparty", "~> 0.8.3"
27
+ s.add_runtime_dependency "multi_json", "~> 1.3.6"
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: viki
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joost van Amersfoort
9
+ - Cedric Chin
10
+ - Tommi Lew
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2012-06-26 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: &70128599563080 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 2.10.0
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: *70128599563080
27
+ - !ruby/object:Gem::Dependency
28
+ name: vcr
29
+ requirement: &70128599562600 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 2.2.2
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *70128599562600
38
+ - !ruby/object:Gem::Dependency
39
+ name: webmock
40
+ requirement: &70128599562100 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.8.7
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *70128599562100
49
+ - !ruby/object:Gem::Dependency
50
+ name: excon
51
+ requirement: &70128599561540 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 0.9.6
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *70128599561540
60
+ - !ruby/object:Gem::Dependency
61
+ name: httparty
62
+ requirement: &70128599560720 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 0.8.3
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: *70128599560720
71
+ - !ruby/object:Gem::Dependency
72
+ name: multi_json
73
+ requirement: &70128599560160 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 1.3.6
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: *70128599560160
82
+ description: Viki-gem is an official wrapper gem for the Viki V3 API.
83
+ email:
84
+ - engineering@viki.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - .gitignore
90
+ - .rspec
91
+ - .rvmrc
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - lib/viki.rb
96
+ - lib/viki/api_object.rb
97
+ - lib/viki/client.rb
98
+ - lib/viki/error.rb
99
+ - lib/viki/request.rb
100
+ - lib/viki/utilities.rb
101
+ - lib/viki/version.rb
102
+ - spec/client_spec.rb
103
+ - spec/error_spec.rb
104
+ - spec/filter_shared_examples_spec.rb
105
+ - spec/request_spec.rb
106
+ - spec/spec_helper.rb
107
+ - spec/support/vcr.rb
108
+ - viki.gemspec
109
+ homepage: http://dev.viki.com
110
+ licenses: []
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project: viki
129
+ rubygems_version: 1.8.11
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: A thin wrapper around the Viki V3 API
133
+ test_files:
134
+ - spec/client_spec.rb
135
+ - spec/error_spec.rb
136
+ - spec/filter_shared_examples_spec.rb
137
+ - spec/request_spec.rb
138
+ - spec/spec_helper.rb
139
+ - spec/support/vcr.rb