ProMotion 1.0.4 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/ProMotion.gemspec +3 -2
  3. data/README.md +10 -7
  4. data/app/screens/basic_screen.rb +12 -0
  5. data/bin/promotion +45 -0
  6. data/lib/ProMotion/cocoatouch/table_view_controller.rb +2 -2
  7. data/lib/ProMotion/cocoatouch/view_controller.rb +2 -2
  8. data/lib/ProMotion/containers/split_screen.rb +6 -1
  9. data/lib/ProMotion/containers/tabs.rb +12 -1
  10. data/lib/ProMotion/delegate/delegate_module.rb +16 -2
  11. data/lib/ProMotion/delegate/delegate_notifications.rb +7 -7
  12. data/lib/ProMotion/map/map_screen_annotation.rb +10 -1
  13. data/lib/ProMotion/map/map_screen_module.rb +8 -3
  14. data/lib/ProMotion/pro_motion.rb +1 -1
  15. data/lib/ProMotion/screen/screen_module.rb +35 -16
  16. data/lib/ProMotion/screen/screen_navigation.rb +11 -13
  17. data/lib/ProMotion/table/extensions/indexable.rb +2 -2
  18. data/lib/ProMotion/table/extensions/searchable.rb +4 -3
  19. data/lib/ProMotion/table/grouped_table.rb +7 -2
  20. data/lib/ProMotion/table/table.rb +54 -47
  21. data/lib/ProMotion/thirdparty/formotion_screen.rb +5 -3
  22. data/lib/ProMotion/version.rb +1 -1
  23. data/lib/ProMotion/view/styling.rb +33 -20
  24. data/resources/test.png +0 -0
  25. data/spec/functional/func_map_screen_spec.rb +60 -3
  26. data/spec/functional/func_screen_spec.rb +29 -6
  27. data/spec/functional/func_searchable_table_spec.rb +13 -1
  28. data/spec/functional/func_split_screen_spec.rb +8 -0
  29. data/spec/functional/func_table_screen_spec.rb +28 -23
  30. data/spec/functional/func_web_screen_spec.rb +1 -1
  31. data/spec/helpers/custom_title_view.rb +4 -0
  32. data/spec/helpers/home_screen.rb +6 -0
  33. data/spec/helpers/table_screen.rb +23 -27
  34. data/spec/helpers/table_screen_formotion.rb +5 -0
  35. data/spec/helpers/table_screen_searchable.rb +10 -0
  36. data/spec/helpers/test_delegate_colors.rb +17 -0
  37. data/spec/helpers/test_helper.rb +5 -0
  38. data/spec/unit/delegate_spec.rb +79 -1
  39. data/spec/unit/map_spec.rb +22 -0
  40. data/spec/unit/screen_helpers_spec.rb +44 -35
  41. data/spec/unit/screen_spec.rb +45 -6
  42. data/spec/unit/split_screen_open_screen_spec.rb +1 -1
  43. data/spec/unit/tables/formotion_screen_spec.rb +6 -0
  44. data/spec/unit/tables/table_module_spec.rb +28 -2
  45. data/spec/unit/tables/table_view_cell_spec.rb +5 -4
  46. data/spec/unit/view_helper_spec.rb +21 -10
  47. metadata +28 -6
  48. data/resources/test.jpeg +0 -0
Binary file
@@ -6,7 +6,20 @@ describe "ProMotion::TestMapScreen functionality" do
6
6
  rotate_device to: :portrait, button: :bottom
7
7
  @map ||= TestMapScreen.new(nav_bar: true)
8
8
  @map.will_appear
9
- @map.navigation_controller
9
+ @map.navigationController
10
+ end
11
+
12
+ def add_image_annotation
13
+ ann = {
14
+ longitude: -82.965972900392,
15
+ latitude: 35.090648651124,
16
+ title: "My Cool Image Pin",
17
+ subtitle: "Image pin subtitle",
18
+ image: UIImage.imageNamed("test.png")
19
+ }
20
+ @map.annotations.count.should == 5
21
+ @map.add_annotation ann
22
+ @map.set_region @map.region(coordinate: @map.annotations.last.coordinate, span: [0.05, 0.05])
10
23
  end
