bubble-wrap 1.3.0 → 1.4.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 (72) hide show
  1. checksums.yaml +6 -14
  2. data/.travis.yml +2 -1
  3. data/CHANGELOG.md +26 -2
  4. data/GETTING_STARTED.md +1 -1
  5. data/Gemfile.lock +1 -1
  6. data/HACKING.md +6 -4
  7. data/README.md +83 -3
  8. data/Rakefile +9 -7
  9. data/lib/bubble-wrap/all.rb +2 -2
  10. data/lib/bubble-wrap/mail.rb +9 -0
  11. data/lib/bubble-wrap/sms.rb +9 -0
  12. data/lib/bubble-wrap/ui.rb +6 -2
  13. data/lib/bubble-wrap/version.rb +1 -1
  14. data/motion/core.rb +1 -1
  15. data/motion/core/app.rb +7 -2
  16. data/motion/core/device/ios/camera.rb +3 -2
  17. data/motion/core/device/ios/screen.rb +19 -0
  18. data/motion/core/ios/app.rb +13 -1
  19. data/motion/core/ios/device.rb +5 -0
  20. data/motion/core/json.rb +1 -3
  21. data/motion/core/kvo.rb +11 -13
  22. data/motion/core/persistence.rb +8 -1
  23. data/motion/core/string.rb +3 -3
  24. data/motion/core/time.rb +5 -0
  25. data/motion/http.rb +1 -1
  26. data/motion/http/query.rb +39 -19
  27. data/motion/http/response.rb +4 -4
  28. data/motion/mail/mail.rb +59 -0
  29. data/motion/mail/result.rb +29 -0
  30. data/motion/reactor/eventable.rb +3 -2
  31. data/motion/reactor/periodic_timer.rb +12 -8
  32. data/motion/reactor/timer.rb +11 -7
  33. data/motion/sms/result.rb +24 -0
  34. data/motion/sms/sms.rb +47 -0
  35. data/motion/ui/pollute.rb +4 -1
  36. data/motion/ui/ui_alert_view.rb +15 -8
  37. data/motion/ui/ui_control_wrapper.rb +16 -0
  38. data/motion/ui/ui_view_controller_wrapper.rb +13 -0
  39. data/motion/ui/ui_view_wrapper.rb +55 -0
  40. data/resources/Localizable.strings +1 -0
  41. data/samples/gesture/Gemfile +2 -2
  42. data/samples/location/Gemfile +1 -1
  43. data/samples/osx/Gemfile +2 -2
  44. data/spec/motion/core/app_spec.rb +6 -0
  45. data/spec/motion/core/device/ios/camera_spec.rb +3 -3
  46. data/spec/motion/core/device/ios/screen_spec.rb +45 -0
  47. data/spec/motion/core/ios/app_spec.rb +29 -0
  48. data/spec/motion/core/persistence_spec.rb +25 -0
  49. data/spec/motion/core/string_spec.rb +2 -2
  50. data/spec/motion/core/time_spec.rb +14 -4
  51. data/spec/motion/core_spec.rb +9 -8
  52. data/spec/motion/http/query_spec.rb +92 -15
  53. data/spec/motion/http/response_spec.rb +4 -3
  54. data/spec/motion/location/location_spec.rb +1 -1
  55. data/spec/motion/mail/mail_spec.rb +125 -0
  56. data/spec/motion/mail/result_spec.rb +53 -0
  57. data/spec/motion/reactor/eventable_spec.rb +85 -0
  58. data/spec/motion/reactor_spec.rb +0 -20
  59. data/spec/motion/sms/result_spec.rb +38 -0
  60. data/spec/motion/sms/sms_spec.rb +71 -0
  61. data/spec/motion/ui/pollute_spec.rb +13 -0
  62. data/spec/motion/ui/ui_bar_button_item_spec.rb +8 -8
  63. data/spec/motion/ui/ui_control_wrapper_spec.rb +35 -0
  64. data/spec/motion/ui/ui_view_controller_wrapper_spec.rb +34 -0
  65. data/spec/motion/ui/ui_view_wrapper_spec.rb +62 -0
  66. data/travis.sh +7 -0
  67. metadata +52 -22
  68. data/motion/ui/gestures.rb +0 -57
  69. data/motion/ui/ui_control.rb +0 -14
  70. data/motion/ui/ui_view_controller.rb +0 -11
  71. data/spec/motion/ui/gestures_spec.rb +0 -62
  72. data/spec/motion/ui/ui_control_spec.rb +0 -42
