mirror of
https://github.com/zhigang1992/ProMotion.git
synced 2026-05-15 07:37:21 +08:00
Merge pull request #546 from clearsightstudio/feature/warn-on-invalid-property
Warn on invalid properties when using `set_attributes` (:warn or higher)
This commit is contained in:
@@ -3,7 +3,7 @@ before_install:
|
||||
- (ruby --version)
|
||||
- sudo chown -R travis ~/Library/RubyMotion
|
||||
- mkdir -p ~/Library/RubyMotion/build
|
||||
- sudo motion update --cache-version=2.33
|
||||
- sudo motion update --cache-version=2.34
|
||||
gemfile:
|
||||
- Gemfile
|
||||
script:
|
||||
|
||||
6
Rakefile
6
Rakefile
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
unless File.exist?("/Library/RubyMotion2.33/lib")
|
||||
abort "Couldn't find RubyMotion 2.33. Run `sudo motion update --cache-version=2.33`."
|
||||
unless File.exist?("/Library/RubyMotion2.34/lib")
|
||||
abort "Couldn't find RubyMotion 2.34. Run `sudo motion update --cache-version=2.34`."
|
||||
end
|
||||
$:.unshift("/Library/RubyMotion2.33/lib")
|
||||
$:.unshift("/Library/RubyMotion2.34/lib")
|
||||
require 'motion/project/template/ios'
|
||||
require 'bundler'
|
||||
Bundler.require(:development)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class FunctionalScreen < PM::Screen
|
||||
attr_accessor :button_was_triggered
|
||||
attr_accessor :on_back_fired
|
||||
|
||||
title "Functional"
|
||||
|
||||
@@ -11,4 +12,8 @@ class FunctionalScreen < PM::Screen
|
||||
def triggered_button
|
||||
self.button_was_triggered = true
|
||||
end
|
||||
|
||||
def on_back
|
||||
@on_back_fired = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
class NavigationScreen < PM::Screen
|
||||
attr_accessor :on_back_fired
|
||||
attr_reader :on_back_fired
|
||||
|
||||
def on_back
|
||||
self.on_back_fired = true
|
||||
@on_back_fired = true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -2,10 +2,8 @@ module ProMotion
|
||||
class NavigationController < UINavigationController
|
||||
|
||||
def popViewControllerAnimated(animated)
|
||||
if self.viewControllers[-2].respond_to? :on_back
|
||||
self.viewControllers[-2].send(:on_back)
|
||||
end
|
||||
super animated
|
||||
super
|
||||
self.viewControllers.last.send(:on_back) if self.viewControllers.last.respond_to?(:on_back)
|
||||
end
|
||||
|
||||
def shouldAutorotate
|
||||
|
||||
@@ -19,12 +19,17 @@ module ProMotion
|
||||
error: [:error],
|
||||
warn: [:error, :warn],
|
||||
info: [:error, :warn, :info],
|
||||
debug: [:error, :warn, :info, :debug],
|
||||
verbose: [:error, :warn, :info, :debug, :verbose],
|
||||
debug: [:error, :warn, :info, :debug, :verbose]
|
||||
}
|
||||
|
||||
def level
|
||||
@level ||= :debug
|
||||
@level ||= (RUBYMOTION_ENV == "release" ? :error : :debug)
|
||||
end
|
||||
|
||||
def level=(new_level)
|
||||
log('LOG LEVEL', 'Setting PM.logger to :verbose will make everything REALLY SLOW!', :purple) if new_level == :verbose
|
||||
@level = new_level
|
||||
end
|
||||
|
||||
def levels
|
||||
|
||||
@@ -12,7 +12,7 @@ module ProMotion
|
||||
check_ancestry
|
||||
resolve_title
|
||||
tab_bar_setup
|
||||
set_attributes self, args
|
||||
apply_properties(args)
|
||||
add_nav_bar(args) if args[:nav_bar]
|
||||
try :screen_setup
|
||||
try :on_init
|
||||
@@ -146,6 +146,11 @@ module ProMotion
|
||||
|
||||
private
|
||||
|
||||
def apply_properties(args)
|
||||
reserved_args = [ :nav_bar, :hide_nav_bar, :hide_tab_bar, :animated, :close_all, :in_tab, :in_detail, :in_master, :to_screen ]
|
||||
set_attributes self, args.dup.delete_if { |k,v| reserved_args.include?(k) }
|
||||
end
|
||||
|
||||
def tab_bar_setup
|
||||
self.tab_bar_item = self.class.send(:get_tab_bar_item)
|
||||
self.refresh_tab_bar_item if self.tab_bar_item
|
||||
|
||||
@@ -18,9 +18,11 @@ module ProMotion
|
||||
element.send("#{k}=", v)
|
||||
elsif v.is_a?(Array) && element.respond_to?("#{k}") && element.method("#{k}").arity == v.length
|
||||
element.send("#{k}", *v)
|
||||
else
|
||||
# Doesn't respond. Check if snake case.
|
||||
set_attribute(element, camelize(k), v) if k.to_s.include?("_")
|
||||
elsif k.to_s.include?("_") # Snake case?
|
||||
set_attribute(element, camelize(k), v)
|
||||
else # Warn
|
||||
PM.logger.debug "set_attribute: #{element.inspect} does not respond to #{k}=."
|
||||
PM.logger.log("BACKTRACE", caller(0).join("\n"), :default) if PM.logger.level == :verbose
|
||||
end
|
||||
element
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
describe "ProMotion::Screen functionality" do
|
||||
tests PM::Screen
|
||||
|
||||
before { UIView.setAnimationDuration 0.01 }
|
||||
|
||||
# Override controller to properly instantiate
|
||||
def controller
|
||||
rotate_device to: :portrait, button: :bottom
|
||||
@@ -69,23 +71,22 @@ describe "ProMotion::Screen functionality" do
|
||||
end
|
||||
|
||||
it "should call the on_back method on the root controller when navigating back" do
|
||||
@nav_screen = NavigationScreen.new nav_bar: true
|
||||
@presented_screen = PresentScreen.new
|
||||
@nav_screen.open @presented_screen
|
||||
@presented_screen.close
|
||||
@nav_screen.on_back_fired.should == true
|
||||
presented_screen = PresentScreen.new
|
||||
@controller.open presented_screen, animated: false
|
||||
@controller.navigationController.viewControllers.should == [ @controller, presented_screen ]
|
||||
presented_screen.close animated: false
|
||||
@controller.on_back_fired.should == true
|
||||
end
|
||||
|
||||
it "should call the correct on_back method when nesting screens" do
|
||||
@base_screen = NavigationScreen.new nav_bar: true
|
||||
@child_screen = @base_screen.open NavigationScreen.new
|
||||
@grandchild_screen = @child_screen.open NavigationScreen.new
|
||||
child_screen = @controller.open NavigationScreen.new, animated: false
|
||||
grandchild_screen = child_screen.open NavigationScreen.new, animated: false
|
||||
|
||||
# start closing
|
||||
@grandchild_screen.close
|
||||
@child_screen.on_back_fired.should == true
|
||||
@child_screen.close
|
||||
@base_screen.on_back_fired.should == true
|
||||
grandchild_screen.close animated: false
|
||||
child_screen.on_back_fired.should == true
|
||||
child_screen.close animated: false
|
||||
@controller.on_back_fired.should == true
|
||||
end
|
||||
|
||||
it "should allow opening and closing a modal screen" do
|
||||
|
||||
@@ -10,6 +10,7 @@ describe "Split screen functionality" do
|
||||
end
|
||||
|
||||
before do
|
||||
UIView.setAnimationDuration 0.01
|
||||
rotate_device to: :landscape, button: :right
|
||||
end
|
||||
|
||||
|
||||
@@ -15,9 +15,15 @@ describe "ProMotion::TableScreen functionality" do
|
||||
end
|
||||
|
||||
def confirmation_class
|
||||
TestHelper.ios7 ? UITableViewCellDeleteConfirmationButton : UITableViewCellDeleteConfirmationControl
|
||||
TestHelper.ios7 ? "UITableViewCellDeleteConfirmationButton" : "UITableViewCellDeleteConfirmationControl"
|
||||
end
|
||||
|
||||
def table_label_class
|
||||
TestHelper.ios7 ? "UILabel" : "UITableViewLabel"
|
||||
end
|
||||
|
||||
before { UIView.setAnimationDuration 0.01 }
|
||||
|
||||
after { @table_screen = nil }
|
||||
|
||||
it "should have a navigation bar" do
|
||||
@@ -31,7 +37,7 @@ describe "ProMotion::TableScreen functionality" do
|
||||
|
||||
it "should add a new table cell on tap" do
|
||||
tap("Add New Row")
|
||||
view("Dynamically Added").class.should == UILabel
|
||||
view("Dynamically Added").class.to_s.should == table_label_class
|
||||
end
|
||||
|
||||
it "should do nothing when no action specified" do
|
||||
@@ -47,7 +53,7 @@ describe "ProMotion::TableScreen functionality" do
|
||||
it "should delete the specified row from the table view on tap" do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 7
|
||||
tap("Delete the row below")
|
||||
wait 0.3 do
|
||||
wait 0.11 do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 6
|
||||
end
|
||||
end
|
||||
@@ -55,7 +61,7 @@ describe "ProMotion::TableScreen functionality" do
|
||||
it "should delete the specified row from the table view on tap with an animation" do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 7
|
||||
tap("Delete the row below with an animation")
|
||||
wait 0.3 do
|
||||
wait 0.11 do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 6
|
||||
end
|
||||
end
|
||||
@@ -66,12 +72,12 @@ describe "ProMotion::TableScreen functionality" do
|
||||
table_screen.cell_was_deleted.should != true
|
||||
flick("Just another deletable blank row", :to => :left)
|
||||
|
||||
wait 0.25 do
|
||||
wait 0.11 do
|
||||
# Tap the delete button
|
||||
view('Just another deletable blank row').superview.superview.subviews.each do |subview|
|
||||
if subview.class == confirmation_class
|
||||
if subview.class.to_s == confirmation_class
|
||||
tap subview
|
||||
wait 0.25 do
|
||||
wait 0.11 do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 6
|
||||
table_screen.cell_was_deleted.should == true
|
||||
end
|
||||
@@ -85,12 +91,12 @@ describe "ProMotion::TableScreen functionality" do
|
||||
table_screen.cell_was_deleted.should != true
|
||||
flick("A non-deletable blank row", :to => :left)
|
||||
|
||||
wait 0.25 do
|
||||
wait 0.11 do
|
||||
# Tap the delete button
|
||||
view('A non-deletable blank row').superview.superview.subviews.each do |subview|
|
||||
if subview.class == confirmation_class
|
||||
tap subview
|
||||
wait 0.25 do
|
||||
wait 0.11 do
|
||||
table_screen.tableView(table_screen.tableView, numberOfRowsInSection:0).should == 7
|
||||
table_screen.cell_was_deleted.should != false
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
describe "ProMotion::TableScreen updating functionality" do
|
||||
tests PM::UpdateTestTableScreen
|
||||
|
||||
before { UIView.setAnimationDuration 0.01 }
|
||||
|
||||
it 'should update a single row in the table view' do
|
||||
table_screen = UpdateTestTableScreen.new
|
||||
table_screen.make_more_cells
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
describe "ProMotion::TestWebScreen functionality" do
|
||||
extend WebStub::SpecHelpers
|
||||
|
||||
before { disable_network_access! }
|
||||
before do
|
||||
disable_network_access!
|
||||
UIView.setAnimationDuration 0.01
|
||||
end
|
||||
after { enable_network_access! }
|
||||
|
||||
def controller
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
class TestHelper
|
||||
def self.ios6
|
||||
UIDevice.currentDevice.systemVersion.to_f >= 6.0 &&
|
||||
UIDevice.currentDevice.systemVersion.to_f < 7.0
|
||||
end
|
||||
|
||||
def self.ios7
|
||||
UIDevice.currentDevice.systemVersion.to_f >= 7.0
|
||||
UIDevice.currentDevice.systemVersion.to_f >= 7.0 &&
|
||||
UIDevice.currentDevice.systemVersion.to_f < 8.0
|
||||
end
|
||||
|
||||
def self.ios8
|
||||
UIDevice.currentDevice.systemVersion.to_f >= 8.0 &&
|
||||
UIDevice.currentDevice.systemVersion.to_f < 9.0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -100,13 +100,13 @@ describe "screen helpers" do
|
||||
|
||||
it "#push_view_controller should use the default navigation controller if not provided" do
|
||||
vcs = @screen.navigationController.viewControllers
|
||||
@screen.push_view_controller @second_vc
|
||||
@screen.push_view_controller @second_vc, @screen.navigationController, false
|
||||
@screen.navigationController.viewControllers.count.should == vcs.count + 1
|
||||
end
|
||||
|
||||
it "#push_view_controller should use a provided navigation controller" do
|
||||
second_nav_controller = UINavigationController.alloc.initWithRootViewController @screen
|
||||
@screen.push_view_controller @second_vc, second_nav_controller
|
||||
@screen.push_view_controller @second_vc, second_nav_controller, false
|
||||
second_nav_controller.viewControllers.count.should == 2
|
||||
end
|
||||
|
||||
@@ -200,7 +200,7 @@ describe "screen helpers" do
|
||||
|
||||
it "should ignore its own navigation controller if current screen has a navigation controller" do
|
||||
basic = BasicScreen.new(nav_bar: true) # creates a dangling nav_bar that will be discarded.
|
||||
screen = @screen.open basic
|
||||
screen = @screen.open basic, animated: false
|
||||
screen.should.be.kind_of BasicScreen
|
||||
basic.navigationController.should == @screen.navigationController
|
||||
end
|
||||
@@ -302,13 +302,13 @@ describe "screen helpers" do
|
||||
|
||||
it "#send_on_return should pass args to the first screen with :root" do
|
||||
first_screen = HomeScreen.new(nav_bar: true)
|
||||
second_screen = first_screen.open(BasicScreen)
|
||||
second_screen.open @screen
|
||||
second_screen = first_screen.open(BasicScreen, animated: false)
|
||||
second_screen.open @screen, animated: false
|
||||
|
||||
|
||||
second_screen.stub!(:on_return) { |args| should.flunk "shouldn't call on_return on second_screen!" }
|
||||
first_screen.mock!(:on_return) { |args| args[:key].should == :value }
|
||||
@screen.close({ key: :value, to_screen: :root })
|
||||
@screen.close key: :value, to_screen: :root, animated: false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ describe "screen properties" do
|
||||
# Issue https://github.com/clearsightstudio/ProMotion/issues/109
|
||||
it "#should_autorotate should fire when shouldAutorotate fires when in a navigation bar" do
|
||||
parent_screen = BasicScreen.new(nav_bar: true)
|
||||
parent_screen.open @screen
|
||||
parent_screen.open @screen, animated: false
|
||||
@screen.mock!(:should_autorotate) { true.should == true }
|
||||
parent_screen.navigationController.shouldAutorotate
|
||||
end
|
||||
|
||||
@@ -31,14 +31,14 @@ describe "split screen `open` functionality" do
|
||||
end
|
||||
|
||||
it "should open a new screen in the master view's navigation controller" do
|
||||
screen = @master_screen.open @detail_screen_2
|
||||
screen = @master_screen.open @detail_screen_2, animated: false
|
||||
@split_screen.detail_screen.should == @detail_screen_1 # no change
|
||||
@master_screen.navigationController.topViewController.should == @detail_screen_2
|
||||
screen.should == @detail_screen_2
|
||||
end
|
||||
|
||||
it "should open a new modal screen in the detail view" do
|
||||
screen = @detail_screen_1.open @detail_screen_2, modal: true
|
||||
screen = @detail_screen_1.open @detail_screen_2, modal: true, animated: false
|
||||
@split_screen.detail_screen.should == @detail_screen_1
|
||||
@detail_screen_1.presentedViewController.should == (@detail_screen_2.navigationController || @detail_screen_2)
|
||||
screen.should == @detail_screen_2
|
||||
@@ -47,7 +47,7 @@ describe "split screen `open` functionality" do
|
||||
it "should not interfere with normal non-split screen navigation" do
|
||||
home = HomeScreen.new(nav_bar: true)
|
||||
child = BasicScreen.new
|
||||
screen = home.open child, in_detail: true, in_master: true
|
||||
screen = home.open child, in_detail: true, in_master: true, animated: false
|
||||
home.navigationController.topViewController.should == child
|
||||
screen.should == child
|
||||
end
|
||||
|
||||
@@ -5,7 +5,8 @@ describe "PM::Table module" do
|
||||
end
|
||||
|
||||
def custom_cell
|
||||
@image = UIImage.imageNamed("list")
|
||||
@image ||= UIImage.imageNamed("list")
|
||||
@pattern_image_color ||= UIColor.colorWithPatternImage(@image)
|
||||
cell_factory({
|
||||
title: "Crazy Full Featured Cell",
|
||||
subtitle: "This is way too huge..see note",
|
||||
@@ -30,12 +31,28 @@ describe "PM::Table module" do
|
||||
radius: 15
|
||||
},
|
||||
properties: {
|
||||
masks_to_bounds: true,
|
||||
background_color: UIColor.colorWithPatternImage(@image)
|
||||
content_view: {
|
||||
background_color: @pattern_image_color,
|
||||
},
|
||||
layer: {
|
||||
masks_to_bounds: true,
|
||||
},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
def default_cell_height
|
||||
return UITableViewAutomaticDimension if TestHelper.ios8
|
||||
return 44.0 if TestHelper.ios7
|
||||
end
|
||||
|
||||
def default_header_height
|
||||
# Thanks, Apple.
|
||||
return -1.0 if TestHelper.ios8
|
||||
return 23.0 if TestHelper.ios7
|
||||
return 22.0 if TestHelper.ios6
|
||||
end
|
||||
|
||||
before do
|
||||
@subject = TestTableScreen.new
|
||||
@subject.mock! :table_data do
|
||||
@@ -101,7 +118,7 @@ describe "PM::Table module" do
|
||||
end
|
||||
|
||||
it "should return the table's cell height if none is given" do
|
||||
@subject.tableView(@subject.table_view, heightForRowAtIndexPath:@ip).should == 44.0 # Built-in default
|
||||
@subject.tableView(@subject.table_view, heightForRowAtIndexPath:@ip).should == default_cell_height
|
||||
end
|
||||
|
||||
it "should allow setting a custom cell height" do
|
||||
@@ -140,11 +157,12 @@ describe "PM::Table module" do
|
||||
|
||||
it "should set a custom cell background image" do
|
||||
@image.should.not.be.nil
|
||||
ip = NSIndexPath.indexPathForRow(0, inSection: 3) # Cell 2-1
|
||||
ip = NSIndexPath.indexPathForRow(0, inSection: 3) # Cell 4-1
|
||||
cell = @subject.tableView(@subject.table_view, cellForRowAtIndexPath: ip)
|
||||
cell.should.be.kind_of(UITableViewCell)
|
||||
cell.backgroundColor.should.be.kind_of(UIColor)
|
||||
cell.backgroundColor.should == UIColor.colorWithPatternImage(@image)
|
||||
cell.layer.masksToBounds.should == true
|
||||
cell.contentView.backgroundColor.should.be.kind_of(UIColor)
|
||||
cell.contentView.backgroundColor.should == @pattern_image_color
|
||||
end
|
||||
|
||||
it "should set a custom cell background color" do
|
||||
@@ -162,8 +180,7 @@ describe "PM::Table module" do
|
||||
end
|
||||
|
||||
it "should use the default section height if none is specified" do
|
||||
header_height = (UIDevice.currentDevice.systemVersion.to_f >= 7.0) ? 23.0 : 22.0
|
||||
@subject.tableView(@subject.table_view, heightForHeaderInSection:4).should == header_height # Built-in default
|
||||
@subject.tableView(@subject.table_view, heightForHeaderInSection:4).should == default_header_height
|
||||
end
|
||||
|
||||
it "should use the set title_view_height if one is specified" do
|
||||
|
||||
Reference in New Issue
Block a user