11
24
 
12
25
  after do
@@ -19,8 +32,8 @@ describe "ProMotion::TestMapScreen functionality" do
19
32
 
20
33
  it "should have the map properly centered" do
21
34
  center_coordinate = @map.center
22
- center_coordinate.latitude.should.be.close 35.090648651123, 0.001
23
- center_coordinate.longitude.should.be.close -82.965972900391, 0.001
35
+ center_coordinate.latitude.should.be.close 35.090648651123, 0.02
36
+ center_coordinate.longitude.should.be.close -82.965972900391, 0.02
24
37
  end
25
38
 
26
39
  it "should move the map center" do
@@ -102,4 +115,48 @@ describe "ProMotion::TestMapScreen functionality" do
102
115
  @map.annotations.count.should == 2
103
116
  end
104
117
 
118
+ it "should add an image based annotation" do
119
+ add_image_annotation
120
+ @map.annotations.count.should == 6
121
+
122
+ # Checking that it conforms to the MKAnnotation protocol manually since this doesn't work in iOS 7:
123
+ # @map.annotations.last.conformsToProtocol(MKAnnotation).should.be.true
124
+ # See this 8 month old bug - https://github.com/siuying/rubymotion-protocol-bug
125
+
126
+ checking = @map.annotations.last
127
+ %w(title subtitle coordinate).each do |method|
128
+ defined?(checking.send(method.to_sym)).nil?.should.be.false
129
+ end
130
+ end
131
+
132
+ it "should select an image annotation" do
133
+ add_image_annotation
134
+ @map.selected_annotations.should == nil
135
+ @map.select_annotation @map.annotations.last
136
+ wait 0.75 do
137
+ @map.selected_annotations.count.should == 1
138
+ end
139
+ end
140
+
141
+ it "should select an image annotation by index" do
142
+ add_image_annotation
143
+ @map.selected_annotations.should == nil
144
+ @map.select_annotation_at 5
145
+ wait 0.75 do
146
+ @map.selected_annotations.count.should == 1
147
+ @map.selected_annotations[0].should == @map.promotion_annotation_data[5]
148
+ end
149
+ end
150
+
151
+ it "should select an image annotation and check that the title is correct" do
152
+ add_image_annotation
153
+ @map.selected_annotations.should == nil
154
+ @map.select_annotation @map.annotations[5]
155
+ wait 0.75 do
156
+ @map.selected_annotations.count.should == 1
157
+ end
158
+ @map.selected_annotations.first.title.should == "My Cool Image Pin"
159
+ @map.selected_annotations.first.subtitle.should == "Image pin subtitle"
160
+ end
161
+
105
162
  end
@@ -6,7 +6,7 @@ describe "ProMotion::Screen functional" do
6
6
  rotate_device to: :portrait, button: :bottom
7
7
  @controller ||= FunctionalScreen.new(nav_bar: true)
8
8
  @root_screen = @controller
9
- @controller.navigation_controller
9
+ @controller.navigationController
10
10
  end
11
11
 
12
12
  after do
@@ -44,8 +44,31 @@ describe "ProMotion::Screen functional" do
44
44
  end
45
45
 
46
46
  end
47
+
47
48
  end
48
49
 
50
+ it "should push another screen with animation by default" do
51
+ basic = @root_screen.open BasicScreen
52
+ wait 0.5 do
53
+ basic.animation_ts.should.be > 0.2
54
+ end
55
+ end
56
+
57
+ it "should push another screen with animation when animated: true" do
58
+ basic = @root_screen.open BasicScreen, animated: true
59
+ wait 0.5 do
60
+ basic.animation_ts.should.be > 0.2
61
+ end
62
+ end
63
+
64
+ it "should push another screen without animation when animated: false" do
65
+ basic = @root_screen.open BasicScreen, animated: false
66
+ wait 0.5 do
67
+ basic.animation_ts.should.be < 0.2
68
+ end
69
+ end
70
+
71
+
49
72
  it "should allow opening and closing a modal screen" do
