bubble-wrap 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +0 -1
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +15 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +24 -0
  6. data/HACKING.md +2 -2
  7. data/README.md +363 -21
  8. data/Rakefile +6 -2
  9. data/lib/bubble-wrap.rb +0 -1
  10. data/lib/bubble-wrap/all.rb +4 -0
  11. data/lib/bubble-wrap/camera.rb +7 -0
  12. data/lib/bubble-wrap/core.rb +3 -2
  13. data/lib/bubble-wrap/ext/motion_project_app.rb +2 -2
  14. data/lib/bubble-wrap/http.rb +1 -0
  15. data/lib/bubble-wrap/loader.rb +19 -12
  16. data/lib/bubble-wrap/location.rb +6 -0
  17. data/lib/bubble-wrap/reactor.rb +10 -0
  18. data/lib/bubble-wrap/requirement.rb +11 -3
  19. data/lib/bubble-wrap/rss_parser.rb +2 -0
  20. data/lib/bubble-wrap/ui.rb +4 -0
  21. data/lib/bubble-wrap/version.rb +1 -1
  22. data/motion/core.rb +8 -2
  23. data/motion/core/app.rb +34 -6
  24. data/motion/core/device.rb +10 -1
  25. data/motion/core/device/camera.rb +219 -0
  26. data/motion/core/device/camera_wrapper.rb +45 -0
  27. data/motion/core/ns_url_request.rb +10 -0
  28. data/motion/core/persistence.rb +7 -0
  29. data/motion/core/pollute.rb +1 -2
  30. data/motion/core/string.rb +23 -0
  31. data/motion/http.rb +142 -83
  32. data/motion/location/location.rb +152 -0
  33. data/motion/location/pollute.rb +5 -0
  34. data/motion/reactor.rb +105 -0
  35. data/motion/reactor/default_deferrable.rb +9 -0
  36. data/motion/reactor/deferrable.rb +126 -0
  37. data/motion/reactor/eventable.rb +24 -0
  38. data/motion/reactor/future.rb +22 -0
  39. data/motion/reactor/periodic_timer.rb +27 -0
  40. data/motion/reactor/queue.rb +60 -0
  41. data/motion/reactor/timer.rb +25 -0
  42. data/motion/rss_parser.rb +131 -0
  43. data/motion/shortcut.rb +18 -0
  44. data/motion/{core → ui}/gestures.rb +15 -9
  45. data/motion/ui/pollute.rb +5 -0
  46. data/motion/{core → ui}/ui_control.rb +0 -0
  47. data/motion/{core → ui}/ui_view_controller.rb +0 -0
  48. data/resources/atom.xml +1705 -0
  49. data/spec/lib/bubble-wrap/ext/motion_project_app_spec.rb +7 -11
  50. data/spec/lib/bubble-wrap/requirement_spec.rb +4 -4
  51. data/spec/lib/bubble-wrap_spec.rb +2 -2
  52. data/spec/motion/core/app_spec.rb +118 -14
  53. data/spec/motion/core/device/camera_spec.rb +130 -0
  54. data/spec/motion/core/device/camera_wrapper_spec.rb +45 -0
  55. data/spec/motion/core/device_spec.rb +0 -50
  56. data/spec/motion/core/gestures_spec.rb +5 -0
  57. data/spec/motion/core/persistence_spec.rb +24 -2
  58. data/spec/motion/core/string_spec.rb +55 -0
  59. data/spec/motion/core_spec.rb +72 -1
  60. data/spec/motion/http_spec.rb +100 -65
  61. data/spec/motion/location/location_spec.rb +152 -0
  62. data/spec/motion/reactor/eventable_spec.rb +40 -0
  63. data/spec/motion/reactor_spec.rb +163 -0
  64. data/spec/motion/rss_parser_spec.rb +36 -0
  65. metadata +75 -16
@@ -36,56 +36,6 @@ describe BubbleWrap::Device do
36
36
  end
