thumbtack 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.
- checksums.yaml +7 -0
- data/lib/thumbtack/client.rb +70 -0
- data/lib/thumbtack/note.rb +35 -0
- data/lib/thumbtack/note_summary.rb +35 -0
- data/lib/thumbtack/notes.rb +26 -0
- data/lib/thumbtack/post.rb +37 -0
- data/lib/thumbtack/posts.rb +186 -0
- data/lib/thumbtack/specification.rb +31 -0
- data/lib/thumbtack/tags.rb +45 -0
- data/lib/thumbtack/types/boolean.rb +52 -0
- data/lib/thumbtack/types/date.rb +47 -0
- data/lib/thumbtack/types/date_time.rb +49 -0
- data/lib/thumbtack/types/identity.rb +26 -0
- data/lib/thumbtack/types/integer.rb +27 -0
- data/lib/thumbtack/types/md5.rb +30 -0
- data/lib/thumbtack/types/tags.rb +53 -0
- data/lib/thumbtack/types/text.rb +26 -0
- data/lib/thumbtack/types/title.rb +26 -0
- data/lib/thumbtack/types/url.rb +26 -0
- data/lib/thumbtack/types.rb +10 -0
- data/lib/thumbtack/user.rb +23 -0
- data/lib/thumbtack/version.rb +6 -0
- data/lib/thumbtack.rb +32 -0
- data/test/test_helper.rb +18 -0
- data/test/thumbtack/client_test.rb +35 -0
- data/test/thumbtack/note_summary_test.rb +24 -0
- data/test/thumbtack/note_test.rb +26 -0
- data/test/thumbtack/notes_test.rb +61 -0
- data/test/thumbtack/post_test.rb +30 -0
- data/test/thumbtack/posts_test.rb +178 -0
- data/test/thumbtack/specification_test.rb +15 -0
- data/test/thumbtack/tags_test.rb +56 -0
- data/test/thumbtack/types/boolean_test.rb +28 -0
- data/test/thumbtack/types/date_test.rb +27 -0
- data/test/thumbtack/types/date_time_test.rb +27 -0
- data/test/thumbtack/types/identity_test.rb +18 -0
- data/test/thumbtack/types/integer_test.rb +26 -0
- data/test/thumbtack/types/md5_test.rb +28 -0
- data/test/thumbtack/types/tags_test.rb +29 -0
- data/test/thumbtack/types/text_test.rb +22 -0
- data/test/thumbtack/types/title_test.rb +22 -0
- data/test/thumbtack/types/url_test.rb +23 -0
- data/test/thumbtack/user_test.rb +29 -0
- metadata +162 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
module Types
|
5
|
+
# Internal: Handles validation of MD5 types as the values supported by the
|
6
|
+
# Pinboard API.
|
7
|
+
class MD5 < Identity
|
8
|
+
# The length of an MD5 value.
|
9
|
+
LENGTH = 32
|
10
|
+
# The valid characters in an MD5 value.
|
11
|
+
CHARACTERS = '0123456789abcdf'.freeze
|
12
|
+
|
13
|
+
# Validate something is a valid MD5 parameter.
|
14
|
+
#
|
15
|
+
# value - A String containing the MD5 to validate.
|
16
|
+
#
|
17
|
+
# Returns nothing.
|
18
|
+
# Raises Types::ValidationError if the value is not a 32 character
|
19
|
+
# hexadecimal MD5 hash.
|
20
|
+
def self.validate(value)
|
21
|
+
unless value.length == 32 &&
|
22
|
+
value.each_char.all? { |char| CHARACTERS.include?(char) }
|
23
|
+
fail ValidationError,
|
24
|
+
"#{value} must be a 32 character hexadecimal MD5 hash"
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
module Types
|
5
|
+
# Internal: Handles validation of tag lists as the values supported by the
|
6
|
+
# Pinboard API.
|
7
|
+
class Tags
|
8
|
+
# The maximum tag length.
|
9
|
+
MAXIMUM_LENGTH = 255
|
10
|
+
# Tags cannot have commas.
|
11
|
+
INVALID_CHARACTER = ','.freeze
|
12
|
+
# Tag parameters are separated by spaces.
|
13
|
+
SEPARATOR = ' '.freeze
|
14
|
+
|
15
|
+
# Validate a tags value.
|
16
|
+
#
|
17
|
+
# value - A String containing a single tag or an Array containing many
|
18
|
+
# tags.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
# Raises Types::ValidationError if any tag contains commas or are longer
|
22
|
+
# than 255 characters.
|
23
|
+
def self.validate(value)
|
24
|
+
Array(value).each do |tag|
|
25
|
+
unless tag.length < MAXIMUM_LENGTH && !tag.include?(INVALID_CHARACTER)
|
26
|
+
fail ValidationError,
|
27
|
+
"#{tag} cannot contain commas or be longer than 255 characters"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Convert a tag value to a parameter acceptable to the Pinboard API.
|
34
|
+
#
|
35
|
+
# value - A String containing a single tag or an Array containing many
|
36
|
+
# tags.
|
37
|
+
#
|
38
|
+
# Returns a String containing the tags, space-separated.
|
39
|
+
def self.to_parameter(value)
|
40
|
+
Array(value).map(&:strip).join(SEPARATOR)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Convert a parameter from the Pinboard API to an Array of tags.
|
44
|
+
#
|
45
|
+
# parameter - A String containing space-separated tags.
|
46
|
+
#
|
47
|
+
# Returns an Array of tags.
|
48
|
+
def self.from_parameter(parameter)
|
49
|
+
parameter.split(SEPARATOR)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
module Types
|
5
|
+
# Internal: Handles validation of text values as supported by Pinboard.
|
6
|
+
class Text < Identity
|
7
|
+
# Maximum length of a text value.
|
8
|
+
MAXIMUM_LENGTH = 65_536
|
9
|
+
|
10
|
+
# Validate text.
|
11
|
+
#
|
12
|
+
# value - A String containing the text to validate.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
# Raises Types::ValidationError if the value is longer than 65536
|
16
|
+
# characters.
|
17
|
+
def self.validate(value)
|
18
|
+
unless value.length <= MAXIMUM_LENGTH
|
19
|
+
fail ValidationError,
|
20
|
+
"#{value} cannot be greater than #{MAXIMUM_LENGTH} characters"
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
module Types
|
5
|
+
# Internal: Handles validation of title values as supported by Pinboard.
|
6
|
+
class Title < Identity
|
7
|
+
# Maximum length of a title value.
|
8
|
+
MAXIMUM_LENGTH = 255
|
9
|
+
|
10
|
+
# Validate a title.
|
11
|
+
#
|
12
|
+
# value - A String containing the title to validate.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
# Raises Types::ValidationError if the value is longer than 255
|
16
|
+
# characters.
|
17
|
+
def self.validate(value)
|
18
|
+
unless value.length <= MAXIMUM_LENGTH
|
19
|
+
fail ValidationError,
|
20
|
+
"#{value} cannot be greater than #{MAXIMUM_LENGTH} characters"
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
module Types
|
5
|
+
# Internal: Handles validation of URL values as supported by Pinboard.
|
6
|
+
class URL < Identity
|
7
|
+
# Valid URL schemes.
|
8
|
+
VALID_SCHEMES = %w(http https javascript mailto ftp file feed).freeze
|
9
|
+
|
10
|
+
# Validate a URL.
|
11
|
+
#
|
12
|
+
# value - A String containing the URL to validate.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
# Raises Types::ValidationError if the URL's scheme isn't one of http,
|
16
|
+
# https, javascript, mailto, ftp, file, or feed.
|
17
|
+
def self.validate(value)
|
18
|
+
unless VALID_SCHEMES.include? URI(value).scheme
|
19
|
+
fail ValidationError,
|
20
|
+
"scheme must be one of #{VALID_SCHEMES.join(', ')}"
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
# Handlers for each of the data types in the Pinboard API. See
|
5
|
+
# https://pinboard.in/api/#data
|
6
|
+
module Types
|
7
|
+
# Internal: Raised when given an invalid argument
|
8
|
+
class ValidationError < StandardError; end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Thumbtack
|
4
|
+
# Internal: Wraps API calls related to users.
|
5
|
+
class User
|
6
|
+
# Internal: Creates a new User.
|
7
|
+
#
|
8
|
+
# client - a Thumbtack::Client to communicate with the Pinboard API.
|
9
|
+
def initialize(client)
|
10
|
+
@client = client
|
11
|
+
end
|
12
|
+
|
13
|
+
# Public: Returns the user's secret RSS key for viewing private feeds.
|
14
|
+
def secret
|
15
|
+
@client.get('/user/secret').fetch('result')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: Returns the user's API token for making calls without a password.
|
19
|
+
def api_token
|
20
|
+
@client.get('/user/api_token').fetch('result')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/thumbtack.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# A simple Pinboard API wrapper
|
4
|
+
module Thumbtack
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'date'
|
8
|
+
require 'json'
|
9
|
+
require 'net/http'
|
10
|
+
require 'uri'
|
11
|
+
|
12
|
+
require 'thumbtack/types'
|
13
|
+
require 'thumbtack/types/boolean'
|
14
|
+
require 'thumbtack/types/date'
|
15
|
+
require 'thumbtack/types/date_time'
|
16
|
+
require 'thumbtack/types/identity'
|
17
|
+
require 'thumbtack/types/integer'
|
18
|
+
require 'thumbtack/types/md5'
|
19
|
+
require 'thumbtack/types/tags'
|
20
|
+
require 'thumbtack/types/text'
|
21
|
+
require 'thumbtack/types/title'
|
22
|
+
require 'thumbtack/types/url'
|
23
|
+
require 'thumbtack/specification'
|
24
|
+
require 'thumbtack/post'
|
25
|
+
require 'thumbtack/posts'
|
26
|
+
require 'thumbtack/tags'
|
27
|
+
require 'thumbtack/user'
|
28
|
+
require 'thumbtack/note'
|
29
|
+
require 'thumbtack/note_summary'
|
30
|
+
require 'thumbtack/notes'
|
31
|
+
require 'thumbtack/client'
|
32
|
+
require 'thumbtack/version'
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thumbtack'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
def auth_token
|
7
|
+
File.open(File.expand_path('../auth_token.txt', __FILE__)).read.strip
|
8
|
+
end
|
9
|
+
|
10
|
+
def username
|
11
|
+
auth_token.split(':').first
|
12
|
+
end
|
13
|
+
|
14
|
+
def token
|
15
|
+
auth_token.split(':').last
|
16
|
+
end
|
17
|
+
|
18
|
+
include Thumbtack
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class ClientTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@client = Client.new(username, token)
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_requests_return_parsed_json
|
11
|
+
response = @client.get('/user/api_token')
|
12
|
+
assert_equal({ 'result' => token }, response)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_request_query_parameters
|
16
|
+
response = @client.get('/tags/delete', tag: 'thumbtack-test-query-params')
|
17
|
+
assert_equal({ 'result' => 'done' }, response)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_posts
|
21
|
+
assert_instance_of Posts, @client.posts
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_tags
|
25
|
+
assert_instance_of Tags, @client.tags
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_user
|
29
|
+
assert_instance_of User, @client.user
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_notes
|
33
|
+
assert_instance_of Notes, @client.notes
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class NoteSummaryTest < Minitest::Test
|
6
|
+
def test_from_hash
|
7
|
+
hash = {
|
8
|
+
'id' => '8e5d6964bb810e0050b0',
|
9
|
+
'title' => 'StarCraft beta coming this week!',
|
10
|
+
'hash' => '0c9c30f60cadabd31415',
|
11
|
+
'created_at' => '2010-02-11 03:46:56',
|
12
|
+
'updated_at' => '2010-02-11 03:47:47',
|
13
|
+
'length' => 19,
|
14
|
+
}
|
15
|
+
note = NoteSummary.from_hash(hash)
|
16
|
+
|
17
|
+
assert_equal '8e5d6964bb810e0050b0', note.id
|
18
|
+
assert_equal 'StarCraft beta coming this week!', note.title
|
19
|
+
assert_equal '0c9c30f60cadabd31415', note.hash
|
20
|
+
assert_equal '2010-02-11 03:46:56', note.created_at
|
21
|
+
assert_equal '2010-02-11 03:47:47', note.updated_at
|
22
|
+
assert_equal 19, note.length
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class NoteTest < Minitest::Test
|
6
|
+
def test_from_hash
|
7
|
+
hash = {
|
8
|
+
'id' => '8e5d6964bb810e0050b0',
|
9
|
+
'title' => 'StarCraft beta coming this week!',
|
10
|
+
'hash' => '0c9c30f60cadabd31415',
|
11
|
+
'created_at' => '2010-02-11 03:46:56',
|
12
|
+
'updated_at' => '2010-02-11 03:47:47',
|
13
|
+
'length' => 19,
|
14
|
+
'text' => 'This is a test note'
|
15
|
+
}
|
16
|
+
note = Note.from_hash(hash)
|
17
|
+
|
18
|
+
assert_equal '8e5d6964bb810e0050b0', note.id
|
19
|
+
assert_equal 'StarCraft beta coming this week!', note.title
|
20
|
+
assert_equal '0c9c30f60cadabd31415', note.hash
|
21
|
+
assert_equal '2010-02-11 03:46:56', note.created_at
|
22
|
+
assert_equal '2010-02-11 03:47:47', note.updated_at
|
23
|
+
assert_equal 19, note.length
|
24
|
+
assert_equal 'This is a test note', note.text
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class NotesTest < Minitest::Test
|
6
|
+
def mock_client(url, params, response)
|
7
|
+
client = Minitest::Mock.new
|
8
|
+
client.expect(:get, response, [url, params].compact)
|
9
|
+
client
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_list
|
13
|
+
client = mock_client('/notes/list',
|
14
|
+
nil,
|
15
|
+
{
|
16
|
+
'count' => 2,
|
17
|
+
'notes' => [
|
18
|
+
{
|
19
|
+
'id' => 'cf73bfc02e00edaa1e2b',
|
20
|
+
'title' => 'Paul Graham on Hirin\' The Ladies',
|
21
|
+
'hash' => '0bbca3cba9246bbbda2c',
|
22
|
+
'created_at' => '2011-10-28 13:37:23',
|
23
|
+
'updated_at' => '2011-10-28 13:37:23',
|
24
|
+
'length' => '890',
|
25
|
+
},
|
26
|
+
{
|
27
|
+
'id' => '8e5d6964bb810e0050b0',
|
28
|
+
'title' => 'StarCraft beta coming this week!',
|
29
|
+
'hash' => '0c9c30f60cadabd31415',
|
30
|
+
'created_at' => '2010-02-11 03:46:56',
|
31
|
+
'updated_at' => '2010-02-11 03:47:47',
|
32
|
+
'length' => '153',
|
33
|
+
},
|
34
|
+
]
|
35
|
+
})
|
36
|
+
notes = Notes.new(client)
|
37
|
+
result = notes.list
|
38
|
+
|
39
|
+
assert_equal 2, result.length
|
40
|
+
assert_equal 'cf73bfc02e00edaa1e2b', result[0].id
|
41
|
+
assert_equal '8e5d6964bb810e0050b0', result[1].id
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_list
|
45
|
+
client = mock_client('/notes/8e5d6964bb810e0050b0',
|
46
|
+
nil,
|
47
|
+
{
|
48
|
+
'id' => '8e5d6964bb810e0050b0',
|
49
|
+
'title' => 'StarCraft beta coming this week!',
|
50
|
+
'text' => 'This is a test note',
|
51
|
+
'hash' => '0c9c30f60cadabd31415',
|
52
|
+
'created_at' => '2010-02-11 03:46:56',
|
53
|
+
'updated_at' => '2010-02-11 03:47:47',
|
54
|
+
'length' => 19
|
55
|
+
})
|
56
|
+
notes = Notes.new(client)
|
57
|
+
result = notes.get('8e5d6964bb810e0050b0')
|
58
|
+
assert_equal '8e5d6964bb810e0050b0', result.id
|
59
|
+
assert_equal 19, result.length
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class PostTest < Minitest::Test
|
6
|
+
def test_from_hash
|
7
|
+
hash = {
|
8
|
+
'href' => 'http://example.org',
|
9
|
+
'description' => 'example.org',
|
10
|
+
'extended' => '',
|
11
|
+
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
12
|
+
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
13
|
+
'time' => '2014-06-29T16:57:45Z',
|
14
|
+
'shared' => 'yes',
|
15
|
+
'toread' => 'no',
|
16
|
+
'tags' => 'test123'
|
17
|
+
}
|
18
|
+
post = Post.from_hash(hash)
|
19
|
+
|
20
|
+
assert_equal 'http://example.org', post.href
|
21
|
+
assert_equal 'example.org', post.description
|
22
|
+
assert_equal '', post.extended
|
23
|
+
assert_equal '46ca40b9b92ee0ea1284785a5d2a9b38', post.meta
|
24
|
+
assert_equal 'dab521de65f9250b4cca7383feef67dc', post.hash
|
25
|
+
assert_equal '2014-06-29T16:57:45Z', post.time
|
26
|
+
assert_equal 'yes', post.shared
|
27
|
+
assert_equal 'no', post.toread
|
28
|
+
assert_equal 'test123', post.tags
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class PostsTest < Minitest::Test
|
6
|
+
def mock_client(url, params, response)
|
7
|
+
client = Minitest::Mock.new
|
8
|
+
client.expect(:get, response, [url, params].compact)
|
9
|
+
client
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_update
|
13
|
+
client = mock_client('/posts/update',
|
14
|
+
nil,
|
15
|
+
{ 'update_time' => '2014-06-26T19:01:33Z' })
|
16
|
+
posts = Posts.new(client)
|
17
|
+
|
18
|
+
assert_equal DateTime.new(2014, 6, 26, 19, 1, 33), posts.update
|
19
|
+
client.verify
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_add
|
23
|
+
client = mock_client('/posts/add',
|
24
|
+
{ url: 'http://example.org',
|
25
|
+
description: 'example.org' },
|
26
|
+
{ 'result_code' => 'done' })
|
27
|
+
posts = Posts.new(client)
|
28
|
+
|
29
|
+
assert_equal posts, posts.add('http://example.org', 'example.org')
|
30
|
+
client.verify
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_add_with_tags
|
34
|
+
client = mock_client('/posts/add',
|
35
|
+
{ url: 'http://example.org',
|
36
|
+
description: 'example.org',
|
37
|
+
tags: 'thumbtack test' },
|
38
|
+
{ 'result_code' => 'done' })
|
39
|
+
posts = Posts.new(client)
|
40
|
+
|
41
|
+
assert_equal posts,
|
42
|
+
posts.add('http://example.org', 'example.org', tags: %w(thumbtack test))
|
43
|
+
client.verify
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_delete
|
47
|
+
client = mock_client('/posts/delete',
|
48
|
+
{ url: 'http://example.org' },
|
49
|
+
{ 'result_code' => 'done' })
|
50
|
+
posts = Posts.new(client)
|
51
|
+
|
52
|
+
assert_equal posts, posts.delete('http://example.org')
|
53
|
+
client.verify
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_get
|
57
|
+
client = mock_client('/posts/get',
|
58
|
+
{ url: 'http://example.org' },
|
59
|
+
{
|
60
|
+
'date' => '2014-06-29T16:57:45Z',
|
61
|
+
'user' => 'nwjsmith',
|
62
|
+
'posts' => [{
|
63
|
+
'href' => 'http://example.org',
|
64
|
+
'description' => 'example.org',
|
65
|
+
'extended' => '',
|
66
|
+
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
67
|
+
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
68
|
+
'time' => '2014-06-29T16:57:45Z',
|
69
|
+
'shared' => 'yes',
|
70
|
+
'toread' => 'no',
|
71
|
+
'tags' => 'test123'
|
72
|
+
}]
|
73
|
+
})
|
74
|
+
posts = Posts.new(client)
|
75
|
+
response = posts.get(url: 'http://example.org')
|
76
|
+
|
77
|
+
assert_equal 1, response.size
|
78
|
+
assert_equal 'http://example.org', response.first.href
|
79
|
+
client.verify
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_recent
|
83
|
+
client = mock_client('/posts/recent',
|
84
|
+
{tag: 'webdev'},
|
85
|
+
{
|
86
|
+
'date' => '2014-06-29T16:57:45Z',
|
87
|
+
'user' => 'nwjsmith',
|
88
|
+
'posts' => [{
|
89
|
+
'href' => 'http://example.org',
|
90
|
+
'description' => 'example.org',
|
91
|
+
'extended' => '',
|
92
|
+
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
93
|
+
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
94
|
+
'time' => '2014-06-29T16:57:45Z',
|
95
|
+
'shared' => 'yes',
|
96
|
+
'toread' => 'no',
|
97
|
+
'tags' => 'webdev'
|
98
|
+
}]
|
99
|
+
})
|
100
|
+
posts = Posts.new(client)
|
101
|
+
response = posts.recent(tag: 'webdev')
|
102
|
+
|
103
|
+
assert_equal 1, response.size
|
104
|
+
assert_equal 'http://example.org', response.first.href
|
105
|
+
client.verify
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_all
|
109
|
+
client = mock_client('/posts/all',
|
110
|
+
{tag: 'webdev'},
|
111
|
+
[{
|
112
|
+
'href' => 'http://example.org',
|
113
|
+
'description' => 'example.org',
|
114
|
+
'extended' => '',
|
115
|
+
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
116
|
+
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
117
|
+
'time' => '2014-06-29T16:57:45Z',
|
118
|
+
'shared' => 'yes',
|
119
|
+
'toread' => 'no',
|
120
|
+
'tags' => 'webdev'
|
121
|
+
}])
|
122
|
+
posts = Posts.new(client)
|
123
|
+
response = posts.all(tag: 'webdev')
|
124
|
+
|
125
|
+
assert_equal 1, response.size
|
126
|
+
assert_equal 'http://example.org', response.first.href
|
127
|
+
client.verify
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_suggest
|
131
|
+
client = mock_client('/posts/suggest',
|
132
|
+
{url: 'http://blog.com'},
|
133
|
+
{
|
134
|
+
'popular' => ['blog', 'blogs', 'people', 'writing'],
|
135
|
+
'recommended' => ['blog', 'writing', 'weblog']
|
136
|
+
})
|
137
|
+
posts = Posts.new(client)
|
138
|
+
response = posts.suggest('http://blog.com')
|
139
|
+
|
140
|
+
assert_equal 2, response.size
|
141
|
+
assert_equal 'blog', response[:popular].first
|
142
|
+
assert_equal 'weblog', response[:recommended].last
|
143
|
+
client.verify
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_dates
|
147
|
+
client = mock_client('/posts/dates',
|
148
|
+
{tag: 'argentina'},
|
149
|
+
{
|
150
|
+
'user' => 'user',
|
151
|
+
'tag' => 'argentina',
|
152
|
+
'dates' => {
|
153
|
+
'2010-11-29' => '5',
|
154
|
+
'2010-11-28' => '15',
|
155
|
+
'2010-11-26' => '2',
|
156
|
+
'2010-11-25' => '2',
|
157
|
+
'2010-11-23' => '7',
|
158
|
+
'2010-11-22' => '20',
|
159
|
+
'2010-11-21' => '16',
|
160
|
+
'2010-11-19' => '4'
|
161
|
+
}
|
162
|
+
})
|
163
|
+
posts = Posts.new(client)
|
164
|
+
response = posts.dates(tag: 'argentina')
|
165
|
+
|
166
|
+
assert_equal({
|
167
|
+
Date.new(2010, 11, 29) => 5,
|
168
|
+
Date.new(2010, 11, 28) => 15,
|
169
|
+
Date.new(2010, 11, 26) => 2,
|
170
|
+
Date.new(2010, 11, 25) => 2,
|
171
|
+
Date.new(2010, 11, 23) => 7,
|
172
|
+
Date.new(2010, 11, 22) => 20,
|
173
|
+
Date.new(2010, 11, 21) => 16,
|
174
|
+
Date.new(2010, 11, 19) => 4
|
175
|
+
}, response)
|
176
|
+
client.verify
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class SpecificationTest < Minitest::Test
|
6
|
+
def test_parameters
|
7
|
+
type_handler = Minitest::Mock.new
|
8
|
+
type_handler.expect(:validate, type_handler, ['value'])
|
9
|
+
type_handler.expect(:to_parameter, 'parameterized', ['value'])
|
10
|
+
|
11
|
+
assert_equal({ key: 'parameterized' },
|
12
|
+
Specification.new(key: type_handler).parameters(key: 'value'))
|
13
|
+
type_handler.verify
|
14
|
+
end
|
15
|
+
end
|