50
73
  @basic = BasicScreen.new(nav_bar: true)
51
74
  wait 0.1 do
@@ -91,19 +114,19 @@ describe "ProMotion::Screen functional" do
91
114
  end
92
115
 
93
116
  it "should pop to the root view controller" do
94
- @root_vc = @controller.navigation_controller.visibleViewController
95
- @controller.navigation_controller.viewControllers.count.should == 1
117
+ @root_vc = @controller.navigationController.visibleViewController
118
+ @controller.navigationController.viewControllers.count.should == 1
96
119
  @controller.open BasicScreen.new
97
120
  wait 0.6 do
98
121
  @controller.open BasicScreen.new
99
122
  wait 0.6 do
100
123
  @controller.open BasicScreen.new
101
124
  wait 0.6 do
102
- @controller.navigation_controller.viewControllers.count.should == 4
125
+ @controller.navigationController.viewControllers.count.should == 4
103
126
  @controller.close to_screen: :root
104
127
  wait 0.6 do
105
- @controller.navigation_controller.viewControllers.count.should == 1
106
- @controller.navigation_controller.topViewController.should == @root_vc
128
+ @controller.navigationController.viewControllers.count.should == 1
129
+ @controller.navigationController.topViewController.should == @root_vc
107
130
  end
108
131
  end
109
132
  end
@@ -5,7 +5,7 @@ describe "Searchable table spec" do
5
5
  def controller
6
6
  @controller ||= TableScreenSearchable.new(nav_bar: true)
7
7
  @controller.on_load
8
- @controller.navigation_controller
8
+ @controller.navigationController
9
9
  end
10
10
 
11
11
  it "should be rotated in portrait mode" do
@@ -41,4 +41,16 @@ describe "Searchable table spec" do
41
41
  @controller.original_search_string.should == false
42
42
  end
43
43
 
44
+ it "should call the start and stop searching callbacks properly" do
45
+ @controller.will_begin_search_called.should == nil
46
+ @controller.will_end_search_called.should == nil
47
+
48
+ @controller.searchDisplayControllerWillBeginSearch(@controller)
49
+ @controller.searchDisplayController(@controller, shouldReloadTableForSearchString:"North")
50
+ @controller.will_begin_search_called.should == true
51
+
52
+ @controller.searchDisplayControllerWillEndSearch(@controller)
53
+ @controller.will_end_search_called.should == true
54
+ end
55
+
44
56
  end
@@ -63,4 +63,12 @@ describe "Split screen functional" do
63
63
 
64
64
  end
65
65
 
66
+ it "should override the title on the button" do
67
+ rotate_device to: :portrait, button: :bottom
68
+
69
+ test_title = "Test Title"
70
+ @controller = @app.open_split_screen @master, @detail, button_title: test_title
71
+ @detail.navigationItem.leftBarButtonItem.title.should == test_title
72
+ end
73
+
66
74
  end
@@ -6,7 +6,11 @@ describe "ProMotion::TestTableScreen functionality" do
6
6
  rotate_device to: :portrait, button: :bottom
7
7
  @controller ||= TestTableScreen.new(nav_bar: true)
8
8
  @controller.on_load
9
- @controller.navigation_controller
9
+ @controller.navigationController
10
+ end
11
+
12
+ def confirmation_class
13
+ TestHelper.ios7 ? UITableViewCellDeleteConfirmationButton : UITableViewCellDeleteConfirmationControl
10
14
  end
11
15
 
12
16
  it "should have a navigation bar" do
@@ -58,7 +62,7 @@ describe "ProMotion::TestTableScreen functionality" do
58
62
  wait 0.25 do
59
63
  # Tap the delete button
60
64
  view('Just another deletable blank row').superview.superview.subviews.each do |subview|
61
- if subview.class == UITableViewCellDeleteConfirmationControl
65
+ if subview.class == confirmation_class
62
66
  tap subview