37
37
  end
38
38
 
39
- describe 'on device with only front facing camera' do
40
- before do
41
- @picker = Object.new.tap do |o|
42
- def o.isCameraDeviceAvailable(c)
43
- c == UIImagePickerControllerCameraDeviceFront
44
- end
45
- def o.method_missing(*args)
46
- UIImagePickerController.send(*args)
47
- end
48
- end
49
- end
50
-
51
- describe '.front_camera?' do
52
- it 'returns true' do
53
- BW::Device.front_camera?(@picker).should == true
54
- end
55
- end
56
-
57
- describe '.rear_camera?' do
58
- it 'returns false' do
59
- BW::Device.rear_camera?(@picker).should == false
60
- end
61
- end
62
- end
63
-
64
- describe 'on device with only rear facing camera' do
65
- before do
66
- @picker = Object.new.tap do |o|
67
- def o.isCameraDeviceAvailable(c)
68
- c == UIImagePickerControllerCameraDeviceRear
69
- end
70
- def o.method_missing(*args)
71
- UIImagePickerController.send(*args)
72
- end
73
- end
74
- end
75
-
76
- describe '.front_camera?' do
77
- it 'returns false' do
78
- BW::Device.front_camera?(@picker).should == false
79
- end
80
- end
81
-
82
- describe '.rear_camera?' do
83
- it 'returns true' do
84
- BW::Device.rear_camera?(@picker).should == true
85
- end
86
- end
87
- end
88
-
89
39
  describe '.simulator?' do
90
40
  it 'returns true' do
91
41
  BW::Device.simulator?.should == true
@@ -11,6 +11,11 @@ describe UIView do
11
11
  end
12
12
 
13
13
  testMethod = proc do |method|
14
+ it "returns a gesture recognizer" do
15
+ recognizer = @view.send(method, false, &:nil)
16
+ recognizer.is_a?(UIGestureRecognizer).should == true
17
+ end
18
+
14
19
  it 'enables interaction when called' do
15
20
  @view.send(method, &:nil)
16
21
  @view.isUserInteractionEnabled.should == true
@@ -30,13 +30,35 @@ describe BubbleWrap::Persistence do
30
30
  BubbleWrap::Persistence['arbitraryNumber'] = 42
31
31
  storage.instance_variable_get(:@sync_was_called).should.equal true
32
32
  end
33
+ end
33
34
 
35
+ describe "storing multiple objects" do
36
+ it 'can persist multiple objects' do
37
+ lambda do
38
+ BubbleWrap::Persistence.merge({
39
+ :anotherArbitraryNumber => 9001,
40
+ :arbitraryString => 'test string'
41
+ })
42
+ end.
43
+ should.not.raise(Exception)
44
+ end
45
+
46
+ it 'must call synchronize' do
47
+ storage = NSUserDefaults.standardUserDefaults
48
+ def storage.synchronize; @sync_was_called = true; end
49
+
50
+ BubbleWrap::Persistence.merge({
51
+ :anotherArbitraryNumber => 9001,
52
+ :arbitraryString => 'test string'
53
+ })
54
+ storage.instance_variable_get(:@sync_was_called).should.equal true
55
+ end
34
56
  end
35
57
 
36
58
  describe "retrieving objects" do
37
59
  it 'can retrieve persisted objects' do
38
60
  BubbleWrap::Persistence['arbitraryNumber'].should == 42
39
- end
61
+ BubbleWrap::Persistence[:arbitraryString].should == 'test string'
62
+ end
40
63
  end
41
-
42
64
  end
@@ -64,6 +64,61 @@ describe BubbleWrap::String do
64
64
  'snake_case'.underscore.should == 'snake_case'
65
65
  end
66
66
  end
67
+
68
+ end
69
+
70
+ before do
71
+ @blue_color = UIColor.blueColor
72
+ @orange_color = UIColor.colorWithRed((255.0/255.0), green:(138.0/255.0), blue:(25.0/255.0), alpha:1.0)
67
73
  end
