module Minitest::Assertions

reopening to add additional functionality

reopening to add association functionality

reopening to add schema validation functionality

reopening to add validations functionality

reopening to add validations functionality

Public Instance Methods

assert_association(klass, association_type, attribute, opts = {}, msg = nil) click to toggle source

Test for associations for the current model by passing the :association_type

it { assert_association(Post, :many_to_many, :tags) }
# File lib/minitest/sequel/associations.rb, line 54
def assert_association(klass, association_type, attribute, opts = {}, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  msg << "Expected #{klass.inspect} to have a #{association_type.inspect}"
  msg << " association #{attribute.inspect}"
  assoc = klass.association_reflection(attribute) || {}
  if assoc.empty?
    msg << " but no association '#{attribute.inspect}' was found"
    arr = []
    klass.associations.each do |a|
      o = klass.association_reflection(a)
      if o[:type] == :many_to_many
        arr << {
          attribute:    o[:name],
          type:         o[:type],
          class:        o[:class_name].to_s,
          join_table:   o[:join_table],
          left_keys:    o[:left_keys],
          right_keys:   o[:right_keys]
        }
      else
        arr << {
          attribute:  o[:name],
          type:       o[:type],
          class:      o[:class_name].to_s,
          keys:       o[:keys]
        }
      end
    end
    msg << " - \navailable associations are: [ #{arr.join(', ')} ]\n"
    assert(false, msg)
  else
    matching = assoc[:type] == association_type
    err_msg = []
    conf_msg = []
    opts.each do |key, value|
      conf_msg << { key => value }
      if assoc[key] != value
        err_msg << { key => assoc[key].to_s }
        matching = false
      end
    end
    msg << " with given options: #{conf_msg.join(', ')} but should be #{err_msg.join(', ')}"
    assert(matching, msg)
  end
end
assert_association_many_to_many(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for a :many_to_many association for the current model

let(:m) { Post.first }

it { assert_association_many_to_many(m, :tags) }
it { m.must_have_many_to_many_association(:tags) }
# File lib/minitest/sequel/associations.rb, line 46
def assert_association_many_to_many(obj, attribute, opts = {}, msg = nil)
  assert_association(obj.class, :many_to_many, attribute, opts, msg)
end
assert_association_many_to_one(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for a :many_to_one association for the current model

let(:m) { Post.first }

it { assert_association_many_to_one(m, :author) }
it { m.must_have_many_to_one_association(:author) }
# File lib/minitest/sequel/associations.rb, line 35
def assert_association_many_to_one(obj, attribute, opts = {}, msg = nil)
  assert_association(obj.class, :many_to_one, attribute, opts, msg)
end
assert_association_one_to_many(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for a :one_to_many association for the current model

let(:m) { Post.first }

it { assert_association_one_to_many(m, :comments) }
it { m.must_have_one_to_many_association(:comments) }
# File lib/minitest/sequel/associations.rb, line 24
def assert_association_one_to_many(obj, attribute, opts = {}, msg = nil)
  assert_association(obj.class, :one_to_many, attribute, opts, msg)
end
assert_association_one_to_one(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for a :one_to_one association for the current model

let(:m) { Post.first }

it { assert_association_one_to_one(m, :first_comment, { class: :Comment, order: :id }) }
it { m.must_have_one_to_one_association(:first_comment, { class: :Comment, order: :id }) }
# File lib/minitest/sequel/associations.rb, line 13
def assert_association_one_to_one(obj, attribute, opts = {}, msg = nil)
  assert_association(obj.class, :one_to_one, attribute, opts, msg)
end
assert_fails_validation(obj)
assert_have_column(obj, attribute, opts = {}, msg = nil) click to toggle source

Conveniently test your Model definitions as follows:

let(:m) { Post.first }

it { assert_have_column(m, :title, type: :string, db_type: 'varchar(250)') }
it { m.must_have_column(:title, type: :string, db_type: 'varchar(250)') }

# assert_have_column(<instance>, <column_name>, <options>, <custom_error_message>)

# <instance>.must_have_column(<column_name>, <options>, <custom_error_message>)

`assert_have_column()` first tests if the column name is defined in the Model and then checks all passed options. The following options are valid and checked:

* :type
* :db_type
* :allow_null
* :max_length
* :default
* :primary_key
* :auto_increment

In the event the specs differ from the actual database implementation an extensive error message with the differing option(s) is provided to help speed up debugging the issue:

Expected Post model to have column: :title with: \
  { type: 'string', db_type: 'varchar(250)', allow_null: 'false' } \
  but found: { db_type: 'varchar(255)' }

**Please NOTE!**

To test options with a value that is either `nil`, `true` or `false`, please use `:nil`, `:false` or `:true` and provide numbers as 'strings' instead.

# File lib/minitest/sequel/columns.rb, line 43
def assert_have_column(obj, attribute, opts = {}, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  msg << "Expected #{obj.class} model to have column: :#{attribute}"
  err_msg  = []
  conf_msg = []
  # check if column exists
  dcol = obj.db.schema(obj.class.table_name).detect { |c| c[0] == attribute }
  matching = !dcol.nil?

  # bail out if no matching column
  unless matching
    msg << " but no such column exists"
    assert(false, msg)
  end

  # bail out if options provided are invalid
  val_opts = [:type, :db_type, :allow_null, :max_length, :default, :primary_key, :auto_increment]
  invalid_opts = opts.keys.reject { |o| val_opts.include?(o) }
  unless invalid_opts.empty?
    msg << ", but the following invalid option(s) was found: { "
    invalid_opts.each { |o| msg << "#{o.inspect}; " }
    msg << " }. Valid options are: #{val_opts.inspect}"
    assert(false, msg)
  end

  # TODO: simplify this mess. quick fix didn't work, so look at it again when time permits.

  unless opts[:type].nil?
    expected = (dcol[1][:type].to_s == opts[:type].to_s)
    conf_msg << "type: '#{opts[:type]}'"
    unless expected
      err_msg << "type: '#{dcol[1][:type]}'"
    end
    matching &&= expected
  end

  unless opts[:db_type].nil?
    expected = (dcol[1][:db_type].to_s == opts[:db_type].to_s)
    conf_msg << "db_type: '#{opts[:db_type]}'"
    unless expected
      err_msg << "db_type: '#{dcol[1][:db_type]}'"
    end
    matching &&= expected
  end

  unless opts[:max_length].nil?
    expected = (dcol[1][:max_length] === opts[:max_length])
    conf_msg << "max_length: '#{opts[:max_length]}'"
    unless expected
      err_msg << "max_length: '#{dcol[1][:max_length]}'"
    end
    matching &&= expected
  end

  unless opts[:allow_null].nil?
    v = _convert_value(opts[:allow_null])
    expected = (dcol[1][:allow_null] === v)
    conf_msg << "allow_null: '#{opts[:allow_null]}'"
    unless expected
      err_msg << "allow_null: '#{dcol[1][:allow_null]}'"
    end
    matching &&= expected
  end

  unless opts[:default].nil?
    v = _convert_value(opts[:default])
    expected = (dcol[1][:default] === v)
    conf_msg << "default: '#{opts[:default]}'"
    unless expected
      err_msg << "default: '#{dcol[1][:default].inspect}'"
    end
    matching &&= expected
  end

  unless opts[:primary_key].nil?
    v = _convert_value(opts[:primary_key])
    expected = (dcol[1][:primary_key] === v)
    conf_msg << "primary_key: '#{opts[:primary_key]}'"
    unless expected
      err_msg << "primary_key: '#{dcol[1][:primary_key]}'"
    end
    matching &&= expected
  end

  unless opts[:auto_increment].nil?
    v = _convert_value(opts[:auto_increment])
    expected = (dcol[1][:auto_increment] === v)
    conf_msg << "auto_increment: '#{opts[:auto_increment]}'"
    unless expected
      err_msg << "auto_increment: '#{dcol[1][:auto_increment]}'"
    end
    matching &&= expected
  end

  msg = msg << " with: { #{conf_msg.join(', ')} } but found: { #{err_msg.join(', ')} }"
  assert(matching, msg)
end
assert_paranoid_model(model, opts = {}) click to toggle source

Test if a model class is paranoid with .plugin(:paranoid) via [Sequel-Paranoid](github.com/sdepold/sequel-paranoid)

   # Declared locally in the Model
   class Comment < Sequel::Model
     plugin(:paranoid)
   end
   proc { assert_paranoid_model(Comment) }.wont_have_error

   # on a non-paranoid model
   class Post < Sequel::Model; end
   proc { assert_paranoid_model(Post) }.must_have_error(/Not a plugin\(:paranoid\) model, available plugins are/)

NOTE!

You can also pass attributes to the created model in the tests via the `opts` hash like this:

   proc { assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"}) }.wont_have_error
# File lib/minitest/sequel/plugins.rb, line 114
def assert_paranoid_model(model, opts = {})
  m = model.create(opts)
  # 1. test for Paranoid plugin
  plugs = model.instance_variable_get("@plugins").map(&:to_s)
  if plugs.include?("Sequel::Plugins::Paranoid")
    assert_nil(m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be NIL on new model")
    # after update
    assert(m.save, "AssertParanoidModel:save - updated model failed. Debug: [#{m.inspect}]")
    assert_nil(m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be NIL on updated model")
    # after destroy
    assert(m.destroy, "AssertParanoidModel:destroy - destroy model failed. Debug: [#{m.inspect}]")
    assert_instance_of(Time, m.deleted_at, "AssertParanoidModel:deleted_at - expected #deleted_at to be instance of Time on destroyed model, Debug: [#{m.inspect}]")
  else
    raise(Minitest::Assertion, "Not a plugin(:paranoid) model, available plugins are: #{plugs.inspect}")
  end
end
assert_raises_validation_failed(obj) click to toggle source
# File lib/minitest/sequel/validations.rb, line 404
def assert_raises_validation_failed(obj)
  assert_raises(::Sequel::ValidationFailed) { obj.save }
end
Also aliased as: assert_fails_validation
assert_timestamped_model(model, opts = {}) click to toggle source

Test if a model class is timestamped with .plugin(:timestamps)

   # Declared locally in the Model
   class Comment < Sequel::Model
     plugin(:timestamps)
   end
   proc { assert_timestamped_model(Comment) }.wont_have_error

   # on a non-timestamped model
   class Post < Sequel::Model; end
   proc { assert_timestamped_model(Post) }.must_have_error(/Not a \.plugin\(:timestamps\) model, available plugins are/)

NOTE!

You can also pass attributes to the created model in the tests via the `opts` hash like this:

   proc { assert_timestamped_model(Comment, {body: "I think...", email: "e@email.com"}) }.wont_have_error
# File lib/minitest/sequel/plugins.rb, line 68
def assert_timestamped_model(model, opts = {})
  m = model.create(opts)
  # 1. test for Timestamps plugin
  plugs = model.instance_variable_get("@plugins").map(&:to_s)
  if plugs.include?("Sequel::Plugins::Timestamps")
    # 2. test for created_at / :updated_at columns
    assert_have_column(m, :created_at, {}, "AssertTimestampedModel - expected model to have column :created_at. Debug: [#{m.inspect}]")
    assert_have_column(m, :updated_at, {}, "AssertTimestampedModel - expected model to have column :updated_at. Debug: [#{m.inspect}]")

    # 3.  initial record
    assert_instance_of(Time, m.created_at, "AssertTimestampedModel:created_at - expected #created_at to be an instance of Time on new record. Debug: [#{m.inspect}]")
    assert_instance_of(NilClass, m.updated_at, "AssertTimestampedModel:updated_at - expected #updated_at to be an instance of NilClass on new record. Debug: [#{m.inspect}]")

    # 4. updated record
    # old_ts = m.created_at
    # sleep 1  # TODO: could this be converted to timecop or similar?
    m.title = "#{m.title} updated"
    assert(m.save, "AssertTimestampedModel:#save - updated model failed. Debug: [#{m.inspect}]")
    assert_instance_of(Time, m.created_at, "AssertTimestampedModel:created_at - expected #created_at to be an instance of Time on updated record. Debug: [#{m.inspect}]")
    assert_instance_of(Time, m.updated_at, "AssertTimestampedModel:updated_at - expected #updated_at to be an instance of Time on updated record. Debug: [#{m.inspect}]")
    # assert_equal(old_ts, m.created_at, "AssertTimestampedModel - expected the :created_at timestamp to be unchanged")
  else
    raise(Minitest::Assertion, "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}")
  end
end
assert_timestamped_model_instance(model, opts = {}) click to toggle source

Test if a model instance is timestamped via .plugin(:timestamps)

let(:m) { Post.create(title: "Dummy") }
proc { assert_timestamped_model_instance(m) }.wont_have_error

You can also test if an updated record is correctly timestamped

m.title = "Updated"
m.save
proc { assert_timestamped_model_instance(m, updated_record: true) }.wont_have_error

Or alternatively test if an updated record is wrongly timestamped

let(:m) { Post.create(title: "Dummy", updated_at: Time.now) }
proc { assert_timestamped_model_instance(m, updated_record: false) }.must_have_error(/expected #.updated_at to be NIL on new record/)
# File lib/minitest/sequel/plugins.rb, line 23
def assert_timestamped_model_instance(model, opts = {})
  model_class = model.class
  # 1. test for Timestamps plugin
  plugs = model_class.instance_variable_get("@plugins").map(&:to_s)
  if plugs.include?("Sequel::Plugins::Timestamps")
    # 2. test for created_at / :updated_at columns
    assert_have_column(model, :created_at, {}, "AssertTimestampedModelInstance - expected model to have column :created_at, Debug: [#{model.inspect}]")
    assert_have_column(model, :updated_at, {}, "AssertTimestampedModelInstance - expected model to have column :updated_at, Debug: [#{model.inspect}]")

    if opts[:updated_record]
      # 4. updated record
      assert_instance_of(Time, model.created_at, "AssertTimestampedModelInstance:created_at - expected #created_at to be an instance of Time on updated record")
      assert_instance_of(Time, model.updated_at, "AssertTimestampedModelInstance:updated_at - expected #updated_at to be an instance of Time on updated record")
    else
      # 3.  initial record
      assert_instance_of(Time, model.created_at, "AssertTimestampedModelInstance:created_at - expected #created_at to be an instance of Time on new record")
      proc {
        assert_nil(model.updated_at, "AssertTimestampedModelInstance:updated - expected #updated_at to be NIL on new record")
      }.wont_have_error
    end
  else
    raise(Minitest::Assertion, "Not a plugin(:timestamps) model, available plugins are: #{plugs.inspect}")
  end
end
assert_validates(obj, validation_type, attribute, opts = {}, msg = nil) click to toggle source

Base test for validations of a model, used mainly as a shortcut for other assertions

# File lib/minitest/sequel/validations.rb, line 165
def assert_validates(obj, validation_type, attribute, opts = {}, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  err_msg  = []
  conf_msg = []
  unless obj.respond_to?(attribute)
    assert(false, "Column :#{attribute} is not defined in #{obj.class}")
  end

  msg << "Expected #{obj.class} to validate :#{validation_type} for :#{attribute} column"

  if _validated_model?(obj)

    if _validated_column?(obj, attribute)

      # checks if the model column is validated by the validation type
      if _validated_with_validation_type?(obj, attribute, validation_type)
        matching = true

        # bail out if options provided are invalid
        val_opts = _valid_validation_options(validation_type)

        invalid_opts = opts.keys.reject { |o| val_opts.include?(o) }
        unless invalid_opts.empty?
          msg << ", but the following invalid option(s) was found: { "
          invalid_opts.each { |o| msg << "#{o.inspect}; " }
          msg << " }. Valid options are: #{val_opts.inspect}"
          assert(false, msg)
        end

        h = _validation_types_hash_for_column(obj, attribute)
        _available_validation_options.each do |ov|
          unless opts[ov].nil?
            expected = (h[validation_type][ov].to_s == opts[ov].to_s)
              conf_msg << "#{ov}: '#{opts[ov]}'"
            unless expected
              err_msg << "#{ov}: '#{h[validation_type][ov]}'"
            end
            matching &&= expected
          end
        end

        msg = msg << " with: { #{conf_msg.join(', ')} }" unless conf_msg.empty?
        msg << " but found: { #{err_msg.join(', ')} }" unless err_msg.empty?
        assert(matching, msg)

      else
        msg << ", but no :#{validation_type} validation is defined for :#{attribute}"
        assert(false, msg)
      end
    else
      msg << ", but no validations are defined for :#{attribute}"
      assert(false, msg)
    end
  else
    assert(false, "No validations defined in #{obj.class}")
  end
end
assert_validates_acceptance(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the acceptance of a model's attribute.

it { assert_validates_acceptance(Order.new, :toc, { message: '...' }) }
it { model.must_validate_acceptance_of(:toc, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 149
def assert_validates_acceptance(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :acceptance, attribute, opts, msg)
end
assert_validates_acceptance_of(obj, attribute, opts = {}, msg = nil)
assert_validates_confirmation(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the confirmation of a model's attribute.

it { assert_validates_confirmation(User.new, :password, { message: '...' }) }
it { User.new.must_validate_confirmation_of(:password, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 159
def assert_validates_confirmation(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :confirmation, attribute, opts, msg)
end
assert_validates_confirmation_of(obj, attribute, opts = {}, msg = nil)
assert_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil) click to toggle source

Test for validating the exact length of a model's attribute.

it { assert_validates_exact_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_exact_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 53
def assert_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil)
  opts.merge!(is: exact_length)
  assert_validates(obj, :length, attribute, opts, msg)
end
assert_validates_exact_length_of(obj, attribute, exact_length, opts = {}, msg = nil)
assert_validates_format(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the format of a model's attribute with a regexp.

it { assert_validates_format(model, :title, 12, { with: /[a-z+]/ }) }
it { model.must_validate_format_of(:title, 12, { with: /[a-z]+/ }) }
# File lib/minitest/sequel/validations.rb, line 97
def assert_validates_format(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :format, attribute, opts, msg)
end
Also aliased as: assert_validates_format_of
assert_validates_format_of(obj, attribute, opts = {}, msg = nil)
assert_validates_inclusion(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is within a specified range or set of values.

it { assert_validates_inclusion(model, :status, { in: [:a, :b, :c] }) }
it { model.must_validate_inclusion_of(:status, { in: [:a, :b, :c] }) }
# File lib/minitest/sequel/validations.rb, line 107
def assert_validates_inclusion(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :inclusion, attribute, opts, msg)
end
assert_validates_inclusion_of(obj, attribute, opts = {}, msg = nil)
assert_validates_integer(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a a model's attribute is an integer.

it { assert_validates_integer(model, :author_id, { message: '...' }) }
it { model.must_validate_integer_of(:author_id, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 117
def assert_validates_integer(obj, attribute, opts = {}, msg = nil)
  opts.merge!(only_integer: true)
  assert_validates(obj, :numericality, attribute, opts, msg)
end
assert_validates_length(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the length of a model's attribute.

Available options:

  • :message - The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length options if present)

  • :nil_message - The message to use use if :maximum option is used and the value is nil (default: 'is not present')

  • :too_long - The message to use use if it the value is too long (default: 'is too long')

  • :too_short - The message to use use if it the value is too short (default: 'is too short')

  • :wrong_length - The message to use use if it the value is not valid (default: 'is the wrong length')

Size related options:

  • :is - The exact size required for the value to be valid (no default)

  • :minimum - The minimum size allowed for the value (no default)

  • :maximum - The maximum size allowed for the value (no default)

  • :within - The array/range that must include the size of the value for it to be valid (no default)

    it { assert_validates_length(model, :title, { maximum: 12 }) }
    it { model.must_validate_length_of(:title, { within: 4..12 }) }
    
# File lib/minitest/sequel/validations.rb, line 43
def assert_validates_length(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :length, attribute, opts, msg)
end
Also aliased as: assert_validates_length_of
assert_validates_length_of(obj, attribute, opts = {}, msg = nil)
assert_validates_length_range(obj, attribute, range, opts = {}, msg = nil) click to toggle source

Test for validating the exact length of a model's attribute.

it { assert_validates_length_range(model, :title, 4..12, { message: '...' }) }
it { model.must_validate_length_range_of(:title, 4..12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 64
def assert_validates_length_range(obj, attribute, range, opts = {}, msg = nil)
  opts.merge!(within: range)
  assert_validates(obj, :length, attribute, opts, msg)
end
assert_validates_length_range_of(obj, attribute, range, opts = {}, msg = nil)
assert_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil) click to toggle source

Test for validating the maximum length of a model's attribute.

it { assert_validates_max_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_max_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 75
def assert_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil)
  opts.merge!(maximum: max_length)
  assert_validates(obj, :length, attribute, opts, msg)
end
assert_validates_max_length_of(obj, attribute, max_length, opts = {}, msg = nil)
assert_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil) click to toggle source

Test for validating the minimum length of a model's attribute.

it { assert_validates_min_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_min_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 86
def assert_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil)
  opts.merge!(minimum: min_length)
  assert_validates(obj, :length, attribute, opts, msg)
end
assert_validates_min_length_of(obj, attribute, min_length, opts = {}, msg = nil)
assert_validates_numericality(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is numeric (number).

it { assert_validates_numericality(model, :author_id, { message: '...' }) }
it { model.must_validate_numericality_of(:author_id, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 127
def assert_validates_numericality(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :numericality, attribute, opts, msg)
end
assert_validates_numericality_of(obj, attribute, opts = {}, msg = nil)
assert_validates_presence(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating presence of a model attribute

it { assert_validates_presence(model, :title) }
it { model.must_validate_presence_of(:title, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 11
def assert_validates_presence(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :presence, attribute, opts, msg)
end
Also aliased as: assert_validates_presence_of
assert_validates_presence_of(obj, attribute, opts = {}, msg = nil)
assert_validates_uniqueness(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is unique.

it { assert_validates_uniqueness(model, :urlslug, { message: '...' }) }
it { model.must_validate_uniqueness_of(:urlslug, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 137
def assert_validates_uniqueness(obj, attribute, opts = {}, msg = nil)
  assert_validates(obj, :uniqueness, attribute, opts, msg)
end
assert_validates_uniqueness_of(obj, attribute, opts = {}, msg = nil)
refute_association(klass, association_type, attribute, msg = nil) click to toggle source

Test to ensure the current model does NOT have an association by type :association_type

it { refute_association(Post, :many_to_many, :tags) }
# File lib/minitest/sequel/associations.rb, line 149
def refute_association(klass, association_type, attribute, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  msg << "Expected #{klass.inspect} to NOT have a #{association_type.inspect}"
  msg << " association #{attribute.inspect}"
  assoc = klass.association_reflection(attribute) || {}

  if assoc.empty?
    assert(true, msg)
  else
    matching = false if assoc[:type] == association_type
    msg << ", but such an association was found"
    assert(matching, msg)
  end
end
refute_association_many_to_many(obj, attribute, msg = nil) click to toggle source

Test to ensure there is no :many_to_many association for the current model

let(:m) { Post.first }

it { refute_association_many_to_many(m, :tags) }
it { m.must_have_many_to_many_association(:tags) }
# File lib/minitest/sequel/associations.rb, line 141
def refute_association_many_to_many(obj, attribute, msg = nil)
  refute_association(obj.class, :many_to_many, attribute, msg)
end
refute_association_many_to_one(obj, attribute, msg = nil) click to toggle source

Test to ensure there is no :many_to_one association for the current model

let(:m) { Post.first }

it { refute_association_many_to_one(m, :author) }
it { m.must_have_many_to_one_association(:author) }
# File lib/minitest/sequel/associations.rb, line 130
def refute_association_many_to_one(obj, attribute, msg = nil)
  refute_association(obj.class, :many_to_one, attribute, msg)
end
refute_association_one_to_many(obj, attribute, msg = nil) click to toggle source

Test to ensure there is no :one_to_many association for the current model

let(:m) { Post.first }

it { refute_association_one_to_many(m, :comments) }
it { m.must_have_one_to_many_association(:comments) }
# File lib/minitest/sequel/associations.rb, line 119
def refute_association_one_to_many(obj, attribute, msg = nil)
  refute_association(obj.class, :one_to_many, attribute, msg)
end
refute_association_one_to_one(obj, attribute, msg = nil) click to toggle source

Test to ensure there is no :one_to_one association for the current model

let(:m) { Post.first }

it { refute_association_one_to_one(m, :first_comment, { class: :Comment, order: :id }) }
it { m.must_have_one_to_one_association(:first_comment, { class: :Comment, order: :id }) }
# File lib/minitest/sequel/associations.rb, line 108
def refute_association_one_to_one(obj, attribute, msg = nil)
  refute_association(obj.class, :one_to_one, attribute, msg)
end
refute_have_column(obj, attribute, msg = nil) click to toggle source
# File lib/minitest/sequel/columns.rb, line 142
def refute_have_column(obj, attribute, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  msg << "Expected #{obj.class} model to NOT have column: :#{attribute}"
  # check if column exists
  dcol = obj.db.schema(obj.class.table_name).detect { |col| col[0] == attribute }
  matching = dcol.nil?
  unless matching
    msg << " but such a column was found"
    assert(matching, msg)
  end
end
refute_paranoid_model(model) click to toggle source

Test to ensure the current model is NOT a :paranoid model

it { refute_paranoid_model(Post) }
# File lib/minitest/sequel/plugins.rb, line 146
def refute_paranoid_model(model)
  plugs = model.instance_variable_get("@plugins").map(&:to_s)
  refute_includes(plugs, "Sequel::Plugins::Paranoid", "RefuteParanoidModel - expected #{model} to NOT be a :paranoid model, but it was, Debug: [#{plugs.inspect}]")
end
refute_timestamped_model(model, opts = {}) click to toggle source

Test to ensure the current model is NOT a :timestamped model

it { refute_timestamped_model(Post) }
# File lib/minitest/sequel/plugins.rb, line 137
def refute_timestamped_model(model, opts = {})
  plugs = model.instance_variable_get("@plugins").map(&:to_s)
  refute_includes(plugs, "Sequel::Plugins::Timestamps", "RefuteTimestampedModel - expected #{model} to NOT be a :timestamped model, but it was, Debug: [#{plugs.inspect}]")
end
refute_validates(obj, validation_type, attribute, opts = {}, msg = nil) click to toggle source

Base test for validations of a model, used mainly as a shortcut for other assertions

# File lib/minitest/sequel/validations.rb, line 385
def refute_validates(obj, validation_type, attribute, opts = {}, msg = nil)
  msg = msg.nil? ? "" : "#{msg}\n"
  unless obj.respond_to?(attribute)
    assert(false, "Column :#{attribute} is not defined in #{obj.class}, so cannot be validated")
  end
  msg << "Expected #{obj.class} NOT to validate :#{attribute} with :#{validation_type}"
  if _validated_model?(obj)
    if _validated_column?(obj, attribute)
      msg << ", but the column :#{attribute} was validated with :#{validation_type}"
      assert(false, msg)
    else
      assert(true, msg)
    end
  else
    assert(false, "No validations defined in #{obj.class}")
  end
end
refute_validates_acceptance(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the acceptance of a model's attribute.

it { refute_validates_acceptance(Order.new, :toc, { message: '...' }) }
it { model.must_validate_acceptance_of(:toc, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 369
def refute_validates_acceptance(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :acceptance, attribute, opts, msg)
end
refute_validates_acceptance_of(obj, attribute, opts = {}, msg = nil)
refute_validates_confirmation(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the confirmation of a model's attribute.

it { refute_validates_confirmation(User.new, :password, { message: '...' }) }
it { User.new.must_validate_confirmation_of(:password, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 379
def refute_validates_confirmation(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :confirmation, attribute, opts, msg)
end
refute_validates_confirmation_of(obj, attribute, opts = {}, msg = nil)
refute_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil) click to toggle source

Test for validating the exact length of a model's attribute.

it { refute_validates_exact_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_exact_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 273
def refute_validates_exact_length(obj, attribute, exact_length, opts = {}, msg = nil)
  opts.merge!(is: exact_length)
  refute_validates(obj, :length, attribute, opts, msg)
end
refute_validates_exact_length_of(obj, attribute, exact_length, opts = {}, msg = nil)
refute_validates_format(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the format of a model's attribute with a regexp.

it { refute_validates_format(model, :title, 12, { with: /[a-z+]/ }) }
it { model.must_validate_format_of(:title, 12, { with: /[a-z]+/ }) }
# File lib/minitest/sequel/validations.rb, line 317
def refute_validates_format(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :format, attribute, opts, msg)
end
Also aliased as: refute_validates_format_of
refute_validates_format_of(obj, attribute, opts = {}, msg = nil)
refute_validates_inclusion(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is within a specified range or set of values.

it { refute_validates_inclusion(model, :status, { in: [:a, :b, :c] }) }
it { model.must_validate_inclusion_of(:status, { in: [:a, :b, :c] }) }
# File lib/minitest/sequel/validations.rb, line 327
def refute_validates_inclusion(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :inclusion, attribute, opts, msg)
end
refute_validates_inclusion_of(obj, attribute, opts = {}, msg = nil)
refute_validates_integer(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a a model's attribute is an integer.

it { refute_validates_integer(model, :author_id, { message: '...' }) }
it { model.must_validate_integer_of(:author_id, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 337
def refute_validates_integer(obj, attribute, opts = {}, msg = nil)
  opts.merge!(only_integer: true)
  refute_validates(obj, :numericality, attribute, opts, msg)
end
refute_validates_length(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating the length of a model's attribute.

Available options:

:message

The message to use (no default, overrides :nil_message, :too_long, :too_short, and :wrong_length options if present)

:nil_message

The message to use use if :maximum option is used and the value is nil (default: 'is not present')

:too_long

The message to use use if it the value is too long (default: 'is too long')

:too_short

The message to use use if it the value is too short (default: 'is too short')

:wrong_length

The message to use use if it the value is not valid

(default: 'is the wrong length')

SIZE RELATED OPTIONS:

:is

The exact size required for the value to be valid (no default)

:minimum

The minimum size allowed for the value (no default)

:maximum

The maximum size allowed for the value (no default)

:within

The array/range that must include the size of the value for it to be valid

(no default)
it { refute_validates_length(model, :title, { maximum: 12 }) }
it { model.must_validate_length_of(:title, { within: 4..12 }) }
# File lib/minitest/sequel/validations.rb, line 263
def refute_validates_length(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :length, attribute, opts, msg)
end
Also aliased as: refute_validates_length_of
refute_validates_length_of(obj, attribute, opts = {}, msg = nil)
refute_validates_length_range(obj, attribute, range, opts = {}, msg = nil) click to toggle source

Test for validating the exact length of a model's attribute.

it { refute_validates_length_range(model, :title, 4..12, { message: '...' }) }
it { model.must_validate_length_range_of(:title, 4..12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 284
def refute_validates_length_range(obj, attribute, range, opts = {}, msg = nil)
  opts.merge!(within: range)
  refute_validates(obj, :length, attribute, opts, msg)
end
refute_validates_length_range_of(obj, attribute, range, opts = {}, msg = nil)
refute_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil) click to toggle source

Test for validating the maximum length of a model's attribute.

it { refute_validates_max_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_max_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 295
def refute_validates_max_length(obj, attribute, max_length, opts = {}, msg = nil)
  opts.merge!(maximum: max_length)
  refute_validates(obj, :length, attribute, opts, msg)
end
refute_validates_max_length_of(obj, attribute, max_length, opts = {}, msg = nil)
refute_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil) click to toggle source

Test for validating the minimum length of a model's attribute.

it { refute_validates_min_length(model, :title, 12, { message: '...' }) }
it { model.must_validate_min_length_of(:title, 12, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 306
def refute_validates_min_length(obj, attribute, min_length, opts = {}, msg = nil)
  opts.merge!(minimum: min_length)
  refute_validates(obj, :length, attribute, opts, msg)
end
refute_validates_min_length_of(obj, attribute, min_length, opts = {}, msg = nil)
refute_validates_numericality(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is numeric (number).

it { refute_validates_numericality(model, :author_id, { message: '...' }) }
it { model.must_validate_numericality_of(:author_id, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 347
def refute_validates_numericality(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :numericality, attribute, opts, msg)
end
refute_validates_numericality_of(obj, attribute, opts = {}, msg = nil)
refute_validates_presence(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating presence of a model attribute

it { refute_validates_presence(model, :title) }
it { model.must_validate_presence_of(:title, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 229
def refute_validates_presence(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :presence, attribute, opts, msg)
end
Also aliased as: refute_validates_presence_of
refute_validates_presence_of(obj, attribute, opts = {}, msg = nil)
refute_validates_uniqueness(obj, attribute, opts = {}, msg = nil) click to toggle source

Test for validating that a model's attribute is unique.

it { refute_validates_uniqueness(model, :urlslug, { message: '...' }) }
it { model.must_validate_uniqueness_of(:urlslug, { message: '...' }) }
# File lib/minitest/sequel/validations.rb, line 357
def refute_validates_uniqueness(obj, attribute, opts = {}, msg = nil)
  refute_validates(obj, :uniqueness, attribute, opts, msg)
end
refute_validates_uniqueness_of(obj, attribute, opts = {}, msg = nil)

Private Instance Methods

_available_validation_options() click to toggle source
# File lib/minitest/sequel/validations.rb, line 452
def _available_validation_options
  [
    :message, :if, :is, :in, :allow_blank, :allow_missing, :allow_nil, :accept, :with, :within,
    :only_integer, :maximum, :minimum, :nil_message, :too_long, :too_short, :wrong_length
  ]
end
_available_validation_types() click to toggle source
# File lib/minitest/sequel/validations.rb, line 447
def _available_validation_types
  [:format, :length, :presence, :numericality, :confirmation, :acceptance, :inclusion, :uniqueness]
end
_convert_value(val) click to toggle source

handles converting `:nil`, `:false` values

# File lib/minitest/sequel.rb, line 12
def _convert_value(val)
  v = case val
      when :nil    then nil
      when :false  then false
      when :true   then true
      else
        val
      end
  v
end
_valid_validation_options(type = nil) click to toggle source
# File lib/minitest/sequel/validations.rb, line 460
def _valid_validation_options(type = nil)
  arr = [:message]
  case type.to_sym
  when :each
    # validates_each (*atts, &block)
    # Adds a validation for each of the given attributes using the supplied block.
    [:allow_blank, :allow_missing, :allow_nil].each { |a| arr << a }
  when :acceptance
    # The value required for the object to be valid (default: '1')
    arr << :accept
  when :format
    # The regular expression to validate the value with (required).
    arr << :with
  when :inclusion
    # An array or range of values to check for validity (required)
    arr << :in
  when :numericality
    # Whether only integers are valid values (default: false)
    arr << :only_integer
  when :length
    #
    # :message     ::  The message to use (no default, overrides :nil_message, :too_long,
    #                  :too_short, and :wrong_length options if present)
    #
    # :nil_message ::  The message to use use if :maximum option is used and the value is nil
    #                  (default: 'is not present')
    #
    # :too_long    ::  The message to use use if it the value is too long (default: 'is too long')
    #
    # :too_short   ::  The message to use use if it the value is too short
    #                  (default: 'is too short')
    #
    # :wrong_length :: The message to use use if it the value is not valid
    #                   (default: 'is the wrong length')
    #
    # SIZE
    # :is         :: The exact size required for the value to be valid (no default)
    # :minimum    :: The minimum size allowed for the value (no default)
    # :maximum    :: The maximum size allowed for the value (no default)
    # :within     :: The array/range that must include the size of the value for it to be valid
    #                 (no default)

    [:is, :maximum, :minimum, :nil_message, :too_long, :too_short, :within, :wrong_length].each { |a| arr << a }
  else
    arr
  end unless type.nil?
  arr
end
_validated_column?(model, attribute) click to toggle source
# File lib/minitest/sequel/validations.rb, line 428
def _validated_column?(model, attribute)
  return false unless _validated_model?(model)
  model.class.validation_reflections.keys.include?(attribute.to_sym)
end
_validated_model?(model) click to toggle source
# File lib/minitest/sequel/validations.rb, line 423
def _validated_model?(model)
  (model.class.respond_to?(:has_validations?) && model.class.has_validations?)
end
_validated_with_validation_type?(model, attribute, validation_type) click to toggle source
# File lib/minitest/sequel/validations.rb, line 434
def _validated_with_validation_type?(model, attribute, validation_type)
  return false unless _validated_column?(model, attribute)
  _validation_types_hash_for_column(model, attribute).keys.include?(validation_type)
end
_validation_types_hash_for_column(model, attribute) click to toggle source
# File lib/minitest/sequel/validations.rb, line 440
def _validation_types_hash_for_column(model, attribute)
  h = {}
  model.class.validation_reflections[attribute].each { |c| h[c[0]] = c[1] }
  h
end