63
67
  wait 0.25 do
64
68
  @controller.tableView(@controller.tableView, numberOfRowsInSection:0).should == 6
@@ -77,7 +81,7 @@ describe "ProMotion::TestTableScreen functionality" do
77
81
  wait 0.25 do
78
82
  # Tap the delete button
79
83
  view('A non-deletable blank row').superview.superview.subviews.each do |subview|
80
- if subview.class == UITableViewCellDeleteConfirmationControl
84
+ if subview.class == confirmation_class
81
85
  tap subview
82
86
  wait 0.25 do
83
87
  @controller.tableView(@controller.tableView, numberOfRowsInSection:0).should == 7
@@ -88,33 +92,34 @@ describe "ProMotion::TestTableScreen functionality" do
88
92
  end
89
93
  end
90
94
 
95
+ # Disabled by Jamon 10/16/2013 -- Bacon doesn't appear to use accessibility labels?
91
96
  it "should call a method when the switch is flipped" do
92
- @controller.scroll_to_bottom
93
- tap "switch_1"
94
- wait 0.3 do
95
- @controller.tap_counter.should == 1
96
- end
97
+ # @controller.scroll_to_bottom
98
+ # tap "switch_1"
99
+ # wait 0.3 do
100
+ # @controller.tap_counter.should == 1
101
+ # end
97
102
  end
98
103
 
99
104
  it "should call the method with arguments when the switch is flipped and when the cell is tapped" do
100
- @controller.scroll_to_bottom
101
- tap "switch_3"
102
- wait 0.3 do
103
- @controller.tap_counter.should == 3
104
-
105
- tap "Switch With Cell Tap, Switch Action And Parameters"
106
- wait 0.3 do
107
- @controller.tap_counter.should == 13
108
- end
109
- end
105
+ # @controller.scroll_to_bottom
106
+ # tap "switch_3"
107
+ # wait 0.3 do
108
+ # @controller.tap_counter.should == 3
109
+
110
+ # tap "Switch With Cell Tap, Switch Action And Parameters"
111
+ # wait 0.3 do
112
+ # @controller.tap_counter.should == 13
113
+ # end
114
+ # end
110
115
  end
111
116
 
112
117
  it "should call the method with arguments when the switch is flipped" do
113
- @controller.scroll_to_bottom
114
- tap "switch_2"
115
- wait 0.3 do
116
- @controller.tap_counter.should == 3
117
- end
118
+ # @controller.scroll_to_bottom
119
+ # tap "switch_2"
120
+ # wait 0.3 do
121
+ # @controller.tap_counter.should == 3
122
+ # end
118
123
  end
119
124
 
120
125
  end
@@ -10,7 +10,7 @@ describe "ProMotion::TestWebScreen functionality" do
10
10
  def controller
11
11
  rotate_device to: :portrait, button: :bottom
12
12
  @webscreen ||= TestWebScreen.new(nav_bar: true)
13
- @webscreen.navigation_controller
13
+ @webscreen.navigationController
14
14
  end
15
15
 
16
16
  after do
@@ -0,0 +1,4 @@
1
+ class CustomTitleView < UITableViewCell
2
+ attr_accessor :title
3
+ end
4
+
@@ -10,4 +10,10 @@ class HomeScreen < ProMotion::Screen
10
10
  def on_return(args={})
11
11
  end
12
12
 
13
+ def subview_styles
14
+ {
15
+ backgroundColor: UIColor.greenColor
16
+ }
17
+ end
18
+
13
19
  end
@@ -2,10 +2,6 @@ class TestTableScreen < ProMotion::TableScreen
2
2
 
3
3
  attr_accessor :tap_counter, :cell_was_deleted
4
4
 
5
- def promotion_table_data
6
- @promotion_table_data
7
- end
8
-
9
5
  def on_load
10
6
  self.tap_counter = 0
11
7
  set_attributes self.view, { backgroundView: nil, backgroundColor: UIColor.whiteColor }
