diff options
Diffstat (limited to 'spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb')
-rw-r--r-- | spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb new file mode 100644 index 00000000000..d72572cd510 --- /dev/null +++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb @@ -0,0 +1,272 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::Importer::PullRequestsImporter do + let(:project) { create(:project, import_source: 'foo/bar') } + let(:client) { double(:client) } + + let(:pull_request) do + double( + :response, + number: 42, + title: 'My Pull Request', + body: 'This is my pull request', + state: 'closed', + head: double( + :head, + sha: '123abc', + ref: 'my-feature', + repo: double(:repo, id: 400), + user: double(:user, id: 4, login: 'alice') + ), + base: double( + :base, + sha: '456def', + ref: 'master', + repo: double(:repo, id: 200) + ), + milestone: double(:milestone, number: 4), + user: double(:user, id: 4, login: 'alice'), + assignee: double(:user, id: 4, login: 'alice'), + created_at: Time.zone.now, + updated_at: Time.zone.now, + merged_at: Time.zone.now + ) + end + + describe '#parallel?' do + it 'returns true when running in parallel mode' do + importer = described_class.new(project, client) + expect(importer).to be_parallel + end + + it 'returns false when running in sequential mode' do + importer = described_class.new(project, client, parallel: false) + expect(importer).not_to be_parallel + end + end + + describe '#execute' do + context 'when running in parallel mode' do + it 'imports pull requests in parallel' do + importer = described_class.new(project, client) + + expect(importer).to receive(:parallel_import) + + importer.execute + end + end + + context 'when running in sequential mode' do + it 'imports pull requests in sequence' do + importer = described_class.new(project, client, parallel: false) + + expect(importer).to receive(:sequential_import) + + importer.execute + end + end + end + + describe '#sequential_import' do + it 'imports each pull request in sequence' do + importer = described_class.new(project, client, parallel: false) + pull_request_importer = double(:pull_request_importer) + + allow(importer) + .to receive(:each_object_to_import) + .and_yield(pull_request) + + expect(Gitlab::GithubImport::Importer::PullRequestImporter) + .to receive(:new) + .with( + an_instance_of(Gitlab::GithubImport::Representation::PullRequest), + project, + client + ) + .and_return(pull_request_importer) + + expect(pull_request_importer).to receive(:execute) + + importer.sequential_import + end + end + + describe '#parallel_import' do + it 'imports each note in parallel' do + importer = described_class.new(project, client) + + allow(importer) + .to receive(:each_object_to_import) + .and_yield(pull_request) + + expect(Gitlab::GithubImport::ImportPullRequestWorker) + .to receive(:perform_async) + .with(project.id, an_instance_of(Hash), an_instance_of(String)) + + waiter = importer.parallel_import + + expect(waiter).to be_an_instance_of(Gitlab::JobWaiter) + expect(waiter.jobs_remaining).to eq(1) + end + end + + describe '#each_object_to_import', :clean_gitlab_redis_cache do + let(:importer) { described_class.new(project, client) } + + before do + page = double(:page, objects: [pull_request], number: 1) + + expect(client) + .to receive(:each_page) + .with( + :pull_requests, + 'foo/bar', + { state: 'all', sort: 'created', direction: 'asc', page: 1 } + ) + .and_yield(page) + end + + it 'yields every pull request to the supplied block' do + expect { |b| importer.each_object_to_import(&b) } + .to yield_with_args(pull_request) + end + + it 'updates the repository if a pull request was updated after the last clone' do + expect(importer) + .to receive(:update_repository?) + .with(pull_request) + .and_return(true) + + expect(importer) + .to receive(:update_repository) + + importer.each_object_to_import { } + end + end + + describe '#update_repository' do + it 'updates the repository' do + importer = described_class.new(project, client) + + expect(project.repository) + .to receive(:fetch_remote) + .with('github', forced: false) + + expect(Rails.logger) + .to receive(:info) + .with(an_instance_of(String)) + + expect(importer.repository_updates_counter) + .to receive(:increment) + .with(project: project.path_with_namespace) + .and_call_original + + Timecop.freeze do + importer.update_repository + + expect(project.last_repository_updated_at).to eq(Time.zone.now) + end + end + end + + describe '#update_repository?' do + let(:importer) { described_class.new(project, client) } + + context 'when the pull request was updated after the last update' do + let(:pr) do + double( + :pr, + updated_at: Time.zone.now, + head: double(:head, sha: '123'), + base: double(:base, sha: '456') + ) + end + + before do + allow(project) + .to receive(:last_repository_updated_at) + .and_return(1.year.ago) + end + + it 'returns true when the head SHA is not present' do + expect(importer) + .to receive(:commit_exists?) + .with(pr.head.sha) + .and_return(false) + + expect(importer.update_repository?(pr)).to eq(true) + end + + it 'returns true when the base SHA is not present' do + expect(importer) + .to receive(:commit_exists?) + .with(pr.head.sha) + .and_return(true) + + expect(importer) + .to receive(:commit_exists?) + .with(pr.base.sha) + .and_return(false) + + expect(importer.update_repository?(pr)).to eq(true) + end + + it 'returns false if both the head and base SHAs are present' do + expect(importer) + .to receive(:commit_exists?) + .with(pr.head.sha) + .and_return(true) + + expect(importer) + .to receive(:commit_exists?) + .with(pr.base.sha) + .and_return(true) + + expect(importer.update_repository?(pr)).to eq(false) + end + end + + context 'when the pull request was updated before the last update' do + it 'returns false' do + pr = double(:pr, updated_at: 1.year.ago) + + allow(project) + .to receive(:last_repository_updated_at) + .and_return(Time.zone.now) + + expect(importer.update_repository?(pr)).to eq(false) + end + end + end + + describe '#commit_exists?' do + let(:importer) { described_class.new(project, client) } + + it 'returns true when a commit exists' do + expect(project.repository) + .to receive(:lookup) + .with('123') + .and_return(double(:commit)) + + expect(importer.commit_exists?('123')).to eq(true) + end + + it 'returns false when a commit does not exist' do + expect(project.repository) + .to receive(:lookup) + .with('123') + .and_raise(Rugged::OdbError) + + expect(importer.commit_exists?('123')).to eq(false) + end + end + + describe '#id_for_already_imported_cache' do + it 'returns the PR number of the given PR' do + importer = described_class.new(project, client) + + expect(importer.id_for_already_imported_cache(pull_request)) + .to eq(42) + end + end +end |