Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-10 00:08:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-10 00:08:33 +0300
commitb296ffa543e23f57fa2692539e6f0028c59e2203 (patch)
treef5224a37cac088506d1c8fd53925ee1d9fd2a02c /spec
parentc172bb9967f280e05bd904188d60a959dff10f00 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/alert_management/components/alert_details_spec.js6
-rw-r--r--spec/frontend/boards/boards_store_spec.js2
-rw-r--r--spec/frontend/boards/list_spec.js1
-rw-r--r--spec/frontend/boards/mock_data.js23
-rw-r--r--spec/frontend/boards/stores/actions_spec.js39
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js55
-rw-r--r--spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap14
-rw-r--r--spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap14
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js6
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js8
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js20
-rw-r--r--spec/frontend/design_management/components/design_sidebar_spec.js8
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js4
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/alert_detail_table_spec.js74
-rw-r--r--spec/graphql/types/current_user_todos_type_spec.rb9
-rw-r--r--spec/graphql/types/design_management/design_type_spec.rb4
-rw-r--r--spec/graphql/types/issue_type_spec.rb4
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb4
-rw-r--r--spec/lib/backup/manager_spec.rb23
-rw-r--r--spec/lib/gitlab/data_builder/deployment_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_queries_spec.rb21
-rw-r--r--spec/lib/object_storage/config_spec.rb41
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb3
-rw-r--r--spec/models/event_spec.rb7
-rw-r--r--spec/models/project_services/chat_message/merge_message_spec.rb69
-rw-r--r--spec/models/project_wiki_spec.rb13
-rw-r--r--spec/policies/project_policy_spec.rb73
-rw-r--r--spec/requests/api/graphql/current_user_todos_spec.rb81
-rw-r--r--spec/services/git/wiki_push_service_spec.rb38
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb6
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb57
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb12
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb28
-rw-r--r--spec/workers/post_receive_spec.rb6
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