@@ -41,32 +37,32 @@ class TestTableScreen < ProMotion::TableScreen
41
37
  }, {
42
38
  title: "Cell Accessory Tests",
43
39
  cells: [{
44
- title: "Switch With Action",
45
- accessory: {
46
- view: :switch,
47
- action: :increment_counter,
48
- accessibility_label: "switch_1"
49
- } ,
50
- }, {
51
- title: "Switch With Action And Parameters",
52
- accessory: {
40
+ title: "Switch With Action",
41
+ accessory: {
53
42
  view: :switch,
54
- action: :increment_counter_by,
55
- arguments: { number: 3 },
56
- accessibility_label: "switch_2"
43
+ action: :increment_counter,
44
+ accessibility_label: "switch_1"
57
45
  } ,
58
- }, {
59
- title: "Switch With Cell Tap, Switch Action And Parameters",
60
- accessory:{
61
- view: :switch,
62
- action: :increment_counter_by,
63
- arguments: { number: 3 },
64
- accessibility_label: "switch_3"
65
- },
46
+ }, {
47
+ title: "Switch With Action And Parameters",
48
+ accessory: {
49
+ view: :switch,
50
+ action: :increment_counter_by,
51
+ arguments: { number: 3 },
52
+ accessibility_label: "switch_2"
53
+ } ,
54
+ }, {
55
+ title: "Switch With Cell Tap, Switch Action And Parameters",
56
+ accessory:{
57
+ view: :switch,
66
58
  action: :increment_counter_by,
67
- arguments: { number: 10 }
68
- }]
69
- }]
59
+ arguments: { number: 3 },
60
+ accessibility_label: "switch_3"
61
+ },
62
+ action: :increment_counter_by,
63
+ arguments: { number: 10 }
64
+ }]
65
+ }]
70
66
  end
71
67
 
72
68
  def edit_profile(args={})
@@ -1,4 +1,5 @@
1
1
  class TestFormotionScreen < PM::FormotionScreen
2
+ attr_accessor :submitted_form
2
3
 
3
4
  title "Formotion Test"
4
5
 
@@ -22,4 +23,8 @@ class TestFormotionScreen < PM::FormotionScreen
22
23
  }
23
24
  end
24
25
 
26
+ def on_submit(form)
27
+ self.submitted_form = form
28
+ end
29
+
25
30
  end
@@ -2,6 +2,8 @@ class TableScreenSearchable < TestTableScreen
2
2
 
3
3
  searchable
4
4
 
5
+ attr_accessor :will_end_search_called, :will_begin_search_called
6
+
5
7
  def table_data
