diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-28 15:08:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-28 15:08:19 +0300 |
commit | 3fa33c82f9c49f4b53ddcf017fe77f1bff48a460 (patch) | |
tree | 6b0fb548b09370de722e06f47548c80380ff452d /spec/scripts | |
parent | dba63244c19187d32f1f998403555f1893f5abdb (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/scripts')
-rw-r--r-- | spec/scripts/pipeline/create_test_failure_issues_spec.rb | 163 |
1 files changed, 103 insertions, 60 deletions
diff --git a/spec/scripts/pipeline/create_test_failure_issues_spec.rb b/spec/scripts/pipeline/create_test_failure_issues_spec.rb index fa27727542e..2a5910f5238 100644 --- a/spec/scripts/pipeline/create_test_failure_issues_spec.rb +++ b/spec/scripts/pipeline/create_test_failure_issues_spec.rb @@ -3,22 +3,28 @@ # rubocop:disable RSpec/VerifiedDoubles require 'fast_spec_helper' +require 'active_support/testing/time_helpers' require 'rspec-parameterized' require_relative '../../../scripts/pipeline/create_test_failure_issues' RSpec.describe CreateTestFailureIssues, feature_category: :tooling do describe CreateTestFailureIssue do + include ActiveSupport::Testing::TimeHelpers + + let(:server_host) { 'example.com' } + let(:project_path) { 'group/project' } + let(:env) do { - 'CI_JOB_URL' => 'ci_job_url', - 'CI_PIPELINE_URL' => 'ci_pipeline_url' + 'CI_SERVER_HOST' => server_host, + 'CI_PROJECT_PATH' => project_path, + 'CI_PIPELINE_URL' => "https://#{server_host}/#{project_path}/-/pipelines/1234" } end - let(:project) { 'group/project' } let(:api_token) { 'api_token' } - let(:creator) { described_class.new(project: project, api_token: api_token) } + let(:creator) { described_class.new(project: project_path, api_token: api_token) } let(:test_name) { 'The test description' } let(:test_file) { 'spec/path/to/file_spec.rb' } let(:test_file_content) do @@ -36,7 +42,7 @@ RSpec.describe CreateTestFailureIssues, feature_category: :tooling do { 'name' => test_name, 'file' => test_file, - 'job_url' => 'job_url' + 'job_url' => "https://#{server_host}/#{project_path}/-/jobs/5678" } end @@ -57,87 +63,124 @@ RSpec.describe CreateTestFailureIssues, feature_category: :tooling do } end + let(:test_hash) { Digest::SHA256.hexdigest(failed_test['file'] + failed_test['name'])[0...12] } + let(:latest_format_issue_title) { "#{failed_test['file']} [test-hash:#{test_hash}]" } + let(:latest_format_issue_description) do + <<~DESCRIPTION + ### Test description + + `#{failed_test['name']}` + + ### Test file path + + [`#{failed_test['file']}`](https://#{server_host}/#{project_path}/-/blob/master/#{failed_test['file']}) + + <!-- Don't add anything after the report list since it's updated automatically --> + ### Reports (1) + + #{failed_test_report_line} + DESCRIPTION + end + + around do |example| + freeze_time { example.run } + end + before do stub_env(env) + allow(creator).to receive(:puts) end - describe '#find' do - let(:expected_payload) do + describe '#upsert' do + let(:expected_search_payload) do { - state: 'opened', - search: "#{failed_test['file']} - ID: #{Digest::SHA256.hexdigest(failed_test['name'])[0...12]}" + state: :opened, + search: test_hash, + in: :title, + per_page: 1 } end let(:find_issue_stub) { double('FindIssues') } - let(:issue_stub) { double(title: expected_payload[:title], web_url: 'issue_web_url') } + let(:issue_stub) { double('Issue', title: latest_format_issue_title, web_url: 'issue_web_url') } - before do - allow(creator).to receive(:puts) + let(:failed_test_report_line) do + "1. #{Time.new.utc.strftime('%F')}: #{failed_test['job_url']} (#{env['CI_PIPELINE_URL']})" end - it 'calls FindIssues#execute(payload)' do - expect(FindIssues).to receive(:new).with(project: project, api_token: api_token).and_return(find_issue_stub) - expect(find_issue_stub).to receive(:execute).with(expected_payload).and_return([issue_stub]) + before do + allow(File).to receive(:open).and_call_original + allow(File).to receive(:open).with(File.expand_path(File.join('..', '..', '..', test_file), __dir__)) + .and_return(test_file_stub) + + allow(FindIssues).to receive(:new).with(project: project_path, api_token: api_token).and_return(find_issue_stub) - creator.find(failed_test) + allow(creator).to receive(:categories_mapping).and_return(categories_mapping) + allow(creator).to receive(:groups_mapping).and_return(groups_mapping) end context 'when no issues are found' do - it 'calls FindIssues#execute(payload)' do - expect(FindIssues).to receive(:new).with(project: project, api_token: api_token).and_return(find_issue_stub) - expect(find_issue_stub).to receive(:execute).with(expected_payload).and_return([]) - - creator.find(failed_test) + let(:create_issue_stub) { double('CreateIssue') } + let(:expected_create_payload) do + { + title: latest_format_issue_title, + description: latest_format_issue_description, + labels: described_class::DEFAULT_LABELS.map { |label| "wip-#{label}" } + [ + "wip-#{categories_mapping['source_code_management']['label']}", + "wip-#{groups_mapping['source_code']['label']}" + ], + weight: 1 + } end - end - end - - describe '#create' do - let(:expected_description) do - <<~DESCRIPTION - ### Full description - - `#{failed_test['name']}` - ### File path - - `#{failed_test['file']}` + before do + allow(find_issue_stub).to receive(:execute).with(expected_search_payload).and_return([]) + end - <!-- Don't add anything after the report list since it's updated automatically --> - ### Reports + it 'calls CreateIssue#execute(payload)' do + expect(CreateIssue).to receive(:new).with(project: project_path, api_token: api_token) + .and_return(create_issue_stub) + expect(create_issue_stub).to receive(:execute).with(expected_create_payload).and_return(issue_stub) - - #{failed_test['job_url']} (#{env['CI_PIPELINE_URL']}) - DESCRIPTION + creator.upsert(failed_test) + end end - let(:expected_payload) do - { - title: "#{failed_test['file']} - ID: #{Digest::SHA256.hexdigest(failed_test['name'])[0...12]}", - description: expected_description, - labels: described_class::DEFAULT_LABELS.map { |label| "wip-#{label}" } + [ - "wip-#{categories_mapping['source_code_management']['label']}", "wip-#{groups_mapping['source_code']['label']}" # rubocop:disable Layout/LineLength - ] - } - end + context 'when issues are found' do + let(:issue_stub) do + double('Issue', iid: 42, title: issue_title, description: issue_description, web_url: 'issue_web_url') + end - let(:create_issue_stub) { double('CreateIssue') } - let(:issue_stub) { double(title: expected_payload[:title], web_url: 'issue_web_url') } + before do + allow(find_issue_stub).to receive(:execute).with(expected_search_payload).and_return([issue_stub]) + end - before do - allow(creator).to receive(:puts) - allow(File).to receive(:open).and_call_original - allow(File).to receive(:open).with(File.expand_path(File.join('..', '..', '..', test_file), __dir__)) - .and_return(test_file_stub) - allow(creator).to receive(:categories_mapping).and_return(categories_mapping) - allow(creator).to receive(:groups_mapping).and_return(groups_mapping) - end + # This shared example can be useful if we want to test migration to a new format in the future + shared_examples 'existing issue update' do + let(:update_issue_stub) { double('UpdateIssue') } + let(:expected_update_payload) do + { + description: latest_format_issue_description.sub(/^### Reports.*$/, '### Reports (2)') + + "\n#{failed_test_report_line}", + weight: 2 + } + end + + it 'calls UpdateIssue#execute(payload)' do + expect(UpdateIssue).to receive(:new).with(project: project_path, api_token: api_token) + .and_return(update_issue_stub) + expect(update_issue_stub).to receive(:execute).with(42, **expected_update_payload) + + creator.upsert(failed_test) + end + end - it 'calls CreateIssue#execute(payload)' do - expect(CreateIssue).to receive(:new).with(project: project, api_token: api_token).and_return(create_issue_stub) - expect(create_issue_stub).to receive(:execute).with(expected_payload).and_return(issue_stub) + context 'when issue already has the latest format' do + let(:issue_description) { latest_format_issue_description } + let(:issue_title) { latest_format_issue_title } - creator.create(failed_test) # rubocop:disable Rails/SaveBang + it_behaves_like 'existing issue update' + end end end end |