diff options
Diffstat (limited to 'spec')
29 files changed, 1067 insertions, 71 deletions
diff --git a/spec/factories/container_expiration_policies.rb b/spec/factories/container_expiration_policies.rb index 951127a4aa7..41c3a7f8cb9 100644 --- a/spec/factories/container_expiration_policies.rb +++ b/spec/factories/container_expiration_policies.rb @@ -2,7 +2,18 @@ FactoryBot.define do factory :container_expiration_policy, class: 'ContainerExpirationPolicy' do - association :project, factory: [:project, :without_container_expiration_policy] + # Note: because of the project_id primary_key on + # container_expiration_policies, and the create_container_expiration_policy + # callback on Project, we need to build the project first before assigning + # it to a container_expiration_policy. + # + # Also, if you wish to assign an existing project to a + # container_expiration_policy, you will then have to destroy the project's + # container_expiration_policy first. + before(:create) do |container_expiration_policy| + container_expiration_policy.project = build(:project) unless container_expiration_policy.project + end + cadence { '1d' } enabled { true } diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 9be0b308680..ba38e1bb312 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -140,12 +140,6 @@ FactoryBot.define do end end - trait :without_container_expiration_policy do - after(:build) do |project| - project.class.skip_callback(:create, :after, :create_container_expiration_policy, raise: false) - end - end - # Build a custom repository by specifying a hash of `filename => content` in # the transient `files` attribute. Each file will be created in its own # commit, operating against the master branch. So, the following call: diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index d12843d7150..94f57cdda74 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -699,6 +699,137 @@ describe 'Merge request > User sees merge widget', :js do end end + context 'when a new error exists' do + let(:base_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + reports.get_suite('junit').add_test_case(create_test_case_java_success) + end + end + + let(:head_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + reports.get_suite('junit').add_test_case(create_test_case_java_error) + end + end + + it 'shows test reports summary which includes the new error' do + within(".js-reports-container") do + click_button 'Expand' + + expect(page).to have_content('Test summary contained 1 failed/error test result out of 2 total tests') + within(".js-report-section-container") do + expect(page).to have_content('rspec found no changed test results out of 1 total test') + expect(page).to have_content('junit found 1 failed/error test result out of 1 total test') + expect(page).to have_content('New') + expect(page).to have_content('addTest') + end + end + end + + context 'when user clicks the new error' do + it 'shows the test report detail' do + within(".js-reports-container") do + click_button 'Expand' + + within(".js-report-section-container") do + click_button 'addTest' + + expect(page).to have_content('8.88') + end + end + end + end + end + + context 'when an existing error exists' do + let(:base_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_error) + reports.get_suite('junit').add_test_case(create_test_case_java_success) + end + end + + let(:head_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_error) + reports.get_suite('junit').add_test_case(create_test_case_java_success) + end + end + + it 'shows test reports summary which includes the existing error' do + within(".js-reports-container") do + click_button 'Expand' + + expect(page).to have_content('Test summary contained 1 failed/error test result out of 2 total tests') + within(".js-report-section-container") do + expect(page).to have_content('rspec found 1 failed/error test result out of 1 total test') + expect(page).to have_content('junit found no changed test results out of 1 total test') + expect(page).not_to have_content('New') + expect(page).to have_content('Test#sum when a is 4 and b is 4 returns summary') + end + end + end + + context 'when user clicks the existing error' do + it 'shows test report detail of it' do + within(".js-reports-container") do + click_button 'Expand' + + within(".js-report-section-container") do + click_button 'Test#sum when a is 4 and b is 4 returns summary' + + expect(page).to have_content('4.44') + end + end + end + end + end + + context 'when a resolved error exists' do + let(:base_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + reports.get_suite('junit').add_test_case(create_test_case_java_error) + end + end + + let(:head_reports) do + Gitlab::Ci::Reports::TestReports.new.tap do |reports| + reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + reports.get_suite('junit').add_test_case(create_test_case_java_success) + end + end + + it 'shows test reports summary which includes the resolved error' do + within(".js-reports-container") do + click_button 'Expand' + + expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests') + within(".js-report-section-container") do + expect(page).to have_content('rspec found no changed test results out of 1 total test') + expect(page).to have_content('junit found 1 fixed test result out of 1 total test') + expect(page).to have_content('addTest') + end + end + end + + context 'when user clicks the resolved error' do + it 'shows test report detail of it' do + within(".js-reports-container") do + click_button 'Expand' + + within(".js-report-section-container") do + click_button 'addTest' + + expect(page).to have_content('5.55') + end + end + end + end + end + context 'properly truncates the report' do let(:base_reports) do Gitlab::Ci::Reports::TestReports.new.tap do |reports| diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb index 4c5bc290402..fc1a85c3efe 100644 --- a/spec/features/projects/settings/registry_settings_spec.rb +++ b/spec/features/projects/settings/registry_settings_spec.rb @@ -10,7 +10,6 @@ describe 'Project > Settings > CI/CD > Container registry tag expiration policy' before do sign_in(user) stub_container_registry_config(enabled: true) - stub_feature_flags(registry_retention_policies_settings: true) end context 'as owner' do @@ -63,15 +62,4 @@ describe 'Project > Settings > CI/CD > Container registry tag expiration policy' expect(page).not_to have_selector('#js-registry-policies') end end - - context 'when feature flag is disabled' do - before do - stub_feature_flags(registry_retention_policies_settings: false) - visit project_settings_ci_cd_path(project) - end - - it 'does not exists' do - expect(page).not_to have_selector('#js-registry-policies') - end - end end diff --git a/spec/fixtures/api/schemas/entities/test_reports_comparer.json b/spec/fixtures/api/schemas/entities/test_reports_comparer.json index d7880801c01..03812527f71 100644 --- a/spec/fixtures/api/schemas/entities/test_reports_comparer.json +++ b/spec/fixtures/api/schemas/entities/test_reports_comparer.json @@ -12,11 +12,13 @@ "properties": { "total": { "type": "integer" }, "resolved": { "type": "integer" }, + "errored": { "type": "integer" }, "failed": { "type": "integer" } }, "required": [ "total", "resolved", + "errored", "failed" ] }, diff --git a/spec/fixtures/api/schemas/entities/test_suite_comparer.json b/spec/fixtures/api/schemas/entities/test_suite_comparer.json index d63fea1f0db..ecb331ae013 100644 --- a/spec/fixtures/api/schemas/entities/test_suite_comparer.json +++ b/spec/fixtures/api/schemas/entities/test_suite_comparer.json @@ -16,17 +16,17 @@ "properties": { "total": { "type": "integer" }, "resolved": { "type": "integer" }, + "errored": { "type": "integer" }, "failed": { "type": "integer" } }, - "required": [ - "total", - "resolved", - "failed" - ] + "required": ["total", "resolved", "errored", "failed"] }, "new_failures": { "type": "array", "items": { "$ref": "test_case.json" } }, "resolved_failures": { "type": "array", "items": { "$ref": "test_case.json" } }, - "existing_failures": { "type": "array", "items": { "$ref": "test_case.json" } } + "existing_failures": { "type": "array", "items": { "$ref": "test_case.json" } }, + "new_errors": { "type": "array", "items": { "$ref": "test_case.json" } }, + "resolved_errors": { "type": "array", "items": { "$ref": "test_case.json" } }, + "existing_errors": { "type": "array", "items": { "$ref": "test_case.json" } } }, "additionalProperties": false } diff --git a/spec/frontend/issuables_list/components/issuable_spec.js b/spec/frontend/issuables_list/components/issuable_spec.js index 81f6b60ae25..980def06078 100644 --- a/spec/frontend/issuables_list/components/issuable_spec.js +++ b/spec/frontend/issuables_list/components/issuable_spec.js @@ -122,6 +122,10 @@ describe('Issuable component', () => { expect(finder().exists()).toBe(false); }); + it('show relative reference path', () => { + expect(wrapper.find('.js-ref-path').text()).toBe(issuable.references.relative); + }); + it('does not have closed text', () => { expect(wrapper.text()).not.toContain(TEXT_CLOSED); }); diff --git a/spec/frontend/issuables_list/issuable_list_test_data.js b/spec/frontend/issuables_list/issuable_list_test_data.js index 617780fd736..19d8ee7f71a 100644 --- a/spec/frontend/issuables_list/issuable_list_test_data.js +++ b/spec/frontend/issuables_list/issuable_list_test_data.js @@ -26,6 +26,9 @@ export const simpleIssue = { web_url: 'http://localhost:3001/h5bp/html5-boilerplate/issues/31', has_tasks: false, weight: null, + references: { + relative: 'html-boilerplate#45', + }, }; export const testLabels = [ diff --git a/spec/frontend/reports/store/utils_spec.js b/spec/frontend/reports/store/utils_spec.js index f0141b9e162..0d9a8dd4585 100644 --- a/spec/frontend/reports/store/utils_spec.js +++ b/spec/frontend/reports/store/utils_spec.js @@ -35,6 +35,16 @@ describe('Reports store utils', () => { ); }); + it('should render text for multiple errored results', () => { + const name = 'Test summary'; + const data = { errored: 7, total: 10 }; + const result = utils.summaryTextBuilder(name, data); + + expect(result).toBe( + 'Test summary contained 7 failed/error test results out of 10 total tests', + ); + }); + it('should render text for multiple fixed results', () => { const name = 'Test summary'; const data = { resolved: 4, total: 10 }; @@ -62,6 +72,27 @@ describe('Reports store utils', () => { 'Test summary contained 1 failed/error test result and 1 fixed test result out of 10 total tests', ); }); + + it('should render text for singular failed, errored, and fixed results', () => { + // these will be singular when the copy is updated + const name = 'Test summary'; + const data = { failed: 1, errored: 1, resolved: 1, total: 10 }; + const result = utils.summaryTextBuilder(name, data); + + expect(result).toBe( + 'Test summary contained 2 failed/error test results and 1 fixed test result out of 10 total tests', + ); + }); + + it('should render text for multiple failed, errored, and fixed results', () => { + const name = 'Test summary'; + const data = { failed: 2, errored: 3, resolved: 4, total: 10 }; + const result = utils.summaryTextBuilder(name, data); + + expect(result).toBe( + 'Test summary contained 5 failed/error test results and 4 fixed test results out of 10 total tests', + ); + }); }); describe('reportTextBuilder', () => { @@ -89,6 +120,14 @@ describe('Reports store utils', () => { expect(result).toBe('Rspec found 3 failed/error test results out of 10 total tests'); }); + it('should render text for multiple errored results', () => { + const name = 'Rspec'; + const data = { errored: 7, total: 10 }; + const result = utils.reportTextBuilder(name, data); + + expect(result).toBe('Rspec found 7 failed/error test results out of 10 total tests'); + }); + it('should render text for multiple fixed results', () => { const name = 'Rspec'; const data = { resolved: 4, total: 10 }; @@ -116,6 +155,27 @@ describe('Reports store utils', () => { 'Rspec found 1 failed/error test result and 1 fixed test result out of 10 total tests', ); }); + + it('should render text for singular failed, errored, and fixed results', () => { + // these will be singular when the copy is updated + const name = 'Rspec'; + const data = { failed: 1, errored: 1, resolved: 1, total: 10 }; + const result = utils.reportTextBuilder(name, data); + + expect(result).toBe( + 'Rspec found 2 failed/error test results and 1 fixed test result out of 10 total tests', + ); + }); + + it('should render text for multiple failed, errored, and fixed results', () => { + const name = 'Rspec'; + const data = { failed: 2, errored: 3, resolved: 4, total: 10 }; + const result = utils.reportTextBuilder(name, data); + + expect(result).toBe( + 'Rspec found 5 failed/error test results and 4 fixed test results out of 10 total tests', + ); + }); }); describe('statusIcon', () => { diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js index 1b006cdbd4e..154aa881d2d 100644 --- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js +++ b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js @@ -5,6 +5,7 @@ import state from '~/reports/store/state'; import component from '~/reports/components/grouped_test_reports_app.vue'; import mountComponent from '../../helpers/vue_mount_component_helper'; import newFailedTestReports from '../mock_data/new_failures_report.json'; +import newErrorsTestReports from '../mock_data/new_errors_report.json'; import successTestReports from '../mock_data/no_failures_report.json'; import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json'; import resolvedFailures from '../mock_data/resolved_failures.json'; @@ -99,6 +100,34 @@ describe('Grouped Test Reports App', () => { }); }); + describe('with new error result', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, newErrorsTestReports, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders error summary text + new badge', done => { + setTimeout(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained 2 failed/error test results out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain( + 'karma found 2 failed/error test results out of 3 total tests', + ); + + expect(vm.$el.textContent).toContain('New'); + expect(vm.$el.textContent).toContain( + 'rspec:pg found no changed test results out of 8 total tests', + ); + done(); + }, 0); + }); + }); + describe('with mixed results', () => { beforeEach(() => { mock.onGet('test_results.json').reply(200, mixedResultsTestReports, {}); @@ -127,7 +156,7 @@ describe('Grouped Test Reports App', () => { }); }); - describe('with resolved failures', () => { + describe('with resolved failures and resolved errors', () => { beforeEach(() => { mock.onGet('test_results.json').reply(200, resolvedFailures, {}); vm = mountComponent(Component, { @@ -139,11 +168,11 @@ describe('Grouped Test Reports App', () => { setTimeout(() => { expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( - 'Test summary contained 2 fixed test results out of 11 total tests', + 'Test summary contained 4 fixed test results out of 11 total tests', ); expect(vm.$el.textContent).toContain( - 'rspec:pg found 2 fixed test results out of 8 total tests', + 'rspec:pg found 4 fixed test results out of 8 total tests', ); done(); }, 0); @@ -161,6 +190,19 @@ describe('Grouped Test Reports App', () => { done(); }, 0); }); + + it('renders resolved errors', done => { + setTimeout(() => { + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_errors[0].name, + ); + + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_errors[1].name, + ); + done(); + }, 0); + }); }); describe('with error', () => { diff --git a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json b/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json index ceaf894375a..6141e5433a6 100644 --- a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json +++ b/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json @@ -1 +1,55 @@ -{"status":"failed","summary":{"total":11,"resolved":2,"failed":2},"suites":[{"name":"rspec:pg","status":"failed","summary":{"total":8,"resolved":2,"failed":1},"new_failures":[{"status":"failed","name":"Test#subtract when a is 2 and b is 1 returns correct result","execution_time":0.00908,"system_output":"Failure/Error: is_expected.to eq(1)\n\n expected: 1\n got: 3\n\n (compared using ==)\n./spec/test_spec.rb:43:in `block (4 levels) in <top (required)>'"}],"resolved_failures":[{"status":"success","name":"Test#sum when a is 1 and b is 2 returns summary","execution_time":0.000318,"system_output":null},{"status":"success","name":"Test#sum when a is 100 and b is 200 returns summary","execution_time":0.000074,"system_output":null}],"existing_failures":[]},{"name":"java ant","status":"failed","summary":{"total":3,"resolved":0,"failed":1},"new_failures":[],"resolved_failures":[],"existing_failures":[{"status":"failed","name":"sumTest","execution_time":0.004,"system_output":"junit.framework.AssertionFailedError: expected:<3> but was:<-1>\n\tat CalculatorTest.sumTest(Unknown Source)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n"}]}]}
\ No newline at end of file +{ + "status": "failed", + "summary": { "total": 11, "resolved": 2, "errored": 0, "failed": 2 }, + "suites": [ + { + "name": "rspec:pg", + "status": "failed", + "summary": { "total": 8, "resolved": 2, "errored": 0, "failed": 1 }, + "new_failures": [ + { + "status": "failed", + "name": "Test#subtract when a is 2 and b is 1 returns correct result", + "execution_time": 0.00908, + "system_output": "Failure/Error: is_expected.to eq(1)\n\n expected: 1\n got: 3\n\n (compared using ==)\n./spec/test_spec.rb:43:in `block (4 levels) in <top (required)>'" + } + ], + "resolved_failures": [ + { + "status": "success", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.000318, + "system_output": null + }, + { + "status": "success", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000074, + "system_output": null + } + ], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "status": "failed", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [ + { + "status": "failed", + "name": "sumTest", + "execution_time": 0.004, + "system_output": "junit.framework.AssertionFailedError: expected:<3> but was:<-1>\n\tat CalculatorTest.sumTest(Unknown Source)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + } + ], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/javascripts/reports/mock_data/new_errors_report.json b/spec/javascripts/reports/mock_data/new_errors_report.json new file mode 100644 index 00000000000..cebf98fdb63 --- /dev/null +++ b/spec/javascripts/reports/mock_data/new_errors_report.json @@ -0,0 +1,38 @@ +{ + "summary": { "total": 11, "resolved": 0, "errored": 2, "failed": 0 }, + "suites": [ + { + "name": "rspec:pg", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "karma", + "summary": { "total": 3, "resolved": 0, "errored": 2, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [ + { + "result": "error", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.009411, + "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'status' of undefined'" + }, + { + "result": "error", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000162, + "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'length' of undefined'" + } + ], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/javascripts/reports/mock_data/new_failures_report.json b/spec/javascripts/reports/mock_data/new_failures_report.json index 930efe16f65..8b9c12c6271 100644 --- a/spec/javascripts/reports/mock_data/new_failures_report.json +++ b/spec/javascripts/reports/mock_data/new_failures_report.json @@ -1 +1,38 @@ -{"summary":{"total":11,"resolved":0,"failed":2},"suites":[{"name":"rspec:pg","summary":{"total":8,"resolved":0,"failed":2},"new_failures":[{"result":"failure","name":"Test#sum when a is 1 and b is 2 returns summary","execution_time":0.009411,"system_output":"Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'"},{"result":"failure","name":"Test#sum when a is 100 and b is 200 returns summary","execution_time":0.000162,"system_output":"Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'"}],"resolved_failures":[],"existing_failures":[]},{"name":"java ant","summary":{"total":3,"resolved":0,"failed":0},"new_failures":[],"resolved_failures":[],"existing_failures":[]}]}
\ No newline at end of file +{ + "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 2 }, + "suites": [ + { + "name": "rspec:pg", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2 }, + "new_failures": [ + { + "result": "failure", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.009411, + "system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'" + }, + { + "result": "failure", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000162, + "system_output": "Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'" + } + ], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/javascripts/reports/mock_data/no_failures_report.json b/spec/javascripts/reports/mock_data/no_failures_report.json index 6c0675ff7dc..7da9e0c6211 100644 --- a/spec/javascripts/reports/mock_data/no_failures_report.json +++ b/spec/javascripts/reports/mock_data/no_failures_report.json @@ -1 +1,28 @@ -{"status":"success","summary":{"total":11,"resolved":0,"failed":0},"suites":[{"name":"rspec:pg","status":"success","summary":{"total":8,"resolved":0,"failed":0},"new_failures":[],"resolved_failures":[],"existing_failures":[]},{"name":"java ant","status":"success","summary":{"total":3,"resolved":0,"failed":0},"new_failures":[],"resolved_failures":[],"existing_failures":[]}]}
\ No newline at end of file +{ + "status": "success", + "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 0 }, + "suites": [ + { + "name": "rspec:pg", + "status": "success", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "status": "success", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/javascripts/reports/mock_data/resolved_failures.json b/spec/javascripts/reports/mock_data/resolved_failures.json index d1f347ce5e6..49de6aa840b 100644 --- a/spec/javascripts/reports/mock_data/resolved_failures.json +++ b/spec/javascripts/reports/mock_data/resolved_failures.json @@ -1,11 +1,11 @@ { "status": "success", - "summary": { "total": 11, "resolved": 2, "failed": 0 }, + "summary": { "total": 11, "resolved": 4, "errored": 0, "failed": 0 }, "suites": [ { "name": "rspec:pg", "status": "success", - "summary": { "total": 8, "resolved": 2, "failed": 0 }, + "summary": { "total": 8, "resolved": 4, "errored": 0, "failed": 0 }, "new_failures": [], "resolved_failures": [ { @@ -23,15 +23,36 @@ "stack_trace": null } ], - "existing_failures": [] + "existing_failures": [], + "new_errors": [], + "resolved_errors": [ + { + "status": "success", + "name": "Test#sum when a is 4 and b is 4 returns summary", + "execution_time": 0.00342, + "system_output": null, + "stack_trace": null + }, + { + "status": "success", + "name": "Test#sum when a is 40 and b is 400 returns summary", + "execution_time": 0.0000231, + "system_output": null, + "stack_trace": null + } + ], + "existing_errors": [] }, { "name": "java ant", "status": "success", - "summary": { "total": 3, "resolved": 0, "failed": 0 }, + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, "new_failures": [], "resolved_failures": [], - "existing_failures": [] + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] } ] } diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb index 6a7fe7a5927..b91cf1dd3ed 100644 --- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb +++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb @@ -99,7 +99,7 @@ describe Gitlab::Ci::Parsers::Test::Junit do let(:testcase_content) { '<error>Some error</error>' } it_behaves_like '<testcase> XML parser', - ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED, + ::Gitlab::Ci::Reports::TestCase::STATUS_ERROR, 'Some error' end diff --git a/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb index 48eef0643b2..d731afe1fff 100644 --- a/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb +++ b/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb @@ -57,6 +57,17 @@ describe Gitlab::Ci::Reports::TestReportsComparer do is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) end end + + context 'when there is an error test case in head suites' do + before do + head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + head_reports.get_suite('junit').add_test_case(create_test_case_java_error) + end + + it 'returns the total status in head suite' do + is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) + end + end end describe '#total_count' do @@ -75,7 +86,7 @@ describe Gitlab::Ci::Reports::TestReportsComparer do describe '#resolved_count' do subject { comparer.resolved_count } - context 'when there is a resolved test case in head suites' do + context 'when there is a resolved failure test case in head suites' do before do base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) base_reports.get_suite('junit').add_test_case(create_test_case_java_failed) @@ -88,6 +99,19 @@ describe Gitlab::Ci::Reports::TestReportsComparer do end end + context 'when there is a resolved error test case in head suites' do + before do + base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + base_reports.get_suite('junit').add_test_case(create_test_case_java_error) + head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + head_reports.get_suite('junit').add_test_case(create_test_case_java_success) + end + + it 'returns the correct count' do + is_expected.to eq(1) + end + end + context 'when there are no resolved test cases in head suites' do before do base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) @@ -127,4 +151,30 @@ describe Gitlab::Ci::Reports::TestReportsComparer do end end end + + describe '#error_count' do + subject { comparer.error_count } + + context 'when there is an error test case in head suites' do + before do + head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + head_reports.get_suite('junit').add_test_case(create_test_case_java_error) + end + + it 'returns the correct count' do + is_expected.to eq(1) + end + end + + context 'when there are no error test cases in head suites' do + before do + head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success) + head_reports.get_suite('junit').add_test_case(create_test_case_rspec_success) + end + + it 'returns the correct count' do + is_expected.to eq(0) + end + end + end end diff --git a/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb index cf4690bb334..2d2179a690b 100644 --- a/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb +++ b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb @@ -9,8 +9,9 @@ describe Gitlab::Ci::Reports::TestSuiteComparer do let(:name) { 'rpsec' } let(:base_suite) { Gitlab::Ci::Reports::TestSuite.new(name) } let(:head_suite) { Gitlab::Ci::Reports::TestSuite.new(name) } - let(:test_case_success) { create_test_case_rspec_success } - let(:test_case_failed) { create_test_case_rspec_failed } + let(:test_case_success) { create_test_case_java_success } + let(:test_case_failed) { create_test_case_java_failed } + let(:test_case_error) { create_test_case_java_error } describe '#new_failures' do subject { comparer.new_failures } @@ -135,6 +136,129 @@ describe Gitlab::Ci::Reports::TestSuiteComparer do end end + describe '#new_errors' do + subject { comparer.new_errors } + + context 'when head suite has a new error test case which does not exist in base' do + before do + base_suite.add_test_case(test_case_success) + head_suite.add_test_case(test_case_error) + end + + it 'returns the error test case' do + is_expected.to eq([test_case_error]) + end + end + + context 'when head suite still has an error test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_error) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + end + + context 'when head suite has a success test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_success) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + end + end + + describe '#existing_errors' do + subject { comparer.existing_errors } + + context 'when head suite has a new error test case which does not exist in base' do + before do + base_suite.add_test_case(test_case_success) + head_suite.add_test_case(test_case_error) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + end + + context 'when head suite still has an error test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_error) + end + + it 'returns the error test case' do + is_expected.to eq([test_case_error]) + end + end + + context 'when head suite has a success test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_success) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + end + end + + describe '#resolved_errors' do + subject { comparer.resolved_errors } + + context 'when head suite has a new error test case which does not exist in base' do + before do + base_suite.add_test_case(test_case_success) + head_suite.add_test_case(test_case_error) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + + it 'returns the correct resolved count' do + expect(comparer.resolved_count).to eq(0) + end + end + + context 'when head suite still has an error test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_error) + end + + it 'does not return the error test case' do + is_expected.to be_empty + end + + it 'returns the correct resolved count' do + expect(comparer.resolved_count).to eq(0) + end + end + + context 'when head suite has a success test case which errored in base' do + before do + base_suite.add_test_case(test_case_error) + head_suite.add_test_case(test_case_success) + end + + it 'returns the resolved test case' do + is_expected.to eq([test_case_success]) + end + + it 'returns the correct resolved count' do + expect(comparer.resolved_count).to eq(1) + end + end + end + describe '#total_count' do subject { comparer.total_count } @@ -208,7 +332,17 @@ describe Gitlab::Ci::Reports::TestSuiteComparer do head_suite.add_test_case(test_case_failed) end - it 'returns the total status in head suite' do + it 'returns the total status in head suite as failed' do + is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) + end + end + + context 'when there is an error test case in head suite' do + before do + head_suite.add_test_case(test_case_error) + end + + it 'returns the total status in head suite as failed' do is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) end end diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb index 8646db43bc8..217713fd899 100644 --- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb +++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb @@ -74,6 +74,15 @@ describe Gitlab::Ci::Reports::TestSuite do it { is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) } end + + context 'when a test case errored' do + before do + test_suite.add_test_case(test_case_success) + test_suite.add_test_case(test_case_error) + end + + it { is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) } + end end Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type| diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 7250258061a..4dadb310029 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -36,8 +36,6 @@ issues: - vulnerability_links - related_vulnerabilities - user_mentions -- blocked_by_issue_links -- blocked_by_issues events: - author - project diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb index 56df73161b4..34a775fc206 100644 --- a/spec/lib/gitlab/runtime_spec.rb +++ b/spec/lib/gitlab/runtime_spec.rb @@ -50,7 +50,7 @@ describe Gitlab::Runtime do allow(puma_type).to receive_message_chain(:cli_config, :options).and_return(max_threads: 2) end - it_behaves_like "valid runtime", :puma, 2 + it_behaves_like "valid runtime", :puma, 3 end context "unicorn" do @@ -71,7 +71,7 @@ describe Gitlab::Runtime do allow(sidekiq_type).to receive(:options).and_return(concurrency: 2) end - it_behaves_like "valid runtime", :sidekiq, 2 + it_behaves_like "valid runtime", :sidekiq, 4 end context "console" do diff --git a/spec/mailers/emails/pipelines_spec.rb b/spec/mailers/emails/pipelines_spec.rb index 8d4afe9f00f..ad1aa915fbb 100644 --- a/spec/mailers/emails/pipelines_spec.rb +++ b/spec/mailers/emails/pipelines_spec.rb @@ -19,6 +19,25 @@ describe Emails::Pipelines do expect(subject).to have_body_text status_text end + context 'when pipeline on master branch has a merge request' do + let(:pipeline) { create(:ci_pipeline, ref: 'master', sha: sha, project: project) } + + let!(:merge_request) do + create(:merge_request, source_branch: 'master', target_branch: 'feature', + source_project: project, target_project: project) + end + + it 'has correct information that there is no merge request link' do + expect(subject) + .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \ + "#{status} for #{pipeline.source_ref} | " \ + "#{pipeline.short_sha}".to_s + + expect(subject).to have_body_text pipeline.source_ref + expect(subject).to have_body_text status_text + end + end + context 'when pipeline for merge requests' do let(:pipeline) { merge_request.all_pipelines.first } @@ -28,7 +47,7 @@ describe Emails::Pipelines do target_project: project) end - it 'has a correct information with merge request link' do + it 'has correct information that there is a merge request link' do expect(subject) .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \ "#{status} for #{pipeline.source_ref} | " \ @@ -39,6 +58,27 @@ describe Emails::Pipelines do expect(subject).not_to have_body_text pipeline.ref end end + + context 'when branch pipeline is set to a merge request as a head pipeline' do + let(:pipeline) do + create(:ci_pipeline, project: project, ref: ref, sha: sha, + merge_requests_as_head_pipeline: [merge_request]) + end + + let(:merge_request) do + create(:merge_request, source_project: project, target_project: project) + end + + it 'has correct information that there is a merge request link' do + expect(subject) + .to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \ + "#{status} for #{pipeline.source_ref} | " \ + "#{pipeline.short_sha} in !#{merge_request.iid}".to_s + + expect(subject).to have_body_text merge_request.to_reference + expect(subject).to have_body_text pipeline.source_ref + end + end end describe '#pipeline_success_email' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index dc055244af7..6c90a1b5614 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -153,6 +153,16 @@ describe Project do expect(project.container_expiration_policy).to be_persisted end + it 'does not create another container expiration policy if there is already one' do + project = build(:project) + + expect do + container_expiration_policy = create(:container_expiration_policy, project: project) + + expect(project.container_expiration_policy).to eq(container_expiration_policy) + end.to change { ContainerExpirationPolicy.count }.by(1) + end + it 'automatically creates a Pages metadata row' do expect(project.pages_metadatum).to be_an_instance_of(ProjectPagesMetadatum) expect(project.pages_metadatum).to be_persisted diff --git a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb new file mode 100644 index 00000000000..0362fef2d2e --- /dev/null +++ b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb @@ -0,0 +1,244 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Updating an image DiffNote' do + include GraphqlHelpers + using RSpec::Parameterized::TableSyntax + + let_it_be(:noteable) { create(:merge_request, :with_diffs) } + let_it_be(:original_body) { 'Original body' } + let_it_be(:original_position) do + Gitlab::Diff::Position.new( + old_path: 'files/images/any_image.png', + new_path: 'files/images/any_image.png', + width: 10, + height: 20, + x: 1, + y: 2, + diff_refs: noteable.diff_refs, + position_type: 'image' + ) + end + let_it_be(:updated_body) { 'Updated body' } + let_it_be(:updated_width) { 50 } + let_it_be(:updated_height) { 100 } + let_it_be(:updated_x) { 5 } + let_it_be(:updated_y) { 10 } + let(:updated_position) do + { + width: updated_width, + height: updated_height, + x: updated_x, + y: updated_y + } + end + let!(:diff_note) do + create(:image_diff_note_on_merge_request, + noteable: noteable, + project: noteable.project, + note: original_body, + position: original_position) + end + let(:mutation) do + variables = { + id: GitlabSchema.id_from_object(diff_note).to_s, + body: updated_body, + position: updated_position + } + + graphql_mutation(:update_image_diff_note, variables) + end + + def mutation_response + graphql_mutation_response(:update_image_diff_note) + end + + context 'when the user does not have permission' do + let_it_be(:current_user) { create(:user) } + + it_behaves_like 'a mutation that returns top-level errors', + errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action'] + + it 'does not update the DiffNote' do + post_graphql_mutation(mutation, current_user: current_user) + + diff_note.reload + + expect(diff_note).to have_attributes( + note: original_body, + position: have_attributes( + width: original_position.width, + height: original_position.height, + x: original_position.x, + y: original_position.y + ) + ) + end + end + + context 'when the user has permission' do + let(:current_user) { diff_note.author } + + it 'updates the DiffNote' do + post_graphql_mutation(mutation, current_user: current_user) + + diff_note.reload + + expect(diff_note).to have_attributes( + note: updated_body, + position: have_attributes( + width: updated_width, + height: updated_height, + x: updated_x, + y: updated_y + ) + ) + end + + it 'returns the updated DiffNote' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['note']).to include( + 'body' => updated_body, + 'position' => hash_including( + 'width' => updated_width, + 'height' => updated_height, + 'x' => updated_x, + 'y' => updated_y + ) + ) + end + + describe 'updating single properties at a time' do + where(:property, :new_value) do + :body | 'foo' + :width | 19 + :height | 18 + :x | 17 + :y | 16 + end + + with_them do + # Properties that will be POSTed: + let(:updated_body) { value(:body) } + let(:updated_width) { value(:width) } + let(:updated_height) { value(:height) } + let(:updated_x) { value(:x) } + let(:updated_y) { value(:y) } + # Expectations of the properties: + let(:expected_body) { value(:body) || original_body } + let(:expected_width) { value(:width) || original_position.width } + let(:expected_height) { value(:height) || original_position.height } + let(:expected_x) { value(:x) || original_position.x } + let(:expected_y) { value(:y) || original_position.y } + + def value(prop) + new_value if property == prop + end + + it 'updates the DiffNote correctly' do + post_graphql_mutation(mutation, current_user: current_user) + + diff_note.reload + + expect(diff_note).to have_attributes( + note: expected_body, + position: have_attributes( + width: expected_width, + height: expected_height, + x: expected_x, + y: expected_y + ) + ) + end + end + + context 'when position is nil' do + let(:updated_position) { nil } + + it 'updates the DiffNote correctly' do + post_graphql_mutation(mutation, current_user: current_user) + + diff_note.reload + + expect(diff_note).to have_attributes( + note: updated_body, + position: original_position + ) + end + end + end + + context 'when both body and position args are blank' do + let(:updated_body) { nil } + let(:updated_position) { nil } + + it_behaves_like 'a mutation that returns top-level errors', errors: ['body or position arguments are required'] + end + + context 'when resource is not a DiffNote on an image' do + let!(:diff_note) { create(:diff_note_on_merge_request, note: original_body) } + + it_behaves_like 'a mutation that returns top-level errors', errors: ['Resource is not an ImageDiffNote'] + end + + context 'when there are ActiveRecord validation errors' do + before do + expect(diff_note).to receive_message_chain( + :errors, + :full_messages + ).and_return(['Error 1', 'Error 2']) + + expect_next_instance_of(Notes::UpdateService) do |service| + expect(service).to receive(:execute).and_return(diff_note) + end + end + + it_behaves_like 'a mutation that returns errors in the response', errors: ['Error 1', 'Error 2'] + + it 'does not update the DiffNote' do + post_graphql_mutation(mutation, current_user: current_user) + + diff_note.reload + + expect(diff_note).to have_attributes( + note: original_body, + position: have_attributes( + width: original_position.width, + height: original_position.height, + x: original_position.x, + y: original_position.y + ) + ) + end + + it 'returns the DiffNote with its original body' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['note']).to include( + 'body' => original_body, + 'position' => hash_including( + 'width' => original_position.width, + 'height' => original_position.height, + 'x' => original_position.x, + 'y' => original_position.y + ) + ) + end + end + + context 'when body only contains quick actions' do + let(:updated_body) { '/close' } + + it 'returns a nil note and empty errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response).to include( + 'errors' => [], + 'note' => nil + ) + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/notes/update_spec.rb b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb index 958f640995a..a5c6b72005e 100644 --- a/spec/requests/api/graphql/mutations/notes/update_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb @@ -22,7 +22,7 @@ describe 'Updating a Note' do end context 'when the user does not have permission' do - let(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user) } it_behaves_like 'a mutation that returns top-level errors', errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action'] @@ -68,5 +68,18 @@ describe 'Updating a Note' do expect(mutation_response['note']['body']).to eq(original_body) end end + + context 'when body only contains quick actions' do + let(:updated_body) { '/close' } + + it 'returns a nil note and empty errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response).to include( + 'errors' => [], + 'note' => nil + ) + end + end end end diff --git a/spec/serializers/test_reports_comparer_entity_spec.rb b/spec/serializers/test_reports_comparer_entity_spec.rb index 2627ad536e4..e7dabc67325 100644 --- a/spec/serializers/test_reports_comparer_entity_spec.rb +++ b/spec/serializers/test_reports_comparer_entity_spec.rb @@ -24,7 +24,7 @@ describe TestReportsComparerEntity do it 'contains correct compared test reports details' do expect(subject[:status]).to eq('success') - expect(subject[:summary]).to include(total: 2, resolved: 0, failed: 0) + expect(subject[:summary]).to include(total: 2, resolved: 0, failed: 0, errored: 0) expect(subject[:suites].first[:name]).to eq('rspec') expect(subject[:suites].first[:status]).to eq('success') expect(subject[:suites].second[:name]).to eq('junit') @@ -42,7 +42,7 @@ describe TestReportsComparerEntity do it 'contains correct compared test reports details' do expect(subject[:status]).to eq('failed') - expect(subject[:summary]).to include(total: 2, resolved: 0, failed: 1) + expect(subject[:summary]).to include(total: 2, resolved: 0, failed: 1, errored: 0) expect(subject[:suites].first[:name]).to eq('rspec') expect(subject[:suites].first[:status]).to eq('success') expect(subject[:suites].second[:name]).to eq('junit') @@ -60,7 +60,7 @@ describe TestReportsComparerEntity do it 'contains correct compared test reports details' do expect(subject[:status]).to eq('success') - expect(subject[:summary]).to include(total: 2, resolved: 1, failed: 0) + expect(subject[:summary]).to include(total: 2, resolved: 1, failed: 0, errored: 0) expect(subject[:suites].first[:name]).to eq('rspec') expect(subject[:suites].first[:status]).to eq('success') expect(subject[:suites].second[:name]).to eq('junit') diff --git a/spec/serializers/test_suite_comparer_entity_spec.rb b/spec/serializers/test_suite_comparer_entity_spec.rb index e22387130a1..9790777a570 100644 --- a/spec/serializers/test_suite_comparer_entity_spec.rb +++ b/spec/serializers/test_suite_comparer_entity_spec.rb @@ -12,6 +12,7 @@ describe TestSuiteComparerEntity do let(:head_suite) { Gitlab::Ci::Reports::TestSuite.new(name) } let(:test_case_success) { create_test_case_rspec_success } let(:test_case_failed) { create_test_case_rspec_failed } + let(:test_case_error) { create_test_case_rspec_error } describe '#as_json' do subject { entity.as_json } @@ -25,7 +26,7 @@ describe TestSuiteComparerEntity do it 'contains correct compared test suite details' do expect(subject[:name]).to eq(name) expect(subject[:status]).to eq('failed') - expect(subject[:summary]).to include(total: 1, resolved: 0, failed: 1) + expect(subject[:summary]).to include(total: 1, resolved: 0, failed: 1, errored: 0) subject[:new_failures].first.tap do |new_failure| expect(new_failure[:status]).to eq(test_case_failed.status) expect(new_failure[:name]).to eq(test_case_failed.name) @@ -37,6 +38,27 @@ describe TestSuiteComparerEntity do end end + context 'when head suite has a new error test case which does not exist in base' do + before do + base_suite.add_test_case(test_case_success) + head_suite.add_test_case(test_case_error) + end + + it 'contains correct compared test suite details' do + expect(subject[:name]).to eq(name) + expect(subject[:status]).to eq('failed') + expect(subject[:summary]).to include(total: 1, resolved: 0, failed: 0, errored: 1) + subject[:new_errors].first.tap do |new_error| + expect(new_error[:status]).to eq(test_case_error.status) + expect(new_error[:name]).to eq(test_case_error.name) + expect(new_error[:execution_time]).to eq(test_case_error.execution_time) + expect(new_error[:system_output]).to eq(test_case_error.system_output) + end + expect(subject[:resolved_failures]).to be_empty + expect(subject[:existing_failures]).to be_empty + end + end + context 'when head suite still has a failed test case which failed in base' do before do base_suite.add_test_case(test_case_failed) @@ -46,7 +68,7 @@ describe TestSuiteComparerEntity do it 'contains correct compared test suite details' do expect(subject[:name]).to eq(name) expect(subject[:status]).to eq('failed') - expect(subject[:summary]).to include(total: 1, resolved: 0, failed: 1) + expect(subject[:summary]).to include(total: 1, resolved: 0, failed: 1, errored: 0) expect(subject[:new_failures]).to be_empty expect(subject[:resolved_failures]).to be_empty subject[:existing_failures].first.tap do |existing_failure| @@ -67,7 +89,7 @@ describe TestSuiteComparerEntity do it 'contains correct compared test suite details' do expect(subject[:name]).to eq(name) expect(subject[:status]).to eq('success') - expect(subject[:summary]).to include(total: 1, resolved: 1, failed: 0) + expect(subject[:summary]).to include(total: 1, resolved: 1, failed: 0, errored: 0) expect(subject[:new_failures]).to be_empty subject[:resolved_failures].first.tap do |resolved_failure| expect(resolved_failure[:status]).to eq(test_case_success.status) @@ -88,42 +110,57 @@ describe TestSuiteComparerEntity do context 'prefers new over existing and resolved' do before do 3.times { add_new_failure } + 3.times { add_new_error } 3.times { add_existing_failure } + 3.times { add_existing_error } 3.times { add_resolved_failure } + 3.times { add_resolved_error } end - it 'returns 2 new failures, and 1 of resolved and existing' do - expect(subject[:summary]).to include(total: 9, resolved: 3, failed: 6) + it 'returns 2 of each new category, and 1 of each resolved and existing' do + expect(subject[:summary]).to include(total: 18, resolved: 6, failed: 6, errored: 6) expect(subject[:new_failures].count).to eq(2) + expect(subject[:new_errors].count).to eq(2) expect(subject[:existing_failures].count).to eq(1) + expect(subject[:existing_errors].count).to eq(1) expect(subject[:resolved_failures].count).to eq(1) + expect(subject[:resolved_errors].count).to eq(1) end end context 'prefers existing over resolved' do before do 3.times { add_existing_failure } + 3.times { add_existing_error } 3.times { add_resolved_failure } + 3.times { add_resolved_error } end - it 'returns 2 existing failures, and 1 resolved' do - expect(subject[:summary]).to include(total: 6, resolved: 3, failed: 3) + it 'returns 2 of each existing category, and 1 of each resolved' do + expect(subject[:summary]).to include(total: 12, resolved: 6, failed: 3, errored: 3) expect(subject[:new_failures].count).to eq(0) + expect(subject[:new_errors].count).to eq(0) expect(subject[:existing_failures].count).to eq(2) + expect(subject[:existing_errors].count).to eq(2) expect(subject[:resolved_failures].count).to eq(1) + expect(subject[:resolved_errors].count).to eq(1) end end context 'limits amount of resolved' do before do 3.times { add_resolved_failure } + 3.times { add_resolved_error } end - it 'returns 2 resolved failures' do - expect(subject[:summary]).to include(total: 3, resolved: 3, failed: 0) + it 'returns 2 of each resolved category' do + expect(subject[:summary]).to include(total: 6, resolved: 6, failed: 0, errored: 0) expect(subject[:new_failures].count).to eq(0) + expect(subject[:new_errors].count).to eq(0) expect(subject[:existing_failures].count).to eq(0) + expect(subject[:existing_errors].count).to eq(0) expect(subject[:resolved_failures].count).to eq(2) + expect(subject[:resolved_errors].count).to eq(2) end end @@ -134,19 +171,38 @@ describe TestSuiteComparerEntity do head_suite.add_test_case(failed_case) end + def add_new_error + error_case = create_test_case_rspec_error(SecureRandom.hex) + head_suite.add_test_case(error_case) + end + def add_existing_failure failed_case = create_test_case_rspec_failed(SecureRandom.hex) base_suite.add_test_case(failed_case) head_suite.add_test_case(failed_case) end + def add_existing_error + error_case = create_test_case_rspec_error(SecureRandom.hex) + base_suite.add_test_case(error_case) + head_suite.add_test_case(error_case) + end + def add_resolved_failure case_name = SecureRandom.hex - failed_case = create_test_case_rspec_failed(case_name) - success_case = create_test_case_rspec_success(case_name) + failed_case = create_test_case_java_failed(case_name) + success_case = create_test_case_java_success(case_name) base_suite.add_test_case(failed_case) head_suite.add_test_case(success_case) end + + def add_resolved_error + case_name = SecureRandom.hex + error_case = create_test_case_java_error(case_name) + success_case = create_test_case_java_success(case_name) + base_suite.add_test_case(error_case) + head_suite.add_test_case(success_case) + end end end end diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb index 7aa8f0ebf8f..1cf1cff51ed 100644 --- a/spec/services/snippets/create_service_spec.rb +++ b/spec/services/snippets/create_service_spec.rb @@ -143,6 +143,34 @@ describe Snippets::CreateService do end end + shared_examples 'creates repository' do + it do + subject + + expect(snippet.repository_exists?).to be_truthy + end + + context 'when snippet creation fails' do + let(:extra_opts) { { content: nil } } + + it 'does not create repository' do + subject + + expect(snippet.repository_exists?).to be_falsey + end + end + + context 'when feature flag :version_snippets is disabled' do + it 'does not create snippet repository' do + stub_feature_flags(version_snippets: false) + + subject + + expect(snippet.repository_exists?).to be_falsey + end + end + end + context 'when Project Snippet' do let_it_be(:project) { create(:project) } @@ -155,6 +183,7 @@ describe Snippets::CreateService do it_behaves_like 'spam check is performed' it_behaves_like 'snippet create data is tracked' it_behaves_like 'an error service response when save fails' + it_behaves_like 'creates repository' end context 'when PersonalSnippet' do @@ -165,6 +194,7 @@ describe Snippets::CreateService do it_behaves_like 'spam check is performed' it_behaves_like 'snippet create data is tracked' it_behaves_like 'an error service response when save fails' + it_behaves_like 'creates repository' end end end diff --git a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb index 2548afc1570..8092f87383d 100644 --- a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb +++ b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb @@ -123,7 +123,7 @@ RSpec.shared_examples 'cycle analytics label based stage' do }) expect(stage).to be_invalid - expect(stage.errors[:start_event_label]).to include("can't be blank") + expect(stage.errors[:start_event_label_id]).to include("can't be blank") end it 'returns validation error when `end_event_label_id` is missing' do @@ -135,7 +135,7 @@ RSpec.shared_examples 'cycle analytics label based stage' do }) expect(stage).to be_invalid - expect(stage.errors[:end_event_label]).to include("can't be blank") + expect(stage.errors[:end_event_label_id]).to include("can't be blank") end end @@ -145,7 +145,7 @@ RSpec.shared_examples 'cycle analytics label based stage' do name: 'My Stage', parent: parent, start_event_identifier: :issue_label_added, - start_event_label: group_label, + start_event_label_id: group_label.id, end_event_identifier: :issue_closed }) @@ -159,7 +159,7 @@ RSpec.shared_examples 'cycle analytics label based stage' do name: 'My Stage', parent: parent_in_subgroup, start_event_identifier: :issue_label_added, - start_event_label: group_label, + start_event_label_id: group_label.id, end_event_identifier: :issue_closed }) @@ -170,30 +170,30 @@ RSpec.shared_examples 'cycle analytics label based stage' do context 'when label is defined for a different group' do let(:error_message) { s_('CycleAnalyticsStage|is not available for the selected group') } - it 'returns validation for `start_event_label`' do + it 'returns validation for `start_event_label_id`' do stage = described_class.new({ name: 'My Stage', parent: parent_outside_of_group_label_scope, start_event_identifier: :issue_label_added, - start_event_label: group_label, + start_event_label_id: group_label.id, end_event_identifier: :issue_closed }) expect(stage).to be_invalid - expect(stage.errors[:start_event_label]).to include(error_message) + expect(stage.errors[:start_event_label_id]).to include(error_message) end - it 'returns validation for `end_event_label`' do + it 'returns validation for `end_event_label_id`' do stage = described_class.new({ name: 'My Stage', parent: parent_outside_of_group_label_scope, start_event_identifier: :issue_closed, end_event_identifier: :issue_label_added, - end_event_label: group_label + end_event_label_id: group_label.id }) expect(stage).to be_invalid - expect(stage.errors[:end_event_label]).to include(error_message) + expect(stage.errors[:end_event_label_id]).to include(error_message) end end |