@@ -0,0 +1,53 @@
1
+ describe BW::Mail::Result do
2
+
3
+ before do
4
+ @subject = BW::Mail::Result.new(MFMailComposeResultCancelled, nil)
5
+ end
6
+
7
+ it "should set sent? when sent" do
8
+ @subject.result = MFMailComposeResultSent
9
+ @subject.should.be.sent
10
+ end
11
+
12
+ it "should not set sent? when not sent" do
13
+ @subject.result = MFMailComposeResultCancelled
14
+ @subject.should.not.be.sent
15
+ end
16
+
17
+ it "should set canceled? when canceled" do
18
+ @subject.result = MFMailComposeResultCancelled
19
+ @subject.should.be.canceled
20
+ end
21
+
22
+ it "should not set canceled? when not canceled" do
23
+ @subject.result = MFMailComposeResultSent
24
+ @subject.should.not.be.canceled
25
+ end
26
+
27
+ it "should set saved? when saved" do
28
+ @subject.result = MFMailComposeResultSaved
29
+ @subject.should.be.saved
30
+ end
31
+
32
+ it "should not set saved? when not saved" do
33
+ @subject.result = MFMailComposeResultFailed
34
+ @subject.should.not.be.saved
35
+ end
36
+
37
+ it "should set failed? when failed" do
38
+ @subject.result = MFMailComposeResultFailed
39
+ @subject.should.be.failed
40
+ end
41
+
42
+ it "should not set failed? when not failed" do
43
+ @subject.result = MFMailComposeResultSent
44
+ @subject.should.not.be.failed
45
+ end
46
+
47
+ it "should set failed? when error" do
48
+ @subject.result = MFMailComposeResultCancelled
49
+ @subject.error = :errored
50
+ @subject.should.be.failed
51
+ end
52
+
53
+ end
@@ -30,6 +30,21 @@ describe BubbleWrap::Reactor::Eventable do
30
30
  @subject.off(:foo, &proof)
31
31
  events[:foo].member?(proof).should == false
32
32
  end
33
+
34
+ it 'calls other event procs when a proc unregisters itself' do
35
+ @proxy.proof = 0
36
+ proof1 = proc do |r|
37
+ @proxy.proof += r
38
+ @subject.off(:foo, &proof1)
39
+ end
40
+ proof2 = proc do |r|
41
+ @proxy.proof += r
42
+ end
43
+ @subject.on(:foo, &proof1)
44
+ @subject.on(:foo, &proof2)
45
+ @subject.trigger(:foo, 2)
46
+ @proxy.proof.should == 4
47
+ end
33
48
  end
34
49
 
35
50
  describe '.trigger' do
@@ -42,6 +57,15 @@ describe BubbleWrap::Reactor::Eventable do
42
57
  @proxy.proof.should == true
43
58
  end
44
59
 
60
+ it 'calls event procs for correct event' do
61
+ @proxy.proof = false
62
+ @subject.on(:foo) do |r|
63
+ @proxy.proof = r
64
+ end
65
+ @subject.trigger(:bar, true)
66
+ @proxy.proof.should == false
67
+ end
68
+
45
69
  it 'calls all the event procs' do
46
70
  @proxy.proof = 0
47
71
  @subject.on(:foo) { |r| @proxy.proof += r }
@@ -50,6 +74,67 @@ describe BubbleWrap::Reactor::Eventable do
50
74
  @subject.trigger(:foo, 2)
51
75
  @proxy.proof.should == 6
52
76
  end
