ProMotion 2.4.2 → 2.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -13
  3. data/lib/ProMotion.rb +40 -14
  4. data/lib/ProMotion/cocoatouch/collection_view_cell.rb +8 -0
  5. data/lib/ProMotion/cocoatouch/collection_view_controller.rb +49 -0
  6. data/lib/ProMotion/cocoatouch/view_controller.rb +5 -0
  7. data/lib/ProMotion/collection/cell/collection_view_cell_module.rb +17 -0
  8. data/lib/ProMotion/collection/collection.rb +106 -0
  9. data/lib/ProMotion/collection/collection_builder.rb +39 -0
  10. data/lib/ProMotion/collection/collection_class_methods.rb +38 -0
  11. data/lib/ProMotion/collection/collection_screen.rb +8 -0
  12. data/lib/ProMotion/collection/data/collection_data.rb +32 -0
  13. data/lib/ProMotion/collection/data/collection_data_builder.rb +18 -0
  14. data/lib/ProMotion/delegate/delegate_module.rb +1 -1
  15. data/lib/ProMotion/ipad/split_screen.rb +0 -1
  16. data/lib/ProMotion/repl/live_reloader.rb +76 -0
  17. data/lib/ProMotion/repl/repl.rb +65 -0
  18. data/lib/ProMotion/screen/nav_bar_module.rb +8 -1
  19. data/lib/ProMotion/screen/screen_module.rb +26 -3
  20. data/lib/ProMotion/screen/screen_navigation.rb +3 -0
  21. data/lib/ProMotion/table/cell/table_view_cell_module.rb +11 -0
  22. data/lib/ProMotion/table/extensions/searchable.rb +11 -0
  23. data/lib/ProMotion/table/table.rb +12 -1
  24. data/lib/ProMotion/table/table_builder.rb +7 -5
  25. data/lib/ProMotion/tabs/tabs.rb +6 -3
  26. data/lib/ProMotion/version.rb +1 -1
  27. data/spec/functional/func_screen_spec.rb +25 -20
  28. data/spec/functional/func_split_screen_spec.rb +2 -2
  29. data/spec/unit/collection_screen_spec.rb +133 -0
  30. data/spec/unit/screen_helpers_spec.rb +1 -1
  31. data/spec/unit/screen_spec.rb +44 -6
  32. data/spec/unit/tables/table_module_spec.rb +28 -2
  33. data/spec/unit/tables/table_refreshable_spec.rb +25 -0
  34. data/spec/unit/tables/table_screen_spec.rb +0 -56
  35. data/spec/unit/tables/table_searchable_spec.rb +41 -0
  36. data/spec/unit/tables/table_view_cell_spec.rb +20 -1
  37. metadata +22 -5
@@ -1,3 +1,3 @@
1
1
  module ProMotion
2
- VERSION = "2.4.2" unless defined?(ProMotion::VERSION)
2
+ VERSION = "2.5.0.beta1" unless defined?(ProMotion::VERSION)
3
3
  end
@@ -1,37 +1,42 @@
1
1
  describe "ProMotion::Screen functionality" do
2
- tests PM::Screen
2
+ tests FunctionalScreen
3
3
 
4
4
  before { UIView.setAnimationDuration 0.01 }
5
5
 
6
6
  # Override controller to properly instantiate
7
+ def screen
8
+ @screen ||= FunctionalScreen.new
9
+ end
10
+
7
11
  def controller
8
- rotate_device to: :portrait, button: :bottom
9
- @controller = FunctionalScreen.new(nav_bar: true)
10
- @controller.navigationController
12
+ screen.navigationController
11
13
  end
12
14
 
15
+ before { rotate_device to: :portrait, button: :bottom }
16
+ after { @screen = nil }
17
+
13
18
  it "should call the on_back method on the root controller when navigating back" do
14
19
  presented_screen = PresentScreen.new
15
- @controller.open presented_screen, animated: false
16
- @controller.navigationController.viewControllers.should == [ @controller, presented_screen ]
20
+ screen.open presented_screen, animated: false
21
+ screen.navigationController.viewControllers.should == [ screen, presented_screen ]
17
22
  presented_screen.close animated: false
18
- @controller.on_back_fired.should == true
23
+ screen.on_back_fired.should == true
19
24
  end
20
25
 
21
26
  it "should call the correct on_back method when nesting screens" do
22
- child_screen = @controller.open NavigationScreen.new, animated: false
27
+ child_screen = screen.open NavigationScreen.new, animated: false
23
28
  grandchild_screen = child_screen.open NavigationScreen.new, animated: false
