thumbtack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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