dribbble-bucket-api 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 +17 -0
- data/.rvmrc +12 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +55 -0
- data/Rakefile +2 -0
- data/dribbble_bucket_api.gemspec +23 -0
- data/lib/dribbble_bucket_api.rb +16 -0
- data/lib/dribbble_bucket_api/bucket.rb +11 -0
- data/lib/dribbble_bucket_api/bucket_collection.rb +38 -0
- data/lib/dribbble_bucket_api/bucket_index_parser.rb +44 -0
- data/lib/dribbble_bucket_api/connection.rb +14 -0
- data/lib/dribbble_bucket_api/official_api.rb +25 -0
- data/lib/dribbble_bucket_api/public_site.rb +63 -0
- data/lib/dribbble_bucket_api/shot.rb +37 -0
- data/lib/dribbble_bucket_api/shot_collection.rb +29 -0
- data/lib/dribbble_bucket_api/shot_index_parser.rb +45 -0
- data/lib/dribbble_bucket_api/version.rb +3 -0
- data/spec/dribbble_bucket_api/bucket_collection_spec.rb +27 -0
- data/spec/dribbble_bucket_api/bucket_index_parser_spec.rb +86 -0
- data/spec/dribbble_bucket_api/bucket_spec.rb +20 -0
- data/spec/dribbble_bucket_api/connection_spec.rb +29 -0
- data/spec/dribbble_bucket_api/official_api_spec.rb +25 -0
- data/spec/dribbble_bucket_api/public_site_spec.rb +33 -0
- data/spec/dribbble_bucket_api/shot_collection_spec.rb +18 -0
- data/spec/dribbble_bucket_api/shot_spec.rb +26 -0
- data/spec/dribbble_bucket_api_spec.rb +21 -0
- data/spec/spec_helper.rb +2 -0
- metadata +163 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
if ! rvm list | grep -q ruby-1.9.3-p194 ; then
|
4
|
+
rvm install 1.9.3-p194
|
5
|
+
fi
|
6
|
+
|
7
|
+
rvm 1.9.3-p194@ryantownsend_dribbble_bucket_api --create
|
8
|
+
|
9
|
+
if ! gem list | grep -q bundler ; then
|
10
|
+
gem install --no-ri --no-rdoc bundler
|
11
|
+
bundle install --without production
|
12
|
+
fi
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ryan Townsend
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# DribbbleBucketApi
|
2
|
+
|
3
|
+
This gem provides an unofficial API for browsing buckets on Dribbble and their contents.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'dribbble-bucket-api'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install dribbble-bucket-api
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
username = "your_username"
|
22
|
+
connection = DribbbleBucketApi.connect(username: username)
|
23
|
+
|
24
|
+
# loading buckets
|
25
|
+
buckets = connection.buckets(page: 1) # => DribbbleBucketApi::BucketCollection
|
26
|
+
buckets.total_pages # => 2
|
27
|
+
buckets.total_entries # => 7
|
28
|
+
buckets.current_page # => 1
|
29
|
+
buckets.next_page # => 2
|
30
|
+
buckets.previous_page # => 1
|
31
|
+
|
32
|
+
buckets.each do |bucket| # => DribbbleBucketApi::Bucket
|
33
|
+
puts bucket.name
|
34
|
+
puts bucket.description
|
35
|
+
|
36
|
+
# loading shots
|
37
|
+
shots = bucket.shots(page: 1) # => DribbbleBucketApi::ShotCollection
|
38
|
+
shots.total_entries # => 14
|
39
|
+
shots.each do |shot| # => DribbbleBucketApi::Shot
|
40
|
+
puts shot.title
|
41
|
+
puts shot.image_url
|
42
|
+
# full list of attributes can be found here:
|
43
|
+
# http://dribbble.com/api#get_shot
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
1. Fork it
|
52
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
53
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
54
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
55
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/dribbble_bucket_api/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.authors = ["Ryan Townsend"]
|
6
|
+
s.email = ["ryan@ryantownsend.co.uk"]
|
7
|
+
s.description = %q{Unofficial API for browsing Dribbble buckets and their contents}
|
8
|
+
s.summary = s.description
|
9
|
+
s.homepage = "https://github.com/ryantownsend/dribbble-bucket-api"
|
10
|
+
|
11
|
+
s.files = `git ls-files`.split($\)
|
12
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
s.test_files = s.files.grep(%r{^(spec|features)/})
|
14
|
+
s.name = "dribbble-bucket-api"
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.version = DribbbleBucketApi::VERSION
|
17
|
+
|
18
|
+
s.add_dependency "nokogiri"
|
19
|
+
s.add_dependency "httparty"
|
20
|
+
s.add_dependency "multi_json"
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "simplecov"
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "dribbble_bucket_api/version"
|
2
|
+
require "dribbble_bucket_api/connection"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
def self.connect(options = {})
|
6
|
+
# ensure we have a username
|
7
|
+
unless options[:username]
|
8
|
+
raise ArgumentError, %Q(
|
9
|
+
Options hash must contain :username
|
10
|
+
e.g: DribbbleBucketApi.connect(username: "ryantownsend")
|
11
|
+
)
|
12
|
+
end
|
13
|
+
# create the connection
|
14
|
+
Connection.new(options[:username])
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "public_site"
|
2
|
+
|
3
|
+
module DribbbleBucketApi
|
4
|
+
class BucketCollection < Array
|
5
|
+
def self.retrieve(options)
|
6
|
+
# ensure we have a connection
|
7
|
+
unless options[:connection]
|
8
|
+
raise ArgumentError, %Q(
|
9
|
+
Options hash must contain :connection
|
10
|
+
e.g: DribbbleBucketApi::BucketCollection.load(connection: connection)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
# load the username
|
14
|
+
username = options[:connection].username
|
15
|
+
# load the page
|
16
|
+
response = PublicSite.new.user_buckets({
|
17
|
+
username: username,
|
18
|
+
page: options[:page] || 1
|
19
|
+
})
|
20
|
+
# create the new array
|
21
|
+
new(response.buckets).tap do |arr|
|
22
|
+
arr.total_entries = response.total_entries
|
23
|
+
arr.total_pages = response.total_pages
|
24
|
+
arr.current_page = response.current_page
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_accessor :total_entries, :total_pages, :current_page
|
29
|
+
|
30
|
+
def next_page
|
31
|
+
current_page + 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def prev_page
|
35
|
+
[current_page - 1, 1].max
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
require_relative "bucket"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
class BucketIndexParser
|
6
|
+
attr_reader :body
|
7
|
+
|
8
|
+
def initialize(body, options = {})
|
9
|
+
@body = body
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def buckets
|
14
|
+
@buckets ||= document.css(".bucket-list > li").map do |bucket|
|
15
|
+
# parse bucket data from HTML
|
16
|
+
id = bucket["class"].gsub(/^bucket\-(\d+)$/, "\1").to_i
|
17
|
+
name = bucket.css(".bucket-title a").first.text
|
18
|
+
# pass data into bucket object
|
19
|
+
Bucket.new(id: id, name: name, username: username)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_page
|
24
|
+
@options[:page] || 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def total_entries
|
28
|
+
@total_entries ||= document.css(".buckets .count").text.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def total_pages
|
32
|
+
(total_entries.to_f / 5).ceil
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def username
|
37
|
+
@options[:username]
|
38
|
+
end
|
39
|
+
|
40
|
+
def document
|
41
|
+
@document ||= Nokogiri::HTML(@body)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "bucket_collection"
|
2
|
+
|
3
|
+
module DribbbleBucketApi
|
4
|
+
class Connection < Struct.new(:username)
|
5
|
+
def buckets(options = {})
|
6
|
+
load_collection(options.merge(connection: self))
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def load_collection(options)
|
11
|
+
BucketCollection.retrieve(options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "multi_json"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
class OfficialApi
|
6
|
+
|
7
|
+
include HTTParty
|
8
|
+
base_uri "api.dribbble.com"
|
9
|
+
|
10
|
+
def get_shot_properties(id)
|
11
|
+
response = self.class.get("/shots/#{id}.json")
|
12
|
+
# ensure it was a successful response
|
13
|
+
unless response.code == 200
|
14
|
+
raise StandardError, %Q(
|
15
|
+
Response returned #{response.code}
|
16
|
+
Body:
|
17
|
+
#{response.body}
|
18
|
+
)
|
19
|
+
end
|
20
|
+
# return the JSON object as a hash
|
21
|
+
MultiJson.load(response.body, symbolize_keys: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require_relative "bucket_index_parser"
|
3
|
+
require_relative "shot_index_parser"
|
4
|
+
|
5
|
+
module DribbbleBucketApi
|
6
|
+
class PublicSite
|
7
|
+
include HTTParty
|
8
|
+
base_uri "dribbble.com"
|
9
|
+
|
10
|
+
def user_buckets(options)
|
11
|
+
response = load_user_buckets(options)
|
12
|
+
# ensure it was a successful response
|
13
|
+
unless response.code == 200
|
14
|
+
raise StandardError, %Q(
|
15
|
+
Response returned #{response.code}
|
16
|
+
Body:
|
17
|
+
#{response.body}
|
18
|
+
)
|
19
|
+
end
|
20
|
+
# return the object
|
21
|
+
BucketIndexParser.new(response.body, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def bucket_contents(options)
|
25
|
+
response = load_bucket_contents(options)
|
26
|
+
# ensure it was a successful response
|
27
|
+
unless response.code == 200
|
28
|
+
raise StandardError, %Q(
|
29
|
+
Response returned #{response.code}
|
30
|
+
Body:
|
31
|
+
#{response.body}
|
32
|
+
)
|
33
|
+
end
|
34
|
+
# return the object
|
35
|
+
ShotIndexParser.new(response.body, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def load_user_buckets(options)
|
40
|
+
# ensure we have a username
|
41
|
+
unless options[:username]
|
42
|
+
raise ArgumentError, %Q(
|
43
|
+
Options hash must contain :username
|
44
|
+
e.g: PublicDribbbleSite.new.user_buckets(username: "ryantownsend")
|
45
|
+
)
|
46
|
+
end
|
47
|
+
# perform the request
|
48
|
+
self.class.get("/#{options[:username]}/buckets?page=#{options[:page] || 1}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def load_bucket_contents(options)
|
52
|
+
# ensure we have a username and bucket id
|
53
|
+
unless options[:username] && options[:bucket_id]
|
54
|
+
raise ArgumentError, %Q(
|
55
|
+
Options hash must contain :username and :bucket_id
|
56
|
+
e.g: PublicDribbbleSite.new.bucket_contents(username: "ryantownsend", bucket_id: 48172)
|
57
|
+
)
|
58
|
+
end
|
59
|
+
# perform the request
|
60
|
+
self.class.get("/#{options[:username]}/buckets/#{options[:bucket_id]}?page=#{options[:page] || 1}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
require_relative "official_api"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
class Shot
|
6
|
+
def initialize(attrs = {})
|
7
|
+
@attrs = attrs
|
8
|
+
# ensure we have an id
|
9
|
+
unless @attrs.has_key?(:id)
|
10
|
+
raise ArgumentError, "Shot must be initialized with an id"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method, *args, &block)
|
15
|
+
# if attrs has the method, and this is an accessor
|
16
|
+
if @attrs.has_key?(method.to_sym) && args.empty? && !block_given?
|
17
|
+
@attrs[method.to_sym]
|
18
|
+
# if we haven't requested the data yet, and this is a accessor
|
19
|
+
elsif !requested_full_data? && args.empty? && !block_given?
|
20
|
+
# request the data, then resubmit the method
|
21
|
+
request_full_data && send(method)
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_full_data
|
28
|
+
@requested_full_data = true
|
29
|
+
properties = OfficialApi.new.get_shot_properties(id)
|
30
|
+
@attrs.merge!(properties)
|
31
|
+
end
|
32
|
+
|
33
|
+
def requested_full_data?
|
34
|
+
!!@requested_full_data
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "public_site"
|
2
|
+
require_relative "shot"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
class ShotCollection < Array
|
6
|
+
def self.retrieve(options)
|
7
|
+
# load the page
|
8
|
+
response = PublicSite.new.bucket_contents({
|
9
|
+
page: 1
|
10
|
+
}.merge(options))
|
11
|
+
# create the new array
|
12
|
+
new(response.shots).tap do |arr|
|
13
|
+
arr.total_entries = response.total_entries
|
14
|
+
arr.total_pages = response.total_pages
|
15
|
+
arr.current_page = response.current_page
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :total_entries, :total_pages, :current_page
|
20
|
+
|
21
|
+
def next_page
|
22
|
+
current_page + 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def prev_page
|
26
|
+
[current_page - 1, 1].max
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
require_relative "bucket"
|
3
|
+
|
4
|
+
module DribbbleBucketApi
|
5
|
+
class ShotIndexParser
|
6
|
+
attr_reader :body
|
7
|
+
|
8
|
+
def initialize(body, options = {})
|
9
|
+
@body = body
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def shots
|
14
|
+
@shots ||= document.css(".dribbbles > li").map do |shot|
|
15
|
+
# parse shot data from HTML
|
16
|
+
id = shot["class"].gsub(/^screenshot\-(\d+)$/, "\1").to_i
|
17
|
+
img_src = shot.css(".dribbble-img img").first["src"]
|
18
|
+
url = "http://dribbble.com" + shot.css("a.dribbble-link").first["href"]
|
19
|
+
# pass data into shot object
|
20
|
+
Shot.new(id: id, image_teaser_url: img_src, url: url)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_page
|
25
|
+
@options[:page] || 1
|
26
|
+
end
|
27
|
+
|
28
|
+
def total_entries
|
29
|
+
@total_entries ||= document.css(".main h2.section").text.gsub(/^(\d+).*$/, "\1").to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def total_pages
|
33
|
+
(total_entries.to_f / 15).ceil
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def username
|
38
|
+
@options[:username]
|
39
|
+
end
|
40
|
+
|
41
|
+
def document
|
42
|
+
@document ||= Nokogiri::HTML(@body)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/bucket_collection"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::BucketCollection do
|
5
|
+
subject { DribbbleBucketApi::BucketCollection }
|
6
|
+
|
7
|
+
let(:connection) do
|
8
|
+
mock("connection", username: "ryantownsend")
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "::retrieve" do
|
12
|
+
context "with a connection" do
|
13
|
+
it "should return an instance of a collection" do
|
14
|
+
result = subject.retrieve(connection: connection)
|
15
|
+
expect(result).to be_kind_of subject
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "without a connection" do
|
20
|
+
it "should raise an exception" do
|
21
|
+
expect {
|
22
|
+
subject.retrieve(connection: nil)
|
23
|
+
}.to raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/bucket_index_parser"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::BucketIndexParser do
|
5
|
+
let(:body) do
|
6
|
+
%Q(
|
7
|
+
<div class="buckets">
|
8
|
+
Buckets
|
9
|
+
<span class="count">29</span>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<ol class="bucket-list">
|
13
|
+
<li class="bucket-12345">
|
14
|
+
<span class="bucket-title">
|
15
|
+
<a href="#loc">Awesome</a>
|
16
|
+
</span>
|
17
|
+
</li>
|
18
|
+
<li class="bucket-67890">
|
19
|
+
<span class="bucket-title">
|
20
|
+
<a href="#loc">Awesome</a>
|
21
|
+
</span>
|
22
|
+
</li>
|
23
|
+
<li class="bucket-98760">
|
24
|
+
<span class="bucket-title">
|
25
|
+
<a href="#loc">Awesome</a>
|
26
|
+
</span>
|
27
|
+
</li>
|
28
|
+
<li class="bucket-54321">
|
29
|
+
<span class="bucket-title">
|
30
|
+
<a href="#loc">Awesome</a>
|
31
|
+
</span>
|
32
|
+
</li>
|
33
|
+
<li class="bucket-12093">
|
34
|
+
<span class="bucket-title">
|
35
|
+
<a href="#loc">Awesome</a>
|
36
|
+
</span>
|
37
|
+
</li>
|
38
|
+
</ol>
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:connection) do
|
43
|
+
mock("connection", username: "ryantownsend")
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:options) do
|
47
|
+
{
|
48
|
+
page: 2,
|
49
|
+
connection: connection
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
subject do
|
54
|
+
DribbbleBucketApi::BucketIndexParser.new(body, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#buckets" do
|
58
|
+
it "should return an item for each bucket in the list" do
|
59
|
+
expect(subject.buckets.size).to eq 5
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return Bucket instances" do
|
63
|
+
subject.buckets.each do |bucket|
|
64
|
+
expect(bucket).to be_kind_of DribbbleBucketApi::Bucket
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#current_page" do
|
70
|
+
it "should return the options page" do
|
71
|
+
expect(subject.current_page).to eq 2
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#total_entries" do
|
76
|
+
it "should return count from the HTML document" do
|
77
|
+
expect(subject.total_entries).to eq 29
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#total_pages" do
|
82
|
+
it "should return the total / 5" do
|
83
|
+
expect(subject.total_pages).to eq 6
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/bucket"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::Bucket do
|
5
|
+
let(:username) { "ryantownsend" }
|
6
|
+
let(:id) { 44001 }
|
7
|
+
|
8
|
+
subject do
|
9
|
+
DribbbleBucketApi::Bucket.new({
|
10
|
+
username: username,
|
11
|
+
id: id
|
12
|
+
})
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#shots" do
|
16
|
+
it "should return a ShotCollection instance" do
|
17
|
+
expect(subject.shots).to be_kind_of DribbbleBucketApi::ShotCollection
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/connection"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::Connection do
|
5
|
+
subject do
|
6
|
+
DribbbleBucketApi::Connection.new("ryantownsend")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#buckets" do
|
10
|
+
context "when provided with a page" do
|
11
|
+
it "should merge the page into a hash with the connection" do
|
12
|
+
subject.should_receive(:load_collection).with({
|
13
|
+
page: 1,
|
14
|
+
connection: subject
|
15
|
+
})
|
16
|
+
subject.buckets(page: 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when not provided with a page" do
|
21
|
+
it "should load the collection using a hash with the connection" do
|
22
|
+
subject.should_receive(:load_collection).with({
|
23
|
+
connection: subject
|
24
|
+
})
|
25
|
+
subject.buckets
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/official_api"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::OfficialApi do
|
5
|
+
subject do
|
6
|
+
DribbbleBucketApi::OfficialApi.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#get_shot_properties" do
|
10
|
+
context "when provided with a valid id" do
|
11
|
+
it "should return a hash of properties" do
|
12
|
+
result = subject.get_shot_properties(156734)
|
13
|
+
expect(result).to be_kind_of(Hash)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when provided with an invalid id" do
|
18
|
+
it "should raise an exception" do
|
19
|
+
expect {
|
20
|
+
subject.get_shot_properties("abc")
|
21
|
+
}.to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/public_site"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::PublicSite do
|
5
|
+
subject do
|
6
|
+
DribbbleBucketApi::PublicSite.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#user_buckets" do
|
10
|
+
context "when provided with a username" do
|
11
|
+
it "should return the remote data" do
|
12
|
+
result = subject.user_buckets(username: "ryantownsend")
|
13
|
+
expect(result).to be_kind_of(DribbbleBucketApi::BucketIndexParser)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when provided with an invalid username" do
|
18
|
+
it "should raise an exception" do
|
19
|
+
expect {
|
20
|
+
subject.user_buckets(username: "h8ahsdIhdasd8q0398d")
|
21
|
+
}.to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when not provided with a username" do
|
26
|
+
it "should raise an exception" do
|
27
|
+
expect {
|
28
|
+
subject.user_buckets(username: nil)
|
29
|
+
}.to raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/shot_collection"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::ShotCollection do
|
5
|
+
subject { DribbbleBucketApi::ShotCollection }
|
6
|
+
|
7
|
+
describe "::retrieve" do
|
8
|
+
context "with a username & bucket" do
|
9
|
+
it "should return an instance of a collection" do
|
10
|
+
result = subject.retrieve({
|
11
|
+
username: "ryantownsend",
|
12
|
+
bucket_id: 44001
|
13
|
+
})
|
14
|
+
expect(result).to be_kind_of subject
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/dribbble_bucket_api/shot"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi::Shot do
|
5
|
+
let(:id) { 156734 }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
DribbbleBucketApi::Shot.new({ id: id })
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#image_url" do
|
12
|
+
context "when the image_url has not yet been loaded" do
|
13
|
+
it "should return a string" do
|
14
|
+
expect(subject.image_url).to match /^https?\:\/\//
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#a_random_method" do
|
20
|
+
it "should return method missing" do
|
21
|
+
expect {
|
22
|
+
subject.a_random_method
|
23
|
+
}.to raise_error(NoMethodError)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../lib/dribbble_bucket_api"
|
3
|
+
|
4
|
+
describe DribbbleBucketApi do
|
5
|
+
describe "::connect" do
|
6
|
+
context "when no username is provided" do
|
7
|
+
it "should raise an exception" do
|
8
|
+
expect {
|
9
|
+
subject.connect(username: nil)
|
10
|
+
}.to raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when a username is provided" do
|
15
|
+
it "should return a connection object containing the username" do
|
16
|
+
connection = subject.connect(username: "ryantownsend")
|
17
|
+
expect(connection.username).to eq("ryantownsend")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dribbble-bucket-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Townsend
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httparty
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: multi_json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: simplecov
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Unofficial API for browsing Dribbble buckets and their contents
|
95
|
+
email:
|
96
|
+
- ryan@ryantownsend.co.uk
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rvmrc
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- dribbble_bucket_api.gemspec
|
108
|
+
- lib/dribbble_bucket_api.rb
|
109
|
+
- lib/dribbble_bucket_api/bucket.rb
|
110
|
+
- lib/dribbble_bucket_api/bucket_collection.rb
|
111
|
+
- lib/dribbble_bucket_api/bucket_index_parser.rb
|
112
|
+
- lib/dribbble_bucket_api/connection.rb
|
113
|
+
- lib/dribbble_bucket_api/official_api.rb
|
114
|
+
- lib/dribbble_bucket_api/public_site.rb
|
115
|
+
- lib/dribbble_bucket_api/shot.rb
|
116
|
+
- lib/dribbble_bucket_api/shot_collection.rb
|
117
|
+
- lib/dribbble_bucket_api/shot_index_parser.rb
|
118
|
+
- lib/dribbble_bucket_api/version.rb
|
119
|
+
- spec/dribbble_bucket_api/bucket_collection_spec.rb
|
120
|
+
- spec/dribbble_bucket_api/bucket_index_parser_spec.rb
|
121
|
+
- spec/dribbble_bucket_api/bucket_spec.rb
|
122
|
+
- spec/dribbble_bucket_api/connection_spec.rb
|
123
|
+
- spec/dribbble_bucket_api/official_api_spec.rb
|
124
|
+
- spec/dribbble_bucket_api/public_site_spec.rb
|
125
|
+
- spec/dribbble_bucket_api/shot_collection_spec.rb
|
126
|
+
- spec/dribbble_bucket_api/shot_spec.rb
|
127
|
+
- spec/dribbble_bucket_api_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
homepage: https://github.com/ryantownsend/dribbble-bucket-api
|
130
|
+
licenses: []
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 1.8.24
|
150
|
+
signing_key:
|
151
|
+
specification_version: 3
|
152
|
+
summary: Unofficial API for browsing Dribbble buckets and their contents
|
153
|
+
test_files:
|
154
|
+
- spec/dribbble_bucket_api/bucket_collection_spec.rb
|
155
|
+
- spec/dribbble_bucket_api/bucket_index_parser_spec.rb
|
156
|
+
- spec/dribbble_bucket_api/bucket_spec.rb
|
157
|
+
- spec/dribbble_bucket_api/connection_spec.rb
|
158
|
+
- spec/dribbble_bucket_api/official_api_spec.rb
|
159
|
+
- spec/dribbble_bucket_api/public_site_spec.rb
|
160
|
+
- spec/dribbble_bucket_api/shot_collection_spec.rb
|
161
|
+
- spec/dribbble_bucket_api/shot_spec.rb
|
162
|
+
- spec/dribbble_bucket_api_spec.rb
|
163
|
+
- spec/spec_helper.rb
|