diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-30 18:09:46 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-30 18:09:46 +0300 |
commit | 7f305b576b51c3503970ef224cf4b31e247a322d (patch) | |
tree | 9a3b0ddfb8640fd1a66307a38fe6ba264e5d99dd /spec | |
parent | 04edf6545802ed0515e221038b63fc96ad3e6d54 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
44 files changed, 1617 insertions, 91 deletions
diff --git a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js index a25aba61516..ff780939026 100644 --- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js @@ -7,27 +7,32 @@ import { file } from '../../helpers'; const localVue = createLocalVue(); localVue.use(Vuex); +const TEST_FILE_PATH = 'test/file/path'; + describe('IDE commit editor header', () => { let wrapper; - let f; let store; - const findDiscardModal = () => wrapper.find({ ref: 'discardModal' }); - const findDiscardButton = () => wrapper.find({ ref: 'discardButton' }); - - beforeEach(() => { - f = file('file'); - store = createStore(); - + const createComponent = (fileProps = {}) => { wrapper = mount(EditorHeader, { store, localVue, propsData: { - activeFile: f, + activeFile: { + ...file(TEST_FILE_PATH), + staged: true, + ...fileProps, + }, }, }); + }; - jest.spyOn(wrapper.vm, 'discardChanges').mockImplementation(); + const findDiscardModal = () => wrapper.find({ ref: 'discardModal' }); + const findDiscardButton = () => wrapper.find({ ref: 'discardButton' }); + + beforeEach(() => { + store = createStore(); + jest.spyOn(store, 'dispatch').mockImplementation(); }); afterEach(() => { @@ -35,29 +40,38 @@ describe('IDE commit editor header', () => { wrapper = null; }); - it('renders button to discard', () => { - expect(wrapper.vm.$el.querySelectorAll('.btn')).toHaveLength(1); + it.each` + fileProps | shouldExist + ${{ staged: false, changed: false }} | ${false} + ${{ staged: true, changed: false }} | ${true} + ${{ staged: false, changed: true }} | ${true} + ${{ staged: true, changed: true }} | ${true} + `('with $fileProps, show discard button is $shouldExist', ({ fileProps, shouldExist }) => { + createComponent(fileProps); + + expect(findDiscardButton().exists()).toBe(shouldExist); }); describe('discard button', () => { - let modal; - beforeEach(() => { - modal = findDiscardModal(); + createComponent(); + const modal = findDiscardModal(); jest.spyOn(modal.vm, 'show'); findDiscardButton().trigger('click'); }); it('opens a dialog confirming discard', () => { - expect(modal.vm.show).toHaveBeenCalled(); + expect(findDiscardModal().vm.show).toHaveBeenCalled(); }); it('calls discardFileChanges if dialog result is confirmed', () => { - modal.vm.$emit('ok'); + expect(store.dispatch).not.toHaveBeenCalled(); + + findDiscardModal().vm.$emit('ok'); - expect(wrapper.vm.discardChanges).toHaveBeenCalledWith(f.path); + expect(store.dispatch).toHaveBeenCalledWith('discardFileChanges', TEST_FILE_PATH); }); }); }); diff --git a/spec/frontend/jira_import/components/jira_import_app_spec.js b/spec/frontend/jira_import/components/jira_import_app_spec.js index 70713ca3cd7..0040e71c192 100644 --- a/spec/frontend/jira_import/components/jira_import_app_spec.js +++ b/spec/frontend/jira_import/components/jira_import_app_spec.js @@ -1,5 +1,5 @@ import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import JiraImportApp from '~/jira_import/components/jira_import_app.vue'; import JiraImportForm from '~/jira_import/components/jira_import_form.vue'; @@ -11,12 +11,16 @@ import { IMPORT_STATE } from '~/jira_import/utils'; const mountComponent = ({ isJiraConfigured = true, errorMessage = '', - showAlert = true, + selectedProject = 'MTG', + showAlert = false, status = IMPORT_STATE.NONE, loading = false, mutate = jest.fn(() => Promise.resolve()), -} = {}) => - shallowMount(JiraImportApp, { + mountType, +} = {}) => { + const mountFunction = mountType === 'mount' ? mount : shallowMount; + + return mountFunction(JiraImportApp, { propsData: { isJiraConfigured, inProgressIllustration: 'in-progress-illustration.svg', @@ -34,15 +38,32 @@ const mountComponent = ({ return { errorMessage, showAlert, + selectedProject, jiraImportDetails: { status, - import: { - jiraProjectKey: 'MTG', - scheduledAt: '2020-04-08T12:17:25+00:00', - scheduledBy: { - name: 'Jane Doe', + imports: [ + { + jiraProjectKey: 'MTG', + scheduledAt: '2020-04-08T10:11:12+00:00', + scheduledBy: { + name: 'John Doe', + }, }, - }, + { + jiraProjectKey: 'MSJP', + scheduledAt: '2020-04-09T13:14:15+00:00', + scheduledBy: { + name: 'Jimmy Doe', + }, + }, + { + jiraProjectKey: 'MTG', + scheduledAt: '2020-04-09T16:17:18+00:00', + scheduledBy: { + name: 'Jane Doe', + }, + }, + ], }, }; }, @@ -53,6 +74,7 @@ const mountComponent = ({ }, }, }); +}; describe('JiraImportApp', () => { let wrapper; @@ -160,6 +182,64 @@ describe('JiraImportApp', () => { }); }); + describe('import in progress screen', () => { + beforeEach(() => { + wrapper = mountComponent({ status: IMPORT_STATE.SCHEDULED }); + }); + + it('shows the illustration', () => { + expect(getProgressComponent().props('illustration')).toBe('in-progress-illustration.svg'); + }); + + it('shows the name of the most recent import initiator', () => { + expect(getProgressComponent().props('importInitiator')).toBe('Jane Doe'); + }); + + it('shows the name of the most recent imported project', () => { + expect(getProgressComponent().props('importProject')).toBe('MTG'); + }); + + it('shows the time of the most recent import', () => { + expect(getProgressComponent().props('importTime')).toBe('2020-04-09T16:17:18+00:00'); + }); + + it('has the path to the issues page', () => { + expect(getProgressComponent().props('issuesPath')).toBe('gitlab-org/gitlab-test/-/issues'); + }); + }); + + describe('jira import form screen', () => { + describe('when selected project has been imported before', () => { + it('shows jira-import::MTG-3 label since project MTG has been imported 2 time before', () => { + wrapper = mountComponent(); + + expect(getFormComponent().props('importLabel')).toBe('jira-import::MTG-3'); + }); + + it('shows warning alert to explain project MTG has been imported 2 times before', () => { + wrapper = mountComponent({ mountType: 'mount' }); + + expect(getAlert().text()).toBe( + 'You have imported from this project 2 times before. Each new import will create duplicate issues.', + ); + }); + }); + + describe('when selected project has not been imported before', () => { + beforeEach(() => { + wrapper = mountComponent({ selectedProject: 'MJP' }); + }); + + it('shows jira-import::MJP-1 label since project MJP has not been imported before', () => { + expect(getFormComponent().props('importLabel')).toBe('jira-import::MJP-1'); + }); + + it('does not show warning alert since project MJP has not been imported before', () => { + expect(getAlert().exists()).toBe(false); + }); + }); + }); + describe('initiating a Jira import', () => { it('calls the mutation with the expected arguments', () => { const mutate = jest.fn(() => Promise.resolve()); @@ -201,6 +281,7 @@ describe('JiraImportApp', () => { wrapper = mountComponent({ errorMessage: 'There was an error importing the Jira project.', showAlert: true, + selectedProject: null, }); expect(getAlert().exists()).toBe(true); diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js index 0987eb11693..dea94e7bf1f 100644 --- a/spec/frontend/jira_import/components/jira_import_form_spec.js +++ b/spec/frontend/jira_import/components/jira_import_form_spec.js @@ -2,11 +2,15 @@ import { GlAvatar, GlButton, GlFormSelect, GlLabel } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import JiraImportForm from '~/jira_import/components/jira_import_form.vue'; +const importLabel = 'jira-import::MTG-1'; +const value = 'MTG'; + const mountComponent = ({ mountType } = {}) => { const mountFunction = mountType === 'mount' ? mount : shallowMount; return mountFunction(JiraImportForm, { propsData: { + importLabel, issuesPath: 'gitlab-org/gitlab-test/-/issues', jiraProjects: [ { @@ -22,6 +26,7 @@ const mountComponent = ({ mountType } = {}) => { value: 'MTG', }, ], + value, }, }); }; @@ -29,6 +34,8 @@ const mountComponent = ({ mountType } = {}) => { describe('JiraImportForm', () => { let wrapper; + const getSelectDropdown = () => wrapper.find(GlFormSelect); + const getCancelButton = () => wrapper.findAll(GlButton).at(1); afterEach(() => { @@ -40,7 +47,7 @@ describe('JiraImportForm', () => { it('is shown', () => { wrapper = mountComponent(); - expect(wrapper.find(GlFormSelect).exists()).toBe(true); + expect(wrapper.contains(GlFormSelect)).toBe(true); }); it('contains a list of Jira projects to select from', () => { @@ -48,8 +55,7 @@ describe('JiraImportForm', () => { const optionItems = ['My Jira Project', 'My Second Jira Project', 'Migrate to GitLab']; - wrapper - .find(GlFormSelect) + getSelectDropdown() .findAll('option') .wrappers.forEach((optionEl, index) => { expect(optionEl.text()).toBe(optionItems[index]); @@ -63,7 +69,7 @@ describe('JiraImportForm', () => { }); it('shows a label which will be applied to imported Jira projects', () => { - expect(wrapper.find(GlLabel).attributes('title')).toBe('jira-import::KEY-1'); + expect(wrapper.find(GlLabel).props('title')).toBe(importLabel); }); it('shows information to the user', () => { @@ -77,7 +83,7 @@ describe('JiraImportForm', () => { }); it('shows an avatar for the Reporter', () => { - expect(wrapper.find(GlAvatar).exists()).toBe(true); + expect(wrapper.contains(GlAvatar)).toBe(true); }); it('shows jira.issue.description.content for the Description', () => { @@ -111,16 +117,19 @@ describe('JiraImportForm', () => { }); }); - it('emits an "initiateJiraImport" event with the selected dropdown value when submitted', () => { - const selectedOption = 'MTG'; + it('emits an "input" event when the input select value changes', () => { + wrapper = mountComponent({ mountType: 'mount' }); + + getSelectDropdown().vm.$emit('change', value); + expect(wrapper.emitted('input')[0]).toEqual([value]); + }); + + it('emits an "initiateJiraImport" event with the selected dropdown value when submitted', () => { wrapper = mountComponent(); - wrapper.setData({ - selectedOption, - }); wrapper.find('form').trigger('submit'); - expect(wrapper.emitted('initiateJiraImport')[0]).toEqual([selectedOption]); + expect(wrapper.emitted('initiateJiraImport')[0]).toEqual([value]); }); }); diff --git a/spec/frontend/jira_import/components/jira_import_progress_spec.js b/spec/frontend/jira_import/components/jira_import_progress_spec.js index ace497295c0..3ccf14554e1 100644 --- a/spec/frontend/jira_import/components/jira_import_progress_spec.js +++ b/spec/frontend/jira_import/components/jira_import_progress_spec.js @@ -9,7 +9,7 @@ const issuesPath = 'gitlab-org/gitlab-test/-/issues'; describe('JiraImportProgress', () => { let wrapper; - const getGlEmptyStateAttribute = attribute => wrapper.find(GlEmptyState).attributes(attribute); + const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute); const getParagraphText = () => wrapper.find('p').text(); @@ -37,21 +37,21 @@ describe('JiraImportProgress', () => { }); it('contains illustration', () => { - expect(getGlEmptyStateAttribute('svgpath')).toBe(illustration); + expect(getGlEmptyStateProp('svgPath')).toBe(illustration); }); it('contains a title', () => { const title = 'Import in progress'; - expect(getGlEmptyStateAttribute('title')).toBe(title); + expect(getGlEmptyStateProp('title')).toBe(title); }); it('contains button text', () => { - expect(getGlEmptyStateAttribute('primarybuttontext')).toBe('View issues'); + expect(getGlEmptyStateProp('primaryButtonText')).toBe('View issues'); }); it('contains button url', () => { const expected = `${issuesPath}?search=${importProject}`; - expect(getGlEmptyStateAttribute('primarybuttonlink')).toBe(expected); + expect(getGlEmptyStateProp('primaryButtonLink')).toBe(expected); }); }); diff --git a/spec/frontend/jira_import/components/jira_import_setup_spec.js b/spec/frontend/jira_import/components/jira_import_setup_spec.js index 4c8cba70d8a..aa94dc4f503 100644 --- a/spec/frontend/jira_import/components/jira_import_setup_spec.js +++ b/spec/frontend/jira_import/components/jira_import_setup_spec.js @@ -8,7 +8,7 @@ const jiraIntegrationPath = 'gitlab-org/gitlab-test/-/services/jira/edit'; describe('JiraImportSetup', () => { let wrapper; - const getGlEmptyStateAttribute = attribute => wrapper.find(GlEmptyState).attributes(attribute); + const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute); beforeEach(() => { wrapper = shallowMount(JiraImportSetup, { @@ -25,19 +25,19 @@ describe('JiraImportSetup', () => { }); it('contains illustration', () => { - expect(getGlEmptyStateAttribute('svgpath')).toBe(illustration); + expect(getGlEmptyStateProp('svgPath')).toBe(illustration); }); it('contains a description', () => { const description = 'You will first need to set up Jira Integration to use this feature.'; - expect(getGlEmptyStateAttribute('description')).toBe(description); + expect(getGlEmptyStateProp('description')).toBe(description); }); it('contains button text', () => { - expect(getGlEmptyStateAttribute('primarybuttontext')).toBe('Set up Jira Integration'); + expect(getGlEmptyStateProp('primaryButtonText')).toBe('Set up Jira Integration'); }); it('contains button link', () => { - expect(getGlEmptyStateAttribute('primarybuttonlink')).toBe(jiraIntegrationPath); + expect(getGlEmptyStateProp('primaryButtonLink')).toBe(jiraIntegrationPath); }); }); diff --git a/spec/frontend/labels_select_spec.js b/spec/frontend/labels_select_spec.js index 5f48bad4970..8b08eb9e124 100644 --- a/spec/frontend/labels_select_spec.js +++ b/spec/frontend/labels_select_spec.js @@ -45,7 +45,6 @@ describe('LabelsSelect', () => { labels: mockLabels, issueUpdateURL: mockUrl, enableScopedLabels: true, - scopedLabelsDocumentationLink: 'docs-link', }), ); }); @@ -71,10 +70,6 @@ describe('LabelsSelect', () => { it('generated label item has a gl-label-text class', () => { expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true); }); - - it('generated label item template does not have gl-label-icon class', () => { - expect($labelEl.find('.gl-label-icon')).toHaveLength(0); - }); }); describe('when scoped label is present', () => { @@ -87,7 +82,6 @@ describe('LabelsSelect', () => { labels: mockScopedLabels, issueUpdateURL: mockUrl, enableScopedLabels: true, - scopedLabelsDocumentationLink: 'docs-link', }), ); }); @@ -106,14 +100,6 @@ describe('LabelsSelect', () => { expect($labelEl.find('a').attr('data-html')).toBe('true'); }); - it('generated label item template has question icon', () => { - expect($labelEl.find('i.fa-question-circle')).toHaveLength(1); - }); - - it('generated label item template has gl-label-icon class', () => { - expect($labelEl.find('.gl-label-icon')).toHaveLength(1); - }); - it('generated label item template has correct label styles', () => { expect($labelEl.find('span.gl-label-text').attr('style')).toBe( `background-color: ${label.color}; color: ${label.text_color};`, @@ -141,7 +127,6 @@ describe('LabelsSelect', () => { labels: mockScopedLabels2, issueUpdateURL: mockUrl, enableScopedLabels: true, - scopedLabelsDocumentationLink: 'docs-link', }), ); }); diff --git a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap index 620ed58bde4..2179e7b4ab5 100644 --- a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap +++ b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap @@ -13,7 +13,7 @@ exports[`AlertWidget Alert firing displays a warning icon and matches snapshot 1 /> <span - class="text-truncate gl-pl-1" + class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me" > Firing: alert-label > 42 @@ -35,7 +35,7 @@ exports[`AlertWidget Alert not firing displays a warning icon and matches snapsh /> <span - class="text-truncate gl-pl-1" + class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me" > alert-label > 42 </span> diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js index a863cddbaee..e50771385dc 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js @@ -38,7 +38,6 @@ export const mockConfig = { labelsFetchPath: '/gitlab-org/my-project/-/labels.json', labelsManagePath: '/gitlab-org/my-project/-/labels', labelsFilterBasePath: '/gitlab-org/my-project/issues', - scopedLabelsDocumentationPath: '/help/user/project/labels.md#scoped-labels-premium', }; export const mockSuggestedColors = { diff --git a/spec/initializers/action_mailer_hooks_spec.rb b/spec/initializers/action_mailer_hooks_spec.rb index 20f96f7e16c..03eee09f737 100644 --- a/spec/initializers/action_mailer_hooks_spec.rb +++ b/spec/initializers/action_mailer_hooks_spec.rb @@ -6,6 +6,10 @@ describe 'ActionMailer hooks' do describe 'smime signature interceptor' do before do class_spy(ActionMailer::Base).as_stubbed_const + + # rspec-rails calls ActionMailer::Base.deliveries.clear after every test + # https://github.com/rspec/rspec-rails/commit/71c12388e2bad78aaeea6443a393ede78341a7a3 + allow(ActionMailer::Base).to receive_message_chain(:deliveries, :clear) end it 'is disabled by default' do diff --git a/spec/lib/gitlab/jira_import/issue_serializer_spec.rb b/spec/lib/gitlab/jira_import/issue_serializer_spec.rb index f24a83994f7..592974bf344 100644 --- a/spec/lib/gitlab/jira_import/issue_serializer_spec.rb +++ b/spec/lib/gitlab/jira_import/issue_serializer_spec.rb @@ -9,6 +9,7 @@ describe Gitlab::JiraImport::IssueSerializer do let_it_be(:project_label) { create(:label, project: project, title: 'bug') } let_it_be(:other_project_label) { create(:label, project: project, title: 'feature') } let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') } + let_it_be(:current_user) { create(:user) } let(:iid) { 5 } let(:key) { 'PROJECT-5' } @@ -51,7 +52,7 @@ describe Gitlab::JiraImport::IssueSerializer do let(:params) { { iid: iid } } - subject { described_class.new(project, jira_issue, params).execute } + subject { described_class.new(project, jira_issue, current_user.id, params).execute } let(:expected_description) do <<~MD @@ -76,7 +77,7 @@ describe Gitlab::JiraImport::IssueSerializer do state_id: 1, updated_at: updated_at, created_at: created_at, - author_id: project.creator_id, + author_id: current_user.id, assignee_ids: nil, label_ids: [project_label.id, group_label.id] + Label.reorder(id: :asc).last(2).pluck(:id) ) @@ -122,13 +123,13 @@ describe Gitlab::JiraImport::IssueSerializer do let!(:user) { create(:user, email: 'reporter@example.com') } it 'defaults the issue author to project creator' do - expect(subject[:author_id]).to eq(project.creator.id) + expect(subject[:author_id]).to eq(current_user.id) end end context 'when reporter does not map to a GitLab user' do it 'defaults the issue author to project creator' do - expect(subject[:author_id]).to eq(project.creator.id) + expect(subject[:author_id]).to eq(current_user.id) end end @@ -136,7 +137,7 @@ describe Gitlab::JiraImport::IssueSerializer do let(:reporter) { nil } it 'defaults the issue author to project creator' do - expect(subject[:author_id]).to eq(project.creator.id) + expect(subject[:author_id]).to eq(current_user.id) end end @@ -144,7 +145,7 @@ describe Gitlab::JiraImport::IssueSerializer do let(:reporter) { double(name: 'Reporter', emailAddress: nil) } it 'defaults the issue author to project creator' do - expect(subject[:author_id]).to eq(project.creator.id) + expect(subject[:author_id]).to eq(current_user.id) end end end diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb index a7cf19a9a5b..6cf06c20e19 100644 --- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb +++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb @@ -6,8 +6,9 @@ describe Gitlab::JiraImport::IssuesImporter do include JiraServiceHelper let_it_be(:user) { create(:user) } + let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:jira_import) { create(:jira_import_state, project: project) } + let_it_be(:jira_import) { create(:jira_import_state, project: project, user: current_user) } let_it_be(:jira_service) { create(:jira_service, project: project) } subject { described_class.new(project) } @@ -39,8 +40,16 @@ describe Gitlab::JiraImport::IssuesImporter do context 'with results returned' do JiraIssue = Struct.new(:id) - let_it_be(:jira_issue1) { JiraIssue.new(1) } - let_it_be(:jira_issue2) { JiraIssue.new(2) } + let_it_be(:jira_issues) { [JiraIssue.new(1), JiraIssue.new(2)] } + + def mock_issue_serializer(count) + serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' }) + + count.times do |i| + expect(Gitlab::JiraImport::IssueSerializer).to receive(:new) + .with(project, jira_issues[i], current_user.id, { iid: i + 1 }).and_return(serializer) + end + end context 'when single page of results is returned' do before do @@ -48,13 +57,11 @@ describe Gitlab::JiraImport::IssuesImporter do end it 'schedules 2 import jobs' do - expect(subject).to receive(:fetch_issues).and_return([jira_issue1, jira_issue2]) + expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1]]) expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).twice expect(Gitlab::Cache::Import::Caching).to receive(:set_add).twice.and_call_original expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.and_call_original - allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance| - allow(instance).to receive(:execute).and_return({ key: 'data' }) - end + mock_issue_serializer(2) job_waiter = subject.execute @@ -69,13 +76,11 @@ describe Gitlab::JiraImport::IssuesImporter do end it 'schedules 3 import jobs' do - expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issue1, jira_issue2]) + expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1]]) expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).twice.times expect(Gitlab::Cache::Import::Caching).to receive(:set_add).twice.times.and_call_original expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.times.and_call_original - allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance| - allow(instance).to receive(:execute).and_return({ key: 'data' }) - end + mock_issue_serializer(2) job_waiter = subject.execute @@ -90,13 +95,11 @@ describe Gitlab::JiraImport::IssuesImporter do end it 'schedules 2 import jobs' do - expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issue1, jira_issue1]) + expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[0]]) expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).once expect(Gitlab::Cache::Import::Caching).to receive(:set_add).once.and_call_original expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.times.and_call_original - allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance| - allow(instance).to receive(:execute).and_return({ key: 'data' }) - end + mock_issue_serializer(1) job_waiter = subject.execute diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb index f4620e54979..8115fbca5e0 100644 --- a/spec/lib/gitlab_danger_spec.rb +++ b/spec/lib/gitlab_danger_spec.rb @@ -9,7 +9,7 @@ describe GitlabDanger do describe '.local_warning_message' do it 'returns an informational message with rules that can run' do - expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry') + expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry, utility_css') end end diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb index cbeb45b92ff..13448ea759b 100644 --- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb +++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' require_relative 'shared_processing_service.rb' +# require_relative 'shared_processing_service_tests_with_yaml.rb' describe Ci::PipelineProcessing::AtomicProcessingService do before do @@ -9,6 +10,9 @@ describe Ci::PipelineProcessing::AtomicProcessingService do end it_behaves_like 'Pipeline Processing Service' + # TODO: This needs to be enabled. There is a different behavior when using `needs` depending on + # a `manual` job. More info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29405#note_327520605 + # it_behaves_like 'Pipeline Processing Service Tests With Yaml' private diff --git a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb index 09b462b7600..d4fb03cf643 100644 --- a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb +++ b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb @@ -2,13 +2,16 @@ require 'spec_helper' require_relative 'shared_processing_service.rb' +require_relative 'shared_processing_service_tests_with_yaml.rb' describe Ci::PipelineProcessing::LegacyProcessingService do before do stub_feature_flags(ci_atomic_processing: false) + stub_feature_flags(ci_composite_status: false) end it_behaves_like 'Pipeline Processing Service' + it_behaves_like 'Pipeline Processing Service Tests With Yaml' private diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb new file mode 100644 index 00000000000..ec3c10b3bb5 --- /dev/null +++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +shared_context 'Pipeline Processing Service Tests With Yaml' do + where(:test_file_path) do + Dir.glob(Rails.root.join('spec/services/ci/pipeline_processing/test_cases/*.yml')) + end + + with_them do + let(:test_file) { YAML.load_file(test_file_path) } + + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline) } + + before do + stub_ci_pipeline_yaml_file(YAML.dump(test_file['config'])) + stub_not_protect_default_branch + project.add_developer(user) + end + + it 'follows transitions', :sidekiq_inline do + expect(pipeline).to be_persisted + check_expectation(test_file.dig('init', 'expect')) + + test_file['transitions'].each do |transition| + event_on_jobs(transition['event'], transition['jobs']) + check_expectation(transition['expect']) + end + end + + private + + def check_expectation(expectation) + expectation.each do |key, value| + case key + when 'pipeline' + expect(pipeline.reload.status).to eq(value) + when 'stages' + expect(pipeline.stages.pluck(:name, :status).to_h).to eq(value) + when 'jobs' + expect(pipeline.builds.latest.pluck(:name, :status).to_h).to eq(value) + end + end + end + + def event_on_jobs(event, job_names) + builds = pipeline.builds.latest.where(name: job_names).to_a + expect(builds.count).to eq(job_names.count) # ensure that we have the same counts + + builds.each { |build| build.public_send("#{event}!") } + end + end +end diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml new file mode 100644 index 00000000000..cfc456387ff --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml @@ -0,0 +1,47 @@ +config: + build: + stage: build + allow_failure: true + script: exit 1 + + test: + stage: test + when: on_failure + script: exit 0 + needs: [build] + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped + +# TODO: What is the real expected behavior here? +# Is `needs` keyword a requirement indicator or just a helper to build dependency tree? +# How should it behave `when: on_failure` with `needs`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml new file mode 100644 index 00000000000..e71ef194c5f --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml @@ -0,0 +1,39 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + needs: [build] + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: failed + stages: + build: failed + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml new file mode 100644 index 00000000000..40a80f6f53b --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml @@ -0,0 +1,39 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: failed + stages: + build: failed + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml new file mode 100644 index 00000000000..b0904a027f8 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml @@ -0,0 +1,43 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + when: always + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: running + stages: + build: failed + test: skipped + deploy: pending + jobs: + build: failed + test: skipped + deploy: pending + +# TODO: `test` is actually skipped, but we run `deploy`. Should we? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml new file mode 100644 index 00000000000..a133023b12d --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml @@ -0,0 +1,62 @@ +config: + build_1: + stage: build + script: exit 0 + + build_2: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + needs: [build_1, test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build_1: pending + build_2: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build_1] + expect: + pipeline: running + stages: + build: running + test: created + deploy: created + jobs: + build_1: success + build_2: pending + test: created + deploy: created + + - event: drop + jobs: [build_2] + expect: + pipeline: running + stages: + build: failed + test: skipped + deploy: pending + jobs: + build_1: success + build_2: failed + test: skipped + deploy: pending + +# TODO: should we run deploy? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml new file mode 100644 index 00000000000..4c676761e5c --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml @@ -0,0 +1,63 @@ +config: + build_1: + stage: build + script: exit 0 + + build_2: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + when: always + needs: [build_1, test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build_1: pending + build_2: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build_1] + expect: + pipeline: running + stages: + build: running + test: created + deploy: created + jobs: + build_1: success + build_2: pending + test: created + deploy: created + + - event: drop + jobs: [build_2] + expect: + pipeline: running + stages: + build: failed + test: skipped + deploy: pending + jobs: + build_1: success + build_2: failed + test: skipped + deploy: pending + +# TODO: what's the actual expected behavior here? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml new file mode 100644 index 00000000000..ea7046262c3 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml @@ -0,0 +1,40 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: failed + stages: + build: failed + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml new file mode 100644 index 00000000000..8860f565cc7 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml @@ -0,0 +1,35 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + when: always + script: exit 0 + needs: [build] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + jobs: + build: pending + test: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: running + stages: + build: failed + test: pending + jobs: + build: failed + test: pending + +# TODO: Should we run `test`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml new file mode 100644 index 00000000000..3fa5a8034a2 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml @@ -0,0 +1,35 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + when: on_failure + script: exit 0 + needs: [build] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + jobs: + build: pending + test: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: running + stages: + build: failed + test: pending + jobs: + build: failed + test: pending + +# TODO: Should we run `test`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml new file mode 100644 index 00000000000..700d4440802 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml @@ -0,0 +1,35 @@ +config: + build: + stage: build + script: exit 0 + + test: + stage: test + when: on_failure + script: exit 0 + needs: [build] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + jobs: + build: pending + test: created + +transitions: + - event: success + jobs: [build] + expect: + pipeline: success + stages: + build: success + test: skipped + jobs: + build: success + test: skipped + +# TODO: Should we run `test`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml new file mode 100644 index 00000000000..f324525bd56 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml @@ -0,0 +1,63 @@ +config: + build_1: + stage: build + script: exit 0 + + build_2: + stage: build + script: exit 0 + + test: + stage: test + script: exit 0 + when: on_failure + + deploy: + stage: deploy + script: exit 0 + needs: [build_1, test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build_1: pending + build_2: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build_1, build_2] + expect: + pipeline: running + stages: + build: success + test: skipped + deploy: pending + jobs: + build_1: success + build_2: success + test: skipped + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: success + jobs: + build_1: success + build_2: success + test: skipped + deploy: success + +# TODO: should we run deploy? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml new file mode 100644 index 00000000000..9986dbaa215 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml @@ -0,0 +1,64 @@ +config: + build_1: + stage: build + script: exit 0 + + build_2: + stage: build + script: exit 0 + + test: + stage: test + script: exit 0 + when: on_failure + + deploy: + stage: deploy + script: exit 0 + when: always + needs: [build_1, test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build_1: pending + build_2: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build_1, build_2] + expect: + pipeline: running + stages: + build: success + test: skipped + deploy: pending + jobs: + build_1: success + build_2: success + test: skipped + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: success + jobs: + build_1: success + build_2: success + test: skipped + deploy: success + +# TODO: should we run deploy? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml new file mode 100644 index 00000000000..8d4d9d403f1 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml @@ -0,0 +1,43 @@ +config: + test: + stage: test + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + test: pending + deploy: created + jobs: + test: pending + deploy: created + +transitions: + - event: drop + jobs: [test] + expect: + pipeline: pending + stages: + test: success + deploy: pending + jobs: + test: failed + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + test: success + deploy: success + jobs: + test: failed + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml new file mode 100644 index 00000000000..1a1412f2a11 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml @@ -0,0 +1,66 @@ +config: + test: + stage: test + when: manual + allow_failure: false + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: manual + stages: + test: manual + deploy: created + jobs: + test: manual + deploy: created + +transitions: + - event: enqueue + jobs: [test] + expect: + pipeline: manual + stages: + test: manual + deploy: created + jobs: + test: pending + deploy: created + + - event: run + jobs: [test] + expect: + pipeline: running + stages: + test: running + deploy: created + jobs: + test: running + deploy: created + + - event: success + jobs: [test] + expect: + pipeline: running + stages: + test: success + deploy: pending + jobs: + test: success + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + test: success + deploy: success + jobs: + test: success + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml new file mode 100644 index 00000000000..39545617926 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml @@ -0,0 +1,58 @@ +config: + test: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: created + stages: + test: skipped + deploy: created + jobs: + test: manual + deploy: created + +transitions: + - event: enqueue + jobs: [test] + expect: + pipeline: pending + stages: + test: running + deploy: created + jobs: + test: pending + deploy: created + + - event: run + jobs: [test] + expect: + pipeline: running + stages: + test: running + deploy: created + jobs: + test: running + deploy: created + + - event: drop + jobs: [test] + expect: + pipeline: running + stages: + test: success + deploy: pending + jobs: + test: failed + deploy: pending + +# TOOD: should we run deploy? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml new file mode 100644 index 00000000000..ba0a20f49a7 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml @@ -0,0 +1,27 @@ +config: + test: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + when: always + script: exit 0 + needs: [test] + +init: + expect: + pipeline: created + stages: + test: skipped + deploy: created + jobs: + test: manual + deploy: created + +transitions: [] + +# TODO: should we run `deploy`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml new file mode 100644 index 00000000000..0c6a5a7e364 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml @@ -0,0 +1,48 @@ +config: + test: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + when: on_failure + script: exit 0 + needs: [test] + +init: + expect: + pipeline: created + stages: + test: skipped + deploy: created + jobs: + test: manual + deploy: created + +transitions: + - event: enqueue + jobs: [test] + expect: + pipeline: pending + stages: + test: running + deploy: created + jobs: + test: pending + deploy: created + + - event: drop + jobs: [test] + expect: + pipeline: success + stages: + test: success + deploy: skipped + jobs: + test: failed + deploy: skipped + +# TODO: should we run `deploy`? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml new file mode 100644 index 00000000000..34073b92ccc --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml @@ -0,0 +1,42 @@ +config: + test1: + stage: test + script: exit 0 + + test2: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + needs: [test1, test2] + +init: + expect: + pipeline: pending + stages: + test: pending + deploy: created + jobs: + test1: pending + test2: manual + deploy: created + +transitions: + - event: success + jobs: [test1] + expect: + pipeline: running + stages: + test: success + deploy: created + jobs: + test1: success + test2: manual + deploy: created + +# TODO: should deploy run? +# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080 diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml new file mode 100644 index 00000000000..5ace621e89c --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml @@ -0,0 +1,66 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + when: on_failure + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: running + stages: + build: failed + test: pending + deploy: created + jobs: + build: failed + test: pending + deploy: created + + - event: success + jobs: [test] + expect: + pipeline: running + stages: + build: failed + test: success + deploy: pending + jobs: + build: failed + test: success + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: failed + stages: + build: failed + test: success + deploy: success + jobs: + build: failed + test: success + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml new file mode 100644 index 00000000000..19524cfd3e4 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml @@ -0,0 +1,40 @@ +config: + build: + stage: build + script: exit 0 + + test: + stage: test + when: on_failure + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + needs: [test] + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: skipped + jobs: + build: success + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml new file mode 100644 index 00000000000..3e081d4411b --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml @@ -0,0 +1,53 @@ +config: + build: + stage: build + allow_failure: true + script: exit 1 + + test: + stage: test + when: on_failure + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: pending + stages: + build: success + test: skipped + deploy: pending + jobs: + build: failed + test: skipped + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: success + jobs: + build: failed + test: skipped + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml new file mode 100644 index 00000000000..0618abf3524 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml @@ -0,0 +1,38 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: failed + stages: + build: failed + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml new file mode 100644 index 00000000000..362ac6e4239 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml @@ -0,0 +1,39 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: failed + stages: + build: failed + test: skipped + deploy: skipped + jobs: + build: failed + test: skipped + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml new file mode 100644 index 00000000000..d37288b2075 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml @@ -0,0 +1,65 @@ +config: + test: + stage: test + when: manual + allow_failure: false + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: manual + stages: + test: manual + deploy: created + jobs: + test: manual + deploy: created + +transitions: + - event: enqueue + jobs: [test] + expect: + pipeline: manual + stages: + test: manual + deploy: created + jobs: + test: pending + deploy: created + + - event: run + jobs: [test] + expect: + pipeline: running + stages: + test: running + deploy: created + jobs: + test: running + deploy: created + + - event: success + jobs: [test] + expect: + pipeline: running + stages: + test: success + deploy: pending + jobs: + test: success + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + test: success + deploy: success + jobs: + test: success + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml new file mode 100644 index 00000000000..bac339cc58d --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml @@ -0,0 +1,54 @@ +config: + test: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + test: skipped + deploy: pending + jobs: + test: manual + deploy: pending + +transitions: + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + test: skipped + deploy: success + jobs: + test: manual + deploy: success + + - event: enqueue + jobs: [test] + expect: + pipeline: running + stages: + test: running + deploy: success + jobs: + test: pending + deploy: success + + - event: drop + jobs: [test] + expect: + pipeline: success + stages: + test: success + deploy: success + jobs: + test: failed + deploy: success diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml new file mode 100644 index 00000000000..ab1b210848a --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml @@ -0,0 +1,44 @@ +config: + test: + stage: test + when: manual + allow_failure: true + script: exit 1 + + deploy: + stage: deploy + when: on_failure + script: exit 0 + +init: + expect: + pipeline: skipped + stages: + test: skipped + deploy: skipped + jobs: + test: manual + deploy: skipped + +transitions: + - event: enqueue + jobs: [test] + expect: + pipeline: pending + stages: + test: running + deploy: skipped + jobs: + test: pending + deploy: skipped + + - event: drop + jobs: [test] + expect: + pipeline: success + stages: + test: success + deploy: skipped + jobs: + test: failed + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml new file mode 100644 index 00000000000..1751cbb2023 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml @@ -0,0 +1,52 @@ +config: + build: + stage: build + script: exit 1 + + test: + stage: test + when: on_failure + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: drop + jobs: [build] + expect: + pipeline: running + stages: + build: failed + test: pending + deploy: created + jobs: + build: failed + test: pending + deploy: created + + - event: success + jobs: [test] + expect: + pipeline: failed + stages: + build: failed + test: success + deploy: skipped + jobs: + build: failed + test: success + deploy: skipped diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml new file mode 100644 index 00000000000..15afe1ce8e1 --- /dev/null +++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml @@ -0,0 +1,52 @@ +config: + build: + stage: build + script: exit 0 + + test: + stage: test + when: on_failure + script: exit 0 + + deploy: + stage: deploy + script: exit 0 + +init: + expect: + pipeline: pending + stages: + build: pending + test: created + deploy: created + jobs: + build: pending + test: created + deploy: created + +transitions: + - event: success + jobs: [build] + expect: + pipeline: running + stages: + build: success + test: skipped + deploy: pending + jobs: + build: success + test: skipped + deploy: pending + + - event: success + jobs: [deploy] + expect: + pipeline: success + stages: + build: success + test: skipped + deploy: success + jobs: + build: success + test: skipped + deploy: success diff --git a/spec/workers/project_export_worker_spec.rb b/spec/workers/project_export_worker_spec.rb index 373e7f32530..6adf9a1335f 100644 --- a/spec/workers/project_export_worker_spec.rb +++ b/spec/workers/project_export_worker_spec.rb @@ -17,14 +17,32 @@ describe ProjectExportWorker do context 'when it succeeds' do it 'calls the ExportService' do - expect_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute) + expect_next_instance_of(::Projects::ImportExport::ExportService) do |service| + expect(service).to receive(:execute) + end subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' }) end + context 'with measurement options provided' do + it 'calls the ExportService with measurement options' do + measurement_options = { measurement_enabled: true } + params = {} + after_export_strategy = { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' } + + expect_next_instance_of(::Projects::ImportExport::ExportService) do |service| + expect(service).to receive(:execute).with(instance_of(Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy), measurement_options) + end + + subject.perform(user.id, project.id, after_export_strategy, params, measurement_options) + end + end + context 'export job' do before do - allow_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute) + allow_next_instance_of(::Projects::ImportExport::ExportService) do |service| + allow(service).to receive(:execute) + end end it 'creates an export job record for the project' do |