77
+
78
+ class TestUIViewControllerWithEventable
79
+ include BubbleWrap::Reactor::Eventable
80
+ def test_on
81
+ on(:foo) do
82
+ end
83
+ end
84
+ def dealloc
85
+ $test_dealloc = true
86
+ super
87
+ end
88
+ end
89
+
90
+ describe 'memory implications' do
91
+
92
+ it 'does not cause a retain-cycle prior to loading __events__' do
93
+ autorelease_pool do
94
+ $test_dealloc = false
95
+ TestUIViewControllerWithEventable.alloc.init
96
+ end
97
+ wait 0 do
98
+ $test_dealloc.should == true
99
+ end
100
+ end
101
+
102
+ it 'does not cause a retain-cycle after calling trigger' do
103
+ autorelease_pool do
104
+ autorelease_pool do
105
+ $test_dealloc = false
106
+ obj = TestUIViewControllerWithEventable.alloc.init
107
+ obj.trigger(:something)
108
+ end
109
+ end
110
+ wait 0 do
111
+ $test_dealloc.should == true
112
+ end
113
+ end
114
+
115
+ it 'does not cause a retain-cycle after loading __events__' do
116
+ autorelease_pool do
117
+ $test_dealloc = false
118
+ obj = TestUIViewControllerWithEventable.alloc.init
119
+ obj.send(:__events__)
120
+ end
121
+ wait 0 do
122
+ $test_dealloc.should == true
123
+ end
124
+ end
125
+
126
+ it 'does not cause a retain-cycle after adding an event' do
127
+ autorelease_pool do
128
+ $test_dealloc = false
129
+ obj = TestUIViewControllerWithEventable.alloc.init
130
+ obj.test_on
131
+ end
132
+ wait 0 do
133
+ $test_dealloc.should == true
134
+ end
135
+ end
136
+
137
+ end
53
138
  end
54
139
 
55
140
  end
@@ -65,17 +65,6 @@ describe BubbleWrap::Reactor do
65
65
  @proxy.proof.should >= 2
66
66
  end
67
67
  end
68
-
69
- it 'runs callbacks repeatedly in common runloop modes' do
70
- @proxy.proof = 0
71
- @timer = @subject.add_periodic_timer 0.5, :common_modes => true do
72
- @proxy.proof = @proxy.proof + 1
73
- @subject.cancel_timer(@timer) if @proxy.proof > 2
74
- end
75
- wait 1.1 do
76
- @proxy.proof.should >= 2
77
- end
78
- end
79
68
  end
80
69
 
81
70
  describe '.cancel_timer' do
@@ -96,15 +85,6 @@ describe BubbleWrap::Reactor do
96
85
  @subject.cancel_timer(timer)
97
86
  @proxy.proof.should == true
98
87
  end
99
-
100
- it 'cancels common modes periodic timers' do
101
- @proxy.proof = true
102
- timer = @subject.add_periodic_timer 10.0, :common_modes => true do
103
- @proxy.proof = false
104
- end
105
- @subject.cancel_timer(timer)
106
- @proxy.proof.should == true
107
- end
108
88
  end
109
89
 
110
90
  describe '.defer' do
