redhead 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +445 -0
- data/lib/redhead.rb +37 -0
- data/lib/redhead/header.rb +83 -0
- data/lib/redhead/header_set.rb +134 -0
- data/lib/redhead/redhead_string.rb +62 -0
- data/rakefile +11 -0
- data/test/header_set_spec.rb +344 -0
- data/test/header_spec.rb +270 -0
- data/test/redhead_spec.rb +1 -0
- data/test/redhead_string_spec.rb +114 -0
- data/test/test_helper.rb +1 -0
- metadata +87 -0
data/test/header_spec.rb
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Redhead::Header do
|
4
|
+
before(:each) do
|
5
|
+
@header_name = :a_header_name
|
6
|
+
@header_raw_name = "A-Header-Name"
|
7
|
+
@header_value = "some value"
|
8
|
+
@separator = Redhead::HEADER_NAME_VALUE_SEPARATOR_CHARACTER
|
9
|
+
|
10
|
+
@full_header_string = "#{@header_raw_name}#{@separator} #{@header_value}"
|
11
|
+
|
12
|
+
@header = Redhead::Header.new(:a_header_name, "A-Header-Name", "some value")
|
13
|
+
@header_copy = Redhead::Header.new(:a_header_name, "A-Header-Name", "some value")
|
14
|
+
|
15
|
+
@different_header_raw_name = "An original HEADER name"
|
16
|
+
@header_different_name = Redhead::Header.new(:a_header_name, "An original HEADER name", "something here")
|
17
|
+
|
18
|
+
@default_to_raw = Redhead.to_raw
|
19
|
+
@default_to_key = Redhead.to_key
|
20
|
+
end
|
21
|
+
|
22
|
+
context "as a class" do
|
23
|
+
it "responds to :parse" do
|
24
|
+
Redhead::Header.respond_to?(:parse).should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "self.parse" do
|
28
|
+
it "parses a string and returns a header" do
|
29
|
+
parsed_header = Redhead::Header.parse(@full_header_string)
|
30
|
+
parsed_header.class.should == Redhead::Header
|
31
|
+
parsed_header.should_not be_nil
|
32
|
+
parsed_header.key.should == @header_name
|
33
|
+
parsed_header.value.should == @header_value
|
34
|
+
parsed_header.raw.should == @header_raw_name
|
35
|
+
end
|
36
|
+
|
37
|
+
it "ignores consecutive non-separating characters by default" do
|
38
|
+
parsed_header = Redhead::Header.parse("one very strange!!! header: anything")
|
39
|
+
parsed_header.key.should == :one_very_strange_header
|
40
|
+
end
|
41
|
+
|
42
|
+
it "ignores whitespace around `:` by default" do
|
43
|
+
spaces = []
|
44
|
+
|
45
|
+
20.times do |n|
|
46
|
+
spaces << [" "*rand(n), " "*rand(n)]
|
47
|
+
end
|
48
|
+
|
49
|
+
spaces.each do |before, after|
|
50
|
+
Redhead::Header.parse("#{@header_raw_name}#{before}:#{after}#{@header_value}").key.should == @header_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a given block" do
|
55
|
+
it "uses the given block as to_key" do
|
56
|
+
Redhead::Header.parse(@full_header_string) { :foo }.key.should == :foo
|
57
|
+
end
|
58
|
+
|
59
|
+
# do not set to_key to the given block so that using parse with a block does not prevent any dynamic
|
60
|
+
# calls up the chain to work out what to_raw should be for each object. i.e., Header#to_key should default
|
61
|
+
# to Redhead.to_key, but since each header doesn't know which headerset it's in, HeaderSet needs to pass down
|
62
|
+
# a block to each Header object. if the Header object set the block as to_key, there'd be problems.
|
63
|
+
#
|
64
|
+
# Similarly, Redhead::String.parse(..., &blk) should not set Header#to_key because then there'd never be any
|
65
|
+
# calls up the hierarchy, since an individual Header's @to_key would exist already.
|
66
|
+
it "sets to_key to the given block" do
|
67
|
+
# note: Proc#== bug!
|
68
|
+
to_key = proc { :foo }
|
69
|
+
Redhead::Header.parse(@full_header_string, &to_key).to_key.should_not == to_key
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#key" do
|
76
|
+
it "returns the symbolic header name" do
|
77
|
+
@header.key.should == :a_header_name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#key!" do
|
82
|
+
it "uses #to_key to convert #raw to a header key" do
|
83
|
+
@header.to_key = proc { "test" }
|
84
|
+
@header.key!.should == "test"
|
85
|
+
|
86
|
+
@header.to_key = proc { |x| x.upcase.reverse.gsub("-", "_").to_sym }
|
87
|
+
@header.key!.should == @header_raw_name.upcase.reverse.gsub("-", "_").to_sym
|
88
|
+
end
|
89
|
+
|
90
|
+
it "does not change #key after being called" do
|
91
|
+
@header.to_key = proc { "test" }
|
92
|
+
@header.key.should == @header_name
|
93
|
+
@header.key!.should == "test"
|
94
|
+
@header.key.should_not == "test"
|
95
|
+
@header.key.should == @header_name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#raw" do
|
100
|
+
it "returns the raw header name stored at creation time" do
|
101
|
+
@header.raw.should == @header_raw_name
|
102
|
+
@header.to_raw = proc { "" }
|
103
|
+
@header.raw!.should == ""
|
104
|
+
@header.raw.should == @header_raw_name
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#raw!" do
|
109
|
+
it "uses #to_raw to convert #key to a raw header, ignoring the value of #raw" do
|
110
|
+
@header.to_raw = proc { "test" }
|
111
|
+
@header.raw!.should == "test"
|
112
|
+
|
113
|
+
@header.to_raw = proc { |x| x.to_s.upcase.reverse }
|
114
|
+
@header.raw!.should == @header_name.to_s.upcase.reverse
|
115
|
+
end
|
116
|
+
|
117
|
+
it "does not change #raw after being called" do
|
118
|
+
@header.to_raw = proc { "test" }
|
119
|
+
@header.raw.should == @header_raw_name
|
120
|
+
@header.raw!.should == "test"
|
121
|
+
@header.raw.should_not == "test"
|
122
|
+
@header.raw.should == @header_raw_name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#value" do
|
127
|
+
it "returns the header value" do
|
128
|
+
@header.value.should == @header_value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#value=" do
|
133
|
+
it "sets a new header value" do
|
134
|
+
@header.value = "new value"
|
135
|
+
@header.value.should == "new value"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#to_s" do
|
140
|
+
it "returns <raw><separator> <value>" do
|
141
|
+
@header.to_s.should == @full_header_string
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with a block" do
|
145
|
+
it "uses the given block to convert #key to a raw header, and returns the raw string" do
|
146
|
+
@header.to_s { "test" }.should == "test#{@separator} #{@header_value}"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "does not set a new value for #to_raw" do
|
150
|
+
@header.to_s { "test" }
|
151
|
+
@header.to_s.should_not == "test#{@separator} #{@header_value}"
|
152
|
+
@header.to_s.should == @full_header_string
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "takes an optional argument which specifies the raw header to use, without side-effects" do
|
157
|
+
@header.to_s("test").should_not == @full_header_string
|
158
|
+
@header.to_s("test").should == "test#{@separator} #{@header_value}"
|
159
|
+
@header.to_s.should == @full_header_string
|
160
|
+
@header.to_s.should_not == "test#{@separator} #{@header_value}"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "ignores the given block if there is an explicit raw header name" do
|
164
|
+
@header.to_s("test") { "foo" }.should_not == "foo#{@separator} #{@header_value}"
|
165
|
+
@header.to_s("test") { "foo" }.should == "test#{@separator} #{@header_value}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#==(other)" do
|
170
|
+
it "returns true if self.raw == other.raw && self.value == other.value, otherwise false" do
|
171
|
+
@header_copy.value = "something else entirely"
|
172
|
+
@header.should_not == @header_copy
|
173
|
+
|
174
|
+
# same raw name, same value
|
175
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should == Redhead::Header.new(:a_header_name, "A-Header-Name", "a")
|
176
|
+
|
177
|
+
# same raw name, different value
|
178
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should_not == Redhead::Header.new(:a_header_name, "A-Header-Name", "aaaaaaa")
|
179
|
+
|
180
|
+
# different raw name, same value
|
181
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should_not == Redhead::Header.new(:a_header_name, "A-Header-Nameeeeeeee", "a")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#reversible?" do
|
186
|
+
it "returns true for the defaults" do
|
187
|
+
@header.reversible?.should be_true
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns true if self.to_raw[self.key!] == self.raw, i.e., if we can't recover the current raw header name via to_key(to_raw(current_raw_header_name))" do
|
191
|
+
@header.to_raw[@header.key!].should == @header_raw_name
|
192
|
+
@header.reversible?.should be_true # by default
|
193
|
+
|
194
|
+
@header.to_raw = proc { |x| "1#{x}" }
|
195
|
+
@header.to_key = proc { |x| "2#{x}" }
|
196
|
+
@header.to_raw[@header.key!].should_not == @header_raw_name
|
197
|
+
@header.reversible?.should be_false # :key does not equal 2Key1Key
|
198
|
+
|
199
|
+
@header.to_raw = proc { |x| x.to_s.reverse }
|
200
|
+
@header.to_key = proc { |x| x.reverse.to_sym }
|
201
|
+
@header.to_raw[@header.key!].should == @header_raw_name
|
202
|
+
@header.reversible?.should be_true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#to_raw" do
|
207
|
+
it "returns Redhead.to_raw by default" do
|
208
|
+
# note: Proc#== bug!
|
209
|
+
@header.to_raw.should == @default_to_raw
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "#to_key" do
|
214
|
+
it "returns Redhead.to_key by default" do
|
215
|
+
# note: Proc#== bug!
|
216
|
+
@header.to_key.should == @default_to_key
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "#to_raw=(blk)" do
|
221
|
+
it "sets to_raw to blk" do
|
222
|
+
new_block = proc { }
|
223
|
+
@header.to_raw.should_not == new_block
|
224
|
+
@header.to_raw = new_block
|
225
|
+
@header.to_raw.should == new_block
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#to_key=(blk)" do
|
230
|
+
it "sets to_key to blk" do
|
231
|
+
new_block = proc { "" + "" }
|
232
|
+
@header.to_key.should_not == new_block
|
233
|
+
@header.to_key = new_block
|
234
|
+
@header.to_key.should == new_block
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "#to_s!" do
|
239
|
+
# TODO: this test doesn't do what it should. know what @header.raw! is going to be and use it in this test
|
240
|
+
# instead of relying on @header.raw! in this test itself. better go through all tests and double-check this.
|
241
|
+
it "returns <raw!><separator> <value>" do
|
242
|
+
@header.to_s!.should == "#{@header.raw!}#{@separator} #{@header_value}"
|
243
|
+
end
|
244
|
+
|
245
|
+
context "with a block argument" do
|
246
|
+
it "uses the given block as though it were #to_raw" do
|
247
|
+
@header.to_s! { "testing" }.should == "testing: #{@header_value}"
|
248
|
+
@header.to_s! { |x| x.to_s.upcase.reverse.gsub("_", "-") }.should == "#{@header_raw_name.to_s.upcase.reverse}: #{@header_value}"
|
249
|
+
end
|
250
|
+
|
251
|
+
it "does not leave to_raw as the given block" do
|
252
|
+
@header.to_s! { "testing" }
|
253
|
+
@header.to_raw.should_not == proc { "testing" }
|
254
|
+
@header.to_raw[:random].should_not == "testing"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
it "takes an optional argument specifying the raw header name to use, without side-effects" do
|
259
|
+
@header.to_s!("test").should_not == @full_header_string
|
260
|
+
@header.to_s!("test").should == "test#{@separator} #{@header_value}"
|
261
|
+
@header.to_s!.should == @full_header_string
|
262
|
+
@header.to_s!.should_not == "test#{@separator} #{@header_value}"
|
263
|
+
end
|
264
|
+
|
265
|
+
it "ignores the given block if there is an explicit raw header name" do
|
266
|
+
@header.to_s("test") { "foo" }.should_not == "foo#{@separator} #{@header_value}"
|
267
|
+
@header.to_s("test") { "foo" }.should == "test#{@separator} #{@header_value}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "test_helper"
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Redhead::String do
|
4
|
+
before(:each) do
|
5
|
+
@string_content = "Lorem ipsum dolor sit amet."
|
6
|
+
@string = "A-Header-Value: value\n\n#{@string_content}"
|
7
|
+
@rh_string = Redhead::String[@string]
|
8
|
+
@copy_rh_string = Redhead::String[@string.clone]
|
9
|
+
end
|
10
|
+
|
11
|
+
context "as a class" do
|
12
|
+
describe "self.[]" do
|
13
|
+
it "is equal (==) in result to using .new" do
|
14
|
+
Redhead::String[@string].should == Redhead::String.new(@string)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "self.new" do
|
19
|
+
context "with a given block:" do
|
20
|
+
it "uses the given block as to_key" do
|
21
|
+
Redhead::String.new(@string) { :foo }.headers.first.key.should == :foo
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets the given block as the HeaderSet's to_key" do
|
25
|
+
# note: Proc#== bug!
|
26
|
+
blk = proc { :foo }
|
27
|
+
Redhead::String.new(@string, &blk).headers.to_key.should == blk
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets each individual header's to_key to the given block" do
|
31
|
+
# note: Proc#== bug!
|
32
|
+
blk = proc { :foo }
|
33
|
+
Redhead::String.new(@string, &blk).headers.each { |header| header.to_key.should == blk }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "before any modifications:" do
|
40
|
+
describe "#to_s" do
|
41
|
+
it "returns a proper String instance" do
|
42
|
+
@rh_string.to_s.class.should == String
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is the contents of the header-less string" do
|
46
|
+
@rh_string.to_s.should == @string_content
|
47
|
+
end
|
48
|
+
|
49
|
+
it "is not in fact the same object as its contained string" do
|
50
|
+
@rh_string.to_s.equal?(@string_content).should be_false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#headers" do
|
56
|
+
it "returns a Redhead::HeaderSet object" do
|
57
|
+
@rh_string.headers.is_a?(Redhead::HeaderSet).should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "provides regular String methods" do
|
62
|
+
String.instance_methods(false).each do |m|
|
63
|
+
@rh_string.respond_to?(m).should be_true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "modifies its containing string with bang-methods" do
|
68
|
+
orig = @rh_string.to_s.dup
|
69
|
+
@rh_string.reverse!
|
70
|
+
@rh_string.to_s.should == orig.reverse
|
71
|
+
@rh_string.reverse!
|
72
|
+
|
73
|
+
orig = @rh_string.to_s.dup
|
74
|
+
@rh_string.upcase!
|
75
|
+
@rh_string.to_s.should == orig.upcase
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#==" do
|
79
|
+
it "returns true if the two Redhead strings contain equal headersets (using HeaderSet#==) and the same string content (using String#==)" do
|
80
|
+
@rh_string.should == @rh_string
|
81
|
+
@copy_rh_string.should == @rh_string
|
82
|
+
|
83
|
+
# change the copy
|
84
|
+
@copy_rh_string.headers[:a_header_value] = "something"
|
85
|
+
@other_rh_string = @copy_rh_string
|
86
|
+
|
87
|
+
@rh_string.headers.should_not == @other_rh_string.headers
|
88
|
+
@rh_string.string.should == @other_rh_string.string
|
89
|
+
@rh_string.should_not == @other_rh_string
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe %Q{#headers!(:a => { :raw => "random raw", :key => "random key" })} do
|
94
|
+
it %Q{modifies the header for key :a by calling raw="random raw", and key="random_key"} do
|
95
|
+
header = @rh_string.headers[:a_header_value]
|
96
|
+
header.raw.should_not == "random raw"
|
97
|
+
header.key.should_not == "random key"
|
98
|
+
|
99
|
+
@rh_string.headers!(:a_header_value => { :raw => "random raw", :key => "random key" })
|
100
|
+
header.raw.should == "random raw"
|
101
|
+
header.key.should == "random key"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "ignores keys with no matching header" do
|
105
|
+
expect { @rh_string.headers!(:lorem_ipsum_dolor_sit_amettttt => {}) }.to_not raise_error
|
106
|
+
end
|
107
|
+
|
108
|
+
it "returns only the changed headers" do
|
109
|
+
@rh_string.headers!(:lorem_ipsum_dolor_sit_amet => {}).empty?.should be_true
|
110
|
+
@rh_string.headers!(:a_header_value => {}).empty?.should_not be_true
|
111
|
+
@rh_string.headers!(:a_header_value => {}).to_a.length.should == 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "redhead"
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redhead
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Prescott
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-04-22 00:00:00.000000000 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: &73758240 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *73758240
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: &73758020 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *73758020
|
37
|
+
description: String header metadata.
|
38
|
+
email:
|
39
|
+
- adam@aprescott.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- lib/redhead/header.rb
|
45
|
+
- lib/redhead/redhead_string.rb
|
46
|
+
- lib/redhead/header_set.rb
|
47
|
+
- lib/redhead.rb
|
48
|
+
- test/redhead_spec.rb
|
49
|
+
- test/redhead_string_spec.rb
|
50
|
+
- test/test_helper.rb
|
51
|
+
- test/header_set_spec.rb
|
52
|
+
- test/header_spec.rb
|
53
|
+
- LICENSE
|
54
|
+
- Gemfile
|
55
|
+
- rakefile
|
56
|
+
- README.md
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: https://github.com/aprescott/redhead
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.6.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: String header metadata.
|
82
|
+
test_files:
|
83
|
+
- test/redhead_spec.rb
|
84
|
+
- test/redhead_string_spec.rb
|
85
|
+
- test/test_helper.rb
|
86
|
+
- test/header_set_spec.rb
|
87
|
+
- test/header_spec.rb
|