require 'spec_helper' require 'pact/matchers' module Pact::Matchers describe Pact::Matchers do include Pact::Matchers describe 'matching with something like' do context 'when the actual is something like the expected' do let(:expected) { Pact::SomethingLike.new( { a: 1 } ) } let(:actual) { { a: 2} } it 'returns an empty diff' do expect(diff(expected, actual)).to eq({}) end end end describe 'option {allow_unexpected_keys: false}' do context "when an unexpected key is found" do let(:expected) { {:a => 1} } let(:actual) { {:a => 1, :b => 2} } let(:difference) { {:b => Difference.new(Pact::UnexpectedKey.new, 2 )} } it "returns it in the diff" do expect(diff(expected, actual, allow_unexpected_keys: false)).to eq difference end end end describe "expecting key to be present with nil value and not finding key" do let(:expected) { {a: nil} } let(:actual) { {} } let(:difference) { {a: Difference.new(nil, Pact::KeyNotFound.new )} } it "returns the key in the diff" do expect(diff(expected, actual)).to eq difference end end describe "expecting a string matching a regexp and not finding key" do let(:expected) { {a: /b/} } let(:actual) { {} } let(:difference) { {:a=> Difference.new(/b/, Pact::KeyNotFound.new) } } it "returns the diff" do expect(diff(expected, actual)).to eq difference end end describe 'structure_diff' do let(:expected) { {a: 'a string', b: 1, c: nil, d: [{e: 'thing'}], f: {g: 10}, h: false} } context "when the classes match" do let(:actual) { {a: 'another string', b: 2, c: nil, d: [{e: 'something'}], f: {g: 100}, h: true} } let(:difference) { {} } it "returns an empty hash" do expect(structure_diff(expected, actual)).to eq difference end end context "when a key is not found" do let(:actual) { {a: 'blah'} } let(:expected) { {b: 'blah'} } let(:difference) { {:b=>Difference.new({:class=>String, :eg=>"blah"}, Pact::KeyNotFound.new)} } it "returns the difference" do expect(structure_diff(expected, actual)).to eq difference end end context "when a number is expected" do let(:expected) { {a: 1} } #let(:difference) { {a: {expected: 'Fixnum (eg. 1)', actual: 'String ("a string")'}} } let(:difference) { {a: Difference.new({:class => Fixnum, eg: 1 } , {:class => String, :value => 'a string'})} } context "and a string is found" do let(:actual) { {a: 'a string'}} it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end context "and nil is found" do let(:actual) { {a: nil}} let(:difference ) { {a: Difference.new({:class => Fixnum, eg: 1}, nil) } } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end context "and a hash is found" do let(:actual) { {a: {b: 1}} } let(:difference) { {:a=>Difference.new({:class=>Fixnum, :eg=>1}, {:class=>Hash, :value=>{:b=>1}}) } } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end context "and an array is found" do let(:actual) { {a: [1] } } let(:difference) { {:a=>Difference.new({:class=>Fixnum, :eg=>1}, {:class=>Array, :value=>[1]} ) } } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end end context "when an array is expected" do let(:expected) { [{name: 'Fred'}, {name: 'Mary'}] } context "when an item with differing class values is found" do let(:actual) { [{name: 'Fred'}, {name: 1}] } let(:difference) { [ Pact::Matchers::NO_DIFF_INDICATOR, {:name => Difference.new( { :class=>String, :eg=>"Mary" }, { :class=>Fixnum, :value=>1} ) } ] } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end end context "when nil is expected" do let(:expected) { {a: nil} } context "and a string is found" do let(:actual) { {a: 'a string'} } let(:difference) { {:a=>Difference.new(nil, {:class=>String, :value=>"a string"}) } } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end end context "when a term is expected" do let(:expected) { {a: Pact::Term.new(:matcher => /p/, :generate => 'apple')} } context "and a non matching string is found" do let(:actual) { {a: 'banana'} } let(:difference) { {:a=>Pact::Matchers::Difference.new(/p/,"banana")} } it "returns the diff" do expect(structure_diff(expected, actual)).to eq difference end end end end describe 'diffing' do context "when expected is longer than the actual" do subject { [1,2,3] } let(:actual) { [1,2]} let(:difference) { [Pact::Matchers::NO_DIFF_INDICATOR, Pact::Matchers::NO_DIFF_INDICATOR, Difference.new(3, Pact::IndexNotFound.new)] } it 'returns the diff' do expect(diff(subject, actual)).to eq(difference) end end context "when actual array is longer than the expected" do subject { [1] } let(:actual) { [1,2]} let(:difference) { [Pact::Matchers::NO_DIFF_INDICATOR, Difference.new(Pact::UnexpectedIndex.new, 2)] } it 'returns the diff' do expect(diff(subject, actual)).to eq(difference) end end context 'where an expected value is a non-empty string' do subject { {:a => 'a', :b => 'b'} } context 'and the actual value is an empty string' do let(:actual) { {:a => 'a', :b => ''} } it 'includes this in the diff' do expect(diff(subject, actual)).to eq({:b => Difference.new('b', '')}) end end end context "when the expected value is a hash" do subject { {a: 'b'} } context "when the actual value is an array" do let(:actual) { [1] } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an hash" do let(:actual) { {b: 'c'} } let(:difference) { { a: Difference.new("b",Pact::KeyNotFound.new)} } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an number" do let(:actual) { 1 } let(:difference) { Difference.new({a: "b"}, 1) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is a string" do let(:actual) { "Thing" } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is the same" do let (:actual) { {a: 'b'} } it "should return an empty hash" do expect(diff(subject, actual)).to eq({}) end end end context "when the expected value is an array" do subject { [1] } context "when the actual value is an array" do let(:actual) { [2] } let(:difference) { [Difference.new(1, 2)] } it "should return the diff" do expect(diff(subject, actual)).to eq difference end end context "when the actual value is an hash" do let(:actual) { {b: 'c'} } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an number" do let(:actual) { 1 } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is a string" do let(:actual) { "Thing" } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is the same" do let (:actual) { [1] } it "should return an empty hash" do expect(diff(subject, actual)).to eql({}) end end end context "when the expected value is a string" do subject { "Thing"} context "when the actual value is an array" do let(:actual) { [2] } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an hash" do let(:actual) { {b: 'c'} } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an number" do let(:actual) { 1 } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is a string" do let(:actual) { "Another Thing" } let(:difference) { Difference.new(subject, actual) } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is the same" do let (:actual) { "Thing" } it "should return an empty hash" do expect(diff(subject, actual)).to eq({}) end end end context "when the expected value is a number" do subject { 1 } let(:difference) { Difference.new(subject, actual) } context "when the actual value is an array" do let(:actual) { [2] } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an hash" do let(:actual) { {b: 'c'} } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is an number" do let(:actual) { 2 } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is a string" do let(:actual) { "Another Thing" } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "when the actual value is the same" do let (:actual) { 1 } it "should return an empty hash" do expect(diff(subject, actual)).to eq({}) end end end context "when the expected value is a String matcher" do end context "when the expected value is a Number matcher" do end context "when the expected value is an array with a matcher" do end context "when the expected value is a hash with a matcher" do end context "when an expected value is nil but not nil is found" do subject { {a: nil} } let(:actual) { {a: 'blah'} } let(:difference) { {:a=>Difference.new(nil, "blah")} } it "should return the diff" do expect(diff(subject, actual)).to eq(difference) end end context "a deep mismatch" do subject { {a: {b: { c: [1,2]}, d: { e: Pact::Term.new(matcher: /a/, generate: 'apple')}}, f: 1, g: {h: 99}} } let(:actual) { {a: {b: { c: [1,2]}, d: { e: 'food'}}, f: "thing"} } let(:difference) { {:a=>{:d=>{:e=> Difference.new(/a/, "food")}}, :f=> Difference.new(1, "thing"), :g=>Difference.new({:h=>99}, Pact::KeyNotFound.new)} } it 'should return the diff' do expect(diff(subject, actual)).to eq(difference) end end context "where a Pact::Term is found that matches the actual value" do subject { {:a => Pact::Term.new(:matcher => /a/, :generate => 'apple')} } let(:actual) { {:a => "apple" } } it 'does not include this in the diff' do expect(diff(subject, actual)).to eq({}) end end context "where an array is expected at a key inside a hash, but a hash is found" do subject { {:a => [1,2,3]} } let(:actual) { {:a => {:b => 1} } } it 'includes this in the diff' do expect(diff(subject, actual)).to eq({:a => Difference.new([1,2,3], {:b => 1})}) end end context "where an array is expected, but a hash is found" do subject { {:a => :b} } let(:actual) { [4,5,6] } it 'includes this in the diff' do expect(diff(subject, actual)).to eq(Difference.new({:a => :b}, [4,5,6] )) end end context "where a hash is expected, but array is found" do subject { [4,5,6] } let(:actual) { {:a => :b} } it 'includes this in the diff' do expect(diff(subject, actual)).to eq(Difference.new([4,5,6],{:a => :b})) end end context "when two different arrays are found" do subject { [4,5,6] } let(:actual) { [4,6,7] } let(:difference) { [Pact::Matchers::NO_DIFF_INDICATOR, Difference.new(5, 6), Difference.new(6, 7)] } it 'includes this in the diff' do expect(diff(subject, actual)).to eq(difference) end end context "when an array that matches the Pact::Term is found" do subject { [Pact::Term.new(:matcher => /4/, :generate => '4'),"5","6"] } let(:actual) { ["4","5","6"] } it 'includes this in the diff' do expect(diff(subject, actual)).to eq({}) end end end end end