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:
Jamon Holmgren
2014-10-11 15:46:33 -07:00
18 changed files with 114 additions and 59 deletions

View File

@@ -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:

View File

@@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,6 +10,7 @@ describe "Split screen functionality" do
end
before do
UIView.setAnimationDuration 0.01
rotate_device to: :landscape, button: :right
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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