summaryrefslogtreecommitdiff
path: root/spec/lib/atlassian/jira_connect/client_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/atlassian/jira_connect/client_spec.rb')
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb165
1 files changed, 142 insertions, 23 deletions
diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb
index cefd1fa3274..6a161854dfb 100644
--- a/spec/lib/atlassian/jira_connect/client_spec.rb
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -7,8 +7,10 @@ RSpec.describe Atlassian::JiraConnect::Client do
subject { described_class.new('https://gitlab-test.atlassian.net', 'sample_secret') }
+ let_it_be(:project) { create_default(:project, :repository) }
+
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
describe '.generate_update_sequence_id' do
@@ -19,41 +21,158 @@ RSpec.describe Atlassian::JiraConnect::Client do
end
end
- describe '#store_dev_info' do
- let_it_be(:project) { create_default(:project, :repository) }
- let_it_be(:merge_requests) { create_list(:merge_request, 2, :unique_branches) }
+ describe '#send_info' do
+ it 'calls store_build_info and store_dev_info as appropriate' do
+ expect(subject).to receive(:store_build_info).with(
+ project: project,
+ update_sequence_id: :x,
+ pipelines: :y
+ ).and_return(:build_stored)
+
+ expect(subject).to receive(:store_dev_info).with(
+ project: project,
+ update_sequence_id: :x,
+ commits: :a,
+ branches: :b,
+ merge_requests: :c
+ ).and_return(:dev_stored)
+
+ args = {
+ project: project,
+ update_sequence_id: :x,
+ commits: :a,
+ branches: :b,
+ merge_requests: :c,
+ pipelines: :y
+ }
+
+ expect(subject.send_info(**args)).to contain_exactly(:dev_stored, :build_stored)
+ end
- let(:expected_jwt) do
- Atlassian::Jwt.encode(
- Atlassian::Jwt.build_claims(
- Atlassian::JiraConnect.app_key,
- '/rest/devinfo/0.10/bulk',
- 'POST'
- ),
- 'sample_secret'
- )
+ it 'only calls methods that we need to call' do
+ expect(subject).to receive(:store_dev_info).with(
+ project: project,
+ update_sequence_id: :x,
+ commits: :a
+ ).and_return(:dev_stored)
+
+ args = {
+ project: project,
+ update_sequence_id: :x,
+ commits: :a
+ }
+
+ expect(subject.send_info(**args)).to contain_exactly(:dev_stored)
+ end
+
+ it 'raises an argument error if there is nothing to send (probably a typo?)' do
+ expect { subject.send_info(project: project, builds: :x) }
+ .to raise_error(ArgumentError)
+ end
+ end
+
+ def expected_headers(path)
+ expected_jwt = Atlassian::Jwt.encode(
+ Atlassian::Jwt.build_claims(Atlassian::JiraConnect.app_key, path, 'POST'),
+ 'sample_secret'
+ )
+
+ {
+ 'Authorization' => "JWT #{expected_jwt}",
+ 'Content-Type' => 'application/json'
+ }
+ end
+
+ describe '#store_build_info' do
+ let_it_be(:mrs_by_title) { create_list(:merge_request, 4, :unique_branches, :jira_title) }
+ let_it_be(:mrs_by_branch) { create_list(:merge_request, 2, :jira_branch) }
+ let_it_be(:red_herrings) { create_list(:merge_request, 1, :unique_branches) }
+
+ let_it_be(:pipelines) do
+ (red_herrings + mrs_by_branch + mrs_by_title).map do |mr|
+ create(:ci_pipeline, merge_request: mr)
+ end
+ end
+
+ let(:build_info_payload_schema) do
+ Atlassian::Schemata.build_info_payload
+ end
+
+ let(:body) do
+ matcher = be_valid_json.according_to_schema(build_info_payload_schema)
+
+ ->(text) { matcher.matches?(text) }
end
before do
- stub_full_request('https://gitlab-test.atlassian.net/rest/devinfo/0.10/bulk', method: :post)
- .with(
- headers: {
- 'Authorization' => "JWT #{expected_jwt}",
- 'Content-Type' => 'application/json'
- }
- )
+ path = '/rest/builds/0.1/bulk'
+ stub_full_request('https://gitlab-test.atlassian.net' + path, method: :post)
+ .with(body: body, headers: expected_headers(path))
+ end
+
+ it "calls the API with auth headers" do
+ subject.send(:store_build_info, project: project, pipelines: pipelines)
+ end
+
+ it 'only sends information about relevant MRs' do
+ expect(subject).to receive(:post).with('/rest/builds/0.1/bulk', { builds: have_attributes(size: 6) })
+
+ subject.send(:store_build_info, project: project, pipelines: pipelines)
+ end
+
+ it 'does not call the API if there is nothing to report' do
+ expect(subject).not_to receive(:post)
+
+ subject.send(:store_build_info, project: project, pipelines: pipelines.take(1))
+ end
+
+ it 'does not call the API if the feature flag is not enabled' do
+ stub_feature_flags(jira_sync_builds: false)
+
+ expect(subject).not_to receive(:post)
+
+ subject.send(:store_build_info, project: project, pipelines: pipelines)
+ end
+
+ it 'does call the API if the feature flag enabled for the project' do
+ stub_feature_flags(jira_sync_builds: project)
+
+ expect(subject).to receive(:post).with('/rest/builds/0.1/bulk', { builds: Array })
+
+ subject.send(:store_build_info, project: project, pipelines: pipelines)
+ end
+
+ it 'avoids N+1 database queries' do
+ baseline = ActiveRecord::QueryRecorder.new do
+ subject.send(:store_build_info, project: project, pipelines: pipelines)
+ end
+
+ pipelines << create(:ci_pipeline, head_pipeline_of: create(:merge_request, :jira_branch))
+
+ expect { subject.send(:store_build_info, project: project, pipelines: pipelines) }.not_to exceed_query_limit(baseline)
+ end
+ end
+
+ describe '#store_dev_info' do
+ let_it_be(:merge_requests) { create_list(:merge_request, 2, :unique_branches) }
+
+ before do
+ path = '/rest/devinfo/0.10/bulk'
+
+ stub_full_request('https://gitlab-test.atlassian.net' + path, method: :post)
+ .with(headers: expected_headers(path))
end
it "calls the API with auth headers" do
- subject.store_dev_info(project: project)
+ subject.send(:store_dev_info, project: project)
end
it 'avoids N+1 database queries' do
- control_count = ActiveRecord::QueryRecorder.new { subject.store_dev_info(project: project, merge_requests: merge_requests) }.count
+ control_count = ActiveRecord::QueryRecorder.new { subject.send(:store_dev_info, project: project, merge_requests: merge_requests) }.count
merge_requests << create(:merge_request, :unique_branches)
- expect { subject.store_dev_info(project: project, merge_requests: merge_requests) }.not_to exceed_query_limit(control_count)
+ expect { subject.send(:store_dev_info, project: project, merge_requests: merge_requests) }.not_to exceed_query_limit(control_count)
end
end
end