require 'dry/logic/rule_compiler' RSpec.describe Dry::Logic::RuleCompiler, '#call' do subject(:compiler) { RuleCompiler.new(predicates) } let(:predicates) { { key?: predicate, attr?: predicate, filled?: predicate, gt?: predicate, one: predicate } } let(:predicate) { double(:predicate, name: :test?, arity: 2).as_null_object } let(:rule) { Rule::Predicate.new(predicate) } let(:key_op) { Operations::Key.new(rule, name: :email) } let(:attr_op) { Operations::Attr.new(rule, name: :email) } let(:check_op) { Operations::Check.new(rule, keys: [:email]) } let(:not_key_op) { Operations::Negation.new(key_op) } let(:and_op) { key_op.curry(:email) & rule } let(:or_op) { key_op.curry(:email) | rule } let(:xor_op) { key_op.curry(:email) ^ rule } let(:set_op) { Operations::Set.new(rule) } let(:each_op) { Operations::Each.new(rule) } it 'compiles key rules' do ast = [[:key, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]] rules = compiler.(ast) expect(rules).to eql([key_op]) end it 'compiles attr rules' do ast = [[:attr, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]] rules = compiler.(ast) expect(rules).to eql([attr_op]) end it 'compiles check rules' do ast = [[:check, [[:email], [:predicate, [:filled?, [[:input, Undefined]]]]]]] rules = compiler.(ast) expect(rules).to eql([check_op]) end it 'compiles attr rules' do ast = [[:attr, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]] rules = compiler.(ast) expect(rules).to eql([attr_op]) end it 'compiles negated rules' do ast = [[:not, [:key, [:email, [:predicate, [:filled?, [[:input, Undefined]]]]]]]] rules = compiler.(ast) expect(rules).to eql([not_key_op]) end it 'compiles and rules' do ast = [ [ :and, [ [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]], [:predicate, [:filled?, [[:input, Undefined]]]] ] ] ] rules = compiler.(ast) expect(rules).to eql([and_op]) end it 'compiles or rules' do ast = [ [ :or, [ [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]], [:predicate, [:filled?, [[:input, Undefined]]]] ] ] ] rules = compiler.(ast) expect(rules).to eql([or_op]) end it 'compiles exclusive or rules' do ast = [ [ :xor, [ [:key, [:email, [:predicate, [:key?, [[:name, :email], [:input, Undefined]]]]]], [:predicate, [:filled?, [[:input, Undefined]]]] ] ] ] rules = compiler.(ast) expect(rules).to eql([xor_op]) end it 'compiles set rules' do ast = [[:set, [[:predicate, [:filled?, [[:input, nil]]]]]]] rules = compiler.(ast) expect(rules).to eql([set_op]) end it 'compiles each rules' do ast = [[:each, [:predicate, [:filled?, [[:input, nil]]]]]] rules = compiler.(ast) expect(rules).to eql([each_op]) end end