24
29
 
25
30
  # start closing
26
31
  grandchild_screen.close animated: false
27
32
  child_screen.on_back_fired.should == true
28
33
  child_screen.close animated: false
29
- @controller.on_back_fired.should == true
34
+ screen.on_back_fired.should == true
30
35
  end
31
36
 
32
37
  it "should fire the will_present, on_present, will_dismiss, and on_dismiss_methods" do
33
38
  @presented_screen = PresentScreen.new
34
- @controller.open @presented_screen, animated: false
39
+ screen.open @presented_screen, animated: false
35
40
 
36
41
  wait 0.01 do
37
42
  @presented_screen.will_present_fired.should == true
@@ -55,20 +60,20 @@ describe "ProMotion::Screen functionality" do
55
60
  end
56
61
  end
57
62
 
58
- it "should pop to the root view controller" do
59
- @root_vc = @controller.navigationController.visibleViewController
60
- @controller.navigationController.viewControllers.count.should == 1
61
- @controller.open BasicScreen.new, animated: false
63
+ it "should pop to the root view screen" do
64
+ @root_vc = screen.navigationController.visibleViewController
65
+ screen.navigationController.viewControllers.count.should == 1
66
+ screen.open BasicScreen.new, animated: false
62
67
  wait 0.01 do
63
- @controller.open BasicScreen.new, animated: false
68
+ screen.open BasicScreen.new, animated: false
64
69
  wait 0.01 do
65
- @controller.open BasicScreen.new, animated: false
70
+ screen.open BasicScreen.new, animated: false
66
71
  wait 0.01 do
67
- @controller.navigationController.viewControllers.count.should == 4
68
- @controller.close to_screen: :root, animated: false
72
+ screen.navigationController.viewControllers.count.should == 4
73
+ screen.close to_screen: :root, animated: false
69
74
  wait 0.01 do
70
- @controller.navigationController.viewControllers.count.should == 1
71
- @controller.navigationController.topViewController.should == @root_vc
75
+ screen.navigationController.viewControllers.count.should == 1
76
+ screen.navigationController.topViewController.should == @root_vc
72
77
  end
73
78
  end
74
79
  end
@@ -31,7 +31,7 @@ describe "Split screen functionality" do
31
31
 
32
32
  it "should allow opening another view from the master view" do
33
33
 
34
- @master.open BasicScreen, animated: false
34
+ @master.open BasicScreen.new(nav_bar: true), animated: false
35
35
 
36
36
  view("Basic").should.be.kind_of UINavigationItemView
37
37
  view("Detail").should.be.kind_of UINavigationItemView
@@ -50,7 +50,7 @@ describe "Split screen functionality" do
50
50
 
51
51
  it "should allow opening another view from the detail view" do
52
52
 
53
- @detail.open BasicScreen, animated: false
53
+ @detail.open BasicScreen.new(nav_bar: true), animated: false
54
54
 
55
55
  view("Basic").should.be.kind_of UINavigationItemView
56
56
  view("Master").should.be.kind_of UINavigationItemView
