diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-09 21:08:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-09 21:08:33 +0000 |
commit | b296ffa543e23f57fa2692539e6f0028c59e2203 (patch) | |
tree | f5224a37cac088506d1c8fd53925ee1d9fd2a02c /spec | |
parent | c172bb9967f280e05bd904188d60a959dff10f00 (diff) | |
download | gitlab-ce-b296ffa543e23f57fa2692539e6f0028c59e2203.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
35 files changed, 584 insertions, 193 deletions
diff --git a/spec/frontend/alert_management/components/alert_details_spec.js b/spec/frontend/alert_management/components/alert_details_spec.js index 504aebd078f..8aa26dbca3b 100644 --- a/spec/frontend/alert_management/components/alert_details_spec.js +++ b/spec/frontend/alert_management/components/alert_details_spec.js @@ -1,7 +1,8 @@ import { mount, shallowMount } from '@vue/test-utils'; -import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui'; +import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; +import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue'; import AlertDetails from '~/alert_management/components/alert_details.vue'; import createIssueMutation from '~/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql'; import { joinPaths } from '~/lib/utils/url_utility'; @@ -22,8 +23,6 @@ describe('AlertDetails', () => { const projectId = '1'; const $router = { replace: jest.fn() }; - const findDetailsTable = () => wrapper.find(GlTable); - function mountComponent({ data, loading = false, mountMethod = shallowMount, stubs = {} } = {}) { wrapper = mountMethod(AlertDetails, { provide: { @@ -66,6 +65,7 @@ describe('AlertDetails', () => { const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]'); const findViewIncidentBtn = () => wrapper.find('[data-testid="viewIncidentBtn"]'); const findIncidentCreationAlert = () => wrapper.find('[data-testid="incidentCreationError"]'); + const findDetailsTable = () => wrapper.find(AlertDetailsTable); describe('Alert details', () => { describe('when alert is null', () => { diff --git a/spec/frontend/boards/boards_store_spec.js b/spec/frontend/boards/boards_store_spec.js index 29cc8f981bd..41971137b95 100644 --- a/spec/frontend/boards/boards_store_spec.js +++ b/spec/frontend/boards/boards_store_spec.js @@ -312,7 +312,7 @@ describe('boardsStore', () => { }); describe('newIssue', () => { - const id = 'not-creative'; + const id = 1; const issue = { some: 'issue data' }; const url = `${endpoints.listsEndpoint}/${id}/issues`; const expectedRequest = expect.objectContaining({ diff --git a/spec/frontend/boards/list_spec.js b/spec/frontend/boards/list_spec.js index b731bb6e474..9c3a6e66ef4 100644 --- a/spec/frontend/boards/list_spec.js +++ b/spec/frontend/boards/list_spec.js @@ -184,6 +184,7 @@ describe('List model', () => { }), ); list.issues = []; + global.gon.features = { boardsWithSwimlanes: false }; }); it('adds new issue to top of list', done => { diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index 7461e9dc0e9..8d20db9f24a 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -117,6 +117,29 @@ export const mockIssue = { ], }; +export const mockIssue2 = { + title: 'Planning', + id: 2, + iid: 2, + confidential: false, + labels: [ + { + id: 1, + title: 'plan', + color: 'blue', + description: 'planning', + }, + ], + assignees: [ + { + id: 1, + name: 'name', + username: 'username', + avatar_url: 'http://avatar_url', + }, + ], +}; + export const BoardsMockData = { GET: { '/test/-/boards/1/lists/300/issues?id=300&page=1': { diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index ab38abd15ba..17792a8f597 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -1,5 +1,5 @@ import testAction from 'helpers/vuex_action_helper'; -import { mockListsWithModel } from '../mock_data'; +import { mockListsWithModel, mockLists, mockIssue } from '../mock_data'; import actions, { gqlClient } from '~/boards/stores/actions'; import * as types from '~/boards/stores/mutation_types'; import { inactiveId, ListType } from '~/boards/constants'; @@ -236,6 +236,43 @@ describe('createNewIssue', () => { expectNotImplemented(actions.createNewIssue); }); +describe('addListIssue', () => { + it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => { + const payload = { + list: mockLists[0], + issue: mockIssue, + position: 0, + }; + + testAction( + actions.addListIssue, + payload, + {}, + [{ type: types.ADD_ISSUE_TO_LIST, payload }], + [], + done, + ); + }); +}); + +describe('addListIssueFailure', () => { + it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => { + const payload = { + list: mockLists[0], + issue: mockIssue, + }; + + testAction( + actions.addListIssueFailure, + payload, + {}, + [{ type: types.ADD_ISSUE_TO_LIST_FAILURE, payload }], + [], + done, + ); + }); +}); + describe('fetchBacklog', () => { expectNotImplemented(actions.fetchBacklog); }); diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js index f80236afacd..2927337f455 100644 --- a/spec/frontend/boards/stores/mutations_spec.js +++ b/spec/frontend/boards/stores/mutations_spec.js @@ -1,7 +1,14 @@ import mutations from '~/boards/stores/mutations'; import * as types from '~/boards/stores/mutation_types'; import defaultState from '~/boards/stores/state'; -import { listObj, listObjDuplicate, mockIssue, mockListsWithModel } from '../mock_data'; +import { + listObj, + listObjDuplicate, + mockIssue, + mockIssue2, + mockListsWithModel, + mockLists, +} from '../mock_data'; const expectNotImplemented = action => { it('is not implemented', () => { @@ -148,7 +155,7 @@ describe('Board Store Mutations', () => { describe('RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS', () => { it('sets isLoadingIssues to false and updates issuesByListId object', () => { const listIssues = { - '1': [mockIssue.id], + '': [mockIssue.id], }; const issues = { '1': mockIssue, @@ -264,6 +271,50 @@ describe('Board Store Mutations', () => { expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR); }); + describe('ADD_ISSUE_TO_LIST', () => { + it('adds issue to issues state and issue id in list in issuesByListId', () => { + const listIssues = { + 'gid://gitlab/List/1': [mockIssue.id], + }; + const issues = { + '1': mockIssue, + }; + + state = { + ...state, + issuesByListId: listIssues, + issues, + }; + + mutations.ADD_ISSUE_TO_LIST(state, { list: mockLists[0], issue: mockIssue2 }); + + expect(state.issuesByListId['gid://gitlab/List/1']).toContain(mockIssue2.id); + expect(state.issues[mockIssue2.id]).toEqual(mockIssue2); + }); + }); + + describe('ADD_ISSUE_TO_LIST_FAILURE', () => { + it('removes issue id from list in issuesByListId', () => { + const listIssues = { + 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id], + }; + const issues = { + '1': mockIssue, + '2': mockIssue2, + }; + + state = { + ...state, + issuesByListId: listIssues, + issues, + }; + + mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issue: mockIssue2 }); + + expect(state.issuesByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id); + }); + }); + describe('SET_CURRENT_PAGE', () => { expectNotImplemented(mutations.SET_CURRENT_PAGE); }); diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap index d20d81c5230..e1db42aeb0b 100644 --- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap +++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap @@ -17,15 +17,15 @@ exports[`Design note component should match the snapshot 1`] = ` /> <div - class="d-flex justify-content-between" + class="gl-display-flex gl-justify-content-space-between" > <div> - <a + <gl-link-stub class="js-user-link" data-user-id="author-id" > <span - class="note-header-author-name bold" + class="note-header-author-name gl-font-weight-bold" > </span> @@ -37,7 +37,7 @@ exports[`Design note component should match the snapshot 1`] = ` > @ </span> - </a> + </gl-link-stub> <span class="note-headline-light note-headline-meta" @@ -46,7 +46,7 @@ exports[`Design note component should match the snapshot 1`] = ` class="system-note-message" /> - <a + <gl-link-stub class="note-timestamp system-note-separator gl-display-block gl-mb-2" href="#note_123" > @@ -55,7 +55,7 @@ exports[`Design note component should match the snapshot 1`] = ` time="2019-07-26T15:02:20Z" tooltipplacement="bottom" /> - </a> + </gl-link-stub> </span> </div> @@ -68,7 +68,7 @@ exports[`Design note component should match the snapshot 1`] = ` </div> <div - class="note-text js-note-text md" + class="note-text js-note-text" data-qa-selector="note_content" /> diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap index e01c79e3520..f8c68ca4c83 100644 --- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap +++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap @@ -1,15 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Design reply form component renders button text as "Comment" when creating a comment 1`] = ` -"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\"> +"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled gl-button\\"> <!----> - Comment -</button>" + <!----> <span class=\\"gl-button-text\\"> + Comment + </span></button>" `; exports[`Design reply form component renders button text as "Save comment" when creating a comment 1`] = ` -"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\"> +"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled gl-button\\"> <!----> - Save comment -</button>" + <!----> <span class=\\"gl-button-text\\"> + Save comment + </span></button>" `; diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js index 98f190bc33a..9fbd9b2c2a3 100644 --- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js +++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js @@ -232,7 +232,7 @@ describe('Design discussions component', () => { { discussionComment: 'test', isFormRendered: true }, ); - findReplyForm().vm.$emit('submitForm'); + findReplyForm().vm.$emit('submit-form'); expect(mutate).toHaveBeenCalledWith(mutationVariables); await mutate(); @@ -250,7 +250,7 @@ describe('Design discussions component', () => { return wrapper.vm .$nextTick() .then(() => { - findReplyForm().vm.$emit('cancelForm'); + findReplyForm().vm.$emit('cancel-form'); expect(wrapper.vm.discussionComment).toBe(''); return wrapper.vm.$nextTick(); @@ -321,6 +321,6 @@ describe('Design discussions component', () => { createComponent(); findReplyPlaceholder().vm.$emit('onClick'); - expect(wrapper.emitted('openForm')).toBeTruthy(); + expect(wrapper.emitted('open-form')).toBeTruthy(); }); }); diff --git a/spec/frontend/design_management/components/design_notes/design_note_spec.js b/spec/frontend/design_management/components/design_notes/design_note_spec.js index c35bb503c96..043091e3dc2 100644 --- a/spec/frontend/design_management/components/design_notes/design_note_spec.js +++ b/spec/frontend/design_management/components/design_notes/design_note_spec.js @@ -133,8 +133,8 @@ describe('Design note component', () => { expect(findReplyForm().exists()).toBe(true); }); - it('hides the form on hideForm event', () => { - findReplyForm().vm.$emit('cancelForm'); + it('hides the form on cancel-form event', () => { + findReplyForm().vm.$emit('cancel-form'); return wrapper.vm.$nextTick().then(() => { expect(findReplyForm().exists()).toBe(false); @@ -142,8 +142,8 @@ describe('Design note component', () => { }); }); - it('calls a mutation on submitForm event and hides a form', () => { - findReplyForm().vm.$emit('submitForm'); + it('calls a mutation on submit-form event and hides a form', () => { + findReplyForm().vm.$emit('submit-form'); expect(mutate).toHaveBeenCalled(); return mutate() diff --git a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js index 16b34f150b8..1a80fc4e761 100644 --- a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js +++ b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js @@ -70,7 +70,7 @@ describe('Design reply form component', () => { }); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('submitForm')).toBeFalsy(); + expect(wrapper.emitted('submit-form')).toBeFalsy(); }); }); @@ -80,20 +80,20 @@ describe('Design reply form component', () => { }); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('submitForm')).toBeFalsy(); + expect(wrapper.emitted('submit-form')).toBeFalsy(); }); }); it('emits cancelForm event on pressing escape button on textarea', () => { findTextarea().trigger('keyup.esc'); - expect(wrapper.emitted('cancelForm')).toBeTruthy(); + expect(wrapper.emitted('cancel-form')).toBeTruthy(); }); it('emits cancelForm event on clicking Cancel button', () => { findCancelButton().vm.$emit('click'); - expect(wrapper.emitted('cancelForm')).toHaveLength(1); + expect(wrapper.emitted('cancel-form')).toHaveLength(1); }); }); @@ -112,7 +112,7 @@ describe('Design reply form component', () => { findSubmitButton().vm.$emit('click'); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('submitForm')).toBeTruthy(); + expect(wrapper.emitted('submit-form')).toBeTruthy(); }); }); @@ -122,7 +122,7 @@ describe('Design reply form component', () => { }); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('submitForm')).toBeTruthy(); + expect(wrapper.emitted('submit-form')).toBeTruthy(); }); }); @@ -132,7 +132,7 @@ describe('Design reply form component', () => { }); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('submitForm')).toBeTruthy(); + expect(wrapper.emitted('submit-form')).toBeTruthy(); }); }); @@ -147,7 +147,7 @@ describe('Design reply form component', () => { it('emits cancelForm event on Escape key if text was not changed', () => { findTextarea().trigger('keyup.esc'); - expect(wrapper.emitted('cancelForm')).toBeTruthy(); + expect(wrapper.emitted('cancel-form')).toBeTruthy(); }); it('opens confirmation modal on Escape key when text has changed', () => { @@ -162,7 +162,7 @@ describe('Design reply form component', () => { it('emits cancelForm event on Cancel button click if text was not changed', () => { findCancelButton().trigger('click'); - expect(wrapper.emitted('cancelForm')).toBeTruthy(); + expect(wrapper.emitted('cancel-form')).toBeTruthy(); }); it('opens confirmation modal on Cancel button click when text has changed', () => { @@ -178,7 +178,7 @@ describe('Design reply form component', () => { findTextarea().trigger('keyup.esc'); findModal().vm.$emit('ok'); - expect(wrapper.emitted('cancelForm')).toBeTruthy(); + expect(wrapper.emitted('cancel-form')).toBeTruthy(); }); }); }); diff --git a/spec/frontend/design_management/components/design_sidebar_spec.js b/spec/frontend/design_management/components/design_sidebar_spec.js index 85513e08d46..700faa8a70f 100644 --- a/spec/frontend/design_management/components/design_sidebar_spec.js +++ b/spec/frontend/design_management/components/design_sidebar_spec.js @@ -154,22 +154,22 @@ describe('Design management design sidebar component', () => { }); it('emits correct event on discussion create note error', () => { - findFirstDiscussion().vm.$emit('createNoteError', 'payload'); + findFirstDiscussion().vm.$emit('create-note-error', 'payload'); expect(wrapper.emitted('onDesignDiscussionError')).toEqual([['payload']]); }); it('emits correct event on discussion update note error', () => { - findFirstDiscussion().vm.$emit('updateNoteError', 'payload'); + findFirstDiscussion().vm.$emit('update-note-error', 'payload'); expect(wrapper.emitted('updateNoteError')).toEqual([['payload']]); }); it('emits correct event on discussion resolve error', () => { - findFirstDiscussion().vm.$emit('resolveDiscussionError', 'payload'); + findFirstDiscussion().vm.$emit('resolve-discussion-error', 'payload'); expect(wrapper.emitted('resolveDiscussionError')).toEqual([['payload']]); }); it('changes prop correctly on opening discussion form', () => { - findFirstDiscussion().vm.$emit('openForm', 'some-id'); + findFirstDiscussion().vm.$emit('open-form', 'some-id'); return wrapper.vm.$nextTick().then(() => { expect(findFirstDiscussion().props('discussionWithOpenForm')).toBe('some-id'); diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js index d189bdb4345..d78d3dc7edd 100644 --- a/spec/frontend/design_management/pages/design/index_spec.js +++ b/spec/frontend/design_management/pages/design/index_spec.js @@ -210,7 +210,7 @@ describe('Design management design index page', () => { }, ); - findDiscussionForm().vm.$emit('submitForm'); + findDiscussionForm().vm.$emit('submit-form'); expect(mutate).toHaveBeenCalledWith(createDiscussionMutationVariables); return wrapper.vm @@ -235,7 +235,7 @@ describe('Design management design index page', () => { }, ); - findDiscussionForm().vm.$emit('cancelForm'); + findDiscussionForm().vm.$emit('cancel-form'); expect(wrapper.vm.comment).toBe(''); diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap index f8c71d76968..3b101e9e815 100644 --- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap +++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap @@ -41,7 +41,7 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] = > <textarea aria-label="Description" - class="note-textarea js-gfm-input js-autosize markdown-area" + class="note-textarea js-gfm-input js-autosize markdown-area js-gfm-input-initialized" data-qa-selector="snippet_description_field" data-supports-quick-actions="false" dir="auto" diff --git a/spec/frontend/vue_shared/components/alert_detail_table_spec.js b/spec/frontend/vue_shared/components/alert_detail_table_spec.js new file mode 100644 index 00000000000..9c38ccad8a7 --- /dev/null +++ b/spec/frontend/vue_shared/components/alert_detail_table_spec.js @@ -0,0 +1,74 @@ +import { mount } from '@vue/test-utils'; +import { GlTable, GlLoadingIcon } from '@gitlab/ui'; +import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue'; + +const mockAlert = { + iid: '1527542', + title: 'SyntaxError: Invalid or unexpected token', + severity: 'CRITICAL', + eventCount: 7, + createdAt: '2020-04-17T23:18:14.996Z', + startedAt: '2020-04-17T23:18:14.996Z', + endedAt: '2020-04-17T23:18:14.996Z', + status: 'TRIGGERED', + assignees: { nodes: [] }, + notes: { nodes: [] }, + todos: { nodes: [] }, +}; + +describe('AlertDetails', () => { + let wrapper; + + function mountComponent(propsData = {}) { + wrapper = mount(AlertDetailsTable, { + propsData: { + alert: mockAlert, + loading: false, + ...propsData, + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const findTableComponent = () => wrapper.find(GlTable); + + describe('Alert details', () => { + describe('empty state', () => { + beforeEach(() => { + mountComponent({ alert: null }); + }); + + it('shows an empty state when no alert is provided', () => { + expect(wrapper.text()).toContain('No alert data to display.'); + }); + }); + + describe('loading state', () => { + beforeEach(() => { + mountComponent({ loading: true }); + }); + + it('displays a loading state when loading', () => { + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + }); + }); + + describe('with table data', () => { + beforeEach(() => { + mountComponent(); + }); + + it('renders a table', () => { + expect(findTableComponent().exists()).toBe(true); + }); + + it('renders a cell based on alert data', () => { + expect(findTableComponent().text()).toContain('SyntaxError: Invalid or unexpected token'); + }); + }); + }); +}); diff --git a/spec/graphql/types/current_user_todos_type_spec.rb b/spec/graphql/types/current_user_todos_type_spec.rb new file mode 100644 index 00000000000..a0015e96788 --- /dev/null +++ b/spec/graphql/types/current_user_todos_type_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['CurrentUserTodos'] do + specify { expect(described_class.graphql_name).to eq('CurrentUserTodos') } + + specify { expect(described_class).to have_graphql_fields(:current_user_todos).only } +end diff --git a/spec/graphql/types/design_management/design_type_spec.rb b/spec/graphql/types/design_management/design_type_spec.rb index 7a38b397965..cae98a013e1 100644 --- a/spec/graphql/types/design_management/design_type_spec.rb +++ b/spec/graphql/types/design_management/design_type_spec.rb @@ -3,8 +3,10 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Design'] do + specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) } + it_behaves_like 'a GraphQL type with design fields' do - let(:extra_design_fields) { %i[notes discussions versions] } + let(:extra_design_fields) { %i[notes current_user_todos discussions versions] } let_it_be(:design) { create(:design, :with_versions) } let(:object_id) { GitlabSchema.id_from_object(design) } let_it_be(:object_id_b) { GitlabSchema.id_from_object(create(:design, :with_versions)) } diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb index db2a1751be0..c55e624dd11 100644 --- a/spec/graphql/types/issue_type_spec.rb +++ b/spec/graphql/types/issue_type_spec.rb @@ -11,11 +11,13 @@ RSpec.describe GitlabSchema.types['Issue'] do specify { expect(described_class.interfaces).to include(Types::Notes::NoteableType) } + specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) } + it 'has specific fields' do fields = %i[id iid title description state reference author assignees participants labels milestone due_date confidential discussion_locked upvotes downvotes user_notes_count web_path web_url relative_position subscribed time_estimate total_time_spent closed_at created_at updated_at task_completion_status - designs design_collection alert_management_alert severity] + designs design_collection alert_management_alert severity current_user_todos] fields.each do |field_name| expect(described_class).to have_graphql_field(field_name) diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb index a9a74114dda..1279f01f104 100644 --- a/spec/graphql/types/merge_request_type_spec.rb +++ b/spec/graphql/types/merge_request_type_spec.rb @@ -9,6 +9,8 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do specify { expect(described_class.interfaces).to include(Types::Notes::NoteableType) } + specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) } + it 'has the expected fields' do expected_fields = %w[ notes discussions user_permissions id iid title title_html description @@ -24,7 +26,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do source_branch_exists target_branch_exists upvotes downvotes head_pipeline pipelines task_completion_status milestone assignees participants subscribed labels discussion_locked time_estimate - total_time_spent reference author merged_at commit_count + total_time_spent reference author merged_at commit_count current_user_todos ] if Gitlab.ee? diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb index 38a5c30506b..feaca6164eb 100644 --- a/spec/lib/backup/manager_spec.rb +++ b/spec/lib/backup/manager_spec.rb @@ -416,5 +416,28 @@ RSpec.describe Backup::Manager do subject.upload end end + + context 'with AzureRM provider' do + before do + stub_backup_setting( + upload: { + connection: { + provider: 'AzureRM', + azure_storage_account_name: 'test-access-id', + azure_storage_access_key: 'secret' + }, + remote_directory: 'directory', + multipart_chunk_size: nil, + encryption: nil, + encryption_key: nil, + storage_class: nil + } + ) + end + + it 'loads the provider' do + expect { subject.upload }.not_to raise_error + end + end end end diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb index 57bde6262a9..155e66e2fcd 100644 --- a/spec/lib/gitlab/data_builder/deployment_spec.rb +++ b/spec/lib/gitlab/data_builder/deployment_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe Gitlab::DataBuilder::Deployment do describe '.build' do it 'returns the object kind for a deployment' do - deployment = build(:deployment) + deployment = build(:deployment, deployable: nil, environment: create(:environment)) data = described_class.build(deployment) diff --git a/spec/lib/gitlab/usage_data_queries_spec.rb b/spec/lib/gitlab/usage_data_queries_spec.rb new file mode 100644 index 00000000000..06f3174dd34 --- /dev/null +++ b/spec/lib/gitlab/usage_data_queries_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::UsageDataQueries do + before do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) + end + + describe '.count' do + it 'returns the raw SQL' do + expect(described_class.count(User)).to start_with('SELECT COUNT("users"."id") FROM "users"') + end + end + + describe '.distinct_count' do + it 'returns the raw SQL' do + expect(described_class.distinct_count(Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"') + end + end +end diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb index a48b5100065..0ead2a1d269 100644 --- a/spec/lib/object_storage/config_spec.rb +++ b/spec/lib/object_storage/config_spec.rb @@ -2,6 +2,7 @@ require 'fast_spec_helper' require 'rspec-parameterized' +require 'fog/core' RSpec.describe ObjectStorage::Config do using RSpec::Parameterized::TableSyntax @@ -35,6 +36,46 @@ RSpec.describe ObjectStorage::Config do subject { described_class.new(raw_config.as_json) } + describe '#load_provider' do + before do + subject.load_provider + end + + context 'with AWS' do + it 'registers AWS as a provider' do + expect(Fog.providers.keys).to include(:aws) + end + end + + context 'with Google' do + let(:credentials) do + { + provider: 'Google', + google_storage_access_key_id: 'GOOGLE_ACCESS_KEY_ID', + google_storage_secret_access_key: 'GOOGLE_SECRET_ACCESS_KEY' + } + end + + it 'registers Google as a provider' do + expect(Fog.providers.keys).to include(:google) + end + end + + context 'with Azure' do + let(:credentials) do + { + provider: 'AzureRM', + azure_storage_account_name: 'azuretest', + azure_storage_access_key: 'ABCD1234' + } + end + + it 'registers AzureRM as a provider' do + expect(Fog.providers.keys).to include(:azurerm) + end + end + end + describe '#credentials' do it { expect(subject.credentials).to eq(credentials) } end diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb index 2920bbf2b58..3b903fe34f9 100644 --- a/spec/models/clusters/kubernetes_namespace_spec.rb +++ b/spec/models/clusters/kubernetes_namespace_spec.rb @@ -61,7 +61,8 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do end describe 'namespace uniqueness validation' do - let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') } + let_it_be(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, cluster: cluster, namespace: 'my-namespace') } subject { kubernetes_namespace } diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index ff53478fea3..bafcb7a3741 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -81,6 +81,8 @@ RSpec.describe Event do describe 'validations' do describe 'action' do context 'for a design' do + let_it_be(:author) { create(:user) } + where(:action, :valid) do valid = described_class::DESIGN_ACTIONS.map(&:to_s).to_set @@ -90,7 +92,7 @@ RSpec.describe Event do end with_them do - let(:event) { build(:design_event, action: action) } + let(:event) { build(:design_event, author: author, action: action) } specify { expect(event.valid?).to eq(valid) } end @@ -731,7 +733,8 @@ RSpec.describe Event do end target = kind == :project ? nil : build(kind, **extra_data) - [kind, build(:event, :created, project: project, target: target)] + + [kind, build(:event, :created, author: project.owner, project: project, target: target)] end.to_h end diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb index 45be5212508..02b266e4fae 100644 --- a/spec/models/project_services/chat_message/merge_message_spec.rb +++ b/spec/models/project_services/chat_message/merge_message_spec.rb @@ -29,23 +29,6 @@ RSpec.describe ChatMessage::MergeMessage do } end - # Integration point in EE - context 'when state is overridden' do - it 'respects the overridden state' do - allow(subject).to receive(:state_or_action_text) { 'devoured' } - - aggregate_failures do - expect(subject.summary).not_to include('opened') - expect(subject.summary).to include('devoured') - - activity_title = subject.activity[:title] - - expect(activity_title).not_to include('opened') - expect(activity_title).to include('devoured') - end - end - end - context 'without markdown' do let(:color) { '#345' } @@ -106,4 +89,56 @@ RSpec.describe ChatMessage::MergeMessage do end end end + + context 'approved' do + before do + args[:object_attributes][:action] = 'approved' + end + + it 'returns a message regarding completed approval of merge requests' do + expect(subject.pretext).to eq( + 'Test User (test.user) approved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\ + 'in <http://somewhere.com|project_name>') + expect(subject.attachments).to be_empty + end + end + + context 'unapproved' do + before do + args[:object_attributes][:action] = 'unapproved' + end + + it 'returns a message regarding revocation of completed approval of merge requests' do + expect(subject.pretext).to eq( + 'Test User (test.user) unapproved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\ + 'in <http://somewhere.com|project_name>') + expect(subject.attachments).to be_empty + end + end + + context 'approval' do + before do + args[:object_attributes][:action] = 'approval' + end + + it 'returns a message regarding added approval of merge requests' do + expect(subject.pretext).to eq( + 'Test User (test.user) added their approval to merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\ + 'in <http://somewhere.com|project_name>') + expect(subject.attachments).to be_empty + end + end + + context 'unapproval' do + before do + args[:object_attributes][:action] = 'unapproval' + end + + it 'returns a message regarding revoking approval of merge requests' do + expect(subject.pretext).to eq( + 'Test User (test.user) removed their approval from merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\ + 'in <http://somewhere.com|project_name>') + expect(subject.attachments).to be_empty + end + end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index d9c5fed542e..29c3d0e1a73 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -17,19 +17,28 @@ RSpec.describe ProjectWiki do end end - describe '#update_container_activity' do + describe '#after_wiki_activity' do it 'updates project activity' do wiki_container.update!( last_activity_at: nil, last_repository_updated_at: nil ) - subject.create_page('Test Page', 'This is content') + subject.send(:after_wiki_activity) wiki_container.reload expect(wiki_container.last_activity_at).to be_within(1.minute).of(Time.current) expect(wiki_container.last_repository_updated_at).to be_within(1.minute).of(Time.current) end end + + describe '#after_post_receive' do + it 'updates project activity and expires caches' do + expect(wiki).to receive(:after_wiki_activity) + expect(ProjectCacheWorker).to receive(:perform_async).with(wiki_container.id, [], [:wiki_size]) + + subject.send(:after_post_receive) + end + end end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 9879fc53461..af17434b4f2 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe ProjectPolicy do include ExternalAuthorizationServiceHelpers include_context 'ProjectPolicy context' + let_it_be(:other_user) { create(:user) } let_it_be(:guest) { create(:user) } let_it_be(:reporter) { create(:user) } @@ -14,78 +15,6 @@ RSpec.describe ProjectPolicy do let_it_be(:admin) { create(:admin) } let(:project) { create(:project, :public, namespace: owner.namespace) } - let(:base_guest_permissions) do - %i[ - read_project read_board read_list read_wiki read_issue - read_project_for_iids read_issue_iid read_label - read_milestone read_snippet read_project_member read_note - create_project create_issue create_note upload_file create_merge_request_in - award_emoji read_release read_issue_link - ] - end - - let(:base_reporter_permissions) do - %i[ - download_code fork_project create_snippet update_issue - admin_issue admin_label admin_list read_commit_status read_build - read_container_image read_pipeline read_environment read_deployment - read_merge_request download_wiki_code read_sentry_issue read_metrics_dashboard_annotation - metrics_dashboard read_confidential_issues admin_issue_link - ] - end - - let(:team_member_reporter_permissions) do - %i[build_download_code build_read_container_image] - end - - let(:developer_permissions) do - %i[ - admin_tag admin_milestone admin_merge_request update_merge_request create_commit_status - update_commit_status create_build update_build create_pipeline - update_pipeline create_merge_request_from create_wiki push_code - resolve_note create_container_image update_container_image destroy_container_image daily_statistics - create_environment update_environment create_deployment update_deployment create_release update_release - create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation - read_terraform_state read_pod_logs - ] - end - - let(:base_maintainer_permissions) do - %i[ - push_to_delete_protected_branch update_snippet - admin_snippet admin_project_member admin_note admin_wiki admin_project - admin_commit_status admin_build admin_container_image - admin_pipeline admin_environment admin_deployment destroy_release add_cluster - read_deploy_token create_deploy_token destroy_deploy_token - admin_terraform_state - ] - end - - let(:public_permissions) do - %i[ - download_code fork_project read_commit_status read_pipeline - read_container_image build_download_code build_read_container_image - download_wiki_code read_release - ] - end - - let(:owner_permissions) do - %i[ - change_namespace change_visibility_level rename_project remove_project - archive_project remove_fork_project destroy_merge_request destroy_issue - set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at - ] - end - - # Used in EE specs - let(:additional_guest_permissions) { [] } - let(:additional_reporter_permissions) { [] } - let(:additional_maintainer_permissions) { [] } - - let(:guest_permissions) { base_guest_permissions + additional_guest_permissions } - let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions } - let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions } - before do project.add_guest(guest) project.add_maintainer(maintainer) diff --git a/spec/requests/api/graphql/current_user_todos_spec.rb b/spec/requests/api/graphql/current_user_todos_spec.rb new file mode 100644 index 00000000000..b657f15d0e9 --- /dev/null +++ b/spec/requests/api/graphql/current_user_todos_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'A Todoable that implements the CurrentUserTodos interface' do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:todoable) { create(:issue, project: project) } + let_it_be(:done_todo) { create(:todo, state: :done, target: todoable, user: current_user) } + let_it_be(:pending_todo) { create(:todo, state: :pending, target: todoable, user: current_user) } + let(:state) { 'null' } + + let(:todoable_response) do + graphql_data_at(:project, :issue, :currentUserTodos, :nodes) + end + + let(:query) do + <<~GQL + { + project(fullPath: "#{project.full_path}") { + issue(iid: "#{todoable.iid}") { + currentUserTodos(state: #{state}) { + nodes { + #{all_graphql_fields_for('Todo', max_depth: 1)} + } + } + } + } + } + GQL + end + + it 'returns todos of the current user' do + post_graphql(query, current_user: current_user) + + expect(todoable_response).to contain_exactly( + a_hash_including('id' => global_id_of(done_todo)), + a_hash_including('id' => global_id_of(pending_todo)) + ) + end + + it 'does not return todos of another user', :aggregate_failures do + post_graphql(query, current_user: create(:user)) + + expect(response).to have_gitlab_http_status(:success) + expect(todoable_response).to be_empty + end + + it 'does not error when there is no logged in user', :aggregate_failures do + post_graphql(query) + + expect(response).to have_gitlab_http_status(:success) + expect(todoable_response).to be_empty + end + + context 'when `state` argument is `pending`' do + let(:state) { 'pending' } + + it 'returns just the pending todo' do + post_graphql(query, current_user: current_user) + + expect(todoable_response).to contain_exactly( + a_hash_including('id' => global_id_of(pending_todo)) + ) + end + end + + context 'when `state` argument is `done`' do + let(:state) { 'done' } + + it 'returns just the done todo' do + post_graphql(query, current_user: current_user) + + expect(todoable_response).to contain_exactly( + a_hash_including('id' => global_id_of(done_todo)) + ) + end + end +end diff --git a/spec/services/git/wiki_push_service_spec.rb b/spec/services/git/wiki_push_service_spec.rb index 7f709be8593..816f20f0bc3 100644 --- a/spec/services/git/wiki_push_service_spec.rb +++ b/spec/services/git/wiki_push_service_spec.rb @@ -6,12 +6,20 @@ RSpec.describe Git::WikiPushService, services: true do include RepoHelpers let_it_be(:key_id) { create(:key, user: current_user).shell_id } - let_it_be(:project) { create(:project, :wiki_repo) } - let_it_be(:current_user) { create(:user) } - let_it_be(:git_wiki) { project.wiki.wiki } - let_it_be(:repository) { git_wiki.repository } + let_it_be(:wiki) { create(:project_wiki) } + let_it_be(:current_user) { wiki.container.default_owner } + let_it_be(:git_wiki) { wiki.wiki } + let_it_be(:repository) { wiki.repository } describe '#execute' do + it 'executes model-specific callbacks' do + expect(wiki).to receive(:after_post_receive) + + create_service(current_sha).execute + end + end + + describe '#process_changes' do context 'the push contains more than the permitted number of changes' do def run_service process_changes { described_class::MAX_CHANGES.succ.times { write_new_page } } @@ -37,8 +45,8 @@ RSpec.describe Git::WikiPushService, services: true do let(:count) { Event::WIKI_ACTIONS.size } def run_service - wiki_page_a = create(:wiki_page, project: project) - wiki_page_b = create(:wiki_page, project: project) + wiki_page_a = create(:wiki_page, wiki: wiki) + wiki_page_b = create(:wiki_page, wiki: wiki) process_changes do write_new_page @@ -135,7 +143,7 @@ RSpec.describe Git::WikiPushService, services: true do end context 'when a page we already know about has been updated' do - let(:wiki_page) { create(:wiki_page, project: project) } + let(:wiki_page) { create(:wiki_page, wiki: wiki) } before do create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) @@ -165,7 +173,7 @@ RSpec.describe Git::WikiPushService, services: true do context 'when a page we do not know about has been updated' do def run_service - wiki_page = create(:wiki_page, project: project) + wiki_page = create(:wiki_page, wiki: wiki) process_changes { update_page(wiki_page.title) } end @@ -189,7 +197,7 @@ RSpec.describe Git::WikiPushService, services: true do context 'when a page we do not know about has been deleted' do def run_service - wiki_page = create(:wiki_page, project: project) + wiki_page = create(:wiki_page, wiki: wiki) process_changes { delete_page(wiki_page.page.path) } end @@ -254,9 +262,9 @@ RSpec.describe Git::WikiPushService, services: true do it_behaves_like 'a no-op push' - context 'but is enabled for a given project' do + context 'but is enabled for a given container' do before do - stub_feature_flags(wiki_events_on_git_push: project) + stub_feature_flags(wiki_events_on_git_push: wiki.container) end it 'creates events' do @@ -280,19 +288,19 @@ RSpec.describe Git::WikiPushService, services: true do def create_service(base, refs = ['refs/heads/master']) changes = post_received(base, refs).changes - described_class.new(project, current_user, changes: changes) + described_class.new(wiki, current_user, changes: changes) end def post_received(base, refs) change_str = refs.map { |ref| +"#{base} #{current_sha} #{ref}" }.join("\n") - post_received = ::Gitlab::GitPostReceive.new(project, key_id, change_str, {}) + post_received = ::Gitlab::GitPostReceive.new(wiki.container, key_id, change_str, {}) allow(post_received).to receive(:identify).with(key_id).and_return(current_user) post_received end def current_sha - repository.gitaly_ref_client.find_branch('master')&.dereferenced_target&.id || Gitlab::Git::BLANK_SHA + repository.commit('master')&.id || Gitlab::Git::BLANK_SHA end # It is important not to re-use the WikiPage services here, since they create @@ -312,7 +320,7 @@ RSpec.describe Git::WikiPushService, services: true do file_content: 'some stuff', branch_name: 'master' } - ::Wikis::CreateAttachmentService.new(container: project, current_user: project.owner, params: params).execute + ::Wikis::CreateAttachmentService.new(container: wiki.container, current_user: current_user, params: params).execute end def update_page(title) diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb index 794491fc50d..3c02b56f1a5 100644 --- a/spec/services/notes/quick_actions_service_spec.rb +++ b/spec/services/notes/quick_actions_service_spec.rb @@ -210,11 +210,13 @@ RSpec.describe Notes::QuickActionsService do let(:service) { described_class.new(project, maintainer) } it_behaves_like 'note on noteable that supports quick actions' do - let(:note) { build(:note_on_issue, project: project) } + let_it_be(:issue, reload: true) { create(:issue, project: project) } + let(:note) { build(:note_on_issue, project: project, noteable: issue) } end it_behaves_like 'note on noteable that supports quick actions' do - let(:note) { build(:note_on_merge_request, project: project) } + let_it_be(:merge_request, reload: true) { create(:merge_request, source_project: project) } + let(:note) { build(:note_on_merge_request, project: project, noteable: merge_request) } end end diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb index 5339fa003b9..dd08d81bc46 100644 --- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb @@ -11,20 +11,22 @@ RSpec.shared_context 'ProjectPolicy context' do let(:base_guest_permissions) do %i[ - read_project read_board read_list read_wiki read_issue - read_project_for_iids read_issue_iid read_label - read_milestone read_snippet read_project_member read_note - create_project create_issue create_note upload_file create_merge_request_in - award_emoji + award_emoji create_issue create_merge_request_in create_note + create_project read_board read_issue read_issue_iid read_issue_link + read_label read_list read_milestone read_note read_project + read_project_for_iids read_project_member read_release read_snippet + read_wiki upload_file ] end let(:base_reporter_permissions) do %i[ - download_code fork_project create_snippet update_issue - admin_issue admin_label admin_list read_commit_status read_build - read_container_image read_pipeline read_environment read_deployment - read_merge_request download_wiki_code read_sentry_issue read_prometheus + admin_issue admin_issue_link admin_label admin_list create_snippet + download_code download_wiki_code fork_project metrics_dashboard + read_build read_commit_status read_confidential_issues + read_container_image read_deployment read_environment read_merge_request + read_metrics_dashboard_annotation read_pipeline read_prometheus + read_sentry_issue update_issue ] end @@ -34,37 +36,42 @@ RSpec.shared_context 'ProjectPolicy context' do let(:developer_permissions) do %i[ - admin_milestone admin_merge_request update_merge_request create_commit_status - update_commit_status create_build update_build create_pipeline - update_pipeline create_merge_request_from create_wiki push_code - resolve_note create_container_image update_container_image - create_environment create_deployment update_deployment create_release update_release - update_environment daily_statistics + admin_merge_request admin_milestone admin_tag create_build + create_commit_status create_container_image create_deployment + create_environment create_merge_request_from + create_metrics_dashboard_annotation create_pipeline create_release + create_wiki daily_statistics delete_metrics_dashboard_annotation + destroy_container_image push_code read_pod_logs read_terraform_state + resolve_note update_build update_commit_status update_container_image + update_deployment update_environment update_merge_request + update_metrics_dashboard_annotation update_pipeline update_release ] end let(:base_maintainer_permissions) do %i[ - push_to_delete_protected_branch update_snippet - admin_snippet admin_project_member admin_note admin_wiki admin_project - admin_commit_status admin_build admin_container_image - admin_pipeline admin_environment admin_deployment destroy_release add_cluster + add_cluster admin_build admin_commit_status admin_container_image + admin_deployment admin_environment admin_note admin_pipeline + admin_project admin_project_member admin_snippet admin_terraform_state + admin_wiki create_deploy_token destroy_deploy_token destroy_release + push_to_delete_protected_branch read_deploy_token update_snippet ] end let(:public_permissions) do %i[ - download_code fork_project read_commit_status read_pipeline - read_container_image build_download_code build_read_container_image - download_wiki_code read_release + build_download_code build_read_container_image download_code + download_wiki_code fork_project read_commit_status read_container_image + read_pipeline read_release ] end let(:base_owner_permissions) do %i[ - change_namespace change_visibility_level rename_project remove_project - archive_project remove_fork_project destroy_merge_request destroy_issue - set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at + archive_project change_namespace change_visibility_level destroy_issue + destroy_merge_request remove_fork_project remove_project rename_project + set_issue_created_at set_issue_iid set_issue_updated_at + set_note_created_at ] end diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb index a881d5f036c..b87f7fe97e1 100644 --- a/spec/support/shared_examples/models/wiki_shared_examples.rb +++ b/spec/support/shared_examples/models/wiki_shared_examples.rb @@ -322,8 +322,8 @@ RSpec.shared_examples 'wiki model' do expect(commit.committer_email).to eq(user.commit_email) end - it 'updates container activity' do - expect(subject).to receive(:update_container_activity) + it 'runs after_wiki_activity callbacks' do + expect(subject).to receive(:after_wiki_activity) subject.create_page('Test Page', 'This is content') end @@ -363,10 +363,10 @@ RSpec.shared_examples 'wiki model' do expect(commit.committer_email).to eq(user.commit_email) end - it 'updates container activity' do + it 'runs after_wiki_activity callbacks' do page - expect(subject).to receive(:update_container_activity) + expect(subject).to receive(:after_wiki_activity) update_page end @@ -389,10 +389,10 @@ RSpec.shared_examples 'wiki model' do expect(commit.committer_email).to eq(user.commit_email) end - it 'updates container activity' do + it 'runs after_wiki_activity callbacks' do page - expect(subject).to receive(:update_container_activity) + expect(subject).to receive(:after_wiki_activity) subject.delete_page(page) end diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb new file mode 100644 index 00000000000..2a596946d86 --- /dev/null +++ b/spec/tasks/gitlab/usage_data_rake_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rake_helper' + +RSpec.describe 'gitlab:usage data take tasks' do + before do + Rake.application.rake_require 'tasks/gitlab/usage_data' + # stub prometheus external http calls https://gitlab.com/gitlab-org/gitlab/-/issues/245277 + stub_request(:get, %r{^http://::1:9090/api/v1/query\?query=.*}) + .to_return( + status: 200, + body: [{}].to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + describe 'dump_sql_in_yaml' do + it 'dumps SQL queries in yaml format' do + expect { run_rake_task('gitlab:usage_data:dump_sql_in_yaml') }.to output(/.*recorded_at:.*/).to_stdout + end + end + + describe 'dump_sql_in_json' do + it 'dumps SQL queries in json format' do + expect { run_rake_task('gitlab:usage_data:dump_sql_in_json') }.to output(/.*"recorded_at":.*/).to_stdout + end + end +end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index f64ee4aa2f7..50d164d1705 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -27,7 +27,7 @@ RSpec.describe PostReceive do context 'with a non-existing project' do let(:gl_repository) { "project-123456789" } let(:error_message) do - "Triggered hook for non-existing project with gl_repository \"#{gl_repository}\"" + "Triggered hook for non-existing gl_repository \"#{gl_repository}\"" end it "returns false and logs an error" do @@ -314,7 +314,7 @@ RSpec.describe PostReceive do it 'processes the changes on the master branch' do expect_next_instance_of(Git::WikiPushService) do |service| - expect(service).to receive(:process_changes).and_call_original + expect(service).to receive(:execute).and_call_original end expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch) expect(project.wiki.repository).to receive(:raw).and_return(raw_repo) @@ -334,7 +334,7 @@ RSpec.describe PostReceive do before do allow_next_instance_of(Git::WikiPushService) do |service| - allow(service).to receive(:process_changes) + allow(service).to receive(:execute) end end |