Class: Kookaburra::UIDriver::UIComponent Abstract

Inherits:
SimpleDelegator
  • Object
show all
Extended by:
HasUIComponents
Includes:
Assertion
Defined in:
lib/kookaburra/ui_driver/ui_component.rb,
lib/kookaburra/ui_driver/ui_component/address_bar.rb

Overview

This class is abstract.

Unless you override the default implementation of #url, you must override the #component_path method if you want the component to be navigable by the AddressBar component.

Note:

Even though a UIComponent should respond to all of the methods on the browser (i.e. all of the Capybara DSL methods), for some reason call to #select get routed to Kernel#select. You can get around this by calling it as self.select. See https://gist.github.com/3192103 for an example of this behavior.

UIComponent is intended to be subclassed to represent each component of your application-under-test's user interface. The purpose of the UIComponent object is to abstract away the implementation details of your interface when testing and allow you to concentrate on testing your business requirements. For instance, a UIComponent subclass for your sign-up form might have accessors for the individual fields as well as methods that allow you to perform distinct operations:

Note that the "browser operation" methods such as #fill_in and #click_button are delegated to a ScopedBrowser and are automatically scoped to the component's DOM element.

Examples:

SignUpForm component

class SignUpForm < Kookaburra::UIDriver::UIComponent
  def component_path
    '/signup'
  end

  # If it can't be inferred from the class name
  def component_locator
    '#user-sign-up'
  end

  def email
    find('#user_email').value
  end

  def email=(new_email)
    fill_in 'user_email', :with => new_email
  end

  def password
    find('#user_password').value
  end

  def password=(new_password)
    fill_in 'user_password', :with => new_password
  end

  def password_confirmation
    find('#user_password_confirmation').value
  end

  def password_confirmation=(new_password_confirmation)
    fill_in 'user_password_confirmation', :with => new_password_confirmation
  end

  def submit
    click_button 'Sign Up'
  end

  def (data = {})
    self.email = data[:email]
    self.password = data[:password]
    self.password_confirmation = data[:password_confirmation]
    submit
  end
end

Direct Known Subclasses

AddressBar

Defined Under Namespace

Classes: AddressBar

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HasUIComponents

ui_component

Methods included from Assertion

#assert

Constructor Details

#initialize(configuration, options = {}) ⇒ UIComponent

New UIComponent instances are typically created for you by your Kookaburra::UIDriver instance.

Parameters:

See Also:

  • Kookaburra::UIDriver.ui_component


98
99
100
101
102
103
104
105
106
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 98

def initialize(configuration, options = {})
  @configuration = configuration
  @options = options
  @browser = configuration.browser
  @app_host = configuration.app_host
  @server_error_detection = configuration.server_error_detection
  scoped_browser = ScopedBrowser.new(@browser, lambda { component_locator })
  super(scoped_browser)
end

Instance Attribute Details

#browserObject (readonly, protected)

The browser object from the initialized configuration



127
128
129
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 127

def browser
  @browser
end

#configurationObject (readonly)

The Configuration with which the component instance was instantiated.



84
85
86
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 84

def configuration
  @configuration
end

#optionsObject (readonly)

The options Hash with which the component instance was instantiated.



88
89
90
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 88

def options
  @options
end

Instance Method Details

#component_locatorString (protected)

The CSS3 selector that will find the element in the DOM

Defaults to a "#" followed by the snake-cased (underscored) version of the class name with '/' replaced by '-'. Override this method in your subclasses if you need a different CSS3 selector to find your component.

Examples:

class My::Awesome::ComponentThingy < Kookaburra::UIDriver::UIComponent
end

x = My::Awesome::ComponentThingy.allocate
x.send(:component_locator)
#=> '#my-awesome-component_thingy'

Returns:

  • (String)


152
153
154
155
156
157
158
159
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 152

def component_locator
  "#" + self.class.name.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    gsub('/', '-').
    downcase
end

#component_pathString (protected)

This method is abstract.

Returns the URL path that should be loaded in order to reach this component.

Returns:

  • (String)

    the URL path that should be loaded in order to reach this component

Raises:

  • (Kookaburra::ConfigurationError)

    raised if you haven't provided an implementation



133
134
135
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 133

def component_path
  raise ConfigurationError, "You must define #{self.class.name}#component_path."
end

#detect_server_error!Object (protected)

Runs the server error detection function specified in Configuration#server_error_detection.

It's a noop if no server error detection was specified.

Raises:

  • (UnexpectedResponse)

    raised if the server error detection function returns true



168
169
170
171
172
173
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 168

def detect_server_error!
  return if @server_error_detection.nil?
  if @server_error_detection.call(browser)
    raise UnexpectedResponse, "Server Error Detected:\n#{browser.text}"
  end
end

#this_elementObject (protected)

Provides a reference to the HTML element represented by this UIComponent

This is useful for getting at attributes of the current element, because the normal find methods are scoped to run inside this element.

Returns:

  • Capybara::Element



183
184
185
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 183

def this_element
  browser.find(component_locator)
end

#url(*args) ⇒ Object

Returns the full URL by appending #component_path to the value of the Configuration#app_host from the initialized configuration.



120
121
122
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 120

def url(*args)
  "#{@app_host}#{component_path(*args)}"
end

#visible?Boolean

Is the component's element found on the page and is it considered "visible" by the browser driver.

Returns:

  • (Boolean)


110
111
112
113
114
115
116
# File 'lib/kookaburra/ui_driver/ui_component.rb', line 110

def visible?
  visible = browser.has_css?(component_locator, :visible)
  unless visible
    detect_server_error!
  end
  visible
end