@@ -0,0 +1,133 @@
1
+ describe "collection screens" do
2
+ tests TestCollectionScreen
3
+
4
+ def screen
5
+ @screen ||= TestCollectionScreen.new(nav_bar: true)
6
+ end
7
+
8
+ def controller
9
+ screen.navigationController
10
+ end
11
+
12
+ describe "basic functionality" do
13
+
14
+ before do
15
+ @screen = TestCollectionScreen.new(nav_bar: true)
16
+ @view = @screen.collection_view
17
+ end
18
+
19
+ after do
20
+ @screen = nil
21
+ end
22
+
23
+ it "should display some sections" do
24
+ @screen.promotion_collection_data.sections.should.be.kind_of(Array)
25
+ end
26
+
27
+ it "should have the proper number of sections" do
28
+ @view.numberOfSections.should == 11
29
+ @screen.numberOfSectionsInCollectionView(@view).should == 11
30
+ end
31
+
32
+ it "should have the proper number of cells" do
33
+ @view.numberOfItemsInSection(1).should == 10
34
+ @screen.collectionView(@view, numberOfItemsInSection: 1).should == 10
35
+ end
36
+
37
+ it "should call the action" do
38
+ @screen.mock! :touched do |args|
39
+ args[:data].should == ['action']
40
+ end
41
+
42
+ index_path = NSIndexPath.indexPathForRow(1, inSection: 1)
43
+ @screen.collectionView(@view, didSelectItemAtIndexPath: index_path)
44
+ end
45
+
46
+ it "should proc the action" do
47
+ @screen.mock! :touched do |args|
48
+ args[:data].should == ['proc']
49
+ end
50
+
51
+ index_path = NSIndexPath.indexPathForRow(1, inSection: 10)
52
+ @screen.collectionView(@view, didSelectItemAtIndexPath: index_path)
53
+ end
54
+
55
+ it "should reload data" do
56
+ data = (1..2).to_a.map do |i|
57
+ (1..3).to_a.map do |o|
58
+ {
59
+ cell_identifier: :custom_cell,
60
+ title: "#{i}x#{o}",
61
+ action: 'touched:',
62
+ background_color: UIColor.colorWithRed(rand(255) / 255.0,
63
+ green: rand(255) / 255.0,
64
+ blue: rand(255) / 255.0,
65
+ alpha: 1.0)
66
+ }
67
+ end
68
+ end
69
+ @screen.update_collection_view_data(data)
70
+ @view.numberOfSections.should == 2
71
+ @view.numberOfItemsInSection(1).should == 3
72
+ end
73
+
74
+ end
75
+
76
+ describe "layout functionality" do
77
+ before do
78
+ @screen = TestCollectionScreen.new
79
+ @view = @screen.collection_view
80
+ @layout = @screen.collectionViewLayout
81
+ end
82
+
83
+ after do
84
+ @screen = nil
85
+ end
86
+
87
+ it "layout should have correct sizes" do
88
+ @layout.estimatedItemSize.should == CGSizeMake(80, 80) if TestHelper.gte_ios8
89
+ @layout.itemSize.should == CGSizeMake(100, 80)
90
+ end
91
+
92
+ it "layout should be :horizontal" do
93
+ @layout.scrollDirection.should == UICollectionViewScrollDirectionHorizontal
94
+ end
95
+
96
+ it "layout should have a correct sectionInset" do
97
+ @layout.sectionInset.should == UIEdgeInsetsMake(10, 10, 10, 10)
98
+ end
99
+
100
+ end
101
+
102
+ describe "cells" do
103
+ before do
104
+ @screen = TestCollectionScreen.new
105
+ @view = @screen.collection_view
106
+ end
107
+
108
+ after do
109
+ @screen = nil
110
+ end
111
+
112
+ it "should be CustomCollectionViewCell cells" do
113
+ index_path = NSIndexPath.indexPathForRow(1, inSection: 1)
114
+
115
+ @screen.collectionView(@view, cellForItemAtIndexPath: index_path).should.be.kind_of CustomCollectionViewCell
116
+ end
117
+
118
+ it "should have a correct size" do
119
+ index_path = NSIndexPath.indexPathForRow(1, inSection: 1)
120
+
121
+ cell = @screen.collectionView(@view, cellForItemAtIndexPath: index_path)
122
+ cell.should.not == nil
123
+ cell.frame.size.should == CGSizeMake(100, 80)
124
+ end
125
+
126
+ it "should get properties" do
127
+ data = @screen.cell_at(section: 1, index: 1)
128
+ data[:background_color].should.be.kind_of UIColor
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -135,7 +135,7 @@ describe "screen helpers" do
135
135
  new_screen.modal?.should == true
136
136
  new_screen.hidesBottomBarWhenPushed.should == true
137
137
  new_screen.nav_bar?.should == true
138
- new_screen.navigationController.isNavigationBarHidden.should == true
138
+ new_screen.instance_variable_get(:@screen_options)[:hide_nav_bar].should == true
139
139
  end
140
140
 
141
141
  it "should present the navigationController when showing a modal screen" do
@@ -6,6 +6,16 @@ describe "screen properties" do
6
6
  @screen.on_load
7
7
  end
8
8
 
9
+ it "does not have a default title" do
10
+ screen = UntitledScreen.new
11
+ screen.title.should == nil
12
+ end
13
+
14
+ it "does not display a default title in the nav bar" do
15
+ screen = UntitledScreen.new
16
+ screen.navigationItem.title.should == nil
17
+ end
18
+
9
19
  it "should store title" do
10
20
  HomeScreen.title.should == "Home"
11
21
  end
@@ -24,12 +34,6 @@ describe "screen properties" do
24
34
  HomeScreen.title.should != 'instance method'
25
35
  end
26
36
 
