require 'spec_helper' require 'method_log/api' require 'method_log/source_file' require 'method_log/repository' require 'method_log/commit' require 'method_log/method_definition' require 'method_log/method_commit' module MethodLog describe API do let(:repository_path) { File.expand_path('../repository.git', __FILE__) } before do FileUtils.mkdir_p(repository_path) Rugged::Repository.init_at(repository_path, :bare) end after do FileUtils.rm_rf(repository_path) end it 'finds class instance method in repository with two commits with single source file' do repository = Repository.new(repository_path) commit_1 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar # implementation 1 end end })) commit_2 = repository.commit(source(path: 'foo.rb', source: %{ # move method definition down one line class Foo def bar # implementation 2 end end })) method_commits, method_diffs = commits_and_diffs_for('Foo#bar') expect(method_commits.first.sha).to eq(commit_2.sha) expect(method_diffs.first.to_s.chomp).to eq(unindent(%{ def bar - # implementation 1 + # implementation 2 end })) end it 'finds significant commits for definition of method' do repository = Repository.new(repository_path) commit_1 = repository.commit(source(path: 'foo.rb', source: %{ class Foo end })) commit_2 = repository.commit(source(path: 'foo.rb', source: %{ class Foo end })) commit_3 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) commit_4 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) commit_5 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar # implementation end end })) method_commits, method_diffs = commits_and_diffs_for('Foo#bar') expect(method_commits.map(&:sha)).to eq([commit_5.sha, commit_3.sha]) end it 'continues past lastest introduction of method if required' do repository = Repository.new(repository_path) commit_1 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) commit_2 = repository.commit(source(path: 'foo.rb', source: %{ class Foo end })) commit_3 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) method_commits, method_diffs = commits_and_diffs_for('Foo#bar', stop_at_latest_introduction_of_method: false) expect(method_commits.map(&:sha)).to eq([commit_3.sha, commit_2.sha]) end it 'continues past lastest introduction of method if required even if method not defined in latest commit' do repository = Repository.new(repository_path) commit_1 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) commit_2 = repository.commit(source(path: 'foo.rb', source: %{ class Foo end })) commit_3 = repository.commit(source(path: 'foo.rb', source: %{ class Foo def bar; end end })) commit_4 = repository.commit(source(path: 'foo.rb', source: %{ class Foo end })) method_commits, method_diffs = commits_and_diffs_for('Foo#bar', stop_at_latest_introduction_of_method: false) expect(method_commits.map(&:sha)).to eq([commit_4.sha, commit_3.sha, commit_2.sha]) end private def commits_and_diffs_for(method_identifier, options = {}) api = API.new(Repository.new(repository_path)) commits_and_diffs = api.diffs(method_identifier, options) method_commits = commits_and_diffs.map(&:first) method_diffs = commits_and_diffs.map(&:last) [method_commits, method_diffs] end end end