68
74
 
75
+ describe "A UIColor should be created from a String with a hex color" do
76
+
77
+ it "with 6 digits" do
78
+ @orange_color_from_hex= '#FF8A19'.to_color
79
+ @orange_color_from_hex.should == @orange_color
80
+ end
81
+
82
+ it "with 3 digits" do
83
+ @blue_color_from_hex = '#00F'.to_color
84
+ @blue_color_from_hex.should == @blue_color
85
+ end
86
+
87
+ it "with no # sign" do
88
+ @orange_color_from_hex= 'FF8A19'.to_color
89
+ @orange_color_from_hex.should == @orange_color
90
+ end
91
+ end
92
+
93
+ describe "a string with a color keyword (blue, red, lightText)" do
94
+ it "should return the corresponding color" do
95
+ 'blue'.to_color.should == UIColor.blueColor
96
+ end
97
+
98
+ it "should accept camelCase" do
99
+ 'lightText'.to_color.should == UIColor.lightTextColor
100
+ end
101
+
102
+ it "should accept snake_case" do
103
+ 'dark_gray'.to_color.should == UIColor.darkGrayColor
104
+ end
105
+ end
106
+
107
+ describe "A UIColor should not be created from an invalid String wuth" do
108
+
109
+
110
+ it "an invalid hex color" do
111
+ should.raise( ArgumentError ) {
112
+ 'XXX'.to_color
113
+ }
114
+ end
115
+
116
+ it "a hex color with the wrong number of digits" do
117
+ should.raise( ArgumentError ) {
118
+ 'FFFF'.to_color
119
+ }
120
+ end
121
+
122
+
123
+ end
69
124
  end
@@ -1,2 +1,73 @@
1
- describe BubbleWrap do
1
+ describe 'BubbleWrap' do
2
+
3
+
4
+ describe "debug flag" do
5
+
6
+ after do
7
+ BubbleWrap.debug = false
8
+ end
9
+
10
+ it "can be set" do
11
+ BubbleWrap.debug = true
12
+ BubbleWrap.debug?.should.equal true
13
+ end
14
+
15
+ it "can be unset" do
16
+ BubbleWrap.debug = false
17
+ BubbleWrap.debug?.should.equal false
18
+ end
19
+
20
+ end
21
+
22
+ describe "RGB color" do
23
+
24
+ before do
25
+ @red = 23
26
+ @green = 45
27
+ @blue = 12
28
+ end
29
+
30
+ it "creates color with rgb devided by 255 with alpha=1" do
31
+ color = UIColor.colorWithRed((@red/255.0), green:(@green/255.0), blue:(@blue/255.0), alpha:1)
32
+ BubbleWrap::rgb_color(@red, @green, @blue).should.equal color
33
+ end
34
+
35
+ it "rgba_color uses the real alpha" do
36
+ alpha = 0.4
37
+ color = UIColor.colorWithRed((@red/255.0), green:(@green/255.0), blue:(@blue/255.0), alpha:alpha)
38
+ BubbleWrap::rgba_color(@red, @green, @blue, alpha).should.equal color
39
+ end
40
+
41
+ end
42
+
43
+ describe "Localized string" do
44
+
45
+ it "loads the string from NSBundle" do
46
+ key = 'fake_key'
47
+ value = 'fake_value'
48
+
49
+ bundle = NSBundle.mainBundle
50
+ def bundle.arguments; @arguments; end
51
+ def bundle.localizedStringForKey(key, value:value, table:table); @arguments = [key, value, table]; end
52
+
53
+ BubbleWrap::localized_string(key, value)
54
+ bundle.arguments.should.equal [key, value, nil]
55
+ end
56
+
57
+ end
58
+
59
+ describe "uuid" do
60
+
61
+ it "creates always the new UUID" do
62
+ previous = BW.create_uuid
63
+ 10.times do
64
+ uuid = BW.create_uuid
65
+ uuid.should.not.equal previous
66
+ uuid.size.should.equal 36
67
+ previous = uuid
68
+ end
69
+ end
70
+
71
+ end
72
+
2
73
  end
