api_hammer 0.19.0 → 0.19.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43a33c5f9ae38cb2f9bdc1fa75f16c9bbb58abc228ae400d1321f90872dc09e6
4
- data.tar.gz: c69e131b3dc28183e32f1cc5a601f38bdb7cd82a8493e0b854818e66c8f9215d
3
+ metadata.gz: 822c3220d1b6c07c850f3b0c66a5f18c6026bfd6415b059ff3c18569af48939b
4
+ data.tar.gz: 3ef1009398f37e4322809a381ccaa23072e3dbb2a32396012ba4f6754ec81d8d
5
5
  SHA512:
6
- metadata.gz: a581e28995ffdeee7f712d9bc743b77db7deca57748267cfbc17e2fb0bf481542facf6a5d511379ed5d8c9291ccb57f4539021eb1e0951834872da6754cdd1bb
7
- data.tar.gz: a1fada15803bcb03ba0745c1c46bdd062845b9c511d792d48795a67271ccac78203106a9e9e955e4aad29fad9ba950b5430db51e2c2f472431e9864358a0bfc1
6
+ metadata.gz: 87b589dc7d2228051c011483ac37738f32b82d2761d6a43b72a86cad0711ce214126657fee707ff3a2ef3d1f872f58e8b664be0786cfa1df4f4791cbb0b5940b
7
+ data.tar.gz: 61f839239d5997277a7ea88e47b20109b6fd2bb0ee81e54520da2f784088a592f8c3d35d91108455efd1b93a331849ccda861077ce884f9c1e94ea7682b1c73c
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # ApiHammer
2
2
 
