bubble-wrap 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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