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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-11 06:13:40 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-11 06:13:40 +0300
commit3e5f51c3717e31b741bca08639932cf6d63533c8 (patch)
tree4017a1b7a7494816a052f1ac3ebf509ddb04f915
parent2546306238465366ac0f0c8038ac4443dc82189e (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/models/member.rb3
-rw-r--r--app/models/members/group_member.rb7
-rw-r--r--app/models/members/project_member.rb7
-rw-r--r--app/services/notification_service.rb36
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/frontend/notes/components/note_form_spec.js114
-rw-r--r--spec/services/notification_service_spec.rb30
-rw-r--r--spec/support/shared_examples/models/members_notifications_shared_example.rb2
-rw-r--r--workhorse/go.mod2
-rw-r--r--workhorse/go.sum4
11 files changed, 78 insertions, 135 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 27d83a4a895..5f84ef38652 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-6583e7d21b0533866bcb1d812fa397f6f34cd3df
+13f08896b308c617c4a4ca585212069808422367
diff --git a/app/models/member.rb b/app/models/member.rb
index 9b3f1742dec..529666a069c 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class Member < ApplicationRecord
+ extend ::Gitlab::Utils::Override
include EachBatch
include AfterCommitQueue
include Sortable
@@ -576,7 +577,7 @@ class Member < ApplicationRecord
end
def after_decline_invite
- # override in subclass
+ notification_service.decline_invite(self)
end
def after_accept_request
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 3bbb7749ce4..aabc902fe03 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class GroupMember < Member
- extend ::Gitlab::Utils::Override
include FromUnion
include CreatedAtFilterable
@@ -108,12 +107,6 @@ class GroupMember < Member
super
end
- def after_decline_invite
- notification_service.decline_group_invite(self)
-
- super
- end
-
def send_welcome_email?
true
end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index ea47435f229..e0fecf702de 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class ProjectMember < Member
- extend ::Gitlab::Utils::Override
SOURCE_TYPE = 'Project'
SOURCE_TYPE_FORMAT = /\AProject\z/.freeze
@@ -146,12 +145,6 @@ class ProjectMember < Member
super
end
- def after_decline_invite
- notification_service.decline_project_invite(self)
-
- super
- end
-
# rubocop: disable CodeReuse/ServiceClass
def event_service
EventCreateService.new
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index c9b8e052bf6..b93b44ce797 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -492,6 +492,18 @@ class NotificationService
mailer.member_access_denied_email(member.real_source_type, member.source_id, member.user_id).deliver_later
end
+ def decline_invite(member)
+ # Must always send, regardless of project/namespace configuration since it's a
+ # response to the user's action.
+
+ mailer.member_invite_declined_email(
+ member.real_source_type,
+ member.source.id,
+ member.invite_email,
+ member.created_by_id
+ ).deliver_later
+ end
+
# Project invite
def invite_project_member(project_member, token)
return true unless project_member.notifiable?(:subscription)
@@ -505,18 +517,6 @@ class NotificationService
mailer.member_invite_accepted_email(project_member.real_source_type, project_member.id).deliver_later
end
- def decline_project_invite(project_member)
- # Must always send, regardless of project/namespace configuration since it's a
- # response to the user's action.
-
- mailer.member_invite_declined_email(
- project_member.real_source_type,
- project_member.project.id,
- project_member.invite_email,
- project_member.created_by_id
- ).deliver_later
- end
-
def new_project_member(project_member)
return true unless project_member.notifiable?(:mention, skip_read_ability: true)
@@ -542,18 +542,6 @@ class NotificationService
mailer.member_invite_accepted_email(group_member.real_source_type, group_member.id).deliver_later
end
- def decline_group_invite(group_member)
- # Must always send, regardless of project/namespace configuration since it's a
- # response to the user's action.
-
- mailer.member_invite_declined_email(
- group_member.real_source_type,
- group_member.group.id,
- group_member.invite_email,
- group_member.created_by_id
- ).deliver_later
- end
-
def new_group_member(group_member)
return true unless group_member.notifiable?(:mention)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fd265e61876..aa59278aa39 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -47060,13 +47060,13 @@ msgstr ""
msgid "UsageQuotas|An error occurred loading the transfer data. Please refresh the page to try again."
msgstr ""
-msgid "UsageQuotas|Namespace transfer data used"
+msgid "UsageQuotas|Container Registry storage statistics are not used to calculate the total project storage. After namespace container deduplication, the total of all unique containers is added to the namespace storage total."
msgstr ""
-msgid "UsageQuotas|The project-level storage statistics for the Container Registry are directional only and do not include savings for instance-wide deduplication."
+msgid "UsageQuotas|Namespace transfer data used"
msgstr ""
-msgid "UsageQuotas|This project-level storage statistic does not include savings for site-wide deduplication and is not used to calculate total namespace storage."
+msgid "UsageQuotas|The project-level storage statistics for the Container Registry are directional only and do not include savings for instance-wide deduplication."
msgstr ""
msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there are no limits set on pipeline usage"
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index 12c3b154fc7..00f75b14e6b 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,11 +1,12 @@
import { GlLink } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
import NoteForm from '~/notes/components/note_form.vue';
import createStore from '~/notes/stores';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { AT_WHO_ACTIVE_CLASS } from '~/gfm_auto_complete';
+import eventHub from '~/environments/event_hub';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { noteableDataMock, notesDataMock, discussionMock, note } from '../mock_data';
jest.mock('~/lib/utils/autosave');
@@ -14,23 +15,25 @@ describe('issue_note_form component', () => {
let store;
let wrapper;
let props;
- let features;
- const createComponentWrapper = () => {
- return mount(NoteForm, {
+ const createComponentWrapper = (propsData = {}, provide = {}) => {
+ wrapper = mountExtended(NoteForm, {
store,
- propsData: props,
+ propsData: {
+ ...props,
+ ...propsData,
+ },
provide: {
- glFeatures: features || {},
+ glFeatures: provide,
},
});
};
- const findCancelButton = () => wrapper.find('[data-testid="cancel"]');
+ const findCancelButton = () => wrapper.findByTestId('cancel');
+ const findCancelCommentButton = () => wrapper.findByTestId('cancelBatchCommentsEnabled');
+ const findMarkdownField = () => wrapper.findComponent(MarkdownField);
beforeEach(() => {
- features = {};
-
store = createStore();
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
@@ -44,7 +47,7 @@ describe('issue_note_form component', () => {
describe('noteHash', () => {
beforeEach(() => {
- wrapper = createComponentWrapper();
+ createComponentWrapper();
});
it('returns note hash string based on `noteId`', () => {
@@ -52,33 +55,29 @@ describe('issue_note_form component', () => {
});
it('return note hash as `#` when `noteId` is empty', async () => {
- wrapper.setProps({
- ...props,
+ createComponentWrapper({
noteId: '',
});
- await nextTick();
expect(wrapper.vm.noteHash).toBe('#');
});
});
it('hides content editor switcher if feature flag content_editor_on_issues is off', () => {
- features = { contentEditorOnIssues: false };
- wrapper = createComponentWrapper();
+ createComponentWrapper({}, { contentEditorOnIssues: false });
expect(wrapper.text()).not.toContain('Rich text');
});
it('shows content editor switcher if feature flag content_editor_on_issues is on', () => {
- features = { contentEditorOnIssues: true };
- wrapper = createComponentWrapper();
+ createComponentWrapper({}, { contentEditorOnIssues: true });
expect(wrapper.text()).toContain('Rich text');
});
describe('conflicts editing', () => {
beforeEach(() => {
- wrapper = createComponentWrapper();
+ createComponentWrapper();
});
it('should show conflict message if note changes outside the component', async () => {
@@ -102,15 +101,13 @@ describe('issue_note_form component', () => {
describe('form', () => {
beforeEach(() => {
- wrapper = createComponentWrapper();
+ createComponentWrapper();
});
it('should render text area with placeholder', () => {
const textarea = wrapper.find('textarea');
- expect(textarea.attributes('placeholder')).toEqual(
- 'Write a comment or drag your files here…',
- );
+ expect(textarea.attributes('placeholder')).toBe('Write a comment or drag your files here…');
});
it('should set data-supports-quick-actions to enable autocomplete', () => {
@@ -130,7 +127,7 @@ describe('issue_note_form component', () => {
...note,
internal,
};
- wrapper = createComponentWrapper();
+ createComponentWrapper();
await nextTick();
@@ -139,11 +136,7 @@ describe('issue_note_form component', () => {
);
it('should link to markdown docs', () => {
- const { markdownDocsPath } = notesDataMock;
- const markdownField = wrapper.findComponent(MarkdownField);
- const markdownFieldProps = markdownField.props();
-
- expect(markdownFieldProps.markdownDocsPath).toBe(markdownDocsPath);
+ expect(findMarkdownField().props('markdownDocsPath')).toBe(notesDataMock.markdownDocsPath);
});
describe('keyboard events', () => {
@@ -156,12 +149,11 @@ describe('issue_note_form component', () => {
describe('up', () => {
it('should ender edit mode', () => {
- // TODO: do not spy on vm
- jest.spyOn(wrapper.vm, 'editMyLastNote');
+ const eventHubSpy = jest.spyOn(eventHub, '$emit');
textarea.trigger('keydown.up');
- expect(wrapper.vm.editMyLastNote).toHaveBeenCalled();
+ expect(eventHubSpy).not.toHaveBeenCalled();
});
});
@@ -169,17 +161,13 @@ describe('issue_note_form component', () => {
it('should save note when cmd+enter is pressed', () => {
textarea.trigger('keydown.enter', { metaKey: true });
- const { handleFormUpdate } = wrapper.emitted();
-
- expect(handleFormUpdate.length).toBe(1);
+ expect(wrapper.emitted('handleFormUpdate')).toHaveLength(1);
});
it('should save note when ctrl+enter is pressed', () => {
textarea.trigger('keydown.enter', { ctrlKey: true });
- const { handleFormUpdate } = wrapper.emitted();
-
- expect(handleFormUpdate.length).toBe(1);
+ expect(wrapper.emitted('handleFormUpdate')).toHaveLength(1);
});
it('should disable textarea when ctrl+enter is pressed', async () => {
@@ -195,24 +183,16 @@ describe('issue_note_form component', () => {
});
describe('actions', () => {
- it('should be possible to cancel', async () => {
- wrapper.setProps({
- ...props,
- });
- await nextTick();
+ it('should be possible to cancel', () => {
+ createComponentWrapper();
- const cancelButton = findCancelButton();
- cancelButton.vm.$emit('click');
- await nextTick();
+ findCancelButton().vm.$emit('click');
- expect(wrapper.emitted().cancelForm).toHaveLength(1);
+ expect(wrapper.emitted('cancelForm')).toHaveLength(1);
});
it('will not cancel form if there is an active at-who-active class', async () => {
- wrapper.setProps({
- ...props,
- });
- await nextTick();
+ createComponentWrapper();
const textareaEl = wrapper.vm.$refs.markdownEditor.$el.querySelector('textarea');
const cancelButton = findCancelButton();
@@ -220,21 +200,18 @@ describe('issue_note_form component', () => {
cancelButton.vm.$emit('click');
await nextTick();
- expect(wrapper.emitted().cancelForm).toBeUndefined();
+ expect(wrapper.emitted('cancelForm')).toBeUndefined();
});
it('should be possible to update the note', async () => {
- wrapper.setProps({
- ...props,
- });
- await nextTick();
+ createComponentWrapper();
const textarea = wrapper.find('textarea');
textarea.setValue('Foo');
const saveButton = wrapper.find('.js-vue-issue-save');
saveButton.vm.$emit('click');
- expect(wrapper.vm.isSubmitting).toBe(true);
+ expect(wrapper.emitted('handleFormUpdate')).toHaveLength(1);
});
});
});
@@ -243,9 +220,7 @@ describe('issue_note_form component', () => {
beforeEach(() => {
store.registerModule('batchComments', batchComments());
- wrapper = createComponentWrapper();
- wrapper.setProps({
- ...props,
+ createComponentWrapper({
isDraft: true,
noteId: '',
discussion: { ...discussionMock, for_commit: false },
@@ -253,13 +228,9 @@ describe('issue_note_form component', () => {
});
it('should be possible to cancel', async () => {
- jest.spyOn(wrapper.vm, 'cancelHandler');
-
- await nextTick();
- const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
- cancelButton.vm.$emit('click');
+ findCancelCommentButton().vm.$emit('click');
- expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
+ expect(wrapper.emitted('cancelForm')).toEqual([[true, false]]);
});
it('shows resolve checkbox', () => {
@@ -267,7 +238,7 @@ describe('issue_note_form component', () => {
});
it('hides resolve checkbox', async () => {
- wrapper.setProps({
+ createComponentWrapper({
isDraft: false,
discussion: {
...discussionMock,
@@ -282,15 +253,11 @@ describe('issue_note_form component', () => {
},
});
- await nextTick();
-
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
});
it('hides actions for commits', async () => {
- wrapper.setProps({ discussion: { for_commit: true } });
-
- await nextTick();
+ createComponentWrapper({ discussion: { for_commit: true } });
expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
});
@@ -299,13 +266,12 @@ describe('issue_note_form component', () => {
it('should start review or add to review when cmd+enter is pressed', async () => {
const textarea = wrapper.find('textarea');
- jest.spyOn(wrapper.vm, 'handleAddToReview');
-
textarea.setValue('Foo');
textarea.trigger('keydown.enter', { metaKey: true });
await nextTick();
- expect(wrapper.vm.handleAddToReview).toHaveBeenCalled();
+
+ expect(wrapper.emitted('handleFormUpdateAddToReview')).toEqual([['Foo', false]]);
});
});
});
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 15e430ddc74..f63f982708d 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -253,6 +253,16 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
it_behaves_like 'participating by assignee notification', check_delivery_jobs_queue: check_delivery_jobs_queue
end
+ shared_examples 'declines the invite' do
+ specify do
+ member = source.members.last
+
+ expect do
+ notification.decline_invite(member)
+ end.to change { ActionMailer::Base.deliveries.size }.by(1)
+ end
+ end
+
describe '.permitted_actions' do
it 'includes public methods' do
expect(described_class.permitted_actions).to include(:access_token_created)
@@ -3029,7 +3039,7 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
end
end
- describe '#decline_group_invite' do
+ describe '#decline_invite' do
let(:creator) { create(:user) }
let(:group) { create(:group) }
let(:member) { create(:user) }
@@ -3039,12 +3049,8 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
group.add_developer(member, creator)
end
- it do
- group_member = group.members.last
-
- expect do
- notification.decline_group_invite(group_member)
- end.to change { ActionMailer::Base.deliveries.size }.by(1)
+ it_behaves_like 'declines the invite' do
+ let(:source) { group }
end
end
@@ -3201,19 +3207,15 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
end
end
- describe '#decline_project_invite' do
+ describe '#decline_invite' do
let(:member) { create(:user) }
before do
project.add_developer(member, current_user: project.first_owner)
end
- it do
- project_member = project.members.last
-
- expect do
- notification.decline_project_invite(project_member)
- end.to change { ActionMailer::Base.deliveries.size }.by(1)
+ it_behaves_like 'declines the invite' do
+ let(:source) { project }
end
end
diff --git a/spec/support/shared_examples/models/members_notifications_shared_example.rb b/spec/support/shared_examples/models/members_notifications_shared_example.rb
index e28220334ac..329cb812a08 100644
--- a/spec/support/shared_examples/models/members_notifications_shared_example.rb
+++ b/spec/support/shared_examples/models/members_notifications_shared_example.rb
@@ -69,7 +69,7 @@ RSpec.shared_examples 'members notifications' do |entity_type|
let(:member) { create(:"#{entity_type}_member", :invited) }
it "calls NotificationService.decline_#{entity_type}_invite" do
- expect(notification_service).to receive(:"decline_#{entity_type}_invite").with(member)
+ expect(notification_service).to receive(:decline_invite).with(member)
member.decline_invite!
end
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 6a989942523..a9d5e533653 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -26,7 +26,7 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/smartystreets/goconvey v1.7.2
github.com/stretchr/testify v1.8.2
- gitlab.com/gitlab-org/gitaly/v15 v15.10.0
+ gitlab.com/gitlab-org/gitaly/v15 v15.10.1
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
gitlab.com/gitlab-org/labkit v1.18.0
gocloud.dev v0.29.0
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 3868d8edf66..45447c67e2c 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -1918,8 +1918,8 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
-gitlab.com/gitlab-org/gitaly/v15 v15.10.0 h1:l6K7AuaK3LPB9FaVk0tLtpPEX7eXEvVgPzRQGRq1FJc=
-gitlab.com/gitlab-org/gitaly/v15 v15.10.0/go.mod h1:ZsyTd8zGxT4WuSZJ0G8ydJb60mauzEP0XJtZJEy/7bc=
+gitlab.com/gitlab-org/gitaly/v15 v15.10.1 h1:43RZwVktIZLOq2GsRvQVUWZ4YiKPEueoWnmzz3T/UWk=
+gitlab.com/gitlab-org/gitaly/v15 v15.10.1/go.mod h1:ZsyTd8zGxT4WuSZJ0G8ydJb60mauzEP0XJtZJEy/7bc=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE=
gitlab.com/gitlab-org/labkit v1.18.0 h1:uYCIqDt/5V1hLIecTR4UNc1sD2+xiYplyKeyfpNN26A=