@@ -0,0 +1,38 @@
1
+ describe BW::SMS::Result do
2
+
3
+ before do
4
+ @subject = BW::SMS::Result.new(MessageComposeResultCancelled)
5
+ end
6
+
7
+ it "should set sent? when sent" do
8
+ @subject.result = MessageComposeResultSent
9
+ @subject.should.be.sent
10
+ end
11
+
12
+ it "should not set sent? when not sent" do
13
+ @subject.result = MessageComposeResultFailed
14
+ @subject.should.not.be.sent
15
+ end
16
+
17
+ it "should set canceled? when canceled" do
18
+ @subject.result = MessageComposeResultCancelled
19
+ @subject.should.be.canceled
20
+ end
21
+
22
+ it "should not set canceled? when not canceled" do
23
+ @subject.result = MessageComposeResultFailed
24
+ @subject.should.not.be.canceled
25
+ end
26
+
27
+
28
+ it "should set failed? when failed" do
29
+ @subject.result = MessageComposeResultFailed
30
+ @subject.should.be.failed
31
+ end
32
+
33
+ it "should not set failed? when not failed" do
34
+ @subject.result = MessageComposeResultSent
35
+ @subject.should.not.be.failed
36
+ end
37
+
38
+ end
@@ -0,0 +1,71 @@
1
+ # Mocking the presentViewController
2
+ class MessageViewController < UIViewController
3
+ attr_accessor :expectation
4
+
5
+ def presentModalViewController(modal, animated: animated)
6
+ expectation.call modal, animated
7
+ end
8
+ end
9
+
10
+ # Monkey-patching MFMessageComposeViewController
11
+ # So we can access the values that are set.
12
+ # This of course breaks MFMessageComposeViewController from actually working,
13
+ # but it's testable.
14
+ class MFMessageComposeViewController
15
+ attr_accessor :recipients, :body
16
+
17
+ # for iOS7 compatibility
18
+ # on similators, MFMessageComposeViewController.alloc.init returns nil
19
+ def init
20
+ self
21
+ end
22
+ end
23
+
24
+ describe BW::SMS do
25
+ describe ".compose" do
26
+ before do
27
+ @view_controller = MessageViewController.new
28
+ @standard_message_options = {
29
+ delegate: @view_controller,
30
+ to: [ "1(234)567-8910" ],
31
+ message: "This is my message. It isn't very long.",
32
+ animated: false
33
+ }
34
+ end
35
+
36
+ it "should open the message controller in a modal" do
37
+ @view_controller.expectation = lambda { |message_controller, animated|
38
+ message_controller.should.be.kind_of(MFMessageComposeViewController)
39
+ }
40
+
41
+ BW::SMS.compose @standard_message_options
42
+ end
43
+
44
+ it "should create a message controller with the right recipient address set" do
45
+ @view_controller.expectation = lambda { |message_controller, animated|
46
+ message_controller.recipients.should.be.kind_of(Array)
47
+ message_controller.recipients.should == @standard_message_options[:to]
48
+ }
49
+
50
+ BubbleWrap::SMS.compose @standard_message_options
51
+ end
52
+
53
+
54
+ it "should create a message controller with the right message: set" do
55
+ @view_controller.expectation = lambda { |message_controller, animated|
56
+ message_controller.body.should.be.kind_of(String)
57
+ message_controller.body.should == @standard_message_options[:message]
58
+ }
59
+
60
+ BubbleWrap::SMS.compose @standard_message_options
61
+ end
62
+
63
+ it "should create a mail controller with the right animation" do
64
+ @view_controller.expectation = lambda { |message_controller, animated|
65
+ animated.should.be.false
66
+ }
67
+ BubbleWrap::SMS.compose @standard_message_options
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,13 @@
1
+ describe "UIKit pollution" do
2
+ it "pollutes UIControl" do
3
+ UIControl.ancestors.should.include BW::UIControlWrapper
4
+ end
5
+
6
+ it "pollutes UIView" do
7
+ UIView.ancestors.should.include BW::UIViewWrapper
8
+ end
9
+
10
+ it "pollutes UIViewController" do
11
+ UIViewController.ancestors.should.include BW::UIViewControllerWrapper
12
+ end
13
+ end
@@ -9,8 +9,8 @@ describe BW::UIBarButtonItem do
9
9
 
10
10
  describe "given an invalid object" do
11
11
  it "raises an exception" do
12
- exception = should.raise(ArgumentError) { BW::UIBarButtonItem.styled(:plain, :object) }
13
- exception.message.should.equal("invalid object - :object")
12
+ exception = should.raise(ArgumentError) { BW::UIBarButtonItem.styled(:plain, 2) }
13
+ exception.message.should.equal("invalid object - 2")
14
14
  end
15
15
  end
16
16
 
@@ -87,7 +87,7 @@ describe BW::UIBarButtonItem do
87
87
  before do
88
88
  @object = UIImage.alloc.init
89
89
  @target = -> { true }
90
- @subject = BW::UIBarButtonItem.styled(:bordered, @object, &@target)
90
+ @subject = BW::UIBarButtonItem.styled(:done, @object, &@target)
91
91
  end
92
92
 
93
93
  it "has the correct class" do
@@ -99,7 +99,7 @@ describe BW::UIBarButtonItem do
99
99
  end
100
100
 
101
101
  it "has the correct style" do