@@ -39,19 +39,19 @@ describe "HTTP" do
39
39
  end
40
40
  end
41
41
 
42
- [:get, :post, :put, :delete, :head, :patch].each do |verb|
43
- it "has access to the proper response scope for #{verb} request" do
44
- class WatchedObj; attr_accessor :test_value end
45
- @watched_object = WatchedObj.new
46
- @name = 'Matt'
47
- query = BubbleWrap::HTTP.send(verb, @localhost_url) do |response|
48
- @watched_object.test_value = @name
49
- end
50
- wait_for_change(@watched_object, 'test_value') do
51
- @watched_object.test_value.should == 'Matt'
52
- end
53
- end
54
- end
42
+ # [:get, :post, :put, :delete, :head, :patch].each do |verb|
43
+ # it "has access to the proper response scope for #{verb} request" do
44
+ # class WatchedObj; attr_accessor :test_value end
45
+ # @watched_object = WatchedObj.new
46
+ # @name = 'Matt'
47
+ # query = BubbleWrap::HTTP.send(verb, @localhost_url) do |response|
48
+ # @watched_object.test_value = @name
49
+ # end
50
+ # wait_for_change(@watched_object, 'test_value') do
51
+ # @watched_object.test_value.should == 'Matt'
52
+ # end
53
+ # end
54
+ # end
55
55
 
56
56
  end
57
57
 
@@ -69,19 +69,19 @@ describe "HTTP" do
69
69
  it "says OK status code 20x" do
70
70
  @response.ok?.should.equal true
71
71
  (200..209).each do |code|
72
- BubbleWrap::HTTP::Response.new({status_code: code}).ok?.should.be.true
72
+ BubbleWrap::HTTP::Response.new(status_code: code).ok?.should.be.true
73
73
  end
74
74
  [100..101, 300..307, 400..417, 500..505].inject([]){|codes, rg| codes += rg.to_a}.each do |code|
75
- BubbleWrap::HTTP::Response.new({status_code: code}).ok?.should.be.false
75
+ BubbleWrap::HTTP::Response.new(status_code: code).ok?.should.be.false
76
76
  end
77
77
  end
78
78
 
79
79
  it "updates ivars when calling update" do
80
- @response.update( { one: 'one', two: 'two' } )
80
+ @response.update(one: 'one', two: 'two')
81
81
  @response.instance_variable_get(:@one).should.equal 'one'
82
82
  @response.instance_variable_get(:@two).should.equal 'two'
83
83
 
84
- @response.update( { one: 'three', two: 'four' } )
84
+ @response.update(one: 'three', two: 'four')
85
85
  @response.instance_variable_get(:@one).should.equal 'three'
86
86
  @response.instance_variable_get(:@two).should.equal 'four'
87
87
  end
@@ -111,7 +111,13 @@ describe "HTTP" do
111
111
  @cache_policy = 24234
112
112
  @leftover_option = 'trololo'
113
113
  @headers = { 'User-Agent' => "Mozilla/5.0 (X11; Linux x86_64; rv:12.0) \n Gecko/20100101 Firefox/12.0" }
