Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds assert_error and assert_no_error #51774

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
* Adds `assert_error`, `assert_no_error`, `assert_valid` and `assert_not_valid` to ensure a model has the right validations
```ruby
assert_error :name, :blank, :user
assert_no_error :name, :blank, :user
assert_valid :name, :blank, :user
assert_not_valid :name, :blank, :user
```

*Daniela Velasquez*

Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activesupport/CHANGELOG.md) for previous changes.
44 changes: 44 additions & 0 deletions activesupport/lib/active_support/testing/assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,50 @@ def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
retval
end

# Assertion that an active model doesn't have an error on a field
#
# assert_no_error :name, :blank, :user
def assert_no_error(attribute, type, obj, msg = nil)
raise ArgumentError.new("#{obj.inspect} does not respond to #errors") unless obj.respond_to?(:errors)
msg = message(msg) {
data = [attribute, type]
"Expected %s to not be %s" % data
}
assert_not(obj.errors.added?(attribute, type), msg)
end

# Assertion that an active model has a specific error on a field
#
# assert_error :name, :blank, :user
def assert_error(attribute, type, obj, msg = nil)
raise ArgumentError.new("#{obj.inspect} does not respond to #errors") unless obj.respond_to?(:errors)
msg = message(msg) {
data = [type, attribute]
"Expected error %s on %s" % data
}
assert(obj.errors.added?(attribute, type), msg)
end

# Assertion that an active model's attribute is not valid after validation
#
# assert_not_valid :name, :blank, :user
def assert_not_valid(attribute, type, obj, msg = nil)
raise ArgumentError.new("#{obj.inspect} does not respond to #validate") unless obj.respond_to?(:validate)

obj.validate
assert_error(attribute, type, obj, msg)
end

# Assertion that an active model's attribute is valid after validation
#
# assert_valid :name, :blank, :user
def assert_valid(attribute, type, obj, msg = nil)
raise ArgumentError.new("#{obj.inspect} does not respond to #validate") unless obj.respond_to?(:validate)

obj.validate
assert_no_error(attribute, type, obj, msg)
end

private
def _assert_nothing_raised_or_warn(assertion, &block)
assert_nothing_raised(&block)
Expand Down
123 changes: 123 additions & 0 deletions activesupport/test/active_model_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# frozen_string_literal: true

require_relative "abstract_unit"
require "active_model"

class ActiveModelTest < ActiveSupport::TestCase
def setup
@active_model = Class.new do
include ActiveModel::Model
include ActiveModel::Attributes

attribute :name, :string
attribute :last_name, :string
validates :name, :last_name, presence: true
validate :name_doesnt_contain_numbers

private
def name_doesnt_contain_numbers
unless name.nil? || name.scan(/\d/).empty?
errors.add(:name, "shouldn't contain numbers")
end
end
end.new
end

test "#assert_no_error asserts active model does not have an error on a field" do
@active_model.name = "name"
@active_model.validate

assert_no_error :name, :blank, @active_model
end

test "#assert_no_error raises ArgumentError with a non-active record" do
error = assert_raises(ArgumentError) do
assert_no_error :name, :blank, Object.new
end

assert_includes error.message, "does not respond to #errors"
end

test "#assert_no_error raises a Minitest::Assertion when validation fails" do
@active_model.validate
error = assert_raises(Minitest::Assertion) do
assert_no_error :name, :blank, @active_model
end
assert_includes error.message, "Expected name to not be blank"
end

test "#assert_error asserts active model has an error on a field" do
@active_model.validate
assert_error :name, :blank, @active_model
end

test "#assert_error asserts active model has an error on a field with a string" do
error_message = "must start with H"
@active_model.errors.add(:name, error_message)

assert_error :name, error_message, @active_model
end

test "#assert_error raises ArgumentError with a non-active record" do
error = assert_raises(ArgumentError) do
assert_error :name, :blank, Object.new
end

assert_includes error.message, "does not respond to #errors"
end

test "#assert_error raises a Minitest::Assertion when validation fails" do
@active_model.name = "h"
@active_model.validate
error = assert_raises(Minitest::Assertion) do
assert_error :name, :blank, @active_model
end
assert_includes error.message, "Expected error blank on name"
end

test "#assert_not_valid asserts active model has error on a field after validation" do
assert_not_valid :name, :blank, @active_model
end

test "#assert_not_valid asserts active model has error on a field with a string message" do
@active_model.name = "Person1"
assert_not_valid :name, "shouldn't contain numbers", @active_model
end

test "#assert_not_valid raises ArgumentError with message about the object nor responding to validate" do
error = assert_raises(ArgumentError) do
assert_not_valid :name, :blank, Object.new
end

assert_includes error.message, "does not respond to #validate"
end

test "#assert_not_valid raises a Minitest::Assertion when validation fails" do
@active_model.name = "Hi"
error = assert_raises(Minitest::Assertion) do
assert_not_valid :name, :blank, @active_model
end
assert_includes error.message, "Expected error blank on name"
end

test "#assert_valid asserts active model does not have an error on a field after validation" do
@active_model.name = "name"

assert_valid :name, :blank, @active_model
end

test "#assert_valid raises ArgumentError with message about the object nor responding to validate" do
error = assert_raises(ArgumentError) do
assert_valid :name, :blank, Object.new
end

assert_includes error.message, "does not respond to #validate"
end

test "#assert_valid raises a Minitest::Assertion when validation fails" do
error = assert_raises(Minitest::Assertion) do
assert_valid :name, :blank, @active_model
end
assert_includes error.message, "Expected name to not be blank"
end
end