3
- [![Build Status](https://travis-ci.org/notEthan/api_hammer.svg?branch=master)](https://travis-ci.org/notEthan/api_hammer)
4
-
5
3
  a collection of little tools I have used when creating APIs. these are generally too small to have their own
6
4
  library, so have been collected here.
7
5
 
data/api_hammer.gemspec CHANGED
@@ -13,27 +13,27 @@ Gem::Specification.new do |spec|
13
13
  'is one large tool.'
14
14
  spec.homepage = 'https://github.com/notEthan/api_hammer'
15
15
  spec.license = 'MIT'
16
-
17
- spec.files = `git ls-files -z`.split("\x0") - ['.gitignore']
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = `git ls-files -z test`.split("\x0") + [
20
- '.simplecov',
21
- ]
16
+ spec.files = [
17
+ *%w(
18
+ .yardopts
19
+ CHANGELOG.md
20
+ LICENSE.txt
21
+ README.md
22
+ api_hammer.gemspec
23
+ bin/hc
24
+ ),
25
+ *Dir['lib/**/*'],
26
+ ].reject { |f| File.lstat(f).ftype == 'directory' }
27
+ spec.bindir = 'bin'
28
+ spec.executables = ['hc']
22
29
  spec.require_paths = ['lib']
23
30
 
24
31
  spec.add_dependency 'rack'
25
- spec.add_dependency 'faraday'
32
+ spec.add_dependency 'faraday', '~> 1.0'
26
33
  spec.add_dependency 'term-ansicolor'
27
34
  spec.add_dependency 'json'
28
35
  spec.add_dependency 'json_pure'
29
36
  spec.add_dependency 'addressable'
30
37
  spec.add_dependency 'coderay'
31
38
  spec.add_dependency 'i18n'
32
- spec.add_development_dependency 'rake'
33
- spec.add_development_dependency 'rack-test'
34
- spec.add_development_dependency 'minitest'
35
- spec.add_development_dependency 'minitest-reporters'
36
- spec.add_development_dependency 'yard'
37
- spec.add_development_dependency 'simplecov'
38
- spec.add_development_dependency 'actionpack'
39
39
  end
@@ -82,7 +82,7 @@ module ApiHammer
82
82
  end
83
83
  begin
84
84
  JSON.generate([body])
85
- rescue Encoding::UndefinedConversionError
85
+ rescue Encoding::UndefinedConversionError, JSON::GeneratorError
86
86
  # if updating by content-type didn't do it, try UTF8 since JSON wants that - but only
87
87
  # if it seems to be valid utf8.
88
88
  # don't try utf8 if the response content-type indicated something else.
@@ -1,3 +1,5 @@
1
+ require 'strscan'
2
+
1
3
  module ApiHammer
2
4
  # parses attributes out of content type header
3
5
  class ContentTypeAttrs
@@ -1,3 +1,3 @@
1
1
  module ApiHammer
2
- VERSION = "0.19.0"
2
+ VERSION = "0.19.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_hammer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-01 00:00:00.000000000 Z
11
+ date: 2024-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: faraday
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: term-ansicolor
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -122,104 +122,6 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: rake
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rack-test
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: minitest
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: minitest-reporters
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: yard
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: simplecov
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: actionpack
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
125
  description: actually a set of small API-related tools. very much unlike a hammer
224
126
  at all, which is one large tool.
225
127
  email:
@@ -229,18 +131,12 @@ executables:
229
131
  extensions: []
230
132
  extra_rdoc_files: []
231
133
  files:
232
- - ".simplecov"
233
- - ".travis.yml"
234
134
  - ".yardopts"
235
135
  - CHANGELOG.md
236
- - Gemfile
237
136
  - LICENSE.txt
238
137
  - README.md
239
- - Rakefile.rb
240
138
  - api_hammer.gemspec
241
139
  - bin/hc
242
- - gemfiles/Gemfile_rack_1
243
- - gemfiles/Gemfile_rack_2
244
140
  - lib/api_hammer.rb
245
141
  - lib/api_hammer/body.rb
246
142
  - lib/api_hammer/content_type_attrs.rb
@@ -275,21 +171,11 @@ files:
275
171
  - lib/logstash/filters/request_bodies_parsed.rb
276
172
  - lib/logstash/filters/ruby_logger.rb
277
173
  - lib/logstash/filters/sidekiq.rb
278
- - test/check_required_params_test.rb
279
- - test/faraday_request_logger_test.rb
280
- - test/halt_test.rb
281
- - test/helper.rb
282
- - test/public_instance_exec_test.rb
283
- - test/request_logger_test.rb
284
- - test/show_text_exceptions_test.rb
285
- - test/trailing_newline_test.rb
286
- - test/weblink_test.rb
287
- - test/ycomb_test.rb
288
174
  homepage: https://github.com/notEthan/api_hammer
289
175
  licenses:
290
176
  - MIT
291
177
  metadata: {}
292
- post_install_message:
178
+ post_install_message:
293
179
  rdoc_options: []
294
180
  require_paths:
295
181
  - lib
@@ -304,20 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
190
  - !ruby/object:Gem::Version
305
191
  version: '0'
306
192
  requirements: []
307
- rubyforge_project:
308
- rubygems_version: 2.7.8
309
- signing_key:
193
+ rubygems_version: 3.5.0.dev
194
+ signing_key:
310
195
  specification_version: 4
311
196
  summary: an API tool
312
- test_files:
313
- - test/check_required_params_test.rb
314
- - test/faraday_request_logger_test.rb
315
- - test/halt_test.rb
316
- - test/helper.rb
317
- - test/public_instance_exec_test.rb
318
- - test/request_logger_test.rb
319
- - test/show_text_exceptions_test.rb
320
- - test/trailing_newline_test.rb
321
- - test/weblink_test.rb
322
- - test/ycomb_test.rb
323
- - ".simplecov"
197
+ test_files: []
data/.simplecov DELETED
@@ -1 +0,0 @@
1
- SimpleCov.start
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- rvm:
2
- - 2.2.10
3
- - 2.3.8
4
- - 2.6.1
5
- gemfile:
6
- - gemfiles/Gemfile_rack_1
7
- - gemfiles/Gemfile_rack_2
8
- matrix:
9
- fast_finish: true
10
- exclude:
11
- - rvm: 2.0.0
12
- gemfile: gemfiles/Gemfile_rack_2
13
- script: rake test
data/Gemfile DELETED
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in api_hammer.gemspec
4
- gemspec
5
-
6
- gem 'byebug'
7
- gem 'wwtd'
8
- if RUBY_VERSION == '2.0.0'
9
- gem 'nokogiri', '~> 1.6.8'
10
- end
data/Rakefile.rb DELETED
@@ -1,12 +0,0 @@
1
- require 'rake/testtask'
2
- Rake::TestTask.new do |t|
3
- t.name = 'test'
4
- t.test_files = FileList['test/**/*_test.rb']
5
- t.verbose = true
6
- end
7
- require 'wwtd/tasks'
8
- task 'default' => 'wwtd'
9
-
10
- require 'yard'
11
- YARD::Rake::YardocTask.new do |t|
12
- end
@@ -1,13 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '..'
4
-
5
- gem 'wwtd'
6
-
7
- gem 'rack', '~> 1.0'
8
- gem 'actionpack', '~> 4.0'
9
-
10
- if RUBY_VERSION == '2.0.0'
11
- gem 'nokogiri', '~> 1.6.8'
12
- gem 'public_suffix', '~> 2.0'
13
- end
@@ -1,12 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '..'
4
-
5
- gem 'wwtd'
6
-
7
- gem 'rack', '~> 2.0'
8
- gem 'actionpack', '~> 5.0'
9
-
10
- if RUBY_VERSION == '2.0.0'
11
- gem 'nokogiri', '~> 1.6.8'
12
- end
@@ -1,80 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- class FakeController
5
- def self.rescue_from(*args)
6
- end
7
-
8
- include(ApiHammer::Rails)
9
- attr_accessor :params
10
- end
11
-
12
- # strong parameters doesn't require its dependencies so good
13
- require 'rack/test'
14
- require 'active_support/core_ext/module'
15
- require 'action_controller/metal/strong_parameters'
16
-
17
- [Hash, ActionController::Parameters].each do |params_class|
18
- describe "ApiHammer::Rails#check_required_params with #{params_class}" do
19
- define_method(:controller_with_params) do |params|
20
- FakeController.new.tap { |c| c.params = params_class.new.merge(params) }
21
- end
22
-
23
- describe 'a moderately complex set of checks' do
24
- let(:checks) { [:id, :person => [:name, :height], :lucky_numbers => Array] }
25
-
26
- it 'passes with a moderately complex example' do
27
- c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'}, :lucky_numbers => ['2'])
28
- c.check_required_params(checks)
29
- end
30
-
31
- it 'is missing id' do
32
- c = controller_with_params(:person => {:name => 'hammer', :height => '3'}, :lucky_numbers => ['2'])
33
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
34
- assert_equal({'error_message' => 'id is required but was not provided', 'errors' => {'id' => ['id is required but was not provided']}}, err.body)
35
- end
36
-
37
- it 'is missing person' do
38
- c = controller_with_params(:id => '99', :lucky_numbers => ['2'])
39
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
40
- assert_equal({'error_message' => 'person is required but was not provided', 'errors' => {'person' => ['person is required but was not provided']}}, err.body)
41
- end
42
-
43
- it 'is has the wrong type for person' do
44
- c = controller_with_params(:id => '99', :person => ['hammer', '3'], :lucky_numbers => ['2'])
45
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
46
- assert_equal({'error_message' => 'person must be a Hash', 'errors' => {'person' => ['person must be a Hash']}}, err.body)
47
- end
48
-
49
- it 'is has the wrong type for person with hash check' do
50
- c = controller_with_params(:person => [])
51
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(:person => {:id => Fixnum}) }
52
- assert_equal({'error_message' => 'person must be a Hash', 'errors' => {'person' => ['person must be a Hash']}}, err.body)
53
- end
54
-
55
- it 'is missing person#name' do
56
- c = controller_with_params(:id => '99', :person => {:height => '3'}, :lucky_numbers => ['2'])
57
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
58
- assert_equal({'error_message' => 'person#name is required but was not provided', 'errors' => {'person#name' => ['person#name is required but was not provided']}}, err.body)
59
- end
60
-
61
- it 'is missing lucky_numbers' do
62
- c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'})
63
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
64
- assert_equal({'error_message' => 'lucky_numbers is required but was not provided', 'errors' => {'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
65
- end
66
-
67
- it 'has the wrong type for lucky_numbers' do
68
- c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'}, :lucky_numbers => '2')
69
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
70
- assert_equal({'error_message' => 'lucky_numbers must be a Array', 'errors' => {'lucky_numbers' => ['lucky_numbers must be a Array']}}, err.body)
71
- end
72
-
73
- it 'has multiple problems' do
74
- c = controller_with_params({})
75
- err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
76
- assert_equal({'error_message' => 'id is required but was not provided. person is required but was not provided. lucky_numbers is required but was not provided.', 'errors' => {'id' => ['id is required but was not provided'], 'person' => ['person is required but was not provided'], 'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
77
- end
78
- end
79
- end
80
- end
@@ -1,228 +0,0 @@
1
- # encoding: utf-8
2
-
3
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
4
- require 'helper'
5
- require 'logger'
6
- require 'stringio'
7
-
8
- describe ApiHammer::RequestLogger do
9
- let(:logio) { StringIO.new }
10
- let(:logger) { Logger.new(logio) }
11
-
12
- it 'logs' do
13
- conn = Faraday.new do |f|
14
- f.use ApiHammer::Faraday::RequestLogger, logger
15
- f.use Faraday::Adapter::Rack, proc { |env| [200, {}, []] }
16
- end
17
- conn.get '/'
18
- assert_match(/200/, logio.string)
19
- lines = logio.string.split("\n")
20
- assert_equal(2, lines.size)
21
- assert lines.last =~ /INFO -- : /
22
- json_bit = $'
23
- JSON.parse json_bit # should not raise
24
- end
25
-
26
- {200 => :intense_green, 400 => :intense_yellow, 500 => :intense_red, 300 => :white}.each do |status, color|
27
- it "colors by #{status} status" do
28
- conn = Faraday.new do |f|
29
- f.use ApiHammer::Faraday::RequestLogger, logger
30
- f.use Faraday::Adapter::Rack, proc { |env| [status, {}, []] }
31
- end
32
- conn.get '/'
33
- assert(logio.string.include?(Term::ANSIColor.send(color, status.to_s)))
34
- end
35
- end
36
-
37
- it 'registers by name' do
38
- conn = Faraday.new do |f|
39
- f.request :api_hammer_request_logger, logger
40
- f.use Faraday::Adapter::Rack, proc { |env| [200, {}, []] }
41
- end
42
- conn.get '/'
43
- assert_match(/200/, logio.string)
44
- end
45
-
46
- describe 'response body encoding' do
47
- it 'deals with encoding specified properly by the content type' do
48
- app = proc do |env|
49
- [200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
50
- end
51
- conn = Faraday.new do |f|
52
- f.request :api_hammer_request_logger, logger
53
- f.use Faraday::Adapter::Rack, app
54
- end
55
- conn.get '/'
56
- assert_match(/Jalapeños/, logio.string)
57
- end
58
-
59
- it 'deals content type specifying no encoding' do
60
- app = proc do |env|
61
- [200, {'Content-Type' => 'text/plain; x=y'}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
62
- end
63
- conn = Faraday.new do |f|
64
- f.request :api_hammer_request_logger, logger
65
- f.use Faraday::Adapter::Rack, app
66
- end
67
- conn.get '/'
68
- assert_match(/Jalapeños/, logio.string)
69
- end
70
-
71
- it 'deals with no content type' do
72
- app = proc do |env|
73
- [200, {}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
74
- end
75
- conn = Faraday.new do |f|
76
- f.request :api_hammer_request_logger, logger
77
- f.use Faraday::Adapter::Rack, app
78
- end
79
- conn.get '/'
80
- assert_match(/Jalapeños/, logio.string)
81
- end
82
-
83
- it 'falls back to array of codepoints when encoding is improperly specified by the content type' do
84
- app = proc do |env|
85
- [200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["xx" + [195].pack("C*")]]
86
- end
87
- conn = Faraday.new do |f|
88
- f.request :api_hammer_request_logger, logger
89
- f.use Faraday::Adapter::Rack, app
90
- end
91
- conn.get '/'
92
- assert_match('[120,120,195]', logio.string)
93
- end
94
-
95
- it 'falls back to array of codepoints when encoding is not specified and not valid utf8' do
96
- app = proc do |env|
97
- [200, {}, ["xx" + [195].pack("C*")]]
98
- end
99
- conn = Faraday.new do |f|
100
- f.request :api_hammer_request_logger, logger
101
- f.use Faraday::Adapter::Rack, app
102
- end
103
- conn.get '/'
104
- assert_match('[120,120,195]', logio.string)
105
- end
106
- end
107
- describe 'logging body by content-type' do
108
- {
109
- 'application/octet-stream' => false,
110
- 'image/png' => false,
111
- 'image/png; charset=what' => false,
112
- 'text/plain' => true,
113
- 'text/plain; charset=utf-8' => true,
114
- }.each do |content_type, istext|
115
- it "does #{istext ? '' : 'not'} log body for #{content_type}" do
116
- app = proc do |env|
117
- [200, {'Content-Type' => content_type}, ['data go here']]
118
- end
119
- conn = Faraday.new do |f|
120
- f.request :api_hammer_request_logger, logger
121
- f.use Faraday::Adapter::Rack, app
122
- end
123
- conn.get '/'
124
- assert(logio.string.include?('data go here') == istext)
125
- end
126
- end
127
- end
128
-
129
- describe 'log_bodies' do
130
- it 'does not log bodies when log_bodies is false' do
131
- app = proc do |env|
132
- [200, {'Content-Type' => 'text/plain'}, ['data go here']]
133
- end
134
- conn = Faraday.new do |f|
135
- f.request :api_hammer_request_logger, logger, :log_bodies => false
136
- f.use Faraday::Adapter::Rack, app
137
- end
138
- conn.get '/'
139
- assert(!logio.string.include?('data go here'))
140
- end
141
- end
142
-
143
- describe 'filtering' do
144
- describe 'json response' do
145
- it 'filters' do
146
- app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['{"pin": "foobar", "bar": "baz"}']] }
147
- conn = Faraday.new do |f|
148
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
149
- f.use Faraday::Adapter::Rack, app
150
- end
151
- conn.get '/'
152
- assert_includes(logio.string, %q("body":"{\"pin\": \"[FILTERED]\", \"bar\": \"baz\"}"))
153
- end
154
- it 'filters nested' do
155
- app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['{"object": {"pin": "foobar"}, "bar": "baz"}']] }
156
- conn = Faraday.new do |f|
157
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
158
- f.use Faraday::Adapter::Rack, app
159
- end
160
- conn.get '/'
161
- assert_includes(logio.string, %q("body":"{\"object\": {\"pin\": \"[FILTERED]\"}, \"bar\": \"baz\"}"))
162
- end
163
- it 'filters in array' do
164
- app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['[{"object": [{"pin": ["foobar"]}], "bar": "baz"}]']] }
165
- conn = Faraday.new do |f|
166
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
167
- f.use Faraday::Adapter::Rack, app
168
- end
169
- conn.get '/'
170
- assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}], \"bar\": \"baz\"}]"))
171
- end
172
- end
173
-
174
- describe 'json request' do
175
- it 'filters a json request' do
176
- app = proc { |env| [200, {}, []] }
177
- conn = Faraday.new do |f|
178
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
179
- f.use Faraday::Adapter::Rack, app
180
- end
181
- conn.post '/', '[{"object": [{"pin": ["foobar"]}], "bar": "baz"}]', {'Content-Type' => 'application/json'}
182
- assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}], \"bar\": \"baz\"}]"))
183
- end
184
- end
185
-
186
- describe 'form encoded response' do
187
- it 'filters' do
188
- app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['pin=foobar&bar=baz']] }
189
- conn = Faraday.new do |f|
190
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
191
- f.use Faraday::Adapter::Rack, app
192
- end
193
- conn.get '/'
194
- assert_includes(logio.string, %q("body":"pin=[FILTERED]&bar=baz"))
195
- end
196
- it 'filters nested' do
197
- app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[pin]=foobar&bar=baz']] }
198
- conn = Faraday.new do |f|
199
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
200
- f.use Faraday::Adapter::Rack, app
201
- end
202
- conn.get '/'
203
- assert_includes(logio.string, %q("body":"object[pin]=[FILTERED]&bar=baz"))
204
- end
205
- it 'filters in array' do
206
- app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[][pin][]=foobar&bar=baz']] }
207
- conn = Faraday.new do |f|
208
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
209
- f.use Faraday::Adapter::Rack, app
210
- end
211
- conn.get '/'
212
- assert_includes(logio.string, %q("body":"object[][pin][]=[FILTERED]&bar=baz"))
213
- end
214
- end
215
-
216
- describe 'form encoded request' do
217
- it 'filters a json request' do
218
- app = proc { |env| [200, {}, []] }
219
- conn = Faraday.new do |f|
220
- f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
221
- f.use Faraday::Adapter::Rack, app
222
- end
223
- conn.post '/', 'object[pin]=foobar&bar=baz', {'Content-Type' => 'application/x-www-form-urlencoded'}
224
- assert_includes(logio.string, %q(object[pin]=[FILTERED]&bar=baz))
225
- end
226
- end
227
- end
228
- end
data/test/halt_test.rb DELETED
@@ -1,66 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- class FakeController
5
- def self.rescue_from(*args)
6
- end
7
-
8
- include(ApiHammer::Rails)
9
-
10
- attr_reader :rendered
11
- def render(opts)
12
- @rendered = opts
13
- end
14
- end
15
-
16
- describe 'ApiHammer::Rails#halt' do
17
- it 'raises ApiHammer::Rails::Halt' do
18
- haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt(200, {}) }
19
- assert_equal({}, haltex.body)
20
- assert_equal(200, haltex.render_options[:status])
21
- end
22
- describe 'status-specific halts' do
23
- it 'halts ok' do
24
- haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt_ok({}) }
25
- assert_equal({}, haltex.body)
26
- assert_equal(200, haltex.render_options[:status])
27
- end
28
- it 'halts unprocessable entity' do
29
- haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt_unprocessable_entity({}) }
30
- assert_equal({'errors' => {}}, haltex.body)
31
- assert_equal(422, haltex.render_options[:status])
32
- end
33
- end
34
-
35
- describe 'find_or_halt' do
36
- it 'returns a record if it exists' do
37
- record = Object.new
38
- model = Class.new do
39
- define_singleton_method(:where) { |attrs| [record] }
40
- define_singleton_method(:table_name) { 'records' }
41
- end
42
- assert_equal record, FakeController.new.find_or_halt(model, {:id => 'anid'})
43
- end
44
- it 'it halts with 404 if not' do
45
- model = Class.new do
46
- (class << self; self; end).class_eval do
47
- define_method(:where) { |attrs| [] }
48
- define_method(:table_name) { 'record' }
49
- end
50
- end
51
- haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.find_or_halt(model, {:id => 'anid'}) }
52
- assert_equal({'error_message' => 'Unknown record! id: anid', 'errors' => {'record' => ['Unknown record! id: anid']}}, haltex.body)
53
- assert_equal(404, haltex.render_options[:status])
54
- end
55
- end
56
- end
57
-
58
- describe 'ApiHammer::Rails#handle_halt' do
59
- it 'renders the things from the error' do
60
- controller = FakeController.new
61
- haltex = (FakeController.new.halt_unprocessable_entity({}) rescue $!)
62
- controller.handle_halt(haltex)
63
- assert_equal(422, controller.rendered[:status])
64
- assert_equal({'errors' => {}}, controller.rendered[:json])
65
- end
66
- end
data/test/helper.rb DELETED
@@ -1,15 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('../lib', File.dirname(__FILE__)))
2
-
3
- require 'bundler'
4
- Bundler.setup
5
-
6
- require 'simplecov'
7
-
8
- # NO EXPECTATIONS
9
- ENV["MT_NO_EXPECTATIONS"] = ''
10
-
11
- require 'minitest/autorun'
12
- require 'minitest/reporters'
13
- Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
14
-
15
- require 'api_hammer'
@@ -1,43 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- require 'api_hammer/public_instance_exec'
5
-
6
- class Foo
7
- def public_method(arg = :public)
8
- arg
9
- end
10
- protected
11
- def protected_method(arg = :protected)
12
- arg
13
- end
14
- private
15
- def private_method(arg = :private)
16
- arg
17
- end
18
- end
19
-
20
- describe '#public_instance_exec' do
21
- it 'does things' do
22
- foo = Foo.new
23
- assert_equal(:public_exec, foo.public_instance_exec(:public_exec) { |arg| public_method(arg) })
24
- regularex = (foo.protected_method rescue $!)
25
- ex = assert_raises(regularex.class) { foo.public_instance_exec(:protected_exec) { |arg| protected_method(arg) } }
26
- assert_includes(regularex.message, ex.message)
27
- regularex = (foo.private_method rescue $!)
28
- ex = assert_raises(regularex.class) { foo.public_instance_exec(:private_exec) { |arg| private_method(arg) } }
29
- assert_includes(regularex.message, ex.message)
30
- end
31
- end
32
- describe '#public_instance_eval' do
33
- it 'does things' do
34
- foo = Foo.new
35
- assert_equal(:public, foo.public_instance_eval { public_method })
36
- regularex = (foo.protected_method rescue $!)
37
- ex = assert_raises(regularex.class) { foo.public_instance_eval { protected_method } }
38
- assert_includes(regularex.message, ex.message)
39
- regularex = (foo.private_method rescue $!)
40
- ex = assert_raises(regularex.class) { foo.public_instance_eval { private_method } }
41
- assert_includes(regularex.message, ex.message)
42
- end
43
- end
@@ -1,136 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
3
- require 'helper'
4
- require 'logger'
5
- require 'stringio'
6
-
7
- describe ApiHammer::RequestLogger do
8
- let(:logio) { StringIO.new }
9
- let(:logger) { Logger.new(logio) }
10
-
11
- it 'logs' do
12
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, []] }, logger)
13
- app.call(Rack::MockRequest.env_for('/')).last.close
14
- assert_match(/200/, logio.string)
15
- end
16
-
17
- it 'colors by status' do
18
- {200 => :intense_green, 400 => :intense_yellow, 500 => :intense_red, 300 => :white}.each do |status, color|
19
- app = ApiHammer::RequestLogger.new(proc { |env| [status, {}, []] }, logger)
20
- app.call(Rack::MockRequest.env_for('/')).last.close
21
- assert(logio.string.include?(Term::ANSIColor.send(color, status.to_s)))
22
- end
23
- end
24
-
25
- it 'logs id and uuid (json)' do
26
- body = %Q({"uuid": "theuuid", "foo_uuid": "thefoouuid", "id": "theid", "id_for_x": "theidforx", "bar.id": "thebarid", "baz-guid": "bazzz", "bigthing": "#{' ' * 4096}"})
27
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }, logger)
28
- app.call(Rack::MockRequest.env_for('/')).last.close
29
- assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
30
- end
31
-
32
- it 'logs id and uuid (json array)' do
33
- body = %Q([{"uuid": "theuuid", "foo_uuid": "thefoouuid"}, {"id": "theid", "id_for_x": "theidforx"}, {"bar.id": "thebarid", "baz-guid": "bazzz", "bigthing": "#{' ' * 4096}"}])
34
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }, logger)
35
- app.call(Rack::MockRequest.env_for('/')).last.close
36
- assert_match(%q("body_ids":[{"uuid":"theuuid","foo_uuid":"thefoouuid"},{"id":"theid","id_for_x":"theidforx"},{"bar.id":"thebarid","baz-guid":"bazzz"}]), logio.string)
37
- end
38
-
39
- it 'logs id and uuid (form encoded)' do
40
- body = %Q(uuid=theuuid&foo_uuid=thefoouuid&id=theid&id_for_x=theidforx&bar.id=thebarid&baz-guid=bazzz&bigthing=#{' ' * 4096})
41
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/x-www-form-urlencoded; charset=UTF8'}, [body]] }, logger)
42
- app.call(Rack::MockRequest.env_for('/')).last.close
43
- assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
44
- end
45
-
46
- it 'logs not-too-big request response bodies' do
47
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, ['the_response_body']] }, logger)
48
- app.call(Rack::MockRequest.env_for('/', :input => 'the_request_body')).last.close
49
- assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
50
- assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
51
- end
52
-
53
- it 'logs request and response body on error (even if big)' do
54
- app = ApiHammer::RequestLogger.new(proc { |env| [400, {}, ["the_response_body #{' ' * 4096}"]] }, logger)
55
- app.call(Rack::MockRequest.env_for('/', :input => "the_request_body #{' ' * 4096}")).last.close
56
- assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
57
- assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
58
- end
59
-
60
- describe 'filtering' do
61
- describe 'json response' do
62
- it 'filters' do
63
- body = %Q({"pin": "foobar"})
64
- app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
65
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
66
- app.call(Rack::MockRequest.env_for('/')).last.close
67
-
68
- assert_includes(logio.string, %q("body":"{\"pin\": \"[FILTERED]\"}"))
69
- end
70
-
71
- it 'filters unicode' do
72
- body = %Q({"key": "Björn"})
73
- app = proc { |env| [200, {"Content-Type" => 'application/json; charset=utf-8'}, [body]] }
74
- app = ApiHammer::RequestLogger.new(app, logger)
75
- app.call(Rack::MockRequest.env_for('/')).last.close
76
-
77
- assert_includes(logio.string, %q("body":"{\"key\": \"Björn\"}"))
78
- end
79
-
80
- it 'filters nested' do
81
- body = %Q({"object": {"pin": "foobar"}})
82
- app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
83
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
84
- app.call(Rack::MockRequest.env_for('/')).last.close
85
-
86
- assert_includes(logio.string, %q("body":"{\"object\": {\"pin\": \"[FILTERED]\"}}"))
87
- end
88
- it 'filters in array' do
89
- body = %Q([{"object": [{"pin": ["foobar"]}]}])
90
- app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
91
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
92
- app.call(Rack::MockRequest.env_for('/')).last.close
93
-
94
- assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}]}]"))
95
- end
96
- end
97
-
98
- describe 'json request' do
99
- it 'filters a json request' do
100
- app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, []] }, logger, :filter_keys => 'pin')
101
- app.call(Rack::MockRequest.env_for('/', :input => '[{"object": [{"pin": ["foobar"]}]}]', 'CONTENT_TYPE' => 'application/json')).last.close
102
- assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}]}]"))
103
- end
104
- end
105
-
106
- describe('form encoded response') do
107
- it 'filters' do
108
- app = proc { |env| [200, {"Content-Type" => 'application/x-www-form-urlencoded'}, ['pin=foobar']] }
109
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
110
- app.call(Rack::MockRequest.env_for('/')).last.close
111
- assert_includes(logio.string, %q("body":"pin=[FILTERED]"))
112
- end
113
- it 'filters nested' do
114
- app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[pin]=foobar']] }
115
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
116
- app.call(Rack::MockRequest.env_for('/')).last.close
117
- assert_includes(logio.string, %q("body":"object[pin]=[FILTERED]"))
118
- end
119
- it 'filters in array' do
120
- app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[][pin][]=foobar']] }
121
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
122
- app.call(Rack::MockRequest.env_for('/')).last.close
123
- assert_includes(logio.string, %q("body":"object[][pin][]=[FILTERED]"))
124
- end
125
- end
126
-
127
- describe 'form encoded request' do
128
- it 'filters a json request' do
129
- app = proc { |env| [200, {}, []] }
130
- app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
131
- app.call(Rack::MockRequest.env_for('/', :input => 'object[pin]=foobar', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded')).last.close
132
- assert_includes(logio.string, %q(object[pin]=[FILTERED]))
133
- end
134
- end
135
- end
136
- end
@@ -1,29 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- describe ApiHammer::ShowTextExceptions do
5
- it 'lets normal responses through untouched' do
6
- orig_response = [200, {}, []]
7
- app = ApiHammer::ShowTextExceptions.new(proc { |env| orig_response }, {})
8
- app_response = app.call(Rack::MockRequest.env_for('/'))
9
- assert_equal(orig_response, app_response)
10
- end
11
- it '500s' do
12
- app = ApiHammer::ShowTextExceptions.new(proc { |env| raise }, :full_error => true)
13
- assert_equal(500, app.call(Rack::MockRequest.env_for('/')).first)
14
- end
15
- it 'includes the full error' do
16
- app = ApiHammer::ShowTextExceptions.new(proc { |env| raise 'foo' }, :full_error => true)
17
- assert_match(/RuntimeError: foo/, app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
18
- end
19
- it 'does not include the full error' do
20
- app = ApiHammer::ShowTextExceptions.new(proc { |env| raise }, :full_error => false)
21
- assert_equal("Internal Server Error\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
22
- end
23
- it 'logs' do
24
- logio=StringIO.new
25
- app = ApiHammer::ShowTextExceptions.new(proc { |env| raise 'foo' }, :logger => Logger.new(logio))
26
- app.call(Rack::MockRequest.env_for('/'))
27
- assert_match(/RuntimeError: foo/, logio.string)
28
- end
29
- end
@@ -1,24 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- describe ApiHammer::TrailingNewline do
5
- it 'adds a trailing newline when one is missing' do
6
- app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, ["foo"]] })
7
- assert_equal("foo\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
8
- end
9
-
10
- it 'does not add a trailing newline when one is present' do
11
- app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, ["foo\n"]] })
12
- assert_equal("foo\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
13
- end
14
-
15
- it 'does not add a trailing newline when the response is blank' do
16
- app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, []] })
17
- assert_equal([], app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a)
18
- end
19
-
20
- it 'updates Content-Length if present' do
21
- app = ApiHammer::TrailingNewline.new(proc { |env| [200, {'Content-Length' => '3'}, ['foo']] })
22
- assert_equal('4', app.call(Rack::MockRequest.env_for('/'))[1]['Content-Length'])
23
- end
24
- end
data/test/weblink_test.rb DELETED
@@ -1,83 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- describe ApiHammer::Weblink do
5
- describe '#parse_link_value' do
6
- it 'parses link headers' do
7
- examples = [
8
- # one link with some attributes
9
- [ %q(<http://example.com>; rel=foo; title=example; title*="an example"),
10
- 'http://example.com',
11
- {'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
12
- ],
13
- # two links
14
- [ %q(<http://example.com>; rel=foo; title=example; title*="an example", <http://example2.com>; rel=bar),
15
- 'http://example.com',
16
- {'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
17
- 'http://example2.com',
18
- {'rel' => 'bar'},
19
- ],
20
- # spaces
21
- [ %q( <http://example.com> ;rel = foo ;title=example; title*="an example" ),
22
- 'http://example.com',
23
- {'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
24
- ],
25
- # empty returns no links
26
- [''],
27
- ]
28
- examples.each do |example|
29
- link_value = example.shift
30
- links = ApiHammer::Weblink.parse_link_value(link_value)
31
- assert_equal(example.size, links.size * 2)
32
- example.each_slice(2).zip(links).each do |((target_uri, attributes), link)|
33
- assert_equal(Addressable::URI.parse(target_uri), link.target_uri)
34
- assert_equal(attributes, link.attributes)
35
- end
36
- end
37
- end
38
-
39
- it 'gives an absolute uri based on context' do
40
- link = ApiHammer::Weblink.parse_link_value('</bar>; rel=foo', 'http://example.com/foo').first
41
- assert_equal(Addressable::URI.parse('http://example.com/bar'), link.absolute_target_uri)
42
- end
43
-
44
- it 'errors without context, trying to generate an absolute uri' do
45
- link = ApiHammer::Weblink.parse_link_value('</bar>; rel=foo').first
46
- assert_raises(ApiHammer::Weblink::NoContextError) { link.absolute_target_uri }
47
- end
48
-
49
- it 'returns an empty array for nil link header' do
50
- assert_equal([], ApiHammer::Weblink.parse_link_value(nil))
51
- end
52
-
53
- it 'parse errors' do
54
- examples = [
55
- # missing >
56
- %q(<http://example.com),
57
- # missing <
58
- %q(http://example.com>; rel=foo),
59
- # , instead of ;
60
- %q(<http://example.com>, rel=foo),
61
- # non-ptoken characters (\,) unquoted
62
- %q(<http://example.com>; rel=b\\ar; title=example),
63
- %q(<http://example.com>; rel=b,ar; title=example),
64
- ]
65
- examples.each do |example|
66
- assert_raises(ApiHammer::Weblink::ParseError) { ApiHammer::Weblink.parse_link_value(example) }
67
- end
68
- end
69
-
70
- describe '#to_s' do
71
- it 'makes a string' do
72
- link = ApiHammer::Weblink.new('http://example.com', :rel => 'foo', :title => 'example', 'title*' => 'an example')
73
- assert_equal(%q(<http://example.com>; rel="foo"; title="example"; title*="an example"), link.to_s)
74
- end
75
- it 'parses the string to the same values' do
76
- link = ApiHammer::Weblink.new('http://example.com', 'rel' => 'foo', 'title' => 'example', 'title*' => 'an example')
77
- parsed_link = ApiHammer::Weblink.parse_link_value(link.to_s).first
78
- assert_equal(link.target_uri, parsed_link.target_uri)
79
- assert_equal(link.attributes, parsed_link.attributes)
80
- end
81
- end
82
- end
83
- end
data/test/ycomb_test.rb DELETED
@@ -1,13 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
2
- require 'helper'
3
-
4
- require 'api_hammer/ycomb'
5
- describe 'ycomb' do
6
- it 'does the needful' do
7
- length = ycomb do |len|
8
- proc{|list| list == [] ? 0 : 1 + len.call(list[1..-1]) }
9
- end
10
- assert_equal(0, length.call([]))
11
- assert_equal(3, length.call([:a, :b, :c]))
12
- end
13
- end