require 'test_helper' require_relative '../lib/sandi_meter/analyzer' describe SandiMeter::Analyzer do let(:analyzer) { SandiMeter::Analyzer.new } describe '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 klass = analyzer.classes.find { |c| c.name == "TestClass" } klass.should have_attributes( first_line: 1, last_line: 5, path: test_file_path(3) ) end it 'finds methods' do method = analyzer.methods["TestClass"].find { |m| m.name == "blah" } method.should have_attributes( first_line: 2, last_line: 4, number_of_arguments: 0, path: test_file_path(3) ) end it 'finds method calls that brakes third rule' do method_call = analyzer.method_calls.first method_call.should have_attributes( first_line: 3, number_of_arguments: 5, path: test_file_path(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 klass = analyzer.classes.find { |c| c.name == "MyApp::TestClass" } klass.should have_attributes( first_line: 2, last_line: nil, path: test_file_path(1) ) end it 'finds methods' do method = analyzer.methods["MyApp::TestClass"].find { |m| m.name == "blah" } method.should have_attributes( first_line: 3, last_line: nil, number_of_arguments: 0, path: test_file_path(1) ) 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 klass = analyzer.classes.find { |c| c.name == "FirstTestClass" } klass.should have_attributes( first_line: 1, last_line: 4, path: test_file_path(4) ) klass = analyzer.classes.find { |c| c.name == "SecondTestClass" } klass.should have_attributes( first_line: 6, last_line: 9, path: test_file_path(4) ) end it 'finds methods' do method = analyzer.methods["FirstTestClass"].find { |m| m.name == "first_meth" } method.should have_attributes( first_line: 2, last_line: 3, number_of_arguments: 1, path: test_file_path(4) ) method = analyzer.methods["SecondTestClass"].find { |m| m.name == "second_meth" } method.should have_attributes( first_line: 7, last_line: 8, number_of_arguments: 1, path: test_file_path(4) ) 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 klass = analyzer.classes.find { |c| c.name == "OneLinerClass" } klass.should have_attributes( first_line: 1, last_line: nil, path: test_file_path(5) ) end it 'finds methods' do analyzer.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 klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User" } klass.should have_attributes( first_line: 5, last_line: 13, path: test_file_path(7) ) klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User::SubUser" } klass.should have_attributes( first_line: 9, last_line: 12, path: test_file_path(7) ) end it 'finds methods' do method = analyzer.methods["MyApp::Blah"].find { |m| m.name == "module_meth" } method.should have_attributes( first_line: 2, last_line: 3, number_of_arguments: 0, path: test_file_path(7) ) method = analyzer.methods["MyApp::Blah::User"].find { |m| m.name == "class_meth" } method.should have_attributes( first_line: 6, last_line: 7, number_of_arguments: 0, path: test_file_path(7) ) method = analyzer.methods["MyApp::Blah::User::SubUser"].find { |m| m.name == "sub_meth" } method.should have_attributes( first_line: 10, last_line: 11, number_of_arguments: 0, path: test_file_path(7) ) 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 klass = analyzer.classes.find { |c| c.name == "RailsController" } klass.should have_attributes( first_line: 1, last_line: 12, path: test_file_path(8) ) end it 'finds methods' do method = analyzer.methods["RailsController"].find { |m| m.name == "index" } method.should have_attributes( first_line: 2, last_line: 3, number_of_arguments: 0, path: test_file_path(8) ) method = analyzer.methods["RailsController"].find { |m| m.name == "destroy" } method.should have_attributes( first_line: 5, last_line: 6, number_of_arguments: 0, path: test_file_path(8) ) method = analyzer.methods["RailsController"].find { |m| m.name == "private_meth" } method.should be_nil 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 method = analyzer.methods["UsersController"].find { |m| m.name == "index" } method.ivars.should eq(["@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 method = analyzer.methods["GuestController"].find { |m| m.name == "create_guest_user" } method.ivars.should be_empty 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 method = analyzer.methods["User"].find { |m| m.name == "initialize" } method.ivars.should be_empty method = analyzer.methods["User"].find { |m| m.name == "hi" } method.ivars.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 method = analyzer.methods["UsersController"].find { |m| m.name == "create" } method.ivars.should eq(["@user"]) end it 'omits actions without instance variables' do method = analyzer.methods["UsersController"].find { |m| m.name == "show" } method.ivars.should be_empty end it 'omits private methods' do method = analyzer.methods["UsersController"].find { |m| m.name == "find_user" } method.should be_nil end it 'omits protected methods' do method = analyzer.methods["UsersController"].find { |m| m.name == "protected_find_user" } method.should be_nil 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 method_call = analyzer.method_calls.first method_call.should have_attributes( first_line: 3, number_of_arguments: 5, path: test_file_path(11) ) 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 klass = analyzer.classes.find { |c| c.name == "Valera" } klass.should have_attributes( first_line: 1, last_line: 109, path: test_file_path(12) ) end it 'are count for method definition' do method = analyzer.methods["Valera"].find { |m| m.name == "doodle" } method.should have_attributes( first_line: 2, last_line: 9, number_of_arguments: 0, path: test_file_path(12) ) 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 describe 'analazing complex methods' do let(:test_class) { test_file_path(14) } let(:methods) { analyzer.methods["TestClass"] } before do analyzer.analyze(test_class) end it 'mark 4line methods good' do method = analyzer.methods["TestClass"].find { |m| m.name == "render4" } method.should have_attributes( first_line: 2, last_line: 7, number_of_arguments: 0, path: test_file_path(14) ) end it 'mark 5line methods good' do method = analyzer.methods["TestClass"].find { |m| m.name == "render5" } method.should have_attributes( first_line: 9, last_line: 15, number_of_arguments: 0, path: test_file_path(14) ) end it 'mark 6line methods bad' do method = analyzer.methods["TestClass"].find { |m| m.name == "render6" } method.should have_attributes( first_line: 17, last_line: 24, number_of_arguments: 0, path: test_file_path(14) ) end end end