# frozen_string_literal: true

RSpec.describe Operations::Check do
  include_context 'predicates'

  describe '#call' do
    context 'with 1-level nesting' do
      subject(:operation) do
        Operations::Check.new(Rule::Predicate.build(eql?).curry(1), id: :compare, keys: [:num])
      end

      it 'applies predicate to args extracted from the input' do
        expect(operation.(num: 1)).to be_success
        expect(operation.(num: 2)).to be_failure
      end
    end

    context 'with 2-levels nesting' do
      subject(:operation) do
        Operations::Check.new(Rule::Predicate.build(eql?), id: :compare, keys: [[:nums, :left], [:nums, :right]])
      end

      it 'applies predicate to args extracted from the input' do
        expect(operation.(nums: { left: 1, right: 1 })).to be_success
        expect(operation.(nums: { left: 1, right: 2 })).to be_failure
      end

      it 'curries args properly' do
        result = operation.(nums: { left: 1, right: 2 })

        expect(result.to_ast).to eql(
          [:failure, [:compare, [:check, [
            [[:nums, :left], [:nums, :right]], [:predicate, [:eql?, [[:left, 1], [:right, 2]]]]]
          ]]]
        )
      end
    end
  end

  describe '#to_ast' do
    subject(:operation) do
      Operations::Check.new(Rule::Predicate.build(str?), keys: [:email])
    end

    it 'returns ast' do
      expect(operation.to_ast).to eql(
        [:check, [[:email], [:predicate, [:str?, [[:input, Undefined]]]]]]
      )
    end
  end
end
