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.
- checksums.yaml +6 -14
- data/.travis.yml +2 -1
- data/CHANGELOG.md +26 -2
- data/GETTING_STARTED.md +1 -1
- data/Gemfile.lock +1 -1
- data/HACKING.md +6 -4
- data/README.md +83 -3
- data/Rakefile +9 -7
- data/lib/bubble-wrap/all.rb +2 -2
- data/lib/bubble-wrap/mail.rb +9 -0
- data/lib/bubble-wrap/sms.rb +9 -0
- data/lib/bubble-wrap/ui.rb +6 -2
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core.rb +1 -1
- data/motion/core/app.rb +7 -2
- data/motion/core/device/ios/camera.rb +3 -2
- data/motion/core/device/ios/screen.rb +19 -0
- data/motion/core/ios/app.rb +13 -1
- data/motion/core/ios/device.rb +5 -0
- data/motion/core/json.rb +1 -3
- data/motion/core/kvo.rb +11 -13
- data/motion/core/persistence.rb +8 -1
- data/motion/core/string.rb +3 -3
- data/motion/core/time.rb +5 -0
- data/motion/http.rb +1 -1
- data/motion/http/query.rb +39 -19
- data/motion/http/response.rb +4 -4
- data/motion/mail/mail.rb +59 -0
- data/motion/mail/result.rb +29 -0
- data/motion/reactor/eventable.rb +3 -2
- data/motion/reactor/periodic_timer.rb +12 -8
- data/motion/reactor/timer.rb +11 -7
- data/motion/sms/result.rb +24 -0
- data/motion/sms/sms.rb +47 -0
- data/motion/ui/pollute.rb +4 -1
- data/motion/ui/ui_alert_view.rb +15 -8
- data/motion/ui/ui_control_wrapper.rb +16 -0
- data/motion/ui/ui_view_controller_wrapper.rb +13 -0
- data/motion/ui/ui_view_wrapper.rb +55 -0
- data/resources/Localizable.strings +1 -0
- data/samples/gesture/Gemfile +2 -2
- data/samples/location/Gemfile +1 -1
- data/samples/osx/Gemfile +2 -2
- data/spec/motion/core/app_spec.rb +6 -0
- data/spec/motion/core/device/ios/camera_spec.rb +3 -3
- data/spec/motion/core/device/ios/screen_spec.rb +45 -0
- data/spec/motion/core/ios/app_spec.rb +29 -0
- data/spec/motion/core/persistence_spec.rb +25 -0
- data/spec/motion/core/string_spec.rb +2 -2
- data/spec/motion/core/time_spec.rb +14 -4
- data/spec/motion/core_spec.rb +9 -8
- data/spec/motion/http/query_spec.rb +92 -15
- data/spec/motion/http/response_spec.rb +4 -3
- data/spec/motion/location/location_spec.rb +1 -1
- data/spec/motion/mail/mail_spec.rb +125 -0
- data/spec/motion/mail/result_spec.rb +53 -0
- data/spec/motion/reactor/eventable_spec.rb +85 -0
- data/spec/motion/reactor_spec.rb +0 -20
- data/spec/motion/sms/result_spec.rb +38 -0
- data/spec/motion/sms/sms_spec.rb +71 -0
- data/spec/motion/ui/pollute_spec.rb +13 -0
- data/spec/motion/ui/ui_bar_button_item_spec.rb +8 -8
- data/spec/motion/ui/ui_control_wrapper_spec.rb +35 -0
- data/spec/motion/ui/ui_view_controller_wrapper_spec.rb +34 -0
- data/spec/motion/ui/ui_view_wrapper_spec.rb +62 -0
- data/travis.sh +7 -0
- metadata +52 -22
- data/motion/ui/gestures.rb +0 -57
- data/motion/ui/ui_control.rb +0 -14
- data/motion/ui/ui_view_controller.rb +0 -11
- data/spec/motion/ui/gestures_spec.rb +0 -62
- 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
|
data/spec/motion/reactor_spec.rb
CHANGED
@@ -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,
|
13
|
-
exception.message.should.equal("invalid 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(:
|
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(
|
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 => :
|
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(
|
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 => :
|
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(
|
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
|