27
- it "should have a default UIStatusBar style" do
28
- @screen.view_will_appear(false)
29
- UIApplication.sharedApplication.isStatusBarHidden.should == false
30
- UIApplication.sharedApplication.statusBarStyle.should == UIStatusBarStyleDefault
31
- end
32
-
33
37
  it "should set the UIStatusBar style to :none" do
34
38
  @screen.class.status_bar :none
35
39
  @screen.view_will_appear(false)
@@ -61,6 +65,13 @@ describe "screen properties" do
61
65
  UIApplication.sharedApplication.statusBarStyle.should == UIStatusBarStyleLightContent
62
66
  end
63
67
 
68
+ it "should default to a hidden UIStatusBar if already hidden" do
69
+ UIApplication.sharedApplication.setStatusBarHidden(true, withAnimation: UIStatusBarAnimationNone)
70
+ @screen.class.status_bar :default
71
+ @screen.view_will_appear(false)
72
+ UIApplication.sharedApplication.isStatusBarHidden.should == true
73
+ end
74
+
64
75
  it "should set the tab bar item with a system item" do
65
76
  @screen.set_tab_bar_item system_item: :contacts
66
77
  comparison = UITabBarItem.alloc.initWithTabBarSystemItem(UITabBarSystemItemContacts, tag: 0)
@@ -201,6 +212,33 @@ describe "screen properties" do
201
212
 
202
213
  end
203
214
 
215
+ describe "memory warnings" do
216
+
217
+ it "should call didReceiveMemoryWarning when exists" do
218
+ memory_screen = MemoryWarningScreenSelfImplemented.new
219
+ memory_screen.memory_warning_from_uikit.should.be.nil
220
+ memory_screen.didReceiveMemoryWarning
221
+ memory_screen.memory_warning_from_uikit.should == true
222
+ end
223
+
224
+ it "should call super up the chain" do
225
+ memory_screen = MemoryWarningNotSoSuperScreen.new
226
+
227
+ memory_screen.memory_warning_from_super.should.be.nil
228
+ memory_screen.didReceiveMemoryWarning
229
+ memory_screen.memory_warning_from_super.should == true
230
+ end
231
+
232
+ it "should call on_memory_warning when implemented" do
233
+ memory_screen = MemoryWarningScreen.new
234
+
235
+ memory_screen.memory_warning_from_pm.should.be.nil
236
+ memory_screen.didReceiveMemoryWarning
237
+ memory_screen.memory_warning_from_pm.should == true
238
+ end
239
+
240
+ end
241
+
204
242
  describe "navigation controller behavior" do
205
243
 
206
244
  it "should have a navigation bar" do
@@ -41,6 +41,16 @@ describe "PM::Table module" do
41
41
  })
42
42
  end
43
43
 
44
+ def proc_cell
45
+ custom_cell.merge({
46
+ action: -> (args, index_path) {
47
+ args[:data].should == [ "lots", "of", "data" ]
48
+ index_path.section.should == 7
49
+ index_path.row.should == 0
50
+ }
51
+ })
52
+ end
53
+
44
54
  def default_cell_height
45
55
  return UITableViewAutomaticDimension if TestHelper.ios8
46
56
  return 97.0 if TestHelper.ios7 # Normally 44, but 97 because of `row_height` designation
@@ -69,7 +79,13 @@ describe "PM::Table module" do
69
79
  },{
70
80
  title: "Custom section title 2", title_view: CustomTitleView.new, title_view_height: 50, cells: [ ]
71
81
  },{
72
- title: "Action WIth Index Path Group", cells: [ cell_factory(title: "IndexPath Group 1", action: :tests_index_path) ]
82
+ title: "Action With Index Path Group", cells: [ cell_factory(title: "IndexPath Group 1", action: :tests_index_path) ]
83
+ }, {
84
+ title: "Action With A Proc", cells: [ proc_cell ]
85
+ },{
86
+ title: "test 40", title_view: DynamicHeightTitleView40, cells: []
87
+ }, {
88
+ title: "test 121", title_view: DynamicHeightTitleView121, cells: []
73
89
  }]
74
90
  end
75
91
 
@@ -77,12 +93,13 @@ describe "PM::Table module" do
77
93
 
78
94
  @ip = NSIndexPath.indexPathForRow(1, inSection: 2) # Cell 3-2
79
95
  @custom_ip = NSIndexPath.indexPathForRow(0, inSection: 3) # Cell "Crazy Full Featured Cell"
96
+ @proc_cell = NSIndexPath.indexPathForRow(0, inSection: 7)
80
97
 
81
98
  @subject.update_table_data
