require "active_support/test_case"
module Cell
# Test your cells.
#
# This class is roughly equal to ActionController::TestCase, exposing the same semantics. It will try
# to infer the tested cell name from the test name if you use declarative testing. You can also set it
# with TestCase.tests.
#
# A declarative test would look like
#
# class SellOutTest < Cell::TestCase
# tests ShoppingCartCell
#
# it "should be rendered nicely" do
# invoke :order_button, :items => @fixture_items
#
# assert_select "button", "Order now!"
# end
#
# You can also do stuff yourself, like
#
# it "should be rendered even nicer" do
# html = render_cell(:shopping_cart, :order_button, , :items => @fixture_items)
# assert_selector "button", "Order now!", html
# end
#
# Or even unit test your cell:
#
# it "should provide #default_items" do
# assert_equal [@item1, @item2], cell(:shopping_cart).default_items
# end
#
# == Test helpers
#
# Basically, we got these new methods:
#
# +invoke+:: Renders the passed +state+ with your tested cell. You may pass options like in #render_cell.
# +render_cell+:: As in your views. Will return the rendered view.
# +assert_selector+:: Like #assert_select except that the last argument is the html markup you wanna test.
# +cell+:: Gives you a cell instance for unit testing and stuff.
class TestCase < ActiveSupport::TestCase
module AssertSelect
# Invokes assert_select for the last argument, the +content+ string.
#
# Example:
# assert_selector "h1", "The latest and greatest!", "
The latest and greatest!
"
#
# would be true.
def assert_selector(*args, &block)
rails_assert_select(HTML::Document.new(args.pop).root, *args, &block)
end
# Invokes assert_select on the markup set by the last #invoke.
#
# Example:
# invoke :latest
# assert_select "h1", "The latest and greatest!"
def assert_select(*args, &block)
super(HTML::Document.new(last_invoke).root, *args, &block)
end
end
module TestMethods
def setup
@controller = Class.new(ActionController::Base).new
@request = ::ActionController::TestRequest.new
@response = ::ActionController::TestResponse.new
@controller.request = @request
@controller.response = @response
@controller.params = {}
end
# Use this for functional tests of your application cells.
#
# Example:
# should "spit out a h1 title" do
# html = render_cell(:news, :latest)
# assert_selekt html, "h1", "The latest and greatest!"
def render_cell(*args)
@controller.render_cell(*args)
end
# Builds an instance of nameCell for unit testing.
# Passes the optional block to cell.instance_eval.
#
# Example:
# assert_equal "Banks kill planet!" cell(:news, :topic => :terror).latest_headline
def cell(name, opts={}, &block)
cell = ::Cell::Base.create_cell_for(@controller, name, opts)
cell.instance_eval &block if block_given?
cell
end
end
include TestMethods
include ActionController::Assertions::SelectorAssertions # imports "their" #assert_select.
alias_method :rails_assert_select, :assert_select # i hate that.
include AssertSelect
attr_reader :last_invoke
def invoke(state, *args)
@last_invoke = self.class.controller_class.new(@controller, *args).render_state(state)
end
class << self
# Sets the controller class name. Useful if the name can't be inferred from test class.
# Expects +controller_class+ as a constant. Example: tests WidgetController.
def tests(controller_class)
self.controller_class = controller_class
end
def controller_class=(new_class)
write_inheritable_attribute(:controller_class, new_class)
end
def controller_class
if current_controller_class = read_inheritable_attribute(:controller_class)
current_controller_class
else
self.controller_class = determine_default_controller_class(name)
end
end
def determine_default_controller_class(name)
name.sub(/Test$/, '').constantize
rescue NameError
nil
end
end
end
end