thumbtack 1.1.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/thumbtack.rb +3 -3
- data/lib/thumbtack/adapters/basic_adapter.rb +31 -6
- data/lib/thumbtack/client.rb +3 -2
- data/lib/thumbtack/hash_to_digest.rb +5 -4
- data/lib/thumbtack/note.rb +15 -15
- data/lib/thumbtack/note_summary.rb +14 -14
- data/lib/thumbtack/notes.rb +1 -1
- data/lib/thumbtack/post.rb +14 -14
- data/lib/thumbtack/posts.rb +11 -11
- data/lib/thumbtack/specification.rb +1 -1
- data/lib/thumbtack/suggestion.rb +3 -3
- data/lib/thumbtack/symbolize_keys.rb +1 -1
- data/lib/thumbtack/tags.rb +1 -1
- data/lib/thumbtack/types/boolean.rb +2 -2
- data/lib/thumbtack/types/date.rb +1 -1
- data/lib/thumbtack/types/identity.rb +1 -1
- data/lib/thumbtack/types/integer.rb +1 -1
- data/lib/thumbtack/types/length_validation.rb +3 -3
- data/lib/thumbtack/types/md5.rb +4 -4
- data/lib/thumbtack/types/range_validation.rb +3 -3
- data/lib/thumbtack/types/tags.rb +7 -7
- data/lib/thumbtack/types/text.rb +1 -1
- data/lib/thumbtack/types/{date_time.rb → time.rb} +13 -13
- data/lib/thumbtack/types/title.rb +1 -1
- data/lib/thumbtack/types/url.rb +4 -4
- data/lib/thumbtack/user.rb +1 -1
- data/lib/thumbtack/version.rb +2 -2
- data/test/test_helper.rb +7 -4
- data/test/thumbtack/client_test.rb +1 -1
- data/test/thumbtack/integration/basic_adapter_test.rb +2 -2
- data/test/thumbtack/note_summary_test.rb +3 -3
- data/test/thumbtack/note_test.rb +3 -3
- data/test/thumbtack/notes_test.rb +1 -1
- data/test/thumbtack/post_test.rb +3 -3
- data/test/thumbtack/posts_test.rb +24 -46
- data/test/thumbtack/specification_test.rb +3 -2
- data/test/thumbtack/suggestion_test.rb +5 -5
- data/test/thumbtack/tags_test.rb +1 -9
- data/test/thumbtack/types/boolean_test.rb +1 -1
- data/test/thumbtack/types/date_test.rb +1 -1
- data/test/thumbtack/types/identity_test.rb +1 -1
- data/test/thumbtack/types/integer_test.rb +1 -1
- data/test/thumbtack/types/md5_test.rb +1 -1
- data/test/thumbtack/types/tags_test.rb +3 -3
- data/test/thumbtack/types/text_test.rb +1 -1
- data/test/thumbtack/types/time_test.rb +32 -0
- data/test/thumbtack/types/title_test.rb +1 -1
- data/test/thumbtack/types/url_test.rb +1 -1
- data/test/thumbtack/user_test.rb +1 -1
- metadata +37 -39
- data/test/thumbtack/types/date_time_test.rb +0 -33
data/lib/thumbtack/types/date.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
@@ -19,8 +19,8 @@ module Thumbtack
|
|
19
19
|
# if the value is not less or equal to the maximum length
|
20
20
|
def self.validate(value, maximum_length)
|
21
21
|
unless value.length <= maximum_length
|
22
|
-
|
23
|
-
|
22
|
+
raise ValidationError,
|
23
|
+
"#{value} cannot be greater than #{maximum_length} characters"
|
24
24
|
end
|
25
25
|
self
|
26
26
|
end
|
data/lib/thumbtack/types/md5.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
@@ -9,7 +9,7 @@ module Thumbtack
|
|
9
9
|
# The length of an MD5 value
|
10
10
|
LENGTH = 32
|
11
11
|
# The valid characters in an MD5 value
|
12
|
-
CHARACTERS = '0123456789abcdf'
|
12
|
+
CHARACTERS = '0123456789abcdf'
|
13
13
|
|
14
14
|
# Validate a string is a valid MD5 parameter
|
15
15
|
#
|
@@ -22,8 +22,8 @@ module Thumbtack
|
|
22
22
|
# if the value is not a 32 character hexadecimal MD5 hash
|
23
23
|
def self.validate(value)
|
24
24
|
unless valid_md5?(value)
|
25
|
-
|
26
|
-
|
25
|
+
raise ValidationError,
|
26
|
+
"#{value} must be a 32 character hexadecimal MD5 hash"
|
27
27
|
end
|
28
28
|
self
|
29
29
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
@@ -22,8 +22,8 @@ module Thumbtack
|
|
22
22
|
# if the value is not within the range
|
23
23
|
def self.validate(value, range)
|
24
24
|
unless range.cover?(value)
|
25
|
-
|
26
|
-
|
25
|
+
raise ValidationError,
|
26
|
+
"#{value} must be between #{range.begin} and #{range.end}"
|
27
27
|
end
|
28
28
|
self
|
29
29
|
end
|
data/lib/thumbtack/types/tags.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
@@ -10,9 +10,9 @@ module Thumbtack
|
|
10
10
|
# The maximum tag length
|
11
11
|
MAXIMUM_LENGTH = 255
|
12
12
|
# Tags cannot have commas
|
13
|
-
INVALID_CHARACTER = ','
|
13
|
+
INVALID_CHARACTER = ','
|
14
14
|
# Tag parameters are separated by spaces
|
15
|
-
SEPARATOR = ' '
|
15
|
+
SEPARATOR = ' '
|
16
16
|
|
17
17
|
# Validate a tags value
|
18
18
|
#
|
@@ -25,10 +25,10 @@ module Thumbtack
|
|
25
25
|
# if any tags contain commas or are longer than 255 characters
|
26
26
|
def self.validate(value)
|
27
27
|
Array(value).each do |tag|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
next if tag_valid?(tag)
|
29
|
+
|
30
|
+
raise ValidationError,
|
31
|
+
"#{tag} cannot contain commas or be longer than 255 characters"
|
32
32
|
end
|
33
33
|
self
|
34
34
|
end
|
data/lib/thumbtack/types/text.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
# Handles conversion and validation of
|
5
|
+
# Handles conversion and validation of Times to parameters supported by
|
6
6
|
# Pinboard
|
7
7
|
#
|
8
8
|
# @api private
|
9
|
-
class
|
9
|
+
class Time
|
10
10
|
# The earliest allowable time
|
11
|
-
EARLIEST = ::
|
11
|
+
EARLIEST = ::Time.new(1, 1, 1, 0, 0, 0, 0)
|
12
12
|
# The latest allowable time
|
13
|
-
LATEST = ::
|
13
|
+
LATEST = ::Time.new(2100, 1, 1, 0, 0, 0, 0)
|
14
14
|
# Pinboard's date time format
|
15
|
-
FORMAT = '%Y-%m-%dT%H:%M:%SZ'
|
15
|
+
FORMAT = '%Y-%m-%dT%H:%M:%SZ'
|
16
16
|
# Pinboard's date time format for notes
|
17
|
-
NOTE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
17
|
+
NOTE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
18
18
|
|
19
19
|
# Validate a time
|
20
20
|
#
|
21
|
-
# @param [
|
21
|
+
# @param [Time] value
|
22
22
|
# The time to validate
|
23
23
|
#
|
24
24
|
# @return [self]
|
@@ -32,7 +32,7 @@ module Thumbtack
|
|
32
32
|
|
33
33
|
# Convert a time to a parameter acceptable to Pinboard
|
34
34
|
#
|
35
|
-
# @param [
|
35
|
+
# @param [Time] value
|
36
36
|
# the time to convert
|
37
37
|
#
|
38
38
|
# @return [String]
|
@@ -46,9 +46,9 @@ module Thumbtack
|
|
46
46
|
# @param [String] parameter
|
47
47
|
# the time formatted yyyy-mm-ddTHH:MM:SSZ
|
48
48
|
#
|
49
|
-
# @return [
|
49
|
+
# @return [Time]
|
50
50
|
def self.deserialize(parameter)
|
51
|
-
::
|
51
|
+
::Time.strptime(parameter, FORMAT)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Convert a parameter from Pinboard's notes to a datetime value
|
@@ -56,9 +56,9 @@ module Thumbtack
|
|
56
56
|
# @param [String] parameter
|
57
57
|
# the time formatted yyyy-mm-dd HH:MM:SS
|
58
58
|
#
|
59
|
-
# @return [
|
59
|
+
# @return [Time]
|
60
60
|
def self.deserialize_from_note(parameter)
|
61
|
-
::
|
61
|
+
::Time.strptime(parameter, NOTE_FORMAT)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
data/lib/thumbtack/types/url.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
@@ -7,7 +7,7 @@ module Thumbtack
|
|
7
7
|
# @api private
|
8
8
|
class URL < Identity
|
9
9
|
# Valid URL schemes
|
10
|
-
VALID_SCHEMES = %w
|
10
|
+
VALID_SCHEMES = %w[http https javascript mailto ftp file feed].freeze
|
11
11
|
|
12
12
|
# Validate a URL
|
13
13
|
#
|
@@ -21,8 +21,8 @@ module Thumbtack
|
|
21
21
|
# file, or feed
|
22
22
|
def self.validate(value)
|
23
23
|
unless VALID_SCHEMES.include? URI(value).scheme
|
24
|
-
|
25
|
-
|
24
|
+
raise ValidationError,
|
25
|
+
"scheme must be one of #{VALID_SCHEMES.join(', ')}"
|
26
26
|
end
|
27
27
|
self
|
28
28
|
end
|
data/lib/thumbtack/user.rb
CHANGED
data/lib/thumbtack/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if ENV.fetch('COVERAGE', false)
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start { add_filter 'test/' }
|
6
|
+
end
|
4
7
|
|
5
8
|
require 'thumbtack'
|
6
9
|
require 'minitest/autorun'
|
@@ -17,4 +20,4 @@ def mock_client_action(url, params)
|
|
17
20
|
client
|
18
21
|
end
|
19
22
|
|
20
|
-
include Thumbtack
|
23
|
+
Minitest::Test.include Thumbtack
|
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
5
5
|
module Integration
|
6
6
|
class BasicAdapterTest < Minitest::Test
|
7
7
|
def setup
|
8
|
-
path = File.expand_path('
|
8
|
+
path = File.expand_path('../../auth_token.txt', __dir__)
|
9
9
|
auth_token = File.open(path).read.strip
|
10
10
|
@username, @token = auth_token.split(':')
|
11
11
|
@adapter = Adapters::BasicAdapter.new(@username, @token)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
@@ -17,8 +17,8 @@ class NoteSummaryTest < Minitest::Test
|
|
17
17
|
assert_equal '8e5d6964bb810e0050b0', note.id
|
18
18
|
assert_equal 'StarCraft beta coming this week!', note.title
|
19
19
|
assert_equal '0c9c30f60cadabd31415', note.digest
|
20
|
-
assert_equal
|
21
|
-
assert_equal
|
20
|
+
assert_equal Time.new(2010, 2, 11, 3, 46, 56), note.created_at
|
21
|
+
assert_equal Time.new(2010, 2, 11, 3, 47, 47), note.updated_at
|
22
22
|
assert_equal 19, note.length
|
23
23
|
end
|
24
24
|
end
|
data/test/thumbtack/note_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
@@ -18,8 +18,8 @@ class NoteTest < Minitest::Test
|
|
18
18
|
assert_equal '8e5d6964bb810e0050b0', note.id
|
19
19
|
assert_equal 'StarCraft beta coming this week!', note.title
|
20
20
|
assert_equal '0c9c30f60cadabd31415', note.digest
|
21
|
-
assert_equal
|
22
|
-
assert_equal
|
21
|
+
assert_equal Time.new(2010, 2, 11, 3, 46, 56), note.created_at
|
22
|
+
assert_equal Time.new(2010, 2, 11, 3, 47, 47), note.updated_at
|
23
23
|
assert_equal 19, note.length
|
24
24
|
assert_equal 'This is a test note', note.text
|
25
25
|
end
|
data/test/thumbtack/post_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
@@ -22,9 +22,9 @@ class PostTest < Minitest::Test
|
|
22
22
|
assert_equal '', post.extended
|
23
23
|
assert_equal '46ca40b9b92ee0ea1284785a5d2a9b38', post.meta
|
24
24
|
assert_equal 'dab521de65f9250b4cca7383feef67dc', post.digest
|
25
|
-
assert_equal
|
25
|
+
assert_equal Time.new(2014, 6, 29, 16, 57, 45), post.time
|
26
26
|
assert_equal true, post.shared
|
27
27
|
assert_equal false, post.toread
|
28
|
-
assert_equal %w
|
28
|
+
assert_equal %w[test123 another], post.tags
|
29
29
|
end
|
30
30
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
@@ -11,7 +11,7 @@ class PostsTest < Minitest::Test
|
|
11
11
|
)
|
12
12
|
posts = Posts.new(client)
|
13
13
|
|
14
|
-
assert_equal
|
14
|
+
assert_equal Time.new(2014, 6, 26, 19, 1, 33), posts.update
|
15
15
|
client.verify
|
16
16
|
end
|
17
17
|
|
@@ -40,7 +40,7 @@ class PostsTest < Minitest::Test
|
|
40
40
|
posts.add(
|
41
41
|
'http://example.org',
|
42
42
|
'example.org',
|
43
|
-
tags: %w
|
43
|
+
tags: %w[thumbtack test]
|
44
44
|
)
|
45
45
|
client.verify
|
46
46
|
end
|
@@ -62,17 +62,7 @@ class PostsTest < Minitest::Test
|
|
62
62
|
{ url: 'http://example.org' },
|
63
63
|
'date' => '2014-06-29T16:57:45Z',
|
64
64
|
'user' => 'nwjsmith',
|
65
|
-
'posts' => [
|
66
|
-
'href' => 'http://example.org',
|
67
|
-
'description' => 'example.org',
|
68
|
-
'extended' => '',
|
69
|
-
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
70
|
-
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
71
|
-
'time' => '2014-06-29T16:57:45Z',
|
72
|
-
'shared' => 'yes',
|
73
|
-
'toread' => 'no',
|
74
|
-
'tags' => 'test123'
|
75
|
-
}]
|
65
|
+
'posts' => [example_post_hash]
|
76
66
|
)
|
77
67
|
posts = Posts.new(client)
|
78
68
|
response = posts.get(url: 'http://example.org')
|
@@ -88,17 +78,7 @@ class PostsTest < Minitest::Test
|
|
88
78
|
{ tag: 'webdev' },
|
89
79
|
'date' => '2014-06-29T16:57:45Z',
|
90
80
|
'user' => 'nwjsmith',
|
91
|
-
'posts' => [
|
92
|
-
'href' => 'http://example.org',
|
93
|
-
'description' => 'example.org',
|
94
|
-
'extended' => '',
|
95
|
-
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
96
|
-
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
97
|
-
'time' => '2014-06-29T16:57:45Z',
|
98
|
-
'shared' => 'yes',
|
99
|
-
'toread' => 'no',
|
100
|
-
'tags' => 'webdev'
|
101
|
-
}]
|
81
|
+
'posts' => [example_post_hash]
|
102
82
|
)
|
103
83
|
posts = Posts.new(client)
|
104
84
|
response = posts.recent(tag: 'webdev')
|
@@ -112,19 +92,7 @@ class PostsTest < Minitest::Test
|
|
112
92
|
client = mock_client_get(
|
113
93
|
'/posts/all',
|
114
94
|
{ tag: 'webdev' },
|
115
|
-
[
|
116
|
-
{
|
117
|
-
'href' => 'http://example.org',
|
118
|
-
'description' => 'example.org',
|
119
|
-
'extended' => '',
|
120
|
-
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
121
|
-
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
122
|
-
'time' => '2014-06-29T16:57:45Z',
|
123
|
-
'shared' => 'yes',
|
124
|
-
'toread' => 'no',
|
125
|
-
'tags' => 'webdev'
|
126
|
-
}
|
127
|
-
]
|
95
|
+
[example_post_hash]
|
128
96
|
)
|
129
97
|
posts = Posts.new(client)
|
130
98
|
response = posts.all(tag: 'webdev')
|
@@ -139,8 +107,8 @@ class PostsTest < Minitest::Test
|
|
139
107
|
'/posts/suggest',
|
140
108
|
{ url: 'http://blog.com' },
|
141
109
|
[
|
142
|
-
{ 'popular' => %w
|
143
|
-
{ 'recommended' => %w
|
110
|
+
{ 'popular' => %w[blog blogs people] },
|
111
|
+
{ 'recommended' => %w[blog writing weblog] }
|
144
112
|
]
|
145
113
|
)
|
146
114
|
posts = Posts.new(client)
|
@@ -159,10 +127,7 @@ class PostsTest < Minitest::Test
|
|
159
127
|
'tag' => 'argentina',
|
160
128
|
'dates' => {
|
161
129
|
'2010-11-29' => '5',
|
162
|
-
'2010-11-28' => '15',
|
163
|
-
'2010-11-26' => '2',
|
164
130
|
'2010-11-25' => '2',
|
165
|
-
'2010-11-23' => '7',
|
166
131
|
'2010-11-22' => '20',
|
167
132
|
'2010-11-21' => '16',
|
168
133
|
'2010-11-19' => '4'
|
@@ -174,10 +139,7 @@ class PostsTest < Minitest::Test
|
|
174
139
|
assert_equal(
|
175
140
|
{
|
176
141
|
Date.new(2010, 11, 29) => 5,
|
177
|
-
Date.new(2010, 11, 28) => 15,
|
178
|
-
Date.new(2010, 11, 26) => 2,
|
179
142
|
Date.new(2010, 11, 25) => 2,
|
180
|
-
Date.new(2010, 11, 23) => 7,
|
181
143
|
Date.new(2010, 11, 22) => 20,
|
182
144
|
Date.new(2010, 11, 21) => 16,
|
183
145
|
Date.new(2010, 11, 19) => 4
|
@@ -186,4 +148,20 @@ class PostsTest < Minitest::Test
|
|
186
148
|
)
|
187
149
|
client.verify
|
188
150
|
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def example_post_hash
|
155
|
+
{
|
156
|
+
'href' => 'http://example.org',
|
157
|
+
'description' => 'example.org',
|
158
|
+
'extended' => '',
|
159
|
+
'meta' => '46ca40b9b92ee0ea1284785a5d2a9b38',
|
160
|
+
'hash' => 'dab521de65f9250b4cca7383feef67dc',
|
161
|
+
'time' => '2014-06-29T16:57:45Z',
|
162
|
+
'shared' => 'yes',
|
163
|
+
'toread' => 'no',
|
164
|
+
'tags' => 'webdev'
|
165
|
+
}
|
166
|
+
end
|
189
167
|
end
|