bubble-wrap 1.0.0 → 1.1.0

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.
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