82
99
  end
83
100
 
84
101
  it "should have the right number of sections" do
85
- @subject.numberOfSectionsInTableView(@subject.table_view).should == 7
102
+ @subject.numberOfSectionsInTableView(@subject.table_view).should == 10
86
103
  end
87
104
 
88
105
  it "should set the section titles" do
@@ -134,6 +151,10 @@ describe "PM::Table module" do
134
151
  @subject.tableView(@subject.table_view, didSelectRowAtIndexPath:@custom_ip)
135
152
  end
136
153
 
154
+ it "should trigger the proc" do
155
+ @subject.tableView(@subject.table_view, didSelectRowAtIndexPath: @proc_cell)
156
+ end
157
+
137
158
  it "should return an NSIndexPath when the action has two parameters" do
138
159
  ip = NSIndexPath.indexPathForRow(0, inSection: 6)
139
160
 
@@ -198,6 +219,11 @@ describe "PM::Table module" do
198
219
  cell = @subject.tableView(@subject.table_view, viewForHeaderInSection: 5)
199
220
  cell.should.be.kind_of(CustomTitleView)
200
221
  end
222
+
223
+ it "should set the height of a title view when the method `height` is implemented" do
224
+ @subject.tableView(@subject.table_view, heightForHeaderInSection:8).should == 40.0
225
+ @subject.tableView(@subject.table_view, heightForHeaderInSection:9).should == 121.0
226
+ end
201
227
  end
202
228
 
203
229
  describe "header view modifications" do
@@ -0,0 +1,25 @@
1
+ describe "table screen refresh functionality" do
2
+
3
+ # Note this test only works if on iOS 6+ or when using CKRefreshControl.
4
+
5
+ before do
6
+ @screen = TableScreenRefreshable.new
7
+ @screen.on_load
8
+ end
9
+
10
+ it "should be refreshable" do
11
+ @screen.class.get_refreshable.should == true
12
+ end
13
+
14
+ it "should create a refresh object" do
15
+ @screen.instance_variable_get("@refresh_control").should.be.kind_of UIRefreshControl
16
+ end
17
+
18
+ it "should respond to start_refreshing and end_refreshing" do
19
+ @screen.respond_to?(:start_refreshing).should == true
20
+ @screen.respond_to?(:end_refreshing).should == true
21
+ end
22
+
23
+ # Animations cause the refresh object to fail when tested. Test manually.
24
+
25
+ end
@@ -64,62 +64,6 @@ describe "table screens" do
64
64
  end
65
65
  end
66
66
 
67
- describe "search functionality" do
68
-
69
- before do
70
- @screen = TableScreenSearchable.new
71
- @screen.on_load
72
- end
73
-
74
- it "should be searchable" do
75
- @screen.class.get_searchable.should == true
76
- end
77
-
78
- it "should create a search header" do
79
- @screen.tableView.tableHeaderView.should.be.kind_of UISearchBar
80
- end
81
-
82
- it "should not hide the search bar initally by default" do
83
- @screen.tableView.contentOffset.should == CGPointMake(0,0)
84
- end
85
-
86
- it "should allow hiding the search bar initally" do
87
- class HiddenSearchScreen < TableScreenSearchable
88
- searchable hide_initially: true
89
- end
90
- screen = HiddenSearchScreen.new
91
- screen.on_load
92
- screen.tableView.contentOffset.should == CGPointMake(0,screen.searchDisplayController.searchBar.frame.size.height)
93
- end
94
-
95
- end
96
-
97
- describe "refresh functionality" do
98
-
99
- # Note this test only works if on iOS 6+ or when using CKRefreshControl.
100
-
101
- before do
102
- @screen = TableScreenRefreshable.new
103
- @screen.on_load
104
- end
105
-
106
- it "should be refreshable" do
107
- @screen.class.get_refreshable.should == true
108
- end
109
-
110
- it "should create a refresh object" do
111
- @screen.instance_variable_get("@refresh_control").should.be.kind_of UIRefreshControl
112
- end
113
-
114
- it "should respond to start_refreshing and end_refreshing" do
115
- @screen.respond_to?(:start_refreshing).should == true
116
- @screen.respond_to?(:end_refreshing).should == true
117
- end
118
-
119
- # Animations cause the refresh object to fail when tested. Test manually.
120
-
121
- end
122
-
123
67
  describe 'test PM::TableScreen\'s method call order' do
124
68
  before do
125
69
  class MethodCallOrderTestTableScreen < PM::TableScreen