require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper') require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'duplication') require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'code_parser') require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'sniffer') require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared') include Reek include Reek::Smells describe Duplication do context 'when a smell is reported' do before :each do @source_name = 'copy-cat' @detector = Duplication.new(@source_name) src = < '@other.thing') end it 'reports repeated call to lvar' do src = 'def double_thing(other) other[@thing] + other[@thing] end' src.should smell_of(Duplication, Duplication::CALL_KEY => 'other[@thing]') end it 'reports call parameters' do src = 'def double_thing() @other.thing(2,3) + @other.thing(2,3) end' src.should smell_of(Duplication, Duplication::CALL_KEY => '@other.thing(2, 3)') end it 'should report nested calls' do src = 'def double_thing() @other.thing.foo + @other.thing.foo end' src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'}, {Duplication::CALL_KEY => '@other.thing.foo'}) end it 'should ignore calls to new' do src = 'def double_thing() @other.new + @other.new end' src.should_not smell_of(Duplication) end end context 'with repeated attribute assignment' do it 'reports repeated assignment' do src = 'def double_thing(thing) @other[thing] = true; @other[thing] = true; end' src.should smell_of(Duplication, Duplication::CALL_KEY => '@other[thing] = true') end it 'does not report multi-assignments' do src = < 3} end it 'does not report double calls' do src = 'def double_thing() @other.thing + @other.thing end' src.should_not smell_of(Duplication).with_config(@config) end it 'does not report triple calls' do src = 'def double_thing() @other.thing + @other.thing + @other.thing end' src.should_not smell_of(Duplication).with_config(@config) end it 'reports quadruple calls' do src = 'def double_thing() @other.thing + @other.thing + @other.thing + @other.thing end' src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing', Duplication::OCCURRENCES_KEY => 4}).with_config(@config) end end context "allowing calls to some methods" do before :each do @config = {Duplication::ALLOW_CALLS_KEY => ['@some.thing',/puts/]} end it 'does not report calls to some methods' do src = 'def double_some_thing() @some.thing + @some.thing end' src.should_not smell_of(Duplication).with_config(@config) end it 'reports calls to other methods' do src = 'def double_other_thing() @other.thing + @other.thing end' src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'}).with_config(@config) end it 'does not report calls to methods specifed with a regular expression' do src = 'def double_puts() puts @other.thing; puts @other.thing end' src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'}).with_config(@config) end end end