Search code examples
unit-testingrubymotion

Testing view controllers in storyboards in RubyMotion


I am using storyboards and RubyMotion. In my spec I have the following:

describe "SignUp scene" do

  tests SignUpFacebook, :storyboard => 'LoginStoryboard', :id => 'SignUp'

  it "some test" do
    tap 'FirstName'
    # some test here      
  end

end

In the view controller I have

class SignUpFacebook < UIViewController

  def viewWillAppear animated
    super
    self.navigationController.setNavigationBarHidden (true, animated:false)
  end

  def viewWillDisappear animated
    super
    self.navigationController.setNavigationBarHidden (false, animated:false)
  end

  #some code to be tested
end

when I "rake spec" I get the error:

[ERROR: NoMethodError - undefined method `setNavigationBarHidden' for nil:NilClass]

so, the navigationController is nil. Am I missing something? Alternatively, can anyone suggest an approach for testing view controllers that reference the navigation controller? Also, for testing that the controller want to perform a segue in certain conditions. Is there some mock or stub I could use?


Solution

  • ok, I found an example of a method which overrides a (macbacon?) method that returns the controller. I've loaded the controller here and set up a navigation controller so the test runs now. Before each test is run, the sequence of events is:

    1. The test 'it' description is output
    2. The built-in 'controller' method gets called which instantiates the view controller (I've overridden the method below)
    3. The test system waits until the view has loaded (so any dependancy injection needed before viewDidLoad has to be done in the 'controller' method)
    4. The test system calls the 'before do .. end' code
    5. The test system runs the test
      def controller
        unless @controller
              storyboard = UIStoryboard.storyboardWithName("LoginStoryboard", bundle:nil)
              @controller = storyboard.instantiateViewControllerWithIdentifier('SignUpFacebook')
              appDelegate = UIApplication.sharedApplication.delegate
              appDelegate.setWindow UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
              appDelegate.window.rootViewController = UINavigationController.alloc.initWithRootViewController @controller
        end
        @controller
      end