dry-rb / dry-schema

Coercion and validation for data structures
https://dry-rb.org/gems/dry-schema
MIT License
425 stars 109 forks source link

Validation passes when array type is invalid #426

Open guilherme-andrade opened 2 years ago

guilherme-andrade commented 2 years ago

This is a duplicate of https://github.com/dry-rb/dry-validation/issues/713

Describe the bug

When creating a custom type and using with the array rule, it appears that the validations applied by the type are not applied always by the rule. See the example below, and note that the last test is failing when it shouldn't:

To Reproduce

require 'dry/validation'
require 'dry/types'

module Types
  include Dry.Types(default: :nominal)

  StringOrHash = Types::Strict::String.enum('foo') | Types::Strict::Hash.schema(bar: Types::Strict::String.enum('baz'))
end

class TestContract < Dry::Validation::Contract
  params do
    required(:test).array(Types::StringOrHash)
  end
end

These tests all pass as expected:

RSpec.describe Types::StringOrHash do
  it 'works with a valid hash input' do
    expect { described_class[{ bar: 'baz' }] }.not_to raise_error
  end

  it 'works with a valid string input' do
    expect { described_class['foo'] }.not_to raise_error
  end

  it 'fails with an invalid string input' do
    expect { described_class['bar'] }.to raise_error
  end

  it 'fails with a hash with invalid values' do
    expect { described_class[{ bar: 'quz' }] }.to raise_error
  end

  it 'fails with a hash with invalid keys' do
    expect { described_class[{ quz: 'baz' }] }.to raise_error
  end
end

The first test passes, the second fails:

RSpec.describe TestContract do
  subject { described_class.new.call(params) }

  context 'when passing a valid array' do
    let(:params) { { test: ['foo', { bar: 'baz' }] } }

    it { is_expected.to be_success }
  end

  # THIS TEST FAILS
  context 'when passing an invalid array' do
    let(:params) { { test: ['foo', { bar: 'qux' }] } }

    it { is_expected.to be_failure }
  end
end

Expected behavior

It is expected that the validation fails when the input value is not of the described value.

My environment