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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/lib/thumbtack/client.rb +70 -0
  3. data/lib/thumbtack/note.rb +35 -0
  4. data/lib/thumbtack/note_summary.rb +35 -0
  5. data/lib/thumbtack/notes.rb +26 -0
  6. data/lib/thumbtack/post.rb +37 -0
  7. data/lib/thumbtack/posts.rb +186 -0
  8. data/lib/thumbtack/specification.rb +31 -0
  9. data/lib/thumbtack/tags.rb +45 -0
  10. data/lib/thumbtack/types/boolean.rb +52 -0
  11. data/lib/thumbtack/types/date.rb +47 -0
  12. data/lib/thumbtack/types/date_time.rb +49 -0
  13. data/lib/thumbtack/types/identity.rb +26 -0
  14. data/lib/thumbtack/types/integer.rb +27 -0
  15. data/lib/thumbtack/types/md5.rb +30 -0
  16. data/lib/thumbtack/types/tags.rb +53 -0
  17. data/lib/thumbtack/types/text.rb +26 -0
  18. data/lib/thumbtack/types/title.rb +26 -0
  19. data/lib/thumbtack/types/url.rb +26 -0
  20. data/lib/thumbtack/types.rb +10 -0
  21. data/lib/thumbtack/user.rb +23 -0
  22. data/lib/thumbtack/version.rb +6 -0
  23. data/lib/thumbtack.rb +32 -0
  24. data/test/test_helper.rb +18 -0
  25. data/test/thumbtack/client_test.rb +35 -0
  26. data/test/thumbtack/note_summary_test.rb +24 -0
  27. data/test/thumbtack/note_test.rb +26 -0
  28. data/test/thumbtack/notes_test.rb +61 -0
  29. data/test/thumbtack/post_test.rb +30 -0
  30. data/test/thumbtack/posts_test.rb +178 -0
  31. data/test/thumbtack/specification_test.rb +15 -0
  32. data/test/thumbtack/tags_test.rb +56 -0
  33. data/test/thumbtack/types/boolean_test.rb +28 -0
  34. data/test/thumbtack/types/date_test.rb +27 -0
  35. data/test/thumbtack/types/date_time_test.rb +27 -0
  36. data/test/thumbtack/types/identity_test.rb +18 -0
  37. data/test/thumbtack/types/integer_test.rb +26 -0
  38. data/test/thumbtack/types/md5_test.rb +28 -0
  39. data/test/thumbtack/types/tags_test.rb +29 -0
  40. data/test/thumbtack/types/text_test.rb +22 -0
  41. data/test/thumbtack/types/title_test.rb +22 -0
  42. data/test/thumbtack/types/url_test.rb +23 -0
  43. data/test/thumbtack/user_test.rb +29 -0
  44. 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
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module Thumbtack
4
+ # Gem version
5
+ VERSION = '0.0.1'.freeze
6
+ 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'
@@ -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