bubble-wrap 1.2.0 → 1.3.0.osx
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 +8 -8
- data/CHANGELOG.md +4 -2
- data/Gemfile.lock +1 -1
- data/README.md +217 -7
- data/Rakefile +23 -2
- data/lib/bubble-wrap/camera.rb +10 -6
- data/lib/bubble-wrap/core.rb +14 -1
- data/lib/bubble-wrap/ext/motion_project_app.rb +8 -0
- data/lib/bubble-wrap/font.rb +3 -1
- data/lib/bubble-wrap/http.rb +2 -0
- data/lib/bubble-wrap/loader.rb +17 -2
- data/lib/bubble-wrap/location.rb +9 -6
- data/lib/bubble-wrap/media.rb +10 -6
- data/lib/bubble-wrap/test.rb +6 -1
- data/lib/bubble-wrap/ui.rb +5 -2
- data/lib/bubble-wrap/version.rb +2 -7
- data/motion/core.rb +6 -1
- data/motion/core/app.rb +3 -64
- data/motion/core/device.rb +0 -55
- data/motion/core/device/{camera.rb → ios/camera.rb} +0 -0
- data/motion/core/device/{camera_wrapper.rb → ios/camera_wrapper.rb} +0 -0
- data/motion/core/device/ios/screen.rb +75 -0
- data/motion/core/device/osx/screen.rb +18 -0
- data/motion/core/device/screen.rb +1 -69
- data/motion/core/ios/app.rb +71 -0
- data/motion/core/ios/device.rb +59 -0
- data/motion/core/osx/app.rb +15 -0
- data/motion/core/osx/device.rb +6 -0
- data/motion/core/string.rb +3 -2
- data/motion/http.rb +0 -364
- data/motion/http/query.rb +367 -0
- data/motion/http/response.rb +32 -0
- data/motion/test_suite_delegate.rb +58 -0
- data/motion/ui/ui_alert_view.rb +169 -0
- data/motion/ui/ui_bar_button_item.rb +55 -53
- data/motion/util/constants.rb +34 -32
- data/samples/alert/.gitignore +16 -0
- data/samples/alert/Gemfile +3 -0
- data/samples/alert/Rakefile +10 -0
- data/samples/alert/app/app_delegate.rb +8 -0
- data/samples/alert/app/controllers/alert_view_controller.rb +74 -0
- data/samples/alert/resources/Default-568h@2x.png +0 -0
- data/samples/alert/spec/main_spec.rb +9 -0
- data/samples/media/.gitignore +16 -0
- data/samples/media/Rakefile +11 -0
- data/samples/media/app/app_delegate.rb +8 -0
- data/samples/media/app/controllers/play_controller.rb +46 -0
- data/samples/media/resources/Default-568h@2x.png +0 -0
- data/samples/media/resources/test.mp3 +0 -0
- data/samples/media/spec/main_spec.rb +9 -0
- data/samples/osx/Gemfile +3 -0
- data/samples/osx/Gemfile.lock +10 -0
- data/samples/osx/Rakefile +11 -0
- data/samples/osx/app/app_delegate.rb +69 -0
- data/samples/osx/app/menu.rb +108 -0
- data/samples/osx/resources/Credits.rtf +29 -0
- data/samples/osx/spec/main_spec.rb +9 -0
- data/spec/motion/core/app_spec.rb +5 -164
- data/spec/motion/core/device/{camera_spec.rb → ios/camera_spec.rb} +0 -0
- data/spec/motion/core/device/{camera_wrapper_spec.rb → ios/camera_wrapper_spec.rb} +0 -0
- data/spec/motion/core/device/ios/device_spec.rb +74 -0
- data/spec/motion/core/device/{screen_spec.rb → ios/screen_spec.rb} +2 -1
- data/spec/motion/core/device/osx/screen_spec.rb +26 -0
- data/spec/motion/core/device_spec.rb +0 -71
- data/spec/motion/core/ios/app_spec.rb +180 -0
- data/spec/motion/core/kvo_spec.rb +23 -7
- data/spec/motion/core/ns_index_path_spec.rb +10 -2
- data/spec/motion/core/osx/app_spec.rb +15 -0
- data/spec/motion/core/string_spec.rb +11 -5
- data/spec/motion/core_spec.rb +13 -2
- data/spec/motion/http/query_spec.rb +731 -0
- data/spec/motion/http/response_spec.rb +44 -0
- data/spec/motion/http_spec.rb +0 -722
- data/spec/motion/{core → ui}/gestures_spec.rb +0 -0
- data/spec/motion/ui/ui_alert_view_spec.rb +1188 -0
- data/spec/motion/{core → ui}/ui_bar_button_item_spec.rb +80 -24
- data/spec/motion/{core → ui}/ui_control_spec.rb +0 -0
- data/spec/motion/util/constants_spec.rb +4 -4
- metadata +86 -26
@@ -1,7 +1,11 @@
|
|
1
1
|
describe "NSIndexPathWrap" do
|
2
2
|
|
3
3
|
before do
|
4
|
-
|
4
|
+
if App.osx?
|
5
|
+
@index = NSIndexPath.indexPathWithIndex(3)
|
6
|
+
else
|
7
|
+
@index = NSIndexPath.indexPathForRow(0, inSection:3)
|
8
|
+
end
|
5
9
|
end
|
6
10
|
|
7
11
|
it "should be able to use an array like accessor" do
|
@@ -13,7 +17,11 @@ describe "NSIndexPathWrap" do
|
|
13
17
|
@index.each do |idx|
|
14
18
|
i << idx
|
15
19
|
end
|
16
|
-
|
20
|
+
if App.osx?
|
21
|
+
i.should == [3]
|
22
|
+
else
|
23
|
+
i.should == [3, 0]
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
27
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe BubbleWrap::App do
|
2
|
+
describe "OS X" do
|
3
|
+
describe '.delegate' do
|
4
|
+
it 'returns a TestSuiteDelegate' do
|
5
|
+
App.delegate.should == NSApplication.sharedApplication.delegate
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.shared' do
|
10
|
+
it 'returns UIApplication.sharedApplication' do
|
11
|
+
App.shared.should == NSApplication.sharedApplication
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -92,8 +92,10 @@ describe BubbleWrap::String do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
before do
|
95
|
-
@blue_color = UIColor.blueColor
|
96
|
-
|
95
|
+
@blue_color = App.osx? ? NSColor.colorWithDeviceRed(0,green:0,blue:1,alpha:1) : UIColor.blueColor
|
96
|
+
r,g,b,a = [1, (138.0/255.0), (25.0/255.0), 1]
|
97
|
+
@orange_color = App.osx? ? NSColor.colorWithDeviceRed(r, green:g, blue:b, alpha: a) :
|
98
|
+
UIColor.colorWithRed(r, green:g, blue:b, alpha:a)
|
97
99
|
end
|
98
100
|
|
99
101
|
describe "A UIColor should be created from a String with a hex color" do
|
@@ -116,15 +118,19 @@ describe BubbleWrap::String do
|
|
116
118
|
|
117
119
|
describe "a string with a color keyword (blue, red, lightText)" do
|
118
120
|
it "should return the corresponding color" do
|
119
|
-
'blue'.to_color.should == UIColor.blueColor
|
121
|
+
'blue'.to_color.should == (App.osx? ? NSColor.blueColor : UIColor.blueColor)
|
120
122
|
end
|
121
123
|
|
122
124
|
it "should accept camelCase" do
|
123
|
-
|
125
|
+
if App.osx?
|
126
|
+
'headerText'.to_color.should == NSColor.headerTextColor
|
127
|
+
else
|
128
|
+
'lightText'.to_color.should == UIColor.lightTextColor
|
129
|
+
end
|
124
130
|
end
|
125
131
|
|
126
132
|
it "should accept snake_case" do
|
127
|
-
'dark_gray'.to_color.should == UIColor.darkGrayColor
|
133
|
+
'dark_gray'.to_color.should == (App.osx? ? NSColor.darkGrayColor : UIColor.darkGrayColor)
|
128
134
|
end
|
129
135
|
end
|
130
136
|
|
data/spec/motion/core_spec.rb
CHANGED
@@ -28,13 +28,24 @@ describe 'BubbleWrap' do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it "creates color with rgb devided by 255 with alpha=1" do
|
31
|
-
color =
|
31
|
+
color = nil
|
32
|
+
r,g,b,a = [(@red/255.0), (@green/255.0), (@blue/255.0), 1]
|
33
|
+
if App.osx?
|
34
|
+
color = NSColor.colorWithDeviceRed(r, green:g, blue:b, alpha: a)
|
35
|
+
else
|
36
|
+
color = UIColor.colorWithRed(r, green:g, blue:b, alpha:a)
|
37
|
+
end
|
32
38
|
BubbleWrap::rgb_color(@red, @green, @blue).should.equal color
|
33
39
|
end
|
34
40
|
|
35
41
|
it "rgba_color uses the real alpha" do
|
36
42
|
alpha = 0.4
|
37
|
-
|
43
|
+
r,g,b,a = [(@red/255.0), (@green/255.0), (@blue/255.0), alpha]
|
44
|
+
if App.osx?
|
45
|
+
color = NSColor.colorWithDeviceRed(r, green:g, blue:b, alpha: a)
|
46
|
+
else
|
47
|
+
color = UIColor.colorWithRed(r, green:g, blue:b, alpha:a)
|
48
|
+
end
|
38
49
|
BubbleWrap::rgba_color(@red, @green, @blue, alpha).should.equal color
|
39
50
|
end
|
40
51
|
|
@@ -0,0 +1,731 @@
|
|
1
|
+
describe BubbleWrap::HTTP::Query do
|
2
|
+
|
3
|
+
before do
|
4
|
+
@localhost_url = 'http://localhost'
|
5
|
+
@fake_url = 'http://fake.url'
|
6
|
+
|
7
|
+
@credentials = { username: 'mneorr', password: '123456xx!@crazy' }
|
8
|
+
@credential_persistence = 0
|
9
|
+
@payload = {
|
10
|
+
user: { name: 'marin', surname: 'usalj' },
|
11
|
+
twitter: '@mneorr',
|
12
|
+
website: 'mneorr.com',
|
13
|
+
values: ['apple', 'orange', 'peach'],
|
14
|
+
credentials: @credentials
|
15
|
+
}
|
16
|
+
@action = Proc.new { |response| @real_response = response; @delegator_was_called = true }
|
17
|
+
@format = "application/x-www-form-urlencoded"
|
18
|
+
@cache_policy = 24234
|
19
|
+
@leftover_option = 'trololo'
|
20
|
+
@headers = { 'User-Agent' => "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \n Gecko/20100101 Firefox/12.0" }
|
21
|
+
@files = {
|
22
|
+
fake_file: NSJSONSerialization.dataWithJSONObject({ fake: 'json' }, options:0, error:nil),
|
23
|
+
empty_file: NSMutableData.data
|
24
|
+
}
|
25
|
+
@options = {
|
26
|
+
action: @action,
|
27
|
+
files: @files,
|
28
|
+
payload: @payload,
|
29
|
+
credentials: @credentials,
|
30
|
+
credential_persistence: @credential_persistence,
|
31
|
+
headers: @headers,
|
32
|
+
cache_policy: @cache_policy,
|
33
|
+
leftover_option: @leftover_option,
|
34
|
+
format: @format
|
35
|
+
}
|
36
|
+
@query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has appropriate attributes" do
|
40
|
+
@query.should.respond_to :request=
|
41
|
+
@query.should.respond_to :connection=
|
42
|
+
@query.should.respond_to :credentials=
|
43
|
+
@query.should.respond_to :proxy_credential=
|
44
|
+
@query.should.respond_to :post_data=
|
45
|
+
|
46
|
+
@query.should.respond_to :method
|
47
|
+
@query.should.respond_to :response
|
48
|
+
@query.should.respond_to :status_code
|
49
|
+
@query.should.respond_to :response_headers
|
50
|
+
@query.should.respond_to :response_size
|
51
|
+
@query.should.respond_to :options
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should accept nil header value" do
|
55
|
+
@headers = { 'Authorization' => nil, 'User-Agent' => "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \n Gecko/20100101 Firefox/12.0" }
|
56
|
+
@options = {
|
57
|
+
headers: @headers,
|
58
|
+
}
|
59
|
+
query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
|
60
|
+
query.should.not.be.nil
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "When initialized" do
|
64
|
+
|
65
|
+
it "should upcase the HTTP method" do
|
66
|
+
@query.method.should.equal "GET"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "throws an error for invalid/missing URL schemes" do
|
70
|
+
%w(http https file ftp).each do |scheme|
|
71
|
+
lambda {
|
72
|
+
BW::HTTP::Query.new("#{scheme}://example.com", :get) { |r| p r.body.to_str }
|
73
|
+
}.should.not.raise InvalidURLError
|
74
|
+
end
|
75
|
+
|
76
|
+
lambda {
|
77
|
+
BW::HTTP::Query.new("bad://example.com", :get) { |r| p r.body.to_str }
|
78
|
+
}.should.raise InvalidURLError
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should set the deleted delegator from options" do
|
82
|
+
@query.instance_variable_get(:@delegator).should.equal @action
|
83
|
+
@options.should.not.has_key? :action
|
84
|
+
end
|
85
|
+
|
86
|
+
it "sets the files to instance variable" do
|
87
|
+
@query.instance_variable_get(:@files).should.equal @files
|
88
|
+
@options.should.not.has_key? :files
|
89
|
+
end
|
90
|
+
|
91
|
+
it "sets the format from options" do
|
92
|
+
@query.instance_variable_get(:@format).should.equal @format
|
93
|
+
@options.should.not.has_key? :format
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should set self as the delegator if action was not passed in" do
|
97
|
+
new_query = BubbleWrap::HTTP::Query.new( 'http://localhost', :get, {})
|
98
|
+
new_query.instance_variable_get(:@delegator).should.equal new_query
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should merge :username and :password in loaded credentials" do
|
102
|
+
@query.credentials.should.equal @credentials
|
103
|
+
|
104
|
+
options = { credentials: {} }
|
105
|
+
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, options)
|
106
|
+
|
107
|
+
generated_credentials = { :username => nil, :password => nil }
|
108
|
+
new_query.credentials.should.equal generated_credentials
|
109
|
+
options.should.be.empty
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
describe "PAYLOAD / UPLOAD FILES" do
|
114
|
+
|
115
|
+
def create_query(payload, files)
|
116
|
+
BubbleWrap::HTTP::Query.new( 'http://haha', :post, { payload: payload, files: files } )
|
117
|
+
end
|
118
|
+
|
119
|
+
def sample_data
|
120
|
+
"twitter:@mneorr".dataUsingEncoding NSUTF8StringEncoding
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should set payload from options{} to @payload" do
|
124
|
+
payload = "user%5Bname%5D=marin&user%5Bsurname%5D=usalj&twitter=%40mneorr&website=mneorr.com&values%5B%5D=apple&values%5B%5D=orange&values%5B%5D=peach&credentials%5Busername%5D=mneorr&credentials%5Bpassword%5D=123456xx%21%40crazy"
|
125
|
+
@query.instance_variable_get(:@payload).should.equal payload
|
126
|
+
@options.should.not.has_key? :payload
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should check if @payload is a hash before generating GET params" do
|
130
|
+
query_string_payload = BubbleWrap::HTTP::Query.new( @fake_url , :get, { payload: "name=apple&model=macbook"} )
|
131
|
+
query_string_payload.instance_variable_get(:@payload).should.equal 'name=apple&model=macbook'
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should check if payload is nil" do
|
135
|
+
lambda{
|
136
|
+
BubbleWrap::HTTP::Query.new( @fake_url , :post, {} )
|
137
|
+
}.should.not.raise NoMethodError
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should set the payload in URL only for GET and HEAD requests" do
|
141
|
+
[:post, :put, :delete, :patch].each do |method|
|
142
|
+
query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: @payload } )
|
143
|
+
query.instance_variable_get(:@url).description.should.equal @localhost_url
|
144
|
+
end
|
145
|
+
|
146
|
+
payload = {name: 'marin'}
|
147
|
+
[:get, :head].each do |method|
|
148
|
+
query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: payload } )
|
149
|
+
query.instance_variable_get(:@url).description.should.equal "#{@localhost_url}?name=marin"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it "processes filenames from file hashes" do
|
154
|
+
files = {
|
155
|
+
upload: {data: sample_data, filename: "test.txt"}
|
156
|
+
}
|
157
|
+
query = BubbleWrap::HTTP::Query.new(@fake_url, :post, {files: files})
|
158
|
+
uuid = query.instance_variable_get(:@boundary)
|
159
|
+
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
160
|
+
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "processes filenames from file hashes, using the name when the filename is missing" do
|
164
|
+
files = {
|
165
|
+
upload: {data: sample_data}
|
166
|
+
}
|
167
|
+
query = BubbleWrap::HTTP::Query.new(@fake_url, :post, {files: files})
|
168
|
+
uuid = query.instance_variable_get(:@boundary)
|
169
|
+
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
170
|
+
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
|
171
|
+
end
|
172
|
+
|
173
|
+
it "throws an error for invalid file parameters" do
|
174
|
+
files = {
|
175
|
+
twitter: {filename: "test.txt", data: nil}
|
176
|
+
}
|
177
|
+
lambda {
|
178
|
+
BW::HTTP::Query.new("http://example.com", :post, { files: files})
|
179
|
+
}.should.raise InvalidFileError
|
180
|
+
end
|
181
|
+
|
182
|
+
it "sets the HTTPBody DATA to @request for all methods except GET and HEAD" do
|
183
|
+
payload = { name: 'apple', model: 'macbook'}
|
184
|
+
files = { twitter: sample_data, site: "mneorr.com".dataUsingEncoding(NSUTF8StringEncoding) }
|
185
|
+
|
186
|
+
puts "\n"
|
187
|
+
[:post, :put, :delete, :patch].each do |method|
|
188
|
+
puts " - #{method}\n"
|
189
|
+
query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: payload, files: files } )
|
190
|
+
uuid = query.instance_variable_get(:@boundary)
|
191
|
+
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
192
|
+
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nmacbook\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"twitter\"; filename=\"twitter\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"site\"; filename=\"site\"\r\nContent-Type: application/octet-stream\r\n\r\nmneorr.com\r\n--#{uuid}--\r\n"
|
193
|
+
end
|
194
|
+
|
195
|
+
[:get, :head].each do |method|
|
196
|
+
puts " - #{method}\n"
|
197
|
+
query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: payload } )
|
198
|
+
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
199
|
+
real_payload.should.be.empty
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it "sets the payload without conversion to-from NSString if the payload was NSData" do
|
204
|
+
data = sample_data
|
205
|
+
lambda { query = create_query(data, nil) }.should.not.raise NoMethodError
|
206
|
+
end
|
207
|
+
|
208
|
+
it "sets the payload as a string if JSON" do
|
209
|
+
json = "{\"foo\":42,\"bar\":\"BubbleWrap\"}"
|
210
|
+
puts "\n"
|
211
|
+
[:put, :post, :delete, :patch].each do |method|
|
212
|
+
puts " - #{method}\n"
|
213
|
+
query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: json } )
|
214
|
+
set_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
215
|
+
set_payload.should.equal json
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
it "sets the payload for a nested hash to multiple form-data parts" do
|
220
|
+
payload = { computer: { name: 'apple', model: 'macbook'} }
|
221
|
+
query = BubbleWrap::HTTP::Query.new( @fake_url, :post, { payload: payload } )
|
222
|
+
uuid = query.instance_variable_get(:@boundary)
|
223
|
+
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
|
224
|
+
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[name]\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[model]\"\r\n\r\nmacbook\r\n--#{uuid}--\r\n"
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should set default timeout to 30s or the one from hash" do
|
230
|
+
@query.instance_variable_get(:@timeout).should == 30
|
231
|
+
|
232
|
+
options = {timeout: 10}
|
233
|
+
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, options)
|
234
|
+
|
235
|
+
new_query.instance_variable_get(:@timeout).should == 10
|
236
|
+
options.should.be.empty
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should delete :headers from options and escape Line Feeds" do
|
240
|
+
escaped_lf = "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \r\n Gecko/20100101 Firefox/12.0"
|
241
|
+
headers = @query.instance_variable_get(:@headers)
|
242
|
+
|
243
|
+
headers["User-Agent"].should.equal escaped_lf
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should delete :cache_policy or set NSURLRequestUseProtocolCachePolicy" do
|
247
|
+
@query.instance_variable_get(:@cache_policy).should.equal @cache_policy
|
248
|
+
@options.should.not.has_key? :cache_policy
|
249
|
+
|
250
|
+
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, {})
|
251
|
+
new_query.instance_variable_get(:@cache_policy).should.equal NSURLRequestUseProtocolCachePolicy
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should delete :credential_persistence or set NSURLCredentialPersistenceForSession" do
|
255
|
+
@query.instance_variable_get(:@credential_persistence).should.equal @credential_persistence
|
256
|
+
@options.should.not.has_key? :credential_persistence
|
257
|
+
|
258
|
+
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, {})
|
259
|
+
new_query.instance_variable_get(:@credential_persistence).should.equal NSURLCredentialPersistenceForSession
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should present base64-encoded credentials in Authorization header when provided" do
|
263
|
+
headers = @query.instance_variable_get(:@headers)
|
264
|
+
|
265
|
+
headers["Authorization"].should.equal "Basic bW5lb3JyOjEyMzQ1Nnh4IUBjcmF6eQ=="
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should not present Authorization header when :present_credentials is false" do
|
269
|
+
query = BubbleWrap::HTTP::Query.new(@fake_url, :get, { credentials: @credentials, present_credentials: false })
|
270
|
+
headers = query.instance_variable_get(:@headers)
|
271
|
+
|
272
|
+
headers.should.equal nil
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
it "should set the rest of options{} to ivar @options" do
|
277
|
+
@query.options.size.should.equal 1
|
278
|
+
@query.options.values[0].should.equal @leftover_option
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should create a new response before instantiating a new request" do
|
282
|
+
@query.response.should.not.equal nil
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should call initiate_request with the URL passed in" do
|
286
|
+
processed_url = "http://localhost?user%5Bname%5D=marin&user%5Bsurname%5D=usalj&twitter=%40mneorr&website=mneorr.com&values%5B%5D=apple&values%5B%5D=orange&values%5B%5D=peach&credentials%5Busername%5D=mneorr&credentials%5Bpassword%5D=123456xx%21%40crazy"
|
287
|
+
@query.instance_variable_get(:@url).description.should.equal processed_url
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should pass the new request in the new connection" do
|
291
|
+
@query.connection.request.URL.description.should.equal @query.request.URL.description
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should start the connection" do
|
295
|
+
@query.connection.was_started.should.equal true
|
296
|
+
end
|
297
|
+
|
298
|
+
if !App.osx?
|
299
|
+
it "should turn on the network indicator" do
|
300
|
+
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should.equal true
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe "create request" do
|
306
|
+
|
307
|
+
before do
|
308
|
+
@url_string = 'http://initiated-request.dev/to convert'
|
309
|
+
@headers = { fake: 'headers' }
|
310
|
+
@get_query = BubbleWrap::HTTP::Query.new( @url_string , :get, { headers: @headers } )
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should create a new request with HTTP method & header fields" do
|
314
|
+
@query.request.HTTPMethod.should.equal @query.method
|
315
|
+
@get_query.request.allHTTPHeaderFields.should.equal @headers
|
316
|
+
end
|
317
|
+
|
318
|
+
it "creates a new NSURLConnection and sets itself as a delegate" do
|
319
|
+
@query.connection.delegate.should.equal @query
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should patch the NSURLRequest with done_loading and done_loading!" do
|
323
|
+
@query.request.done_loading?.should.equal @query.request.instance_variable_get(:@done_loading)
|
324
|
+
|
325
|
+
@query.request.instance_variable_set(:@done_loading, false)
|
326
|
+
@query.request.done_loading?.should.equal false
|
327
|
+
@query.request.done_loading!
|
328
|
+
@query.request.done_loading?.should.equal true
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should pass the right arguments when creating new request" do
|
332
|
+
@query.request.cachePolicy.should.equal @query.instance_variable_get(:@cache_policy)
|
333
|
+
@query.request.timeoutInterval.should.equal @query.instance_variable_get(:@timeout)
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
describe "create POST request" do
|
339
|
+
|
340
|
+
before do
|
341
|
+
@url_string = 'http://initiated-request.dev/post'
|
342
|
+
@headers = { fake: 'headers' }
|
343
|
+
@payload = { key:'abc1234' }
|
344
|
+
@post_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: @payload})
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should add default Content Type if no payload is given" do
|
348
|
+
query_without_payload = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers})
|
349
|
+
query_without_payload.request.allHTTPHeaderFields.should.include? 'Content-Type'
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should automatically provide Content-Type if a payload is provided" do
|
353
|
+
@post_query.request.allHTTPHeaderFields.should.include?('Content-Type')
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should use the format parameter to decide the Content-Type" do
|
357
|
+
json_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, format: :json, payload: "{\"key\":\"abc1234\"}"})
|
358
|
+
json_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/json"
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should default to multipart/form-data for payloads with a hash" do
|
362
|
+
uuid = @post_query.instance_variable_get(:@boundary)
|
363
|
+
@post_query.request.allHTTPHeaderFields['Content-Type'].should.equal "multipart/form-data; boundary=#{uuid}"
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should default to application/x-www-form-urlencoded for non-hash payloads" do
|
367
|
+
string_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: "{\"key\":\"abc1234\"}"})
|
368
|
+
string_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/x-www-form-urlencoded"
|
369
|
+
end
|
370
|
+
|
371
|
+
it "should not add Content-Type if you provide one yourself" do
|
372
|
+
# also ensures check is case insenstive
|
373
|
+
@headers = { fake: 'headers', 'CONTENT-TYPE' => 'x-banana' }
|
374
|
+
@post_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: @payload})
|
375
|
+
@post_query.request.allHTTPHeaderFields['CONTENT-TYPE'].should.equal @headers['CONTENT-TYPE']
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
describe "Generating payloads" do
|
381
|
+
|
382
|
+
it "should create payload key/value pairs from nested hashes with prefix[key]=value" do
|
383
|
+
expected_params = [
|
384
|
+
['user[name]', 'marin'],
|
385
|
+
['user[surname]', 'usalj'],
|
386
|
+
['twitter', '@mneorr'],
|
387
|
+
['website', 'mneorr.com'],
|
388
|
+
['values[]', 'apple'],
|
389
|
+
['values[]', 'orange'],
|
390
|
+
['values[]', 'peach'],
|
391
|
+
['credentials[username]', 'mneorr'],
|
392
|
+
['credentials[password]', '123456xx!@crazy']
|
393
|
+
]
|
394
|
+
@query.send(:process_payload_hash, @payload).should.equal expected_params
|
395
|
+
end
|
396
|
+
|
397
|
+
it "should create payload key/value pairs from nested arrays of hashes with prefix[key][][nested_key]=value" do
|
398
|
+
payload = {
|
399
|
+
user: {
|
400
|
+
phones_attributes: [
|
401
|
+
{ number: 1234567, area_code: 213 },
|
402
|
+
{ number: 7654321, area_code: 310 }
|
403
|
+
]
|
404
|
+
}
|
405
|
+
}
|
406
|
+
expected_params = [
|
407
|
+
['user[phones_attributes][][number]', 1234567],
|
408
|
+
['user[phones_attributes][][area_code]', 213],
|
409
|
+
['user[phones_attributes][][number]', 7654321],
|
410
|
+
['user[phones_attributes][][area_code]', 310]
|
411
|
+
]
|
412
|
+
@query.send(:process_payload_hash, payload).should.equal expected_params
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
describe "when didReceiveResponse:" do
|
417
|
+
|
418
|
+
it "should assign status_code, headers and response_size" do
|
419
|
+
headers = { foo: 'bar' }
|
420
|
+
status_code = 234
|
421
|
+
length = 123.53
|
422
|
+
|
423
|
+
response = FakeURLResponse.new(status_code, headers, length)
|
424
|
+
@query.connection(nil, didReceiveResponse:response)
|
425
|
+
|
426
|
+
@query.status_code.should.equal status_code
|
427
|
+
@query.response_headers.should.equal headers
|
428
|
+
@query.response_size.should.equal length
|
429
|
+
end
|
430
|
+
|
431
|
+
end
|
432
|
+
|
433
|
+
describe "when didRecieveData:" do
|
434
|
+
|
435
|
+
def query_received_data
|
436
|
+
@query.instance_variable_get(:@received_data)
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should initialize @received_data and append the received data" do
|
440
|
+
query_received_data.should.equal nil
|
441
|
+
data = NSData.dataWithBytesNoCopy(Pointer.new(:char, 'abc'), length:24, freeWhenDone: false)
|
442
|
+
|
443
|
+
@query.connection(nil, didReceiveData:nil)
|
444
|
+
query_received_data.should.not.equal nil
|
445
|
+
|
446
|
+
@query.connection(nil, didReceiveData:data)
|
447
|
+
query_received_data.length.should.equal 24
|
448
|
+
|
449
|
+
@query.connection(nil, didReceiveData:data)
|
450
|
+
query_received_data.length.should.equal 48
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
|
455
|
+
|
456
|
+
|
457
|
+
describe "when requestDidFailWithError:" do
|
458
|
+
before do
|
459
|
+
@fake_error = NSError.errorWithDomain('testing', code:7768, userInfo:nil)
|
460
|
+
end
|
461
|
+
|
462
|
+
if !App.osx?
|
463
|
+
it "should turn off network indicator" do
|
464
|
+
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == true
|
465
|
+
@query.connection(nil, didFailWithError:@fake_error)
|
466
|
+
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
it "should set request_done to true" do
|
471
|
+
@query.request.done_loading?.should == false
|
472
|
+
@query.connection(nil, didFailWithError:@fake_error)
|
473
|
+
@query.request.done_loading?.should == true
|
474
|
+
end
|
475
|
+
|
476
|
+
it "should set the error message to response object" do
|
477
|
+
@query.response.error_message.should.equal nil
|
478
|
+
@query.connection(nil, didFailWithError:@fake_error)
|
479
|
+
@query.response.error_message.should.equal @fake_error.localizedDescription
|
480
|
+
end
|
481
|
+
|
482
|
+
it "should check if there's a callback block and pass the response in" do
|
483
|
+
expected_response = BubbleWrap::HTTP::Response.new
|
484
|
+
real_response = nil
|
485
|
+
block = lambda{ |response, query| real_response = response }
|
486
|
+
|
487
|
+
query = BubbleWrap::HTTP::Query.new(@localhost_url, :get, { :action => block })
|
488
|
+
query.instance_variable_set(:@response, expected_response)
|
489
|
+
|
490
|
+
query.connection(nil, didFailWithError:@fake_error)
|
491
|
+
real_response.should.equal expected_response
|
492
|
+
end
|
493
|
+
|
494
|
+
end
|
495
|
+
|
496
|
+
describe "when connectionDidFinishLoading:" do
|
497
|
+
|
498
|
+
if !App.osx?
|
499
|
+
it "should turn off the network indicator" do
|
500
|
+
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == true
|
501
|
+
|
502
|
+
@query.connectionDidFinishLoading(nil)
|
503
|
+
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should set request_done to true" do
|
508
|
+
@query.request.done_loading?.should == false
|
509
|
+
|
510
|
+
@query.connectionDidFinishLoading(nil)
|
511
|
+
@query.request.done_loading?.should == true
|
512
|
+
end
|
513
|
+
|
514
|
+
it "should set response_body to @received data if not nil" do
|
515
|
+
data = NSData.dataWithBytesNoCopy(Pointer.new(:char, 'abc'), length:24, freeWhenDone: false)
|
516
|
+
headers = { foo: 'bar' }
|
517
|
+
status_code = 234
|
518
|
+
response = FakeURLResponse.new(status_code, headers, 65456)
|
519
|
+
|
520
|
+
@query.connection(nil, didReceiveResponse:response)
|
521
|
+
@query.connection(nil, didReceiveData:data)
|
522
|
+
@query.connectionDidFinishLoading(nil)
|
523
|
+
|
524
|
+
@query.response.body.should.equal data
|
525
|
+
@query.response.status_code.should.equal status_code
|
526
|
+
@query.response.headers.should.equal headers
|
527
|
+
@query.response.url.should.equal @query.instance_variable_get(:@url)
|
528
|
+
end
|
529
|
+
|
530
|
+
it "should check if there's a callback block and pass the response in" do
|
531
|
+
expected_response = BubbleWrap::HTTP::Response.new
|
532
|
+
real_response = nil
|
533
|
+
block = lambda{ |response, query| real_response = response }
|
534
|
+
query = BubbleWrap::HTTP::Query.new(@localhost_url, :get, { :action => block })
|
535
|
+
query.instance_variable_set(:@response, expected_response)
|
536
|
+
|
537
|
+
query.connectionDidFinishLoading(nil)
|
538
|
+
real_response.should.equal expected_response
|
539
|
+
end
|
540
|
+
|
541
|
+
end
|
542
|
+
|
543
|
+
describe "when connection:willSendRequest:redirectResponse:" do
|
544
|
+
before do
|
545
|
+
@request = NSMutableURLRequest.requestWithURL NSURL.URLWithString('http://fakehost.local/')
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should forward the new request for 30 times/redirections" do
|
549
|
+
1.upto(35) do |numbah|
|
550
|
+
request = @query.connection(nil, willSendRequest:@request, redirectResponse:nil)
|
551
|
+
request.should.equal numbah < 30 ? @request : nil
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
it "should always allow canonical redirects" do
|
556
|
+
@query.options.update({:no_redirect => 1})
|
557
|
+
request = @query.connection(nil, willSendRequest:@request, redirectResponse:nil)
|
558
|
+
request.should.equal @request
|
559
|
+
end
|
560
|
+
|
561
|
+
it "should disallow non-canonical redirects if requested not to" do
|
562
|
+
@query.options.update({:no_redirect => 1})
|
563
|
+
request = @query.connection(nil, willSendRequest:@request, redirectResponse:"monkey")
|
564
|
+
request.should.equal nil
|
565
|
+
end
|
566
|
+
|
567
|
+
it "should allow non-canonical redirects by default" do
|
568
|
+
@query.options.delete(:no_redirect)
|
569
|
+
request = @query.connection(nil, willSendRequest:@request, redirectResponse:"monkey")
|
570
|
+
request.should.equal @request
|
571
|
+
end
|
572
|
+
|
573
|
+
describe "after 30 redirects" do
|
574
|
+
before do
|
575
|
+
31.times do
|
576
|
+
@query.connection(nil, willSendRequest:@request, redirectResponse:nil)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
it "sets the error message on response" do
|
581
|
+
@real_response.error_message.should.equal "Too many redirections"
|
582
|
+
end
|
583
|
+
|
584
|
+
it "sets the request.done_loading" do
|
585
|
+
@query.request.done_loading?.should.equal true
|
586
|
+
end
|
587
|
+
|
588
|
+
it "calls the delegator block" do
|
589
|
+
@delegator_was_called.should.equal true
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
it "should update the request URL after redirecting by default" do
|
594
|
+
query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, {} )
|
595
|
+
redirected_request = NSMutableURLRequest.requestWithURL NSURL.URLWithString('http://expanded.local/')
|
596
|
+
query.connection(nil, willSendRequest:redirected_request, redirectResponse:nil)
|
597
|
+
query.connectionDidFinishLoading(nil)
|
598
|
+
query.response.url.absoluteString.should.equal redirected_request.URL.absoluteString
|
599
|
+
query.response.original_url.absoluteString.should.equal @localhost_url
|
600
|
+
end
|
601
|
+
|
602
|
+
end
|
603
|
+
|
604
|
+
describe "didReceiveAuthenticationChallenge" do
|
605
|
+
before do
|
606
|
+
@challenge = FakeChallenge.new
|
607
|
+
@challenge.previousFailureCount = 0
|
608
|
+
@query.connection(nil, didReceiveAuthenticationChallenge:@challenge)
|
609
|
+
end
|
610
|
+
|
611
|
+
it "should cancel the authentication if the failure count was not 0" do
|
612
|
+
@challenge.previousFailureCount = 1
|
613
|
+
@query.connection(nil, didReceiveAuthenticationChallenge:@challenge)
|
614
|
+
@challenge.sender.was_cancelled.should.equal true
|
615
|
+
end
|
616
|
+
|
617
|
+
it "should pass in Credentials and the challenge itself to the sender" do
|
618
|
+
@challenge.sender.challenge.should.equal @challenge
|
619
|
+
@challenge.sender.credential.user.should.equal @credentials[:username]
|
620
|
+
@challenge.sender.credential.password.should.equal @credentials[:password]
|
621
|
+
end
|
622
|
+
|
623
|
+
it "should use Credential Persistence set in options" do
|
624
|
+
@challenge.sender.credential.persistence.should.equal @credential_persistence
|
625
|
+
end
|
626
|
+
|
627
|
+
it 'should continue without credentials when no credentials provided' do
|
628
|
+
@options.delete :credentials
|
629
|
+
query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
|
630
|
+
query.connection(nil, didReceiveAuthenticationChallenge:@challenge)
|
631
|
+
@challenge.sender.continue_without_credential.should.equal true
|
632
|
+
end
|
633
|
+
|
634
|
+
end
|
635
|
+
|
636
|
+
describe "empty payload" do
|
637
|
+
|
638
|
+
before do
|
639
|
+
@payload = {}
|
640
|
+
@url_string = 'http://fake.url/method'
|
641
|
+
@get_query = BubbleWrap::HTTP::Query.new(@url_string, :get, :payload => @payload)
|
642
|
+
end
|
643
|
+
|
644
|
+
it "should not append a ? to the end of the URL" do
|
645
|
+
@get_query.instance_variable_get(:@url).description.should.equal('http://fake.url/method')
|
646
|
+
end
|
647
|
+
|
648
|
+
end
|
649
|
+
|
650
|
+
describe "properly format payload to url get query string" do
|
651
|
+
|
652
|
+
before do
|
653
|
+
@payload = {"we love" => '#==Rock&Roll==#', "radio" => "Ga Ga", "qual" => 3.0, "incr" => -1, "RFC3986" => "!*'();:@&=+$,/?%#[]"}
|
654
|
+
@url_string = 'http://fake.url/method'
|
655
|
+
@get_query = BubbleWrap::HTTP::Query.new(@url_string, :get, :payload => @payload)
|
656
|
+
@escaped_url = "http://fake.url/method?we%20love=%23%3D%3DRock%26Roll%3D%3D%23&radio=Ga%20Ga&qual=3.0&incr=-1&RFC3986=%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%25%23%5B%5D"
|
657
|
+
end
|
658
|
+
|
659
|
+
it "should escape !*'();:@&=+$,/?%#[] characters only in keys and values" do
|
660
|
+
@get_query.instance_variable_get(:@url).description.should.equal @escaped_url
|
661
|
+
end
|
662
|
+
|
663
|
+
end
|
664
|
+
|
665
|
+
describe 'properly support cookie-option for nsmutableurlrequest' do
|
666
|
+
|
667
|
+
before do
|
668
|
+
@no_cookie_query = BubbleWrap::HTTP::Query.new("http://haz-no-cookiez.url", :get, {:payload => {:something => "else"}, :cookies => false})
|
669
|
+
@cookie_query = BubbleWrap::HTTP::Query.new("http://haz-cookiez.url", :get, :payload => {:something => "else"})
|
670
|
+
end
|
671
|
+
|
672
|
+
it 'should disabled cookie-usage on nsurlrequest' do
|
673
|
+
@no_cookie_query.instance_variable_get(:@request).HTTPShouldHandleCookies.should.equal false
|
674
|
+
end
|
675
|
+
|
676
|
+
it 'should keep sane cookie-related defaults on nsurlrequest' do
|
677
|
+
@cookie_query.instance_variable_get(:@request).HTTPShouldHandleCookies.should.equal true
|
678
|
+
end
|
679
|
+
|
680
|
+
|
681
|
+
end
|
682
|
+
|
683
|
+
class FakeSender
|
684
|
+
attr_reader :challenge, :credential, :was_cancelled, :continue_without_credential
|
685
|
+
def cancelAuthenticationChallenge(challenge)
|
686
|
+
@was_cancelled = true
|
687
|
+
end
|
688
|
+
def useCredential(credential, forAuthenticationChallenge:challenge)
|
689
|
+
@challenge = challenge
|
690
|
+
@credential = credential
|
691
|
+
end
|
692
|
+
def continueWithoutCredentialForAuthenticationChallenge(challenge)
|
693
|
+
@continue_without_credential = true
|
694
|
+
end
|
695
|
+
end
|
696
|
+
|
697
|
+
class FakeChallenge
|
698
|
+
attr_accessor :previousFailureCount
|
699
|
+
|
700
|
+
def sender
|
701
|
+
@fake_sender ||= FakeSender.new
|
702
|
+
end
|
703
|
+
end
|
704
|
+
|
705
|
+
class BubbleWrap::HTTP::Query
|
706
|
+
def create_connection(request, delegate); FakeURLConnection.new(request, delegate); end
|
707
|
+
end
|
708
|
+
|
709
|
+
class FakeURLConnection < NSURLConnection
|
710
|
+
attr_reader :delegate, :request, :was_started
|
711
|
+
def initialize(request, delegate)
|
712
|
+
@request = request
|
713
|
+
@delegate = delegate
|
714
|
+
self.class.connectionWithRequest(request, delegate:delegate)
|
715
|
+
end
|
716
|
+
def start
|
717
|
+
@was_started = true
|
718
|
+
super
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class FakeURLResponse < NSHTTPURLResponse
|
723
|
+
attr_reader :statusCode, :allHeaderFields, :expectedContentLength
|
724
|
+
def initialize(status_code, headers, length)
|
725
|
+
@statusCode = status_code
|
726
|
+
@allHeaderFields = headers
|
727
|
+
@expectedContentLength = length
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
end
|