summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-10 03:07:43 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-10 03:07:43 +0000
commit677227413ae31f5a02fd4c8e10f6ef50c228334f (patch)
treefbd07453cf1aaded55f081bb42fa043b3f3ffc2b
parent3f22924df411018ba665ecf72ab0768d61173477 (diff)
downloadgitlab-ce-677227413ae31f5a02fd4c8e10f6ef50c228334f.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/dropzone_input.js2
-rw-r--r--app/assets/javascripts/notes/components/attachments_warning.vue18
-rw-r--r--app/assets/javascripts/notes/components/comment_field_layout.vue17
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue5
-rw-r--r--app/assets/javascripts/notes/i18n.js3
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue47
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue1
-rw-r--r--app/controllers/projects/issues_controller.rb1
-rw-r--r--app/mailers/emails/service_desk.rb2
-rw-r--r--config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml8
-rw-r--r--db/post_migrate/20230201082038_drop_web_hook_calls_high_column.rb23
-rw-r--r--db/schema_migrations/202302010820381
-rw-r--r--db/structure.sql4
-rw-r--r--doc/ci/yaml/index.md1
-rw-r--r--doc/user/project/merge_requests/status_checks.md6
-rw-r--r--locale/gitlab.pot12
-rw-r--r--spec/features/projects/issues/email_participants_spec.rb14
-rw-r--r--spec/frontend/notes/components/attachments_warning_spec.js16
-rw-r--r--spec/frontend/notes/components/comment_field_layout_spec.js64
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_list_spec.js28
-rw-r--r--spec/mailers/emails/service_desk_spec.rb2
21 files changed, 214 insertions, 61 deletions
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index e6f7a31e07b..f90d29c84b8 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -87,8 +87,8 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const processingFileCount = this.getQueuedFiles().length + this.getUploadingFiles().length;
const shouldPad = processingFileCount >= 1;
+ addFileToForm(response.link.url, header.size);
pasteText(response.link.markdown, shouldPad);
- addFileToForm(response.link.url);
},
error: (file, errorMessage = __('Attaching the file failed.'), xhr) => {
// If 'error' event is fired by dropzone, the second parameter is error message.
diff --git a/app/assets/javascripts/notes/components/attachments_warning.vue b/app/assets/javascripts/notes/components/attachments_warning.vue
new file mode 100644
index 00000000000..aaa4b0d92b9
--- /dev/null
+++ b/app/assets/javascripts/notes/components/attachments_warning.vue
@@ -0,0 +1,18 @@
+<script>
+import { COMMENT_FORM } from '../i18n';
+
+export default {
+ i18n: COMMENT_FORM.attachmentMsg,
+ data() {
+ return {
+ message: this.$options.i18n,
+ };
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-note-warning" data-testid="attachment-warning">
+ {{ message }}
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/comment_field_layout.vue b/app/assets/javascripts/notes/components/comment_field_layout.vue
index 84bda1b0b5c..cc372520c70 100644
--- a/app/assets/javascripts/notes/components/comment_field_layout.vue
+++ b/app/assets/javascripts/notes/components/comment_field_layout.vue
@@ -1,14 +1,18 @@
<script>
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
import EmailParticipantsWarning from './email_participants_warning.vue';
+import AttachmentsWarning from './attachments_warning.vue';
const DEFAULT_NOTEABLE_TYPE = 'Issue';
export default {
components: {
+ AttachmentsWarning,
EmailParticipantsWarning,
NoteableWarning,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
noteableData: {
type: Object,
@@ -29,6 +33,11 @@ export default {
required: false,
default: false,
},
+ containsLink: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
isLocked() {
@@ -46,6 +55,13 @@ export default {
showEmailParticipantsWarning() {
return this.emailParticipants.length && !this.isInternalNote;
},
+ showAttachmentWarning() {
+ return (
+ this.glFeatures.serviceDeskNewNoteEmailNativeAttachments &&
+ this.showEmailParticipantsWarning &&
+ this.containsLink
+ );
+ },
},
};
</script>
@@ -68,6 +84,7 @@ export default {
:confidential-noteable-docs-path="noteableData.confidential_issues_docs_path"
/>
<slot></slot>
+ <attachments-warning v-if="showAttachmentWarning" />
<email-participants-warning
v-if="showEmailParticipantsWarning"
class="gl-border-t-1 gl-border-t-solid gl-border-t-gray-100 gl-rounded-base gl-rounded-top-left-none! gl-rounded-top-right-none!"
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index c6e7117cf2e..4f7256d0b0e 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -28,6 +28,7 @@ import CommentTypeDropdown from './comment_type_dropdown.vue';
import DiscussionLockedWidget from './discussion_locked_widget.vue';
import NoteSignedOutWidget from './note_signed_out_widget.vue';
+const ATTACHMENT_REGEXP = /!?\[.*?\]\(\/uploads\/[0-9a-f]{32}\/.*?\)/;
export default {
name: 'CommentForm',
i18n: COMMENT_FORM,
@@ -176,6 +177,9 @@ export default {
disableSubmitButton() {
return this.note.length === 0 || this.isSubmitting;
},
+ containsLink() {
+ return ATTACHMENT_REGEXP.test(this.note);
+ },
},
mounted() {
// jQuery is needed here because it is a custom event being dispatched with jQuery.
@@ -356,6 +360,7 @@ export default {
:noteable-data="getNoteableData"
:is-internal-note="noteIsInternal"
:noteable-type="noteableType"
+ :contains-link="containsLink"
>
<markdown-field
ref="markdownField"
diff --git a/app/assets/javascripts/notes/i18n.js b/app/assets/javascripts/notes/i18n.js
index 9b5fd69f816..a758a55014a 100644
--- a/app/assets/javascripts/notes/i18n.js
+++ b/app/assets/javascripts/notes/i18n.js
@@ -45,4 +45,7 @@ export const COMMENT_FORM = {
commentHelp: __('Add a general comment to this %{noteableDisplayName}.'),
internalCommentHelp: __('Add a confidential internal note to this %{noteableDisplayName}.'),
},
+ attachmentMsg: s__(
+ 'Notes|Attachments are sent by email. Attachments over 10 MB are sent as links to your GitLab instance, and only accessible to project members.',
+ ),
};
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
index d07d0a7673f..7485f8282ee 100644
--- a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
@@ -1,6 +1,5 @@
<script>
import { GlButton, GlFormCheckbox, GlKeysetPagination } from '@gitlab/ui';
-import { filter } from 'lodash';
import { __ } from '~/locale';
export default {
@@ -52,24 +51,31 @@ export default {
return this.pagination.hasPreviousPage || this.pagination.hasNextPage;
},
disableDeleteButton() {
- return this.isLoading || filter(this.selectedReferences).length === 0;
+ return this.isLoading || this.selectedItems.length === 0;
},
selectedItems() {
return this.items.filter(this.isSelected);
},
- selectAll: {
- get() {
- return this.items.every(this.isSelected);
- },
- set(value) {
- this.items.forEach((item) => {
- const id = item[this.idProperty];
- this.$set(this.selectedReferences, id, value);
- });
- },
+ disabled() {
+ return this.items.length === 0;
+ },
+ checked() {
+ return this.items.every(this.isSelected);
+ },
+ indeterminate() {
+ return !this.checked && this.items.some(this.isSelected);
+ },
+ label() {
+ return this.checked ? __('Unselect all') : __('Select all');
},
},
methods: {
+ onChange(event) {
+ this.items.forEach((item) => {
+ const id = item[this.idProperty];
+ this.$set(this.selectedReferences, id, event);
+ });
+ },
selectItem(item) {
const id = item[this.idProperty];
this.$set(this.selectedReferences, id, !this.selectedReferences[id]);
@@ -80,7 +86,7 @@ export default {
},
},
i18n: {
- deleteSelected: __('Delete Selected'),
+ deleteSelected: __('Delete selected'),
},
};
</script>
@@ -91,9 +97,18 @@ export default {
v-if="!hiddenDelete"
class="gl-display-flex gl-justify-content-space-between gl-mb-3 gl-align-items-center"
>
- <gl-form-checkbox v-model="selectAll" class="gl-ml-2 gl-pt-2">
- <span class="gl-font-weight-bold">{{ title }}</span>
- </gl-form-checkbox>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-form-checkbox
+ class="gl-ml-2 gl-pt-2"
+ :aria-label="label"
+ :checked="checked"
+ :disabled="disabled"
+ :indeterminate="indeterminate"
+ @change="onChange"
+ />
+
+ <p class="gl-font-weight-bold gl-mb-0">{{ title }}</p>
+ </div>
<gl-button
:disabled="disableDeleteButton"
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
index 66c8238a865..5d0ee6adffe 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -33,6 +33,7 @@ export default {
'gl-border-t-transparent': !this.first && !this.selected,
'gl-border-t-gray-100': this.first && !this.selected,
'gl-border-b-gray-100': !this.selected,
+ 'gl-border-t-transparent!': this.selected && !this.first,
'gl-bg-blue-50 gl-border-blue-200': this.selected,
};
},
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 6f0b3ad1f35..3731257033d 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -46,6 +46,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:preserve_unchanged_markdown, project)
push_frontend_feature_flag(:content_editor_on_issues, project)
+ push_frontend_feature_flag(:service_desk_new_note_email_native_attachments, project)
end
before_action only: [:index, :show] do
diff --git a/app/mailers/emails/service_desk.rb b/app/mailers/emails/service_desk.rb
index ef0dd4fd2f9..835abacbed5 100644
--- a/app/mailers/emails/service_desk.rb
+++ b/app/mailers/emails/service_desk.rb
@@ -63,7 +63,7 @@ module Emails
next unless template_body = template_content(email_type)
options[:body] = template_body
- options[:content_type] = 'text/html'
+ options[:content_type] = 'text/html' unless attachments.present?
end
end
diff --git a/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml b/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml
deleted file mode 100644
index b8d1b1f4175..00000000000
--- a/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: only_allow_merge_if_all_status_checks_passed
-introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96765"
-rollout_issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/372340"
-milestone: '15.5'
-type: development
-group: group::compliance
-default_enabled: true
diff --git a/db/post_migrate/20230201082038_drop_web_hook_calls_high_column.rb b/db/post_migrate/20230201082038_drop_web_hook_calls_high_column.rb
new file mode 100644
index 00000000000..7f90b3293d8
--- /dev/null
+++ b/db/post_migrate/20230201082038_drop_web_hook_calls_high_column.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class DropWebHookCallsHighColumn < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ if column_exists?(:plan_limits, :web_hook_calls_high) # rubocop:disable Style/IfUnlessModifier
+ remove_column :plan_limits, :web_hook_calls_high
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ unless column_exists?(:plan_limits, :web_hook_calls_high)
+ # rubocop:disable Migration/SchemaAdditionMethodsNoPost
+ add_column :plan_limits, :web_hook_calls_high, :integer, default: 0
+ # rubocop:enable Migration/SchemaAdditionMethodsNoPost
+ end
+ end
+ end
+end
diff --git a/db/schema_migrations/20230201082038 b/db/schema_migrations/20230201082038
new file mode 100644
index 00000000000..b7e1ee666db
--- /dev/null
+++ b/db/schema_migrations/20230201082038
@@ -0,0 +1 @@
+0b735c9ccd267734fd4c4f6f15f6dfac67ec212786e4c31d75b73e2fae537617 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 067e8646819..0c9612dc425 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -19745,9 +19745,7 @@ CREATE TABLE plan_limits (
enforcement_limit integer DEFAULT 0 NOT NULL,
notification_limit integer DEFAULT 0 NOT NULL,
dashboard_limit_enabled_at timestamp with time zone,
- web_hook_calls_high integer DEFAULT 0,
- web_hook_calls integer DEFAULT 0 NOT NULL,
- CONSTRAINT check_0fa68f370e CHECK ((web_hook_calls_high IS NOT NULL))
+ web_hook_calls integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index dfe4ac7446e..dd36d649227 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -1116,6 +1116,7 @@ Caches are:
- Shared between pipelines and jobs.
- By default, not shared between [protected](../../user/project/protected_branches.md) and unprotected branches.
- Restored before [artifacts](#artifacts).
+- Limited to a maximum of four [different caches](../caching/index.md#use-multiple-caches).
You can [disable caching for specific jobs](../caching/index.md#disable-cache-for-specific-jobs),
for example to override:
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index dadb1b392d9..c9f63ffd3da 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -31,11 +31,7 @@ see the [external status checks epic](https://gitlab.com/groups/gitlab-org/-/epi
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369859) in GitLab 15.5 [with a flag](../../../administration/feature_flags.md) named `only_allow_merge_if_all_status_checks_passed`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/372340) in GitLab 15.8.
-> - Enabled on self-managed in GitLab 15.9.
-
-FLAG:
-On self-managed GitLab, this feature is available by default. To disable it per project or for your entire instance, ask an administrator to
-[disable the feature flag](../../../administration/feature_flags.md) named `only_allow_merge_if_all_status_checks_passed`. On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
+> - Enabled on self-managed and feature flag [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111492) in GitLab 15.9.
By default, merge requests in projects can be merged even if external status checks fail. To block the merging of merge requests when external checks fail:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 39e9d8e1f11..02dcf7d0398 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13356,9 +13356,6 @@ msgstr ""
msgid "Delete Key"
msgstr ""
-msgid "Delete Selected"
-msgstr ""
-
msgid "Delete Value Stream"
msgstr ""
@@ -13434,6 +13431,9 @@ msgstr ""
msgid "Delete row"
msgstr ""
+msgid "Delete selected"
+msgstr ""
+
msgid "Delete self-monitoring project"
msgstr ""
@@ -28488,6 +28488,9 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Attachments are sent by email. Attachments over 10 MB are sent as links to your GitLab instance, and only accessible to project members."
+msgstr ""
+
msgid "Notes|Collapse replies"
msgstr ""
@@ -40887,9 +40890,6 @@ msgstr ""
msgid "StatusCheck|Check for a status response in merge requests. %{link_start}Learn more%{link_end}."
msgstr ""
-msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
-msgstr ""
-
msgid "StatusCheck|Examples: QA, Security."
msgstr ""
diff --git a/spec/features/projects/issues/email_participants_spec.rb b/spec/features/projects/issues/email_participants_spec.rb
index 753c4ea18c5..a902c8294d7 100644
--- a/spec/features/projects/issues/email_participants_spec.rb
+++ b/spec/features/projects/issues/email_participants_spec.rb
@@ -65,4 +65,18 @@ RSpec.describe 'viewing an issue', :js, feature_category: :service_desk do
end
end
end
+
+ context 'for feature flags' do
+ before do
+ sign_in(user)
+ end
+
+ it 'pushes service_desk_new_note_email_native_attachments feature flag to frontend' do
+ stub_feature_flags(service_desk_new_note_email_native_attachments: true)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_pushed_frontend_feature_flags(serviceDeskNewNoteEmailNativeAttachments: true)
+ end
+ end
end
diff --git a/spec/frontend/notes/components/attachments_warning_spec.js b/spec/frontend/notes/components/attachments_warning_spec.js
new file mode 100644
index 00000000000..0e99c26ed2b
--- /dev/null
+++ b/spec/frontend/notes/components/attachments_warning_spec.js
@@ -0,0 +1,16 @@
+import { mount } from '@vue/test-utils';
+import AttachmentsWarning from '~/notes/components/attachments_warning.vue';
+
+describe('Attachments Warning Component', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = mount(AttachmentsWarning);
+ });
+
+ it('shows warning', () => {
+ const expected =
+ 'Attachments are sent by email. Attachments over 10 MB are sent as links to your GitLab instance, and only accessible to project members.';
+ expect(wrapper.text()).toBe(expected);
+ });
+});
diff --git a/spec/frontend/notes/components/comment_field_layout_spec.js b/spec/frontend/notes/components/comment_field_layout_spec.js
index 6662492fd81..93b54f95021 100644
--- a/spec/frontend/notes/components/comment_field_layout_spec.js
+++ b/spec/frontend/notes/components/comment_field_layout_spec.js
@@ -1,17 +1,13 @@
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import CommentFieldLayout from '~/notes/components/comment_field_layout.vue';
+import AttachmentsWarning from '~/notes/components/attachments_warning.vue';
import EmailParticipantsWarning from '~/notes/components/email_participants_warning.vue';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
describe('Comment Field Layout Component', () => {
let wrapper;
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const LOCKED_DISCUSSION_DOCS_PATH = 'docs/locked/path';
const CONFIDENTIAL_ISSUES_DOCS_PATH = 'docs/confidential/path';
@@ -22,18 +18,32 @@ describe('Comment Field Layout Component', () => {
confidential_issues_docs_path: CONFIDENTIAL_ISSUES_DOCS_PATH,
};
+ const commentFieldWithAttachmentData = {
+ noteableData: {
+ ...noteableDataMock,
+ issue_email_participants: [{ email: 'someone@gitlab.com' }, { email: 'another@gitlab.com' }],
+ },
+ containsLink: true,
+ };
+
const findIssuableNoteWarning = () => wrapper.findComponent(NoteableWarning);
const findEmailParticipantsWarning = () => wrapper.findComponent(EmailParticipantsWarning);
+ const findAttachmentsWarning = () => wrapper.findComponent(AttachmentsWarning);
const findErrorAlert = () => wrapper.findByTestId('comment-field-alert-container');
- const createWrapper = (props = {}, slots = {}) => {
+ const createWrapper = (props = {}, provide = {}) => {
wrapper = extendedWrapper(
shallowMount(CommentFieldLayout, {
propsData: {
noteableData: noteableDataMock,
...props,
},
- slots,
+ provide: {
+ glFeatures: {
+ serviceDeskNewNoteEmailNativeAttachments: true,
+ },
+ ...provide,
+ },
}),
);
};
@@ -108,23 +118,25 @@ describe('Comment Field Layout Component', () => {
expect(findEmailParticipantsWarning().exists()).toBe(false);
});
+
+ it('does not show AttachmentWarning', () => {
+ createWrapper();
+
+ expect(findAttachmentsWarning().exists()).toBe(false);
+ });
});
describe('issue has email participants', () => {
beforeEach(() => {
- createWrapper({
- noteableData: {
- ...noteableDataMock,
- issue_email_participants: [
- { email: 'someone@gitlab.com' },
- { email: 'another@gitlab.com' },
- ],
- },
- });
+ createWrapper(commentFieldWithAttachmentData);
});
it('shows EmailParticipantsWarning', () => {
- expect(findEmailParticipantsWarning().isVisible()).toBe(true);
+ expect(findEmailParticipantsWarning().exists()).toBe(true);
+ });
+
+ it('shows AttachmentsWarning', () => {
+ expect(findAttachmentsWarning().isVisible()).toBe(true);
});
it('sets EmailParticipantsWarning props', () => {
@@ -148,4 +160,22 @@ describe('Comment Field Layout Component', () => {
expect(findEmailParticipantsWarning().exists()).toBe(false);
});
});
+
+ describe('serviceDeskNewNoteEmailNativeAttachments flag', () => {
+ it('shows warning message when flag is enabled', () => {
+ createWrapper(commentFieldWithAttachmentData, {
+ glFeatures: { serviceDeskNewNoteEmailNativeAttachments: true },
+ });
+
+ expect(findAttachmentsWarning().exists()).toBe(true);
+ });
+
+ it('shows warning message when flag is disables', () => {
+ createWrapper(commentFieldWithAttachmentData, {
+ glFeatures: { serviceDeskNewNoteEmailNativeAttachments: false },
+ });
+
+ expect(findAttachmentsWarning().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
index aaca58d21bb..2e2d5e26d33 100644
--- a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
@@ -54,6 +54,28 @@ describe('Registry List', () => {
it('exists', () => {
expect(findSelectAll().exists()).toBe(true);
+ expect(findSelectAll().attributes('aria-label')).toBe('Select all');
+ expect(findSelectAll().attributes('disabled')).toBeUndefined();
+ expect(findSelectAll().attributes('indeterminate')).toBeUndefined();
+ });
+
+ it('sets disabled prop to true when items length is 0', () => {
+ mountComponent({ propsData: { ...defaultPropsData, items: [] } });
+
+ expect(findSelectAll().attributes('disabled')).toBe('true');
+ });
+
+ it('when few are selected, sets indeterminate prop to true', async () => {
+ await findScopedSlotSelectButton(0).trigger('click');
+
+ expect(findSelectAll().attributes('indeterminate')).toBe('true');
+ });
+
+ it('when all are selected, sets the right checkbox label', async () => {
+ findSelectAll().vm.$emit('change', true);
+ await nextTick();
+
+ expect(findSelectAll().attributes('aria-label')).toBe('Unselect all');
});
it('select and unselect all', async () => {
@@ -63,7 +85,7 @@ describe('Registry List', () => {
});
// simulate selection
- findSelectAll().vm.$emit('input', true);
+ findSelectAll().vm.$emit('change', true);
await nextTick();
// all rows selected
@@ -72,12 +94,12 @@ describe('Registry List', () => {
});
// simulate de-selection
- findSelectAll().vm.$emit('input', '');
+ findSelectAll().vm.$emit('change', false);
await nextTick();
// no row is not selected
items.forEach((item, index) => {
- expect(findScopedSlotIsSelectedValue(index).text()).toBe('');
+ expect(findScopedSlotIsSelectedValue(index).text()).toBe('false');
});
});
});
diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb
index e753bf2c76c..1f55aabc535 100644
--- a/spec/mailers/emails/service_desk_spec.rb
+++ b/spec/mailers/emails/service_desk_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe Emails::ServiceDesk do
is_expected.to have_referable_subject(issue, include_project: false, reply: reply_in_subject)
is_expected.to have_body_text(expected_body)
expect(subject.attachments.count).to eq(attachments_count.to_i)
- expect(subject.content_type).to include('text/html')
+ expect(subject.content_type).to include(attachments_count.to_i > 0 ? 'multipart/mixed' : 'text/html')
end
end
end