114
- @options = { action: @action,
114
+ @files = {
115
+ fake_file: NSJSONSerialization.dataWithJSONObject({ fake: 'json' }, options:0, error:nil),
116
+ empty_file: NSMutableData.data
117
+ }
118
+ @options = {
119
+ action: @action,
120
+ files: @files,
115
121
  payload: @payload,
116
122
  credentials: @credentials,
117
123
  headers: @headers,
@@ -146,6 +152,11 @@ describe "HTTP" do
146
152
  @query.instance_variable_get(:@delegator).should.equal @action
147
153
  @options.should.not.has_key? :action
148
154
  end
155
+
156
+ it "sets the files to instance variable" do
157
+ @query.instance_variable_get(:@files).should.equal @files
158
+ @options.should.not.has_key? :files
159
+ end
149
160
 
150
161
  it "should set self as the delegator if action was not passed in" do
151
162
  new_query = BubbleWrap::HTTP::Query.new( 'http://localhost', :get, {})
@@ -163,10 +174,70 @@ describe "HTTP" do
163
174
  options.should.be.empty
164
175
  end
165
176
 
166
- it "should set payload from options{} to @payload" do
167
- payload = "user[name]=marin&user[surname]=usalj&twitter=@mneorr&website=mneorr.com&values[]=apple&values[]=orange&values[]=peach&credentials[username]=mneorr&credentials[password]=123456xx!@crazy"
168
- @query.instance_variable_get(:@payload).should.equal payload
169
- @options.should.not.has_key? :payload
177
+
178
+ describe "PAYLOAD / UPLOAD FILES" do
179
+
180
+ def create_query(payload, files)
181
+ BubbleWrap::HTTP::Query.new( '', :post, { payload: payload, files: files } )
182
+ end
183
+
184
+ def sample_data
185
+ "twitter:@mneorr".dataUsingEncoding NSUTF8StringEncoding
186
+ end
187
+
188
+ it "should set payload from options{} to @payload" do
189
+ payload = "user[name]=marin&user[surname]=usalj&twitter=@mneorr&website=mneorr.com&values[]=apple&values[]=orange&values[]=peach&credentials[username]=mneorr&credentials[password]=123456xx!@crazy"
190
+ @query.instance_variable_get(:@payload).should.equal payload
191
+ @options.should.not.has_key? :payload
192
+ end
193
+
194
+ it "should check if @payload is a hash before generating GET params" do
195
+ query_string_payload = BubbleWrap::HTTP::Query.new( 'nil' , :get, { payload: "name=apple&model=macbook"} )
196
+ query_string_payload.instance_variable_get(:@payload).should.equal 'name=apple&model=macbook'
197
+ end
198
+
199
+ it "should check if payload is nil" do
200
+ lambda{
201
+ BubbleWrap::HTTP::Query.new( 'nil' , :post, {} )
202
+ }.should.not.raise NoMethodError
203
+ end
204
+
205
+ it "should set the payload in URL only for GET and HEAD requests" do
206
+ [:post, :put, :delete, :patch].each do |method|
207
+ query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: @payload } )
208
+ query.instance_variable_get(:@url).description.should.equal @localhost_url
209
+ end
210
+
211
+ payload = {name: 'marin'}
212
+ [:get, :head].each do |method|
213
+ query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: payload } )
214
+ query.instance_variable_get(:@url).description.should.equal "#{@localhost_url}?name=marin"
215
+ end
216
+ end
217
+
218
+ it "sets the HTTPBody DATA to @request for all methods except GET and HEAD" do
219
+ payload = { name: 'apple', model: 'macbook'}
220
+ files = { twitter: sample_data, site: "mneorr.com".dataUsingEncoding(NSUTF8StringEncoding) }
221
+
222
+ [:post, :put, :delete, :patch].each do |method|
223
+ query = BubbleWrap::HTTP::Query.new( 'nil' , method, { payload: payload, files: files } )
224
+ uuid = query.instance_variable_get(:@boundary)
225
+ real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
226
+ real_payload.should.equal "\r\n--#{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"
227
+ end
228
+
229
+ [:get, :head].each do |method|
230
+ query = BubbleWrap::HTTP::Query.new( 'nil' , method, { payload: payload } )
231
+ real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
232
+ real_payload.should.be.empty
233
+ end
234
+ end
235
+
236
+ it "sets the payload without conversion to-from NSString if the payload was NSData" do
237
+ data = sample_data
238
+ lambda { query = create_query(data, nil) }.should.not.raise NoMethodError
239
+ end
240
+
170
241
  end