102
- @subject.style.should.equal(UIBarButtonItemStyleBordered)
102
+ @subject.style.should.equal(UIBarButtonItemStyleDone)
103
103
  end
104
104
 
105
105
  it "has the correct image" do
@@ -349,7 +349,7 @@ describe BW::UIBarButtonItem do
349
349
 
350
350
  describe "given options for a styled item with an image" do
351
351
  before do
352
- @options = { :styled => :bordered, :image => UIImage.alloc.init }
352
+ @options = { :styled => :done, :image => UIImage.alloc.init }
353
353
  @target = -> { true }
354
354
  @subject = BW::UIBarButtonItem.new(@options, &@target)
355
355
  end
@@ -363,7 +363,7 @@ describe BW::UIBarButtonItem do
363
363
  end
364
364
 
365
365
  it "has the correct style" do
366
- @subject.style.should.equal(UIBarButtonItemStyleBordered)
366
+ @subject.style.should.equal(UIBarButtonItemStyleDone)
367
367
  end
368
368
 
369
369
  it "has the correct image" do
@@ -384,7 +384,7 @@ describe BW::UIBarButtonItem do
384
384
  describe "given options for a styled item with two images" do
385
385
  before do
386
386
  @options = {
387
- :styled => :bordered,
387
+ :styled => :done,
388
388
  :image => UIImage.alloc.init,
389
389
  :landscape => UIImage.alloc.init
390
390
  }
@@ -401,7 +401,7 @@ describe BW::UIBarButtonItem do
401
401
  end
402
402
 
403
403
  it "has the correct style" do
404
- @subject.style.should.equal(UIBarButtonItemStyleBordered)
404
+ @subject.style.should.equal(UIBarButtonItemStyleDone)
405
405
  end
406
406
 
407
407
  it "has the correct image" do
@@ -0,0 +1,35 @@
1
+ describe BW::UIControlWrapper do
2
+ describe "#when" do
3
+ before do
4
+ @subject = UIControl.alloc.init
5
+ @touched = []
6
+
7
+ @subject.when(UIControlEventTouchUpInside) do
8
+ @touched << 'for the very first time'
9
+ end
10
+ end
11
+
12
+ it "supports the 'when' event handler" do
13
+ @subject.sendActionsForControlEvents(UIControlEventTouchUpInside)
14
+ @touched.should.equal ['for the very first time']
15
+ end
16
+
17
+ it "replaces the target for a given control event by default" do
18
+ @subject.when(UIControlEventTouchUpInside) do
19
+ @touched << 'touched'
20
+ end
21
+
22
+ @subject.sendActionsForControlEvents(UIControlEventTouchUpInside)
23
+ @touched.should.equal ['touched']
24
+ end
25
+
26
+ it "allows multiple targets for a given control event if specified" do
27
+ @subject.when(UIControlEventTouchUpInside, append: true) do
28
+ @touched << 'touched'
29
+ end
30
+
31
+ @subject.sendActionsForControlEvents(UIControlEventTouchUpInside)
32
+ @touched.should.equal ['for the very first time', 'touched']
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ describe BW::UIViewControllerWrapper do
2
+ describe "#content_frame" do
3
+ describe "given a UIViewController" do
4
+ before do
5
+ @subject = UIViewController.alloc.init
6
+ end
7
+
8
+ it "has the correct content frame" do
9
+ height = App.frame.size.height
10
+ expected = CGRectMake(0, 0, App.frame.size.width, height)
11
+
12
+ @subject.content_frame.should.equal(expected)
13
+ end
14
+ end
15
+
16
+ ###############################################################################################
17
+
18
+ describe "given a UIViewController inside a UINavigationController" do
19
+ before do
20
+ @subject = UIViewController.alloc.init
21
+
22
+ UINavigationController.alloc.initWithRootViewController(@subject)
23
+ end
24
+
25
+ it "has the correct content frame" do
26
+ height = App.frame.size.height
27
+ height -= @subject.navigationController.navigationBar.frame.size.height
28
+ expected = CGRectMake(0, 0, App.frame.size.width, height)
29
+
30
+ @subject.content_frame.should.equal(expected)
31
+ end
32
+ end
33
+ end
34
+ end