diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-21 15:13:58 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-21 15:13:58 +0300 |
commit | c0a3d287c0d613cc439a31683d06dd70f3411f8c (patch) | |
tree | 67852660a05456dd7960453f33d7f60650a21cbc /spec | |
parent | 0cb932429fb8b8d93d677f0f375f527e9d9a4c9b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
42 files changed, 640 insertions, 439 deletions
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index f198a1f42e2..077e63b028d 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -82,6 +82,34 @@ RSpec.describe 'Editing file blob', :js do end end + context 'blob edit toolbar' do + toolbar_buttons = [ + "Add bold text", + "Add italic text", + "Add strikethrough text", + "Insert a quote", + "Insert code", + "Add a link", + "Add a bullet list", + "Add a numbered list", + "Add a checklist", + "Add a collapsible section", + "Add a table" + ] + + before do + visit project_edit_blob_path(project, tree_join(branch, readme_file_path)) + end + + it "has defined set of toolbar buttons" do + buttons = page.all('.file-buttons .md-header-toolbar button[type="button"]') + expect(buttons.length).to eq(toolbar_buttons.length) + toolbar_buttons.each_with_index do |button_title, i| + expect(buttons[i]['title']).to include(button_title) + end + end + end + context 'from blob file path' do before do visit project_blob_path(project, tree_join(branch, file_path)) diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js index 20ba23d56ff..89b5ad27690 100644 --- a/spec/frontend/editor/source_editor_instance_spec.js +++ b/spec/frontend/editor/source_editor_instance_spec.js @@ -160,7 +160,7 @@ describe('Source Editor Instance', () => { }); describe('public API', () => { - it.each(['use', 'unuse'], 'provides "%s" as public method by default', (method) => { + it.each(['use', 'unuse'])('provides "%s" as public method by default', (method) => { seInstance = new SourceEditorInstance(); expect(seInstance[method]).toBeDefined(); }); diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js index 3aa66644c19..4570aa33a6c 100644 --- a/spec/frontend/groups/components/group_item_spec.js +++ b/spec/frontend/groups/components/group_item_spec.js @@ -245,19 +245,14 @@ describe('GroupItemComponent', () => { expect(vm.$el.querySelector('.group-list-tree')).toBeDefined(); }); }); + describe('schema.org props', () => { describe('when showSchemaMarkup is disabled on the group', () => { - it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', (attr) => { + it.each(['itemprop', 'itemtype', 'itemscope'])('does not set %s', (attr) => { expect(wrapper.attributes(attr)).toBeUndefined(); }); - it.each( - ['.js-group-avatar', '.js-group-name', '.js-group-description'], - 'it does not set `itemprop` on sub-nodes', - (selector) => { - expect(wrapper.find(selector).attributes('itemprop')).toBeUndefined(); - }, - ); }); + describe('when group has microdata', () => { beforeEach(() => { const group = withMicrodata({ diff --git a/spec/frontend/members/components/table/member_action_buttons_spec.js b/spec/frontend/members/components/table/member_action_buttons_spec.js index f3f50bf620a..03cfc6ca0f6 100644 --- a/spec/frontend/members/components/table/member_action_buttons_spec.js +++ b/spec/frontend/members/components/table/member_action_buttons_spec.js @@ -27,7 +27,7 @@ describe('MemberActionButtons', () => { wrapper.destroy(); }); - test.each` + it.each` memberType | member | expectedComponent | expectedComponentName ${MEMBER_TYPES.user} | ${memberMock} | ${UserActionButtons} | ${'UserActionButtons'} ${MEMBER_TYPES.group} | ${group} | ${GroupActionButtons} | ${'GroupActionButtons'} diff --git a/spec/frontend/members/components/table/member_avatar_spec.js b/spec/frontend/members/components/table/member_avatar_spec.js index 35f82c28fc5..dc5c97f41df 100644 --- a/spec/frontend/members/components/table/member_avatar_spec.js +++ b/spec/frontend/members/components/table/member_avatar_spec.js @@ -22,7 +22,7 @@ describe('MemberList', () => { wrapper.destroy(); }); - test.each` + it.each` memberType | member | expectedComponent | expectedComponentName ${MEMBER_TYPES.user} | ${memberMock} | ${UserAvatar} | ${'UserAvatar'} ${MEMBER_TYPES.group} | ${group} | ${GroupAvatar} | ${'GroupAvatar'} diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js index fd56699602e..0b0140b0cdb 100644 --- a/spec/frontend/members/components/table/members_table_cell_spec.js +++ b/spec/frontend/members/components/table/members_table_cell_spec.js @@ -95,7 +95,7 @@ describe('MembersTableCell', () => { wrapper = null; }); - test.each` + it.each` member | expectedMemberType ${memberMock} | ${MEMBER_TYPES.user} ${group} | ${MEMBER_TYPES.group} diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js index 0271483801c..8bef2096a2a 100644 --- a/spec/frontend/members/utils_spec.js +++ b/spec/frontend/members/utils_spec.js @@ -89,7 +89,7 @@ describe('Members Utils', () => { }); describe('isGroup', () => { - test.each` + it.each` member | expected ${group} | ${true} ${memberMock} | ${false} @@ -99,7 +99,7 @@ describe('Members Utils', () => { }); describe('isDirectMember', () => { - test.each` + it.each` member | expected ${directMember} | ${true} ${inheritedMember} | ${false} @@ -109,7 +109,7 @@ describe('Members Utils', () => { }); describe('isCurrentUser', () => { - test.each` + it.each` currentUserId | expected ${IS_CURRENT_USER_ID} | ${true} ${IS_NOT_CURRENT_USER_ID} | ${false} @@ -119,7 +119,7 @@ describe('Members Utils', () => { }); describe('canRemove', () => { - test.each` + it.each` member | expected ${{ ...directMember, canRemove: true }} | ${true} ${{ ...inheritedMember, canRemove: true }} | ${false} @@ -130,7 +130,7 @@ describe('Members Utils', () => { }); describe('canResend', () => { - test.each` + it.each` member | expected ${invite} | ${true} ${{ ...invite, invite: { ...invite.invite, canResend: false } }} | ${false} @@ -140,7 +140,7 @@ describe('Members Utils', () => { }); describe('canUpdate', () => { - test.each` + it.each` member | currentUserId | expected ${{ ...directMember, canUpdate: true }} | ${IS_NOT_CURRENT_USER_ID} | ${true} ${{ ...directMember, canUpdate: true }} | ${IS_CURRENT_USER_ID} | ${false} diff --git a/spec/frontend/monitoring/requests/index_spec.js b/spec/frontend/monitoring/requests/index_spec.js index 03bf5d70153..6f9af911a9f 100644 --- a/spec/frontend/monitoring/requests/index_spec.js +++ b/spec/frontend/monitoring/requests/index_spec.js @@ -129,7 +129,7 @@ describe('monitoring metrics_requests', () => { }); }); - test.each` + it.each` code | reason ${statusCodes.BAD_REQUEST} | ${'Parameters are missing or incorrect'} ${statusCodes.UNPROCESSABLE_ENTITY} | ${"Expression can't be executed"} diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js index 31975052077..6c6c3d6b90f 100644 --- a/spec/frontend/monitoring/utils_spec.js +++ b/spec/frontend/monitoring/utils_spec.js @@ -290,7 +290,7 @@ describe('monitoring/utils', () => { expect(() => expandedPanelPayloadFromUrl(metricsDashboardViewModel, search)).toThrow(); }); - test.each` + it.each` group | title | yLabel | missingField ${'NOT_A_GROUP'} | ${title} | ${yLabel} | ${'group'} ${group} | ${'NOT_A_TITLE'} | ${yLabel} | ${'title'} @@ -367,7 +367,7 @@ describe('monitoring/utils', () => { ], }; - [ + it.each([ { input: { metrics: undefined }, output: {}, @@ -393,12 +393,10 @@ describe('monitoring/utils', () => { output: multipleMetricExpected, testCase: 'barChartsDataParser returns multiple series object with multiple metrics', }, - ].forEach(({ input, output, testCase }) => { - it(testCase, () => { - expect(monitoringUtils.barChartsDataParser(input.metrics)).toEqual( - expect.objectContaining(output), - ); - }); + ])('$testCase', ({ input, output }) => { + expect(monitoringUtils.barChartsDataParser(input.metrics)).toEqual( + expect.objectContaining(output), + ); }); }); diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js index 8f6f4d8cff9..f0347ad19ac 100644 --- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js +++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js @@ -360,7 +360,7 @@ describe('Pipeline editor branch switcher', () => { }); describe('loading icon', () => { - test.each` + it.each` isQueryLoading | isRendered ${true} | ${true} ${false} | ${false} diff --git a/spec/frontend/token_access/token_access_spec.js b/spec/frontend/token_access/token_access_spec.js index 024e7dfff8c..e6aef41cc8b 100644 --- a/spec/frontend/token_access/token_access_spec.js +++ b/spec/frontend/token_access/token_access_spec.js @@ -40,7 +40,7 @@ describe('TokenAccess component', () => { const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findAddProjectBtn = () => wrapper.findByRole('button', { name: 'Add project' }); const findRemoveProjectBtn = () => wrapper.findByRole('button', { name: 'Remove access' }); - const findTokenSection = () => wrapper.find('[data-testid="token-section"]'); + const findTokenDisabledAlert = () => wrapper.findByTestId('token-disabled-alert'); const createMockApolloProvider = (requestHandlers) => { return createMockApollo(requestHandlers); @@ -80,7 +80,7 @@ describe('TokenAccess component', () => { }); describe('toggle', () => { - it('the toggle should be enabled and the token section should show', async () => { + it('the toggle is on and the alert is hidden', async () => { createComponent([ [getCIJobTokenScopeQuery, enabledJobTokenScopeHandler], [getProjectsWithCIJobTokenScopeQuery, getProjectsWithScope], @@ -89,10 +89,10 @@ describe('TokenAccess component', () => { await waitForPromises(); expect(findToggle().props('value')).toBe(true); - expect(findTokenSection().exists()).toBe(true); + expect(findTokenDisabledAlert().exists()).toBe(false); }); - it('the toggle should be disabled and the token section should show', async () => { + it('the toggle is off and the alert is visible', async () => { createComponent([ [getCIJobTokenScopeQuery, disabledJobTokenScopeHandler], [getProjectsWithCIJobTokenScopeQuery, getProjectsWithScope], @@ -101,7 +101,7 @@ describe('TokenAccess component', () => { await waitForPromises(); expect(findToggle().props('value')).toBe(false); - expect(findTokenSection().exists()).toBe(true); + expect(findTokenDisabledAlert().exists()).toBe(true); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js index 1900b53ac11..d85574262fe 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js @@ -15,9 +15,9 @@ describe('Merge request widget merge checks failed state component', () => { }); it.each` - mrState | displayText - ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'} - ${{ blockingMergeRequests: { total_count: 1 } }} | ${'blockingMergeRequests'} + mrState | displayText + ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'} + ${{ detailedMergeStatus: 'BLOCKED_STATUS' }} | ${'blockingMergeRequests'} `('display $displayText text for $mrState', ({ mrState, displayText }) => { factory({ mr: mrState }); diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js index d5619d4996d..bd158d59d74 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js @@ -6,31 +6,42 @@ import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_i describe('PipelineFailed', () => { let wrapper; - const createComponent = () => { + const createComponent = (mr = {}) => { wrapper = shallowMount(PipelineFailed, { + propsData: { + mr, + }, stubs: { GlSprintf, }, }); }; - beforeEach(() => { - createComponent(); - }); - afterEach(() => { wrapper.destroy(); wrapper = null; }); it('should render error status icon', () => { + createComponent(); + expect(wrapper.findComponent(StatusIcon).exists()).toBe(true); expect(wrapper.findComponent(StatusIcon).props().status).toBe('failed'); }); it('should render error message with a disabled merge button', () => { + createComponent(); + expect(wrapper.text()).toContain('Merge blocked: pipeline must succeed.'); expect(wrapper.text()).toContain('Push a commit that fixes the failure'); expect(wrapper.findComponent(GlLink).text()).toContain('learn about other solutions'); }); + + it('should render pipeline blocked message', () => { + createComponent({ isPipelineBlocked: true }); + + expect(wrapper.text()).toContain( + "Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.", + ); + }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js index 9a6bf66909e..0aced0eea65 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -300,6 +300,48 @@ describe('ReadyToMerge', () => { expect(wrapper.vm.isMergeButtonDisabled).toBe(true); }); }); + + describe('sourceBranchDeletedText', () => { + const should = 'Source branch will be deleted.'; + const shouldNot = 'Source branch will not be deleted.'; + const did = 'Deleted the source branch.'; + const didNot = 'Did not delete the source branch.'; + const scenarios = [ + "the MR hasn't merged yet, and the backend-provided value expects to delete the branch", + "the MR hasn't merged yet, and the backend-provided value expects to leave the branch", + "the MR hasn't merged yet, and the backend-provided value is a non-boolean falsey value", + "the MR hasn't merged yet, and the backend-provided value is a non-boolean truthy value", + 'the MR has merged, and the backend reports that the branch has been removed', + 'the MR has been merged, and the backend reports that the branch has not been removed', + 'the MR has been merged, and the backend reports a non-boolean falsey value', + 'the MR has been merged, and the backend reports a non-boolean truthy value', + ]; + + it.each` + describe | premerge | mrShould | mrRemoved | output + ${scenarios[0]} | ${true} | ${true} | ${null} | ${should} + ${scenarios[1]} | ${true} | ${false} | ${null} | ${shouldNot} + ${scenarios[2]} | ${true} | ${null} | ${null} | ${shouldNot} + ${scenarios[3]} | ${true} | ${'yeah'} | ${null} | ${should} + ${scenarios[4]} | ${false} | ${null} | ${true} | ${did} + ${scenarios[5]} | ${false} | ${null} | ${false} | ${didNot} + ${scenarios[6]} | ${false} | ${null} | ${null} | ${didNot} + ${scenarios[7]} | ${false} | ${null} | ${'yep'} | ${did} + `( + 'in the case that $describe, returns "$output"', + ({ premerge, mrShould, mrRemoved, output }) => { + createComponent({ + mr: { + state: !premerge ? 'merged' : 'literally-anything-else', + shouldRemoveSourceBranch: mrShould, + sourceBranchRemoved: mrRemoved, + }, + }); + + expect(wrapper.vm.sourceBranchDeletedText).toBe(output); + }, + ); + }); }); describe('methods', () => { diff --git a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js index cc894f94f80..b42abcec3eb 100644 --- a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js @@ -771,34 +771,40 @@ describe('MrWidgetOptions', () => { }); describe('security widget', () => { - describe.each` - context | hasPipeline | shouldRender - ${'there is a pipeline'} | ${true} | ${true} - ${'no pipeline'} | ${false} | ${false} - `('given $context', ({ hasPipeline, shouldRender }) => { - beforeEach(() => { - const mrData = { - ...mockData, - ...(hasPipeline ? {} : { pipeline: null }), - }; + const setup = async (hasPipeline) => { + const mrData = { + ...mockData, + ...(hasPipeline ? {} : { pipeline: null }), + }; - // Override top-level mocked requests, which always use a fresh copy of - // mockData, which always includes the full pipeline object. - mock.onGet(mockData.merge_request_widget_path).reply(() => [200, mrData]); - mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, mrData]); - - return createComponent(mrData, { - apolloProvider: createMockApollo([ - [ - securityReportMergeRequestDownloadPathsQuery, - async () => ({ data: securityReportMergeRequestDownloadPathsQueryResponse }), - ], - ]), - }); + // Override top-level mocked requests, which always use a fresh copy of + // mockData, which always includes the full pipeline object. + mock.onGet(mockData.merge_request_widget_path).reply(() => [200, mrData]); + mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, mrData]); + + return createComponent(mrData, { + apolloProvider: createMockApollo([ + [ + securityReportMergeRequestDownloadPathsQuery, + async () => ({ data: securityReportMergeRequestDownloadPathsQueryResponse }), + ], + ]), }); + }; + + describe('with a pipeline', () => { + it('renders the security widget', async () => { + await setup(true); + + expect(findSecurityMrWidget().exists()).toBe(true); + }); + }); + + describe('with no pipeline', () => { + it('does not render the security widget', async () => { + await setup(false); - it(shouldRender ? 'renders' : 'does not render', () => { - expect(findSecurityMrWidget().exists()).toBe(shouldRender); + expect(findSecurityMrWidget().exists()).toBe(false); }); }); }); diff --git a/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js b/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js index 0246a8d4b0f..88d9d0b4cff 100644 --- a/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js +++ b/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js @@ -16,12 +16,13 @@ describe('getStateKey', () => { commitsCount: 2, hasConflicts: false, draft: false, + detailedMergeStatus: null, }; const bound = getStateKey.bind(context); expect(bound()).toEqual(null); - context.canBeMerged = true; + context.detailedMergeStatus = 'MERGEABLE'; expect(bound()).toEqual('readyToMerge'); @@ -36,21 +37,15 @@ describe('getStateKey', () => { expect(bound()).toEqual('shaMismatch'); context.canMerge = false; - context.isPipelineBlocked = true; - - expect(bound()).toEqual('pipelineBlocked'); - - context.hasMergeableDiscussionsState = true; - context.autoMergeEnabled = false; + context.detailedMergeStatus = 'DISCUSSIONS_NOT_RESOLVED'; expect(bound()).toEqual('unresolvedDiscussions'); - context.draft = true; + context.detailedMergeStatus = 'DRAFT_STATUS'; expect(bound()).toEqual('draft'); - context.onlyAllowMergeIfPipelineSucceeds = true; - context.isPipelineFailed = true; + context.detailedMergeStatus = 'CI_MUST_PASS'; expect(bound()).toEqual('pipelineFailed'); @@ -62,7 +57,7 @@ describe('getStateKey', () => { expect(bound()).toEqual('conflicts'); - context.mergeStatus = 'unchecked'; + context.detailedMergeStatus = 'CHECKING'; expect(bound()).toEqual('checking'); diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js index 10eacff630d..7a8f94b3746 100644 --- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js +++ b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js @@ -121,7 +121,7 @@ describe('date time picker lib', () => { const utcResult = '2019-09-08T01:01:01Z'; const localResult = '2019-09-08T08:01:01Z'; - test.each` + it.each` val | locatTimezone | utc | result ${value} | ${'UTC'} | ${undefined} | ${utcResult} ${value} | ${'UTC'} | ${false} | ${utcResult} @@ -167,7 +167,7 @@ describe('date time picker lib', () => { const utcResult = '2019-09-08 08:01:01'; const localResult = '2019-09-08 01:01:01'; - test.each` + it.each` val | locatTimezone | utc | result ${value} | ${'UTC'} | ${undefined} | ${utcResult} ${value} | ${'UTC'} | ${false} | ${utcResult} diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index 1703727db21..c75e9caa77a 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -51,12 +51,13 @@ RSpec.describe ApplicationSettingsHelper do end it 'contains rate limit parameters' do - expect(helper.visible_attributes).to include(*%i( - issues_create_limit notes_create_limit project_export_limit - project_download_export_limit project_export_limit project_import_limit - raw_blob_request_limit group_export_limit group_download_export_limit - group_import_limit users_get_by_id_limit search_rate_limit search_rate_limit_unauthenticated - )) + expect(helper.visible_attributes).to include( + *%i( + issues_create_limit notes_create_limit project_export_limit + project_download_export_limit project_export_limit project_import_limit + raw_blob_request_limit group_export_limit group_download_export_limit + group_import_limit users_get_by_id_limit search_rate_limit search_rate_limit_unauthenticated + )) end context 'when GitLab.com' do @@ -233,23 +234,24 @@ RSpec.describe ApplicationSettingsHelper do end it 'returns available formats correctly' do - expect(helper.kroki_available_formats).to eq([ - { - name: 'kroki_formats_blockdiag', - label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)', - value: true - }, - { - name: 'kroki_formats_bpmn', - label: 'BPMN', - value: false - }, - { - name: 'kroki_formats_excalidraw', - label: 'Excalidraw', - value: false - } - ]) + expect(helper.kroki_available_formats).to eq( + [ + { + name: 'kroki_formats_blockdiag', + label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)', + value: true + }, + { + name: 'kroki_formats_bpmn', + label: 'BPMN', + value: false + }, + { + name: 'kroki_formats_excalidraw', + label: 'Excalidraw', + value: false + } + ]) end end diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb index 0cc53da98b2..27738f73ea5 100644 --- a/spec/helpers/commits_helper_spec.rb +++ b/spec/helpers/commits_helper_spec.rb @@ -227,10 +227,11 @@ RSpec.describe CommitsHelper do end it 'returns data for cherry picking into a project' do - expect(helper.cherry_pick_projects_data(forked_project)).to match_array([ - { id: project.id.to_s, name: project.full_path, refsUrl: refs_project_path(project) }, - { id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) } - ]) + expect(helper.cherry_pick_projects_data(forked_project)).to match_array( + [ + { id: project.id.to_s, name: project.full_path, refsUrl: refs_project_path(project) }, + { id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) } + ]) end end diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb index bd8af384d40..b32a99fe989 100644 --- a/spec/helpers/issuables_description_templates_helper_spec.rb +++ b/spec/helpers/issuables_description_templates_helper_spec.rb @@ -64,12 +64,12 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do it 'returns project templates' do value = [ - "", - [ - { name: "another_issue_template", id: "another_issue_template", project_id: project.id }, - { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id } - ] - ].to_json + "", + [ + { name: "another_issue_template", id: "another_issue_template", project_id: project.id }, + { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id } + ] + ].to_json expect(helper.available_service_desk_templates_for(@project)).to eq(value) end end diff --git a/spec/helpers/listbox_helper_spec.rb b/spec/helpers/listbox_helper_spec.rb index 0a27aa04b37..cba00b43ae5 100644 --- a/spec/helpers/listbox_helper_spec.rb +++ b/spec/helpers/listbox_helper_spec.rb @@ -26,13 +26,14 @@ RSpec.describe ListboxHelper do describe '#gl_redirect_listbox_tag' do it 'creates root element with expected classes' do - expect(subject.classes).to include(*%w[ - dropdown - b-dropdown - gl-new-dropdown - btn-group - js-redirect-listbox - ]) + expect(subject.classes).to include( + *%w[ + dropdown + b-dropdown + gl-new-dropdown + btn-group + js-redirect-listbox + ]) end it 'sets data attributes for items and selected' do @@ -41,14 +42,15 @@ RSpec.describe ListboxHelper do end it 'adds styled button' do - expect(subject.at_css('button').classes).to include(*%w[ - btn - dropdown-toggle - btn-default - btn-md - gl-button - gl-dropdown-toggle - ]) + expect(subject.at_css('button').classes).to include( + *%w[ + btn + dropdown-toggle + btn-default + btn-md + gl-button + gl-dropdown-toggle + ]) end it 'sets button text to selected item' do diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index 617a796781e..c2c78be6a0f 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -204,11 +204,12 @@ RSpec.describe UsersHelper do badges = helper.user_badges_in_admin_section(user) - expect(badges).to match_array([ - { text: s_("AdminUsers|Blocked"), variant: "danger" }, - { text: s_("AdminUsers|Admin"), variant: "success" }, - { text: s_("AdminUsers|External"), variant: "secondary" } - ]) + expect(badges).to match_array( + [ + { text: s_("AdminUsers|Blocked"), variant: "danger" }, + { text: s_("AdminUsers|Admin"), variant: "success" }, + { text: s_("AdminUsers|External"), variant: "secondary" } + ]) end end diff --git a/spec/lib/api/helpers/merge_requests_helpers_spec.rb b/spec/lib/api/helpers/merge_requests_helpers_spec.rb index 1d68b7985f1..80810133469 100644 --- a/spec/lib/api/helpers/merge_requests_helpers_spec.rb +++ b/spec/lib/api/helpers/merge_requests_helpers_spec.rb @@ -25,9 +25,7 @@ RSpec.describe API::Helpers::MergeRequestsHelpers do context 'when merge request is invalid' do before do allow(merge_request).to receive(:valid?).and_return(false) - allow(helper).to receive_messages([ - :unprocessable_entity!, :conflict!, :render_validation_error! - ]) + allow(helper).to receive_messages([:unprocessable_entity!, :conflict!, :render_validation_error!]) end API::Helpers::MergeRequestsHelpers::UNPROCESSABLE_ERROR_KEYS.each do |error_key| diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb index c342a831d62..12cdb5cfb95 100644 --- a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb @@ -309,11 +309,12 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter do it 'links to valid references' do doc = reference_filter("See #{references}") - expect(doc.css('a').map { |a| a.attr('href') }).to match_array([ - urls.project_issues_url(project, label_name: bug.name), - urls.project_issues_url(project, label_name: feature_proposal.name), - urls.project_issues_url(project, label_name: technical_debt.name) - ]) + expect(doc.css('a').map { |a| a.attr('href') }).to match_array( + [ + urls.project_issues_url(project, label_name: bug.name), + urls.project_issues_url(project, label_name: feature_proposal.name), + urls.project_issues_url(project, label_name: technical_debt.name) + ]) expect(doc.text).to eq 'See bug, feature proposal, technical debt' end end @@ -324,11 +325,12 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter do it 'links to valid references' do doc = reference_filter("See #{references}") - expect(doc.css('a').map { |a| a.attr('href') }).to match_array([ - urls.project_issues_url(project, label_name: bug.name), - urls.project_issues_url(project, label_name: feature_proposal.name), - urls.project_issues_url(project, label_name: technical_debt.name) - ]) + expect(doc.css('a').map { |a| a.attr('href') }).to match_array( + [ + urls.project_issues_url(project, label_name: bug.name), + urls.project_issues_url(project, label_name: feature_proposal.name), + urls.project_issues_url(project, label_name: technical_debt.name) + ]) expect(doc.text).to eq 'See bug feature proposal technical debt' end end diff --git a/spec/lib/csv_builders/stream_spec.rb b/spec/lib/csv_builders/stream_spec.rb index 204baf965d0..7df55fe4230 100644 --- a/spec/lib/csv_builders/stream_spec.rb +++ b/spec/lib/csv_builders/stream_spec.rb @@ -25,18 +25,20 @@ RSpec.describe CsvBuilders::Stream do end it 'returns all rows up to default max value' do - expect(builder.render.to_a).to eq([ - "Title,Description\n", - "Added salt,A teaspoon\n", - "Added sugar,Just a pinch\n" - ]) + expect(builder.render.to_a).to eq( + [ + "Title,Description\n", + "Added salt,A teaspoon\n", + "Added sugar,Just a pinch\n" + ]) end it 'truncates to max rows' do - expect(builder.render(1).to_a).to eq([ - "Title,Description\n", - "Added salt,A teaspoon\n" - ]) + expect(builder.render(1).to_a).to eq( + [ + "Title,Description\n", + "Added salt,A teaspoon\n" + ]) end end end diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb index 1108d26b2a9..0c5d587d8e8 100644 --- a/spec/lib/expand_variables_spec.rb +++ b/spec/lib/expand_variables_spec.rb @@ -87,9 +87,7 @@ RSpec.describe ExpandVariables do "simple expansion using Collection": { value: 'key$variable', result: 'keyvalue', - variables: Gitlab::Ci::Variables::Collection.new([ - { key: 'variable', value: 'value' } - ]) + variables: Gitlab::Ci::Variables::Collection.new([{ key: 'variable', value: 'value' }]) } } end diff --git a/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb b/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb index 34c5bd6c6ae..06438f8497d 100644 --- a/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb +++ b/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb @@ -23,10 +23,11 @@ RSpec.describe Gitlab::Analytics::UsageTrends::WorkersArgumentBuilder do subject { described_class.new(measurement_identifiers: measurement_identifiers, recorded_at: recorded_at).execute } it 'returns worker arguments' do - expect(subject).to eq([ - [projects_measurement_identifier, project_1.id, project_3.id, recorded_at], - [users_measurement_identifier, user_1.id, user_1.id, recorded_at] - ]) + expect(subject).to eq( + [ + [projects_measurement_identifier, project_1.id, project_3.id, recorded_at], + [users_measurement_identifier, user_1.id, user_1.id, recorded_at] + ]) end context 'when bogus measurement identifiers are given' do @@ -36,10 +37,11 @@ RSpec.describe Gitlab::Analytics::UsageTrends::WorkersArgumentBuilder do end it 'skips bogus measurement identifiers' do - expect(subject).to eq([ - [projects_measurement_identifier, project_1.id, project_3.id, recorded_at], - [users_measurement_identifier, user_1.id, user_1.id, recorded_at] - ]) + expect(subject).to eq( + [ + [projects_measurement_identifier, project_1.id, project_3.id, recorded_at], + [users_measurement_identifier, user_1.id, user_1.id, recorded_at] + ]) end end diff --git a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb index d8a7ec775dd..e6588644b4f 100644 --- a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb +++ b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb @@ -7,13 +7,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat let(:integrations) { table(:integrations) } let(:namespaced_integrations) do - Set.new(%w[ - Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog - Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost - MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker - Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao - Github GitlabSlackApplication - ]).freeze + Set.new( + %w[ + Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog + Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost + MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker + Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao + Github GitlabSlackApplication + ]).freeze end before do @@ -40,13 +41,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat expect(queries.count).to be(16) expect(queries.log.grep(/^SELECT/).size).to be(11) expect(queries.log.grep(/^UPDATE/).size).to be(5) - expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq([ - 'WHERE integrations.id BETWEEN 2 AND 3', - 'WHERE integrations.id BETWEEN 4 AND 5', - 'WHERE integrations.id BETWEEN 6 AND 7', - 'WHERE integrations.id BETWEEN 8 AND 9', - 'WHERE integrations.id BETWEEN 10 AND 10' - ]) + expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq( + [ + 'WHERE integrations.id BETWEEN 2 AND 3', + 'WHERE integrations.id BETWEEN 4 AND 5', + 'WHERE integrations.id BETWEEN 6 AND 7', + 'WHERE integrations.id BETWEEN 8 AND 9', + 'WHERE integrations.id BETWEEN 10 AND 10' + ]) expect(integrations.where(id: 2..10).pluck(:type, :type_new)).to contain_exactly( ['AssemblaService', 'Integrations::Assembla'], diff --git a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb index 8a3671b2e53..dd202acc372 100644 --- a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb +++ b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb @@ -40,23 +40,26 @@ RSpec.describe Gitlab::BackgroundMigration::CleanupOrphanedLfsObjectsProjects, s it 'lfs_objects_projects without an existing lfs object or project are removed' do subject.perform(without_object1.id, without_object3.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3, - without_project1, without_project2, without_project_and_object - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3, + without_project1, without_project2, without_project_and_object + ]) subject.perform(with_project_and_object1.id, with_project_and_object3.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3, - without_project1, without_project2, without_project_and_object - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3, + without_project1, without_project2, without_project_and_object + ]) subject.perform(without_project1.id, without_project_and_object.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3 - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3 + ]) expect(lfs_objects.ids).to contain_exactly(lfs_object.id, another_lfs_object.id) expect(projects.ids).to contain_exactly(project.id, another_project.id) diff --git a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb index 31b6ee0c7cd..c3ae2cc060c 100644 --- a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb @@ -79,10 +79,11 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers, it 'produces a union of the given queries' do alice = commit_users.create!(name: 'Alice', email: 'alice@example.com') bob = commit_users.create!(name: 'Bob', email: 'bob@example.com') - users = commit_users.union([ - commit_users.where(name: 'Alice').to_sql, - commit_users.where(name: 'Bob').to_sql - ]) + users = commit_users.union( + [ + commit_users.where(name: 'Alice').to_sql, + commit_users.where(name: 'Bob').to_sql + ]) expect(users).to include(alice) expect(users).to include(bob) diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb index a609227be05..29cc4f34f6d 100644 --- a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb +++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb @@ -246,9 +246,15 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence end it 'drops duplicates and related records', :aggregate_failures do - expect(vulnerability_findings.pluck(:id)).to match_array([ - finding_with_correct_uuid.id, finding_with_incorrect_uuid.id, finding_with_correct_uuid2.id, finding_with_incorrect_uuid2.id, finding_with_incorrect_uuid3.id, duplicate_not_in_the_same_batch.id - ]) + expect(vulnerability_findings.pluck(:id)).to match_array( + [ + finding_with_correct_uuid.id, + finding_with_incorrect_uuid.id, + finding_with_correct_uuid2.id, + finding_with_incorrect_uuid2.id, + finding_with_incorrect_uuid3.id, + duplicate_not_in_the_same_batch.id + ]) expect { subject }.to change(vulnerability_finding_pipelines, :count).from(16).to(8) .and change(vulnerability_findings, :count).from(6).to(3) @@ -306,7 +312,8 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence it 'retries the recalculation' do subject - expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding).to have_received(:find_by).with(uuid: uuid).once + expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding) + .to have_received(:find_by).with(uuid: uuid).once end it 'logs the conflict' do diff --git a/spec/lib/gitlab/ci/ansi2json_spec.rb b/spec/lib/gitlab/ci/ansi2json_spec.rb index 4b3b049176f..0f8f3759834 100644 --- a/spec/lib/gitlab/ci/ansi2json_spec.rb +++ b/spec/lib/gitlab/ci/ansi2json_spec.rb @@ -7,70 +7,74 @@ RSpec.describe Gitlab::Ci::Ansi2json do describe 'lines' do it 'prints non-ansi as-is' do - expect(convert_json('Hello')).to eq([ - { offset: 0, content: [{ text: 'Hello' }] } - ]) + expect(convert_json('Hello')).to eq([{ offset: 0, content: [{ text: 'Hello' }] }]) end context 'new lines' do it 'adds new line when encountering \n' do - expect(convert_json("Hello\nworld")).to eq([ - { offset: 0, content: [{ text: 'Hello' }] }, - { offset: 6, content: [{ text: 'world' }] } - ]) + expect(convert_json("Hello\nworld")).to eq( + [ + { offset: 0, content: [{ text: 'Hello' }] }, + { offset: 6, content: [{ text: 'world' }] } + ]) end it 'adds new line when encountering \r\n' do - expect(convert_json("Hello\r\nworld")).to eq([ - { offset: 0, content: [{ text: 'Hello' }] }, - { offset: 7, content: [{ text: 'world' }] } - ]) + expect(convert_json("Hello\r\nworld")).to eq( + [ + { offset: 0, content: [{ text: 'Hello' }] }, + { offset: 7, content: [{ text: 'world' }] } + ]) end it 'ignores empty newlines' do - expect(convert_json("Hello\n\nworld")).to eq([ - { offset: 0, content: [{ text: 'Hello' }] }, - { offset: 7, content: [{ text: 'world' }] } - ]) - expect(convert_json("Hello\r\n\r\nworld")).to eq([ - { offset: 0, content: [{ text: 'Hello' }] }, - { offset: 9, content: [{ text: 'world' }] } - ]) + expect(convert_json("Hello\n\nworld")).to eq( + [ + { offset: 0, content: [{ text: 'Hello' }] }, + { offset: 7, content: [{ text: 'world' }] } + ]) + expect(convert_json("Hello\r\n\r\nworld")).to eq( + [ + { offset: 0, content: [{ text: 'Hello' }] }, + { offset: 9, content: [{ text: 'world' }] } + ]) end it 'replace the current line when encountering \r' do - expect(convert_json("Hello\rworld")).to eq([ - { offset: 0, content: [{ text: 'world' }] } - ]) + expect(convert_json("Hello\rworld")).to eq([{ offset: 0, content: [{ text: 'world' }] }]) end end it 'recognizes color changing ANSI sequences' do - expect(convert_json("\e[31mHello\e[0m")).to eq([ - { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] } - ]) + expect(convert_json("\e[31mHello\e[0m")).to eq( + [ + { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] } + ]) end it 'recognizes color changing ANSI sequences across multiple lines' do - expect(convert_json("\e[31mHello\nWorld\e[0m")).to eq([ - { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] }, - { offset: 11, content: [{ text: 'World', style: 'term-fg-red' }] } - ]) + expect(convert_json("\e[31mHello\nWorld\e[0m")).to eq( + [ + { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] }, + { offset: 11, content: [{ text: 'World', style: 'term-fg-red' }] } + ]) end it 'recognizes background and foreground colors' do - expect(convert_json("\e[31;44mHello")).to eq([ - { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red term-bg-blue' }] } - ]) + expect(convert_json("\e[31;44mHello")).to eq( + [ + { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red term-bg-blue' }] } + ]) end it 'recognizes style changes within the same line' do - expect(convert_json("\e[31;44mHello\e[0m world")).to eq([ - { offset: 0, content: [ - { text: 'Hello', style: 'term-fg-red term-bg-blue' }, - { text: ' world' } - ] } - ]) + expect(convert_json("\e[31;44mHello\e[0m world")).to eq( + [ + { offset: 0, content: [ + { text: 'Hello', style: 'term-fg-red term-bg-blue' }, + { text: ' world' } + ] } + ]) end context 'with section markers' do @@ -82,130 +86,137 @@ RSpec.describe Gitlab::Ci::Ansi2json do let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K" } it 'marks the first line of the section as header' do - expect(convert_json("Hello#{section_start}world!")).to eq([ - { - offset: 0, - content: [{ text: 'Hello' }] - }, - { - offset: 5, - content: [{ text: 'world!' }], - section: 'prepare-script', - section_header: true - } - ]) + expect(convert_json("Hello#{section_start}world!")).to eq( + [ + { + offset: 0, + content: [{ text: 'Hello' }] + }, + { + offset: 5, + content: [{ text: 'world!' }], + section: 'prepare-script', + section_header: true + } + ]) end it 'does not marks the other lines of the section as header' do - expect(convert_json("outside section#{section_start}Hello\nworld!")).to eq([ - { - offset: 0, - content: [{ text: 'outside section' }] - }, - { - offset: 15, - content: [{ text: 'Hello' }], - section: 'prepare-script', - section_header: true - }, - { - offset: 65, - content: [{ text: 'world!' }], - section: 'prepare-script' - } - ]) + expect(convert_json("outside section#{section_start}Hello\nworld!")).to eq( + [ + { + offset: 0, + content: [{ text: 'outside section' }] + }, + { + offset: 15, + content: [{ text: 'Hello' }], + section: 'prepare-script', + section_header: true + }, + { + offset: 65, + content: [{ text: 'world!' }], + section: 'prepare-script' + } + ]) end it 'marks the last line of the section as footer' do - expect(convert_json("#{section_start}Good\nmorning\nworld!#{section_end}")).to eq([ - { - offset: 0, - content: [{ text: 'Good' }], - section: 'prepare-script', - section_header: true - }, - { - offset: 49, - content: [{ text: 'morning' }], - section: 'prepare-script' - }, - { - offset: 57, - content: [{ text: 'world!' }], - section: 'prepare-script' - }, - { - offset: 63, - content: [], - section_duration: '01:03', - section: 'prepare-script' - } - ]) + expect(convert_json("#{section_start}Good\nmorning\nworld!#{section_end}")).to eq( + [ + { + offset: 0, + content: [{ text: 'Good' }], + section: 'prepare-script', + section_header: true + }, + { + offset: 49, + content: [{ text: 'morning' }], + section: 'prepare-script' + }, + { + offset: 57, + content: [{ text: 'world!' }], + section: 'prepare-script' + }, + { + offset: 63, + content: [], + section_duration: '01:03', + section: 'prepare-script' + } + ]) end it 'marks the first line as header and footer if is the only line in the section' do - expect(convert_json("#{section_start}Hello world!#{section_end}")).to eq([ - { - offset: 0, - content: [{ text: 'Hello world!' }], - section: 'prepare-script', - section_header: true - }, - { - offset: 56, - content: [], - section: 'prepare-script', - section_duration: '01:03' - } - ]) + expect(convert_json("#{section_start}Hello world!#{section_end}")).to eq( + [ + { + offset: 0, + content: [{ text: 'Hello world!' }], + section: 'prepare-script', + section_header: true + }, + { + offset: 56, + content: [], + section: 'prepare-script', + section_duration: '01:03' + } + ]) end it 'does not add sections attribute to lines after the section is closed' do - expect(convert_json("#{section_start}Hello#{section_end}world")).to eq([ - { - offset: 0, - content: [{ text: 'Hello' }], - section: 'prepare-script', - section_header: true - }, - { - offset: 49, - content: [], - section: 'prepare-script', - section_duration: '01:03' - }, - { - offset: 91, - content: [{ text: 'world' }] - } - ]) + expect(convert_json("#{section_start}Hello#{section_end}world")).to eq( + [ + { + offset: 0, + content: [{ text: 'Hello' }], + section: 'prepare-script', + section_header: true + }, + { + offset: 49, + content: [], + section: 'prepare-script', + section_duration: '01:03' + }, + { + offset: 91, + content: [{ text: 'world' }] + } + ]) end it 'ignores section_end marker if no section_start exists' do - expect(convert_json("Hello #{section_end}world")).to eq([ - { - offset: 0, - content: [{ text: 'Hello world' }] - } - ]) + expect(convert_json("Hello #{section_end}world")).to eq( + [ + { + offset: 0, + content: [{ text: 'Hello world' }] + } + ]) end context 'when section name contains .-_ and capital letters' do let(:section_name) { 'a.Legit-SeCtIoN_namE' } it 'sanitizes the section name' do - expect(convert_json("Hello#{section_start}world!")).to eq([ - { - offset: 0, - content: [{ text: 'Hello' }] - }, - { - offset: 5, - content: [{ text: 'world!' }], - section: 'a-legit-section-name', - section_header: true - } - ]) + expect(convert_json("Hello#{section_start}world!")).to eq( + [ + { + offset: 0, + content: [{ text: 'Hello' }] + }, + { + offset: 5, + content: [{ text: 'world!' }], + section: 'a-legit-section-name', + section_header: true + } + ]) end end @@ -213,12 +224,13 @@ RSpec.describe Gitlab::Ci::Ansi2json do let(:section_name) { 'my_$ection' } it 'ignores the section' do - expect(convert_json("#{section_start}hello")).to eq([ - { - offset: 0, - content: [{ text: 'hello' }] - } - ]) + expect(convert_json("#{section_start}hello")).to eq( + [ + { + offset: 0, + content: [{ text: 'hello' }] + } + ]) end end @@ -226,31 +238,33 @@ RSpec.describe Gitlab::Ci::Ansi2json do let(:section_name) { '<a_tag>' } it 'ignores the section' do - expect(convert_json("#{section_start}hello")).to eq([ - { - offset: 0, - content: [{ text: 'hello' }] - } - ]) + expect(convert_json("#{section_start}hello")).to eq( + [ + { + offset: 0, + content: [{ text: 'hello' }] + } + ]) end end it 'prints HTML tags as is' do trace = "#{section_start}section_end:1:2<div>hello</div>#{section_end}" - expect(convert_json(trace)).to eq([ - { - offset: 0, - content: [{ text: 'section_end:1:2<div>hello</div>' }], - section: 'prepare-script', - section_header: true - }, - { - offset: 75, - content: [], - section: 'prepare-script', - section_duration: '01:03' - } - ]) + expect(convert_json(trace)).to eq( + [ + { + offset: 0, + content: [{ text: 'section_end:1:2<div>hello</div>' }], + section: 'prepare-script', + section_header: true + }, + { + offset: 75, + content: [], + section: 'prepare-script', + section_duration: '01:03' + } + ]) end context 'with nested section' do @@ -264,7 +278,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do it 'adds multiple sections to the lines inside the nested section' do trace = "Hello#{section_start}foo#{nested_section_start}bar#{nested_section_end}baz#{section_end}world" - expect(convert_json(trace)).to eq([ + expect(convert_json(trace)).to eq( + [ { offset: 0, content: [{ text: 'Hello' }] @@ -308,7 +323,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do it 'adds multiple sections to the lines inside the nested section and closes all sections together' do trace = "Hello#{section_start}\e[91mfoo\e[0m#{nested_section_start}bar#{nested_section_end}#{section_end}" - expect(convert_json(trace)).to eq([ + expect(convert_json(trace)).to eq( + [ { offset: 0, content: [{ text: 'Hello' }] @@ -346,24 +362,25 @@ RSpec.describe Gitlab::Ci::Ansi2json do it 'provides section options when set' do trace = "#{option_section_start}hello#{section_end}" - expect(convert_json(trace)).to eq([ - { - offset: 0, - content: [{ text: 'hello' }], - section: 'prepare-script', - section_header: true, - section_options: { - 'collapsed' => 'true', - 'unused_option' => '123' + expect(convert_json(trace)).to eq( + [ + { + offset: 0, + content: [{ text: 'hello' }], + section: 'prepare-script', + section_header: true, + section_options: { + 'collapsed' => 'true', + 'unused_option' => '123' + } + }, + { + offset: 83, + content: [], + section: 'prepare-script', + section_duration: '01:03' } - }, - { - offset: 83, - content: [], - section: 'prepare-script', - section_duration: '01:03' - } - ]) + ]) end end end diff --git a/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb index 937642f07e7..a16f1cf9e43 100644 --- a/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb @@ -91,10 +91,11 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Parallel do describe '#value' do it 'returns job needs configuration' do - expect(parallel.value).to match(matrix: [ - { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] }, - { PROVIDER: 'gcp', STACK: %w[data processing] } - ]) + expect(parallel.value).to match(matrix: + [ + { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] }, + { PROVIDER: 'gcp', STACK: %w[data processing] } + ]) end end diff --git a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb index 9da8d106862..a8dc7897082 100644 --- a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb @@ -174,9 +174,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do context 'when job is provided as a variable' do let(:variables) do - Gitlab::Ci::Variables::Collection.new([ - { key: 'VAR1', value: 'a_secret_variable_value', masked: true } - ]) + Gitlab::Ci::Variables::Collection.new( + [ + { key: 'VAR1', value: 'a_secret_variable_value', masked: true } + ]) end let(:params) { { artifact: 'generated.yml', job: 'a_secret_variable_value' } } diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb index 72a85c9b03d..0ba92d1e92d 100644 --- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb @@ -163,9 +163,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do context 'when non-existing project is used with a masked variable' do let(:variables) do - Gitlab::Ci::Variables::Collection.new([ - { key: 'VAR1', value: 'a_secret_variable_value', masked: true } - ]) + Gitlab::Ci::Variables::Collection.new([{ key: 'VAR1', value: 'a_secret_variable_value', masked: true }]) end let(:params) do @@ -180,9 +178,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do context 'when a project contained in an array is used with a masked variable' do let(:variables) do - Gitlab::Ci::Variables::Collection.new([ - { key: 'VAR1', value: 'a_secret_variable_value', masked: true } - ]) + Gitlab::Ci::Variables::Collection.new([{ key: 'VAR1', value: 'a_secret_variable_value', masked: true }]) end let(:params) do @@ -231,10 +227,11 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do context 'when project name and ref include masked variables' do let(:variables) do - Gitlab::Ci::Variables::Collection.new([ - { key: 'VAR1', value: 'a_secret_variable_value1', masked: true }, - { key: 'VAR2', value: 'a_secret_variable_value2', masked: true } - ]) + Gitlab::Ci::Variables::Collection.new( + [ + { key: 'VAR1', value: 'a_secret_variable_value1', masked: true }, + { key: 'VAR2', value: 'a_secret_variable_value2', masked: true } + ]) end let(:params) { { project: 'a_secret_variable_value1', ref: 'a_secret_variable_value2', file: '/file.yml' } } diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb index 9eaba12f388..c13e65084c1 100644 --- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb +++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb @@ -226,9 +226,9 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do context 'when passing max number of files' do let(:values) do { include: [ - { 'local' => local_file }, - { 'remote' => remote_url } - ], + { 'local' => local_file }, + { 'remote' => remote_url } + ], image: 'image:1.0' } end @@ -242,9 +242,9 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do context "when too many 'includes' are defined" do let(:values) do { include: [ - { 'local' => local_file }, - { 'remote' => remote_url } - ], + { 'local' => local_file }, + { 'remote' => remote_url } + ], image: 'image:1.0' } end @@ -416,10 +416,11 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do context "when locations are same after masking variables" do let(:variables) do - Gitlab::Ci::Variables::Collection.new([ - { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file1', 'masked' => true }, - { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file2', 'masked' => true } - ]) + Gitlab::Ci::Variables::Collection.new( + [ + { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file1', 'masked' => true }, + { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file2', 'masked' => true } + ]) end let(:values) do diff --git a/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb index c54a3268bbe..f58a463f047 100644 --- a/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb +++ b/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb @@ -72,12 +72,13 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator d it { is_expected.not_to be_valid } it "outputs errors for each validation failure" do - expect(validator.errors).to match_array([ - "property '/components/0' is missing required keys: name", - "property '/components/0/type' is not one of: [\"application\", \"framework\"," \ - " \"library\", \"container\", \"operating-system\", \"device\", \"firmware\", \"file\"]", - "property '/components/1' is missing required keys: type" - ]) + expect(validator.errors).to match_array( + [ + "property '/components/0' is missing required keys: name", + "property '/components/0/type' is not one of: [\"application\", \"framework\"," \ + " \"library\", \"container\", \"operating-system\", \"device\", \"firmware\", \"file\"]", + "property '/components/1' is missing required keys: type" + ]) end end end @@ -121,10 +122,11 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator d it { is_expected.not_to be_valid } it "outputs errors for each validation failure" do - expect(validator.errors).to match_array([ - "property '/metadata/properties/0/name' is not of type: string", - "property '/metadata/properties/0/value' is not of type: string" - ]) + expect(validator.errors).to match_array( + [ + "property '/metadata/properties/0/name' is not of type: string", + "property '/metadata/properties/0/value' is not of type: string" + ]) end end end diff --git a/spec/presenters/blobs/unfold_presenter_spec.rb b/spec/presenters/blobs/unfold_presenter_spec.rb index 14c36461e90..9b3b7f5a1c8 100644 --- a/spec/presenters/blobs/unfold_presenter_spec.rb +++ b/spec/presenters/blobs/unfold_presenter_spec.rb @@ -5,13 +5,13 @@ require 'spec_helper' RSpec.describe Blobs::UnfoldPresenter do include FakeBlobHelpers - let(:project) { create(:project, :repository) } - let(:blob) { fake_blob(path: 'foo', data: "1\n2\n3") } - let(:subject) { described_class.new(blob, params) } + let(:project) { nil } # Project object is not needed but `fake_blob` helper requires it to be defined. + let(:blob) { fake_blob(path: 'foo', data: data) } + let(:data) { "1\n\2\n3" } - describe '#initialize' do - let(:result) { subject } + subject(:result) { described_class.new(blob, params) } + describe '#initialize' do context 'with empty params' do let(:params) { {} } @@ -71,7 +71,7 @@ RSpec.describe Blobs::UnfoldPresenter do describe '#diff_lines' do let(:total_lines) { 50 } - let(:blob) { fake_blob(path: 'foo', data: (1..total_lines).to_a.join("\n")) } + let(:data) { (1..total_lines).to_a.join("\n") } context 'when "full" is true' do let(:params) { { full: true } } @@ -91,7 +91,7 @@ RSpec.describe Blobs::UnfoldPresenter do end context 'when last line is empty' do - let(:blob) { fake_blob(path: 'foo', data: "1\n2\n") } + let(:data) { "1\n2\n" } it 'disregards last line' do lines = subject.diff_lines @@ -123,7 +123,7 @@ RSpec.describe Blobs::UnfoldPresenter do expect(line.new_pos).to eq(5) end - context '"to" is higher than blob size' do + context 'when "to" is higher than blob size' do let(:params) { default_params.merge(to: total_lines + 10, bottom: true) } it 'does not add bottom match line' do @@ -133,7 +133,7 @@ RSpec.describe Blobs::UnfoldPresenter do end end - context '"to" is equal to blob size' do + context 'when "to" is equal to blob size' do let(:params) { default_params.merge(to: total_lines, bottom: true) } it 'does not add bottom match line' do @@ -143,7 +143,7 @@ RSpec.describe Blobs::UnfoldPresenter do end end - context '"to" is less than blob size' do + context 'when "to" is less than blob size' do let(:params) { default_params.merge(to: total_lines - 3, bottom: true) } it 'adds bottom match line' do diff --git a/spec/requests/projects/incident_management/timeline_events_spec.rb b/spec/requests/projects/incident_management/timeline_events_spec.rb new file mode 100644 index 00000000000..f7dead4834d --- /dev/null +++ b/spec/requests/projects/incident_management/timeline_events_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Timeline Events' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:incident) { create(:incident, project: project) } + + describe 'POST /preview_markdown' do + let(:timeline_text) { "timeline text with image ![img](img/src.png) and reference #{incident.to_reference}" } + + context 'when authorized' do + let(:expected_img) do + '<a class="with-attachment-icon" href="img/src.png" target="_blank" rel="noopener noreferrer">img</a>' + end + + let(:expected_reference) do + %(<a href="/#{project.full_path}/-/issues/#{incident.iid}" data-reference-type="issue" ) + + %(data-original="##{incident.iid}" data-link="false" data-link-reference="false" ) + + %(data-project="#{project.id}" data-issue="#{incident.id}" data-project-path="#{project.full_path}" ) + + %(data-iid="#{incident.iid}" data-issue-type="incident" data-container="body" data-placement="top" ) + + %(title="#{incident.title}" class="gfm gfm-issue">##{incident.iid}</a>) + end + + let(:expected_body) do + "<p>timeline text with image #{expected_img} and reference #{expected_reference}</p>" + end + + before do + project.add_developer(user) + login_as(user) + end + + it 'renders JSON in a correct format' do + post preview_markdown_project_incident_management_timeline_events_path(project, format: :json), + params: { text: timeline_text } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({ + body: expected_body, + references: { + commands: '', + suggestions: [], + users: [] + } + }.as_json) + end + end + + context 'when not authorized' do + it 'returns 302' do + post preview_markdown_project_incident_management_timeline_events_path(project, format: :json), + params: { text: timeline_text } + + expect(response).to have_gitlab_http_status(:found) + end + end + end +end diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index eea2ea3271f..a69db3b9970 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -19,22 +19,34 @@ RSpec.describe Projects::UpdatePagesService do subject { described_class.new(project, build) } - context 'when a deploy stage already exists' do + context 'when a deploy stage already exists', :aggregate_failures do let!(:stage) { create(:ci_stage, name: 'deploy', pipeline: pipeline) } it 'assigns the deploy stage' do - subject.execute + expect { subject.execute } + .to change(GenericCommitStatus, :count).by(1) + .and change(Ci::Stage.where(name: 'deploy'), :count).by(0) - expect(GenericCommitStatus.last.ci_stage).to eq(stage) - expect(GenericCommitStatus.last.ci_stage.name).to eq('deploy') + status = GenericCommitStatus.last + + expect(status.ci_stage).to eq(stage) + expect(status.ci_stage.name).to eq('deploy') + expect(status.stage_name).to eq('deploy') + expect(status.stage).to eq('deploy') end end context 'when a deploy stage does not exists' do it 'assigns the deploy stage' do - subject.execute + expect { subject.execute } + .to change(GenericCommitStatus, :count).by(1) + .and change(Ci::Stage.where(name: 'deploy'), :count).by(1) + + status = GenericCommitStatus.last - expect(GenericCommitStatus.last.ci_stage.name).to eq('deploy') + expect(status.ci_stage.name).to eq('deploy') + expect(status.stage_name).to eq('deploy') + expect(status.stage).to eq('deploy') end end diff --git a/spec/support/matchers/event_store.rb b/spec/support/matchers/event_store.rb index 4ecb924b3ed..7cf25468eb2 100644 --- a/spec/support/matchers/event_store.rb +++ b/spec/support/matchers/event_store.rb @@ -33,7 +33,16 @@ RSpec::Matchers.define :publish_event do |expected_event_class| end failure_message do - "expected #{expected_event_class} with #{@expected_data} to be published, but got #{@events}" + message = "expected #{expected_event_class} with #{@expected_data} to be published" + + if @events.present? + <<~MESSAGE + #{message}, but only the following events were published: + #{events_list} + MESSAGE + else + "#{message}, but no events were published." + end end match_when_negated do |proc| @@ -45,4 +54,10 @@ RSpec::Matchers.define :publish_event do |expected_event_class| expect(Gitlab::EventStore).not_to have_received(:publish).with(instance_of(expected_event_class)) end + + def events_list + @events.map do |event| + " - #{event.class.name} #{event.data}" + end.join("\n") + end end diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index b5ab6c51a7c..304b473e55c 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -8848,7 +8848,6 @@ - './spec/presenters/award_emoji_presenter_spec.rb' - './spec/presenters/blob_presenter_spec.rb' - './spec/presenters/blobs/notebook_presenter_spec.rb' -- './spec/presenters/blobs/unfold_presenter_spec.rb' - './spec/presenters/ci/bridge_presenter_spec.rb' - './spec/presenters/ci/build_presenter_spec.rb' - './spec/presenters/ci/build_runner_presenter_spec.rb' |