ProMotion 2.4.2 → 2.5.0.beta1

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 (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