require 'test_helper' require_relative '../lib/sandi_meter/analyzer' describe SandiMeter::Analyzer do let(:analyzer) { SandiMeter::Analyzer.new } describe 'finds properly indented classes with lines' do let(:test_class) { test_file_path(3) } before do analyzer.analyze(test_class) end it 'finds indentation warnings for method' do analyzer.classes.should eq([["TestClass", 1, 5, true, "#{test_file_path(3)}:1"]]) analyzer.misindented_classes.should be_empty end it 'finds methods' do analyzer.methods.should eq({"TestClass"=>[["blah", 2, 4, 0, true, "#{test_file_path(3)}:2"]]}) analyzer.misindented_methods.should be_empty end it 'finds method calls that brakes third rule' do analyzer.method_calls.should eq([[5, "#{test_file_path(3)}:3"]]) end end describe 'finds misindented classes without last line' do let(:test_class) { test_file_path(1) } before do analyzer.analyze(test_class) end it 'finds indentation warnings for method' do analyzer.classes.should be_empty analyzer.misindented_classes.should eq([["MyApp::TestClass", 2, nil, "#{test_file_path(1)}:2"]]) end it 'finds methods' do analyzer.methods.should be_empty analyzer.misindented_methods.should eq({"MyApp::TestClass"=>[["blah", 3, nil, 0, "#{test_file_path(1)}:3"]]}) end end describe 'finds properly indented classes in one file' do let(:test_class) { test_file_path(4) } before do analyzer.analyze(test_class) end it 'finds classes' do analyzer.classes.should include(["FirstTestClass", 1, 4, true, "#{test_file_path(4)}:1"]) analyzer.classes.should include(["SecondTestClass", 6, 9, true, "#{test_file_path(4)}:6"]) analyzer.misindented_classes.should be_empty end it 'finds methods' do analyzer.methods["FirstTestClass"].should eq([["first_meth", 2, 3, 1, true, "#{test_file_path(4)}:2"]]) analyzer.methods["SecondTestClass"].should eq([["second_meth", 7, 8, 1, true, "#{test_file_path(4)}:7"]]) analyzer.misindented_methods.should be_empty end end describe 'finds one liner class' do let(:test_class) { test_file_path(5) } before do analyzer.analyze(test_class) end it 'finds classes' do analyzer.misindented_classes.should eq([["OneLinerClass", 1, nil, "#{test_file_path(5)}:1"]]) analyzer.classes.should be_empty end it 'finds methods' do analyzer.methods.should be_empty analyzer.misindented_methods.should be_empty end end describe 'finds subclass of a class' do let(:test_class) { test_file_path(7) } before do analyzer.analyze(test_class) end it 'finds class and subclass' do analyzer.classes.should include(["MyApp::Blah::User", 5, 13, true, "#{test_file_path(7)}:5"]) analyzer.classes.should include(["MyApp::Blah::User::SubUser", 9, 12, true, "#{test_file_path(7)}:9"]) analyzer.misindented_classes.should be_empty end it 'finds methods' do analyzer.methods["MyApp::Blah"].should eq([["module_meth", 2, 3, 0, true, "#{test_file_path(7)}:2"]]) analyzer.methods["MyApp::Blah::User"].should eq([["class_meth", 6, 7, 0, true, "#{test_file_path(7)}:6"]]) analyzer.methods["MyApp::Blah::User::SubUser"].should eq([["sub_meth", 10, 11, 0, true, "#{test_file_path(7)}:10"]]) analyzer.misindented_methods.should be_empty end end describe 'finds class and methods with private methods' do let(:test_class) { test_file_path(8) } before do analyzer.analyze(test_class) end it 'finds class and subclass' do analyzer.classes.should include(["RailsController", 1, 12, true, "#{test_file_path(8)}:1"]) analyzer.misindented_classes.should be_empty end it 'finds methods' do analyzer.methods["RailsController"].should include(["index", 2, 3, 0, true, "#{test_file_path(8)}:2"]) analyzer.methods["RailsController"].should include(["destroy", 5, 6, 0, true, "#{test_file_path(8)}:5"]) analyzer.methods["RailsController"].should include(["private_meth", 9, 10, 0, true, "#{test_file_path(8)}:9"]) analyzer.misindented_methods.should be_empty end end describe 'instance variables in methods' do context 'in controller class' do let(:test_class) { test_file_path('9_controller') } before do analyzer.analyze(test_class) end it 'finds instance variable' do analyzer.instance_variables.should eq({"UsersController"=>{"index"=>["@users"]}}) end end context 'in controller class with non instance variables' do let(:test_class) { test_file_path('14_controller') } before do analyzer.analyze(test_class) end it 'does not find instance variables' do analyzer.instance_variables.should eq({"GuestController"=>{"create_guest_user"=>[]}}) end end context 'not in controller class' do let(:test_class) { test_file_path(10) } before do analyzer.analyze(test_class) end it 'does not find instance variable' do analyzer.instance_variables.should be_empty end end context 'in controller class with private method' do let(:test_class) { test_file_path("15_controller") } before do analyzer.analyze(test_class) end it 'finds method defined after public keyword' do analyzer.instance_variables["UsersController"].should have_key("create") end it 'omits actions without instance variables' do analyzer.instance_variables["UsersController"].should_not have_key("show") end it 'omits private methods' do analyzer.instance_variables["UsersController"].should_not have_key("find_user") end it 'omits protected methods' do analyzer.instance_variables["UsersController"].should_not have_key("protected_find_user") end end end describe 'hash method arguments' do let(:test_class) { test_file_path(11) } before do analyzer.analyze(test_class) end it 'counts arguments' do analyzer.method_calls.should eq([[5, "#{test_file_path(11)}:3"]]) end end describe 'empty lines inside class' do let(:test_class) { test_file_path(12) } before do analyzer.analyze(test_class) end it 'are count for class definition' do analyzer.classes.should eq([["Valera", 1, 109, false, "#{test_file_path(12)}:1"]]) end it 'are count for method definition' do analyzer.methods.should eq({"Valera"=>[["doodle", 2, 9, 0, false, "#{test_file_path(12)}:2"]]}) end end describe 'inline code in class definition' do let(:test_class) { test_file_path(13) } before do analyzer.analyze(test_class) end it 'is not scanned' do analyzer.method_calls.should be_empty end end end