api_hammer 0.19.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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