6
8
  @search_table_data ||= [{
7
9
  cells: [
@@ -59,4 +61,12 @@ class TableScreenSearchable < TestTableScreen
59
61
  }]
60
62
  end
61
63
 
64
+ def will_begin_search
65
+ self.will_begin_search_called = true
66
+ end
67
+
68
+ def will_end_search
69
+ self.will_end_search_called = true
70
+ end
71
+
62
72
  end
@@ -0,0 +1,17 @@
1
+ class TestDelegateColored < TestDelegate
2
+ status_bar false
3
+
4
+ def on_load(app, options)
5
+ open BasicScreen.new(nav_bar: true)
6
+ end
7
+ end
8
+
9
+ class TestDelegateRed < TestDelegateColored
10
+ tint_color UIColor.redColor
11
+ end
12
+
13
+ # Other colors
14
+
15
+ # class TestDelegateBlack < TestDelegateColored
16
+ # tint_color UIColor.blackColor
17
+ # end
@@ -0,0 +1,5 @@
1
+ class TestHelper
2
+ def self.ios7
3
+ UIDevice.currentDevice.systemVersion.to_f >= 7.0
4
+ end
5
+ end
@@ -1,5 +1,4 @@
1
1
  describe "PM::Delegate" do
2
-
3
2
  before { @subject = TestDelegate.new }
4
3
 
5
4
  it 'should call on_load on launch' do
@@ -27,6 +26,53 @@ describe "PM::Delegate" do
27
26
 
28
27
  end
29
28
 
29
+ it "should return the registered push notification types as an array" do
30
+ @subject.registered_push_notifications.should == []
31
+ bits = 0
32
+ types = []
33
+ { badge: UIRemoteNotificationTypeBadge,
34
+ sound: UIRemoteNotificationTypeSound,
35
+ alert: UIRemoteNotificationTypeAlert,
36
+ newsstand: UIRemoteNotificationTypeNewsstandContentAvailability }.each do |symbol, bit|
37
+ UIApplication.sharedApplication.stub!(:enabledRemoteNotificationTypes, return: bit)
38
+ @subject.registered_push_notifications.should == [symbol]
39
+
40
+ bits |= bit
41
+ types << symbol
42
+ UIApplication.sharedApplication.stub!(:enabledRemoteNotificationTypes, return: bits)
43
+ @subject.registered_push_notifications.should == types
44
+ end
45
+ end
46
+
47
+ it "should return false for was_launched if the app is currently active on screen" do
48
+ @subject.mock!(:on_push_notification) do |notification, was_launched|
49
+ was_launched.should.be.false
50
+ end
51
+
52
+ fake_app = Struct.new(:applicationState).new(UIApplicationStateActive)
53
+ remote_notification = PM::PushNotification.fake_notification.notification
54
+ @subject.application(fake_app, didReceiveRemoteNotification: remote_notification)
55
+ end
56
+
57
+ it "should return true for was_launched if app was launched from background" do
58
+ @subject.mock!(:on_push_notification) do |notification, was_launched|
59
+ was_launched.should.be.true
60
+ end
61
+
62
+ fake_app = Struct.new(:applicationState).new(UIApplicationStateBackground)
63
+ remote_notification = PM::PushNotification.fake_notification.notification
64
+ @subject.application(fake_app, didReceiveRemoteNotification: remote_notification)
65
+ end
66
+
67
+ it "should return true for was_launched if the app wasn't running" do
68
+ @subject.mock!(:on_push_notification) do |notification, was_launched|
69
+ was_launched.should.be.true
70
+ end
71
+
72
+ launch_options = { UIApplicationLaunchOptionsRemoteNotificationKey => PM::PushNotification.fake_notification.notification }
73
+ @subject.application(UIApplication.sharedApplication, didFinishLaunchingWithOptions:launch_options )
74
+ end
75
+
30
76
  it "should set home_screen when opening a new screen" do
31
77
  @subject.application(UIApplication.sharedApplication, willFinishLaunchingWithOptions: nil)
32
78
  @subject.application(UIApplication.sharedApplication, didFinishLaunchingWithOptions: nil)
@@ -84,4 +130,36 @@ describe "PM::Delegate" do
84
130
  @subject.called_on_unload.should == true
85
131
  end
86
132
 
133
+ it "should handle open URL" do
134
+ url = NSURL.URLWithString("http://example.com")
135
+ sourceApplication = 'com.example'
136
+ annotation = {jamon: true}
137
+ @subject.mock!(:on_open_url) do |parameters|
138
+ parameters[:url].should == url
139
+ parameters[:source_app].should == sourceApplication
140
+ parameters[:annotation][:jamon].should.be.true
141
+ end
142
+
143
+ @subject.application(UIApplication.sharedApplication, openURL: url, sourceApplication:sourceApplication, annotation: annotation)
144
+ end
145
+
87
146
  end
147
+
148
+ # iOS 7 ONLY tests
149
+ if TestHelper.ios7
150
+ describe "PM::Delegate Colors" do
151
+
152
+ before do
153
+ @subject = TestDelegateRed.new
154
+ @map = TestMapScreen.new modal: true, nav_bar: true
155
+ @map.view_will_appear(false)
156
+ @subject.open @map
157
+ end
158
+
159
+ it 'should set the application tint color on iOS 7' do
160
+ @map.view.tintColor.should == UIColor.redColor
161
+ end
162
+
163
+ end
164
+
165
+ end # End iOS 7 ONLY tests