171
242
 
172
243
  it "should set default timeout to 30s or the one from hash" do
@@ -206,6 +277,10 @@ describe "HTTP" do
206
277
  @query.instance_variable_get(:@url).description.should.equal processed_url
207
278
  end
208
279
 
280
+ it "should pass the new request in the new connection" do
281
+ @query.connection.request.URL.description.should.equal @query.request.URL.description
282
+ end
283
+
209
284
  it "should start the connection" do
210
285
  @query.connection.was_started.should.equal true
211
286
  end
@@ -216,48 +291,12 @@ describe "HTTP" do
216
291
 
217
292
  end
218
293
 
219
- describe "initiate request" do
294
+ describe "create request" do
220
295
 
221
296
  before do
222
297
  @url_string = 'http://initiated-request.dev/to convert'
223
- @payload = { name: 'apple', model: 'macbook'}
224
298
  @headers = { fake: 'headers' }
225
- @get_query = BubbleWrap::HTTP::Query.new( @url_string , :get, { headers: @headers, payload: @payload } )
226
- @get_query.initiate_request @url_string
227
- end
228
-
229
- it "should check if @payload is a hash before generating params" do
230
- @get_query.instance_variable_get(:@payload).should.equal 'name=apple&model=macbook'
231
-
232
- query_string_payload = BubbleWrap::HTTP::Query.new( 'nil' , :get, { payload: "name=apple&model=macbook"} )
233
- query_string_payload.instance_variable_get(:@payload).should.equal 'name=apple&model=macbook'
234
- end
235
-
236
- it "should check if payload is nil" do
237
- nil_payload = BubbleWrap::HTTP::Query.new( 'nil' , :post, {} )
238
- lambda{ nil_payload.initiate_request('fake') }.should.not.raise NoMethodError
239
- end
240
-
241
- it "should set the payload in URL only for GET request" do
242
- [:post, :put, :delete, :head, :patch].each do |method|
243
- query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: @payload } )
244
- query.instance_variable_get(:@url).description.should.equal @localhost_url
245
- end
246
- end
247
-
248
- it "sets the HTTPBody DATA to @request for all methods except GET" do
249
-
250
- [:post, :put, :delete, :head, :patch].each do |method|
251
- query = BubbleWrap::HTTP::Query.new( 'nil' , method, { payload: @payload } )
252
- real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
253
-
254
- real_payload.should.equal 'name=apple&model=macbook'
255
- end
256
-
257
- end
258
-
259
- it "should add UTF8 escaping on the URL string" do
260
- @get_query.instance_variable_get(:@url).description.should.equal 'http://initiated-request.dev/to%20convert?name=apple&model=macbook'
299
+ @get_query = BubbleWrap::HTTP::Query.new( @url_string , :get, { headers: @headers } )
261
300
  end
262
301
 
263
302
  it "should create a new request with HTTP method & header fields" do
@@ -269,10 +308,6 @@ describe "HTTP" do
269
308
  @query.connection.delegate.should.equal @query
270
309
  end
271
310
 
272
- it "should pass the new request in the new connection" do
273
- @query.connection.request.URL.description.should.equal @query.request.URL.description
274
- end
275
-
276
311
  it "should patch the NSURLRequest with done_loading and done_loading!" do
277
312
  @query.request.done_loading.should.equal @query.request.instance_variable_get(:@done_loading)
278
313
 
@@ -303,7 +338,7 @@ describe "HTTP" do
303
338
  "credentials[username]=mneorr",
304
339
  "credentials[password]=123456xx!@crazy"
305
340
  ]
306
- @query.generate_params(@payload).should.equal expected_params
341
+ @query.send(:generate_get_params, @payload).should.equal expected_params
307
342
  end
308
343
 
309
344
  end