Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Working to get riot-rails back into shape. About 50% there
- Loading branch information
Showing
10 changed files
with
270 additions
and
372 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,88 @@ | ||
module Riot #:nodoc: | ||
class Assertion | ||
# Asserts that the body of the response equals or matches the expected expression. Expects actual to | ||
# be the controller. | ||
# | ||
# controller.renders("a bunch of html") | ||
# controller.renders(/bunch of/) | ||
assertion(:renders) do |actual, expected| | ||
actual_body = actual.response.body | ||
if expected.kind_of?(Regexp) && actual_body =~ expected | ||
fail("expected response body #{actual_body.inspect} to match #{expected.inspect}") | ||
elsif expected == actual_body | ||
fail("expected response body #{actual_body.inspect} to equal #{expected.inspect}") | ||
else | ||
pass | ||
end | ||
class Riot::Assertion | ||
# Asserts that the body of the response equals or matches the expected expression. Expects actual to | ||
# be the controller. | ||
# | ||
# controller.renders("a bunch of html") | ||
# controller.renders(/bunch of/) | ||
assertion(:renders) do |actual, expected| | ||
actual_body = actual.response.body | ||
if (expected.kind_of?(Regexp) ? (actual_body =~ expected) : (expected == actual_body)) | ||
pass | ||
else | ||
verb = expected.kind_of?(Regexp) ? "match" : "equal" | ||
fail("expected response body #{actual_body.inspect} to #{verb} #{expected.inspect}") | ||
end | ||
end | ||
|
||
# Asserts that the name you provide is the basename of the rendered template. For instance, if you | ||
# expect the rendered template is named "foo_bar.html.haml" and you pass "foo_bar" into | ||
# renders_template, the assertion would pass. If instead you pass "foo" into renders_template, the | ||
# assertion will fail. Using Rails' assert_template both assertions would pass | ||
# | ||
# controlling :things | ||
# controller.renders_template(:index) | ||
# controller.renders_template("index") | ||
# controller.renders_template("index.erb") # fails even if that's the name of the template | ||
assertion(:renders_template) do |actual, expected_name| | ||
name = expected_name.to_s | ||
actual_template_path = actual.response.rendered[:template].to_s | ||
actual_template_name = File.basename(actual_template_path) | ||
msg = "expected template #{name.inspect}, not #{actual_template_path.inspect}" | ||
actual_template_name.to_s.match(/^#{name}(\.\w+)*$/) ? pass : fail(msg) | ||
end | ||
# Asserts that the name you provide is the basename of the rendered template. For instance, if you | ||
# expect the rendered template is named "foo_bar.html.haml" and you pass "foo_bar" into | ||
# renders_template, the assertion would pass. If instead you pass "foo" into renders_template, the | ||
# assertion will fail. Using Rails' assert_template both assertions would pass | ||
# | ||
# controlling :things | ||
# controller.renders_template(:index) | ||
# controller.renders_template("index") | ||
# controller.renders_template("index.erb") # fails even if that's the name of the template | ||
assertion(:renders_template) do |actual, expected_name| | ||
name = expected_name.to_s | ||
actual_template_path = actual.response.rendered[:template].to_s | ||
actual_template_name = File.basename(actual_template_path) | ||
msg = "expected template #{name.inspect}, not #{actual_template_path.inspect}" | ||
actual_template_name.to_s.match(/^#{name}(\.\w+)*$/) ? pass : fail(msg) | ||
end | ||
|
||
# Asserts that the HTTP response code equals your expectation. You can use the symbolized form of the | ||
# status code or the integer code itself. Not currently supporting status ranges; such as: +:success+, | ||
# +:redirect+, etc. | ||
# | ||
# controller.response_code(:ok) | ||
# controller.response_code(200) | ||
# | ||
# controller.response_code(:not_found) | ||
# controller.response_code(404) | ||
# | ||
# # A redirect | ||
# controller.response_code(:found) | ||
# controller.response_code(302) | ||
# | ||
# See +ActionController::StatusCodes+ for the list of available codes. | ||
assertion(:response_code) do |actual, expected_code| | ||
if expected_code.kind_of?(Symbol) | ||
expected_code = ::ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE[expected_code] | ||
end | ||
actual_code = actual.response.response_code | ||
expected_code == actual_code ? pass : fail("expected response code #{expected_code}, not #{actual_code}") | ||
# Asserts that the HTTP response code equals your expectation. You can use the symbolized form of the | ||
# status code or the integer code itself. Not currently supporting status ranges; such as: +:success+, | ||
# +:redirect+, etc. | ||
# | ||
# controller.response_code(:ok) | ||
# controller.response_code(200) | ||
# | ||
# controller.response_code(:not_found) | ||
# controller.response_code(404) | ||
# | ||
# # A redirect | ||
# controller.response_code(:found) | ||
# controller.response_code(302) | ||
# | ||
# See +ActionController::StatusCodes+ for the list of available codes. | ||
assertion(:response_code) do |actual, expected_code| | ||
if expected_code.kind_of?(Symbol) | ||
expected_code = ::ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE[expected_code] | ||
end | ||
actual_code = actual.response.response_code | ||
expected_code == actual_code ? pass : fail("expected response code #{expected_code}, not #{actual_code}") | ||
end | ||
|
||
# Asserts that the response from an action is a redirect and that the path or URL matches your | ||
# expectations. If the response code is not in the 300s, the assertion will fail. If the reponse code | ||
# is fine, but the redirect-to path or URL do not exactly match your expectation, the assertion will | ||
# fail. | ||
# | ||
# +redirected_to+ expects you to provide your expected path in a block. This is so you can use named | ||
# routes, which is - as it turns out - handy. It's also what I would expect to be able to do. | ||
# | ||
# controlling :people | ||
# setup do | ||
# post :create, :person { ... } | ||
# end | ||
# | ||
# controller.redirected_to { person_path(...) } | ||
# | ||
# PS: There is a difference between saying +named_route_path+ and +named_route_url+ and Riot Rails will | ||
# be very strict (read: annoying) about it :) | ||
assertion(:redirected_to) do |actual, &expectation_block| | ||
actual_response_code = actual.response.response_code | ||
if (300...400).member?(actual_response_code) | ||
expected_redirect = actual.url_for(situation.instance_eval(&expectation_block)) | ||
actual_redirect = actual.url_for(actual.response.redirected_to) | ||
msg = "expected to redirect to <#{expected_redirect}>, not <#{actual_redirect}>" | ||
expected_redirect == actual_redirect || fail(msg) | ||
else | ||
fail("expected response to be a redirect, but was #{actual_response_code}") | ||
end | ||
# Asserts that the response from an action is a redirect and that the path or URL matches your | ||
# expectations. If the response code is not in the 300s, the assertion will fail. If the reponse code | ||
# is fine, but the redirect-to path or URL do not exactly match your expectation, the assertion will | ||
# fail. | ||
# | ||
# +redirected_to+ expects you to provide your expected path in a lambda. This is so you can use named | ||
# routes, which are - as it turns out - handy. It's also what I would expect to be able to do. Using | ||
# lambdas is not ideal, so if you're smart, solve this problem :) | ||
# | ||
# controlling :people | ||
# setup do | ||
# post :create, :person { ... } | ||
# end | ||
# | ||
# controller.redirected_to( lambda { person_path(...) } ) | ||
# | ||
# PS: There is a difference between saying +named_route_path+ and +named_route_url+ and Riot Rails will | ||
# be very strict (read: annoying) about it :) | ||
assertion(:redirected_to) do |actual, *expectings| | ||
expectation_block = expectings.last | ||
actual_response_code = actual.response.response_code | ||
if (300...400).member?(actual_response_code) | ||
expected_redirect = actual.url_for(actual.instance_eval(&expectation_block)) # need to execute in situation somehow | ||
actual_redirect = actual.url_for(actual.response.redirected_to) | ||
msg = "expected to redirect to <#{expected_redirect}>, not <#{actual_redirect}>" | ||
expected_redirect == actual_redirect ? pass : fail(msg) | ||
else | ||
fail("expected response to be a redirect, but was #{actual_response_code}") | ||
end | ||
end # Assertion | ||
end # Riot | ||
end | ||
|
||
end # Riot::Assertion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,101 @@ | ||
module Riot | ||
class Assertion | ||
class Riot::Assertion | ||
|
||
# An ActiveRecord assertion that expects to fail when a given attribute is validated after a nil value | ||
# is provided to it. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.validates_presence_of(:name) | ||
# end | ||
assertion(:validates_presence_of) do |actual, attribute| | ||
msg = "expected to validate presence of #{attribute.inspect}" | ||
error_from_writing_value(actual, attribute, nil) ? pass : fail(msg) | ||
end | ||
# An ActiveRecord assertion that expects to fail when a given attribute is validated after a nil value | ||
# is provided to it. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.validates_presence_of(:name) | ||
# end | ||
assertion(:validates_presence_of) do |actual, attribute| | ||
msg = "expected to validate presence of #{attribute.inspect}" | ||
error_from_writing_value(actual, attribute, nil) ? pass : fail(msg) | ||
end | ||
|
||
# An ActiveRecord assertion that expects to pass with a given value or set of values for a given | ||
# attribute. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.allows_values_for :email, "a@b.cd" | ||
# topic.allows_values_for :email, "a@b.cd", "e@f.gh" | ||
# end | ||
assertion(:allows_values_for) do |actual, attribute, *values| | ||
bad_values = [] | ||
values.each do |value| | ||
bad_values << value if error_from_writing_value(actual, attribute, value) | ||
end | ||
msg = "expected #{attribute.inspect} to allow value(s) #{bad_values.inspect}" | ||
bad_values.empty? ? pass : fail(msg) | ||
# An ActiveRecord assertion that expects to pass with a given value or set of values for a given | ||
# attribute. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.allows_values_for :email, "a@b.cd" | ||
# topic.allows_values_for :email, "a@b.cd", "e@f.gh" | ||
# end | ||
assertion(:allows_values_for) do |actual, attribute, *values| | ||
bad_values = [] | ||
values.each do |value| | ||
bad_values << value if error_from_writing_value(actual, attribute, value) | ||
end | ||
msg = "expected #{attribute.inspect} to allow value(s) #{bad_values.inspect}" | ||
bad_values.empty? ? pass : fail(msg) | ||
end | ||
|
||
# An ActiveRecord assertion that expects to fail with a given value or set of values for a given | ||
# attribute. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.does_not_allow_values_for :email, "a" | ||
# topic.does_not_allow_values_for :email, "a@b", "e f@g.h" | ||
# end | ||
assertion(:does_not_allow_values_for) do |actual, attribute, *values| | ||
good_values = [] | ||
values.each do |value| | ||
good_values << value unless error_from_writing_value(actual, attribute, value) | ||
end | ||
msg = "expected #{attribute.inspect} not to allow value(s) #{good_values.inspect}" | ||
good_values.empty? ? pass : fail(msg) | ||
# An ActiveRecord assertion that expects to fail with a given value or set of values for a given | ||
# attribute. | ||
# | ||
# context "a User" do | ||
# setup { User.new } | ||
# topic.does_not_allow_values_for :email, "a" | ||
# topic.does_not_allow_values_for :email, "a@b", "e f@g.h" | ||
# end | ||
assertion(:does_not_allow_values_for) do |actual, attribute, *values| | ||
good_values = [] | ||
values.each do |value| | ||
good_values << value unless error_from_writing_value(actual, attribute, value) | ||
end | ||
msg = "expected #{attribute.inspect} not to allow value(s) #{good_values.inspect}" | ||
good_values.empty? ? pass : fail(msg) | ||
end | ||
|
||
# An ActiveRecord assertion that expects to fail with an attribute is not valid for record because the | ||
# value of the attribute is not unique. Requires the topic of the context to be a created record; one | ||
# that returns false for a call to +new_record?+. | ||
# | ||
# context "a User" do | ||
# setup { User.create(:email => "a@b.cde", ... ) } | ||
# topic.validates_uniqueness_of :email | ||
# end | ||
assertion(:validates_uniqueness_of) do |actual, attribute| | ||
actual_record = actual | ||
if actual_record.new_record? | ||
fail("topic is not a new record when testing uniqueness of #{attribute}") | ||
else | ||
copied_model = actual_record.class.new | ||
actual_record.attributes.each do |dup_attribute, dup_value| | ||
copied_model.write_attribute(dup_attribute, dup_value) | ||
end | ||
copied_value = actual_record.read_attribute(attribute) | ||
msg = "expected to fail because #{attribute.inspect} is not unique" | ||
error_from_writing_value(copied_model, attribute, copied_value) ? pass : fail(msg) | ||
# An ActiveRecord assertion that expects to fail with an attribute is not valid for record because the | ||
# value of the attribute is not unique. Requires the topic of the context to be a created record; one | ||
# that returns false for a call to +new_record?+. | ||
# | ||
# context "a User" do | ||
# setup { User.create(:email => "a@b.cde", ... ) } | ||
# topic.validates_uniqueness_of :email | ||
# end | ||
assertion(:validates_uniqueness_of) do |actual, attribute| | ||
actual_record = actual | ||
if actual_record.new_record? | ||
fail("topic is not a new record when testing uniqueness of #{attribute}") | ||
else | ||
copied_model = actual_record.class.new | ||
actual_record.attributes.each do |dup_attribute, dup_value| | ||
copied_model.write_attribute(dup_attribute, dup_value) | ||
end | ||
copied_value = actual_record.read_attribute(attribute) | ||
msg = "expected to fail because #{attribute.inspect} is not unique" | ||
error_from_writing_value(copied_model, attribute, copied_value) ? pass : fail(msg) | ||
end | ||
end | ||
|
||
# An ActiveRecord assertion macro that expects to pass when a given attribute is defined as +has_many+ | ||
# association. Will fail if an association is not defined for the attribute and if the association is | ||
# not +has_many. | ||
# | ||
# context "a Room" do | ||
# setup { Room.new } | ||
# | ||
# topic.has_many(:doors) | ||
# topic.has_many(:floors) # should probably fail given our current universe :) | ||
# end | ||
assertion(:has_many) do |actual, attribute| | ||
reflection = actual.class.reflect_on_association(attribute) | ||
static_msg = "expected #{attribute.inspect} to be a has_many association, but was " | ||
if reflection.nil? | ||
fail(static_msg + "not") | ||
elsif "has_many" != reflection.macro.to_s | ||
fail(static_msg + "a #{reflection.macro} instead") | ||
else | ||
pass | ||
end | ||
# An ActiveRecord assertion macro that expects to pass when a given attribute is defined as +has_many+ | ||
# association. Will fail if an association is not defined for the attribute and if the association is | ||
# not +has_many.jekyll | ||
# | ||
# context "a Room" do | ||
# setup { Room.new } | ||
# | ||
# topic.has_many(:doors) | ||
# topic.has_many(:floors) # should probably fail given our current universe :) | ||
# end | ||
assertion(:has_many) do |actual, attribute| | ||
reflection = actual.class.reflect_on_association(attribute) | ||
static_msg = "expected #{attribute.inspect} to be a has_many association, but was " | ||
if reflection.nil? | ||
fail(static_msg + "not") | ||
elsif "has_many" != reflection.macro.to_s | ||
fail(static_msg + "a #{reflection.macro} instead") | ||
else | ||
pass | ||
end | ||
private | ||
end | ||
private | ||
|
||
def error_from_writing_value(model, attribute, value) | ||
model.write_attribute(attribute, value) | ||
model.valid? | ||
model.errors.on(attribute) | ||
end | ||
def error_from_writing_value(model, attribute, value) | ||
model.write_attribute(attribute, value) | ||
model.valid? | ||
model.errors.on(attribute) | ||
end | ||
|
||
end # Assertion | ||
end # Riot | ||
end # Riot::Assertion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.