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-12-19 15:10:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-19 15:10:37 +0300
commita4db97517ad095914c0652a07486ac607d99dab4 (patch)
tree58f57b42c52b1b4231cab44ef3934cbe55991d25 /spec/frontend
parent17295c75a1a28df78f719e0098dd31fe45ce0446 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/organizations/settings/general/components/organization_settings_spec.js61
-rw-r--r--spec/frontend/organizations/shared/components/new_edit_form_spec.js39
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js36
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/avatar_upload_dropzone_spec.js116
4 files changed, 245 insertions, 7 deletions
diff --git a/spec/frontend/organizations/settings/general/components/organization_settings_spec.js b/spec/frontend/organizations/settings/general/components/organization_settings_spec.js
index d1c637331a8..eca6d9fdc4a 100644
--- a/spec/frontend/organizations/settings/general/components/organization_settings_spec.js
+++ b/spec/frontend/organizations/settings/general/components/organization_settings_spec.js
@@ -5,7 +5,11 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import OrganizationSettings from '~/organizations/settings/general/components/organization_settings.vue';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import NewEditForm from '~/organizations/shared/components/new_edit_form.vue';
-import { FORM_FIELD_NAME, FORM_FIELD_ID } from '~/organizations/shared/constants';
+import {
+ FORM_FIELD_NAME,
+ FORM_FIELD_ID,
+ FORM_FIELD_AVATAR,
+} from '~/organizations/shared/constants';
import organizationUpdateMutation from '~/organizations/settings/general/graphql/mutations/organization_update.mutation.graphql';
import {
organizationUpdateResponse,
@@ -38,22 +42,27 @@ describe('OrganizationSettings', () => {
},
};
+ const file = new File(['foo'], 'foo.jpg', {
+ type: 'text/plain',
+ });
+
const successfulResponseHandler = jest.fn().mockResolvedValue(organizationUpdateResponse);
const createComponent = ({
handlers = [[organizationUpdateMutation, successfulResponseHandler]],
+ provide = {},
} = {}) => {
mockApollo = createMockApollo(handlers);
wrapper = shallowMountExtended(OrganizationSettings, {
- provide: defaultProvide,
+ provide: { ...defaultProvide, ...provide },
apolloProvider: mockApollo,
});
};
const findForm = () => wrapper.findComponent(NewEditForm);
- const submitForm = async () => {
- findForm().vm.$emit('submit', { name: 'Foo bar', path: 'foo-bar' });
+ const submitForm = async (data = {}) => {
+ findForm().vm.$emit('submit', { name: 'Foo bar', path: 'foo-bar', avatar: file, ...data });
await nextTick();
};
@@ -75,7 +84,7 @@ describe('OrganizationSettings', () => {
expect(findForm().props()).toMatchObject({
loading: false,
initialFormValues: defaultProvide.organization,
- fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID],
+ fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_AVATAR],
});
});
@@ -108,6 +117,7 @@ describe('OrganizationSettings', () => {
input: {
id: 'gid://gitlab/Organizations::Organization/1',
name: 'Foo bar',
+ avatar: file,
},
});
expect(visitUrlWithAlerts).toHaveBeenCalledWith(window.location.href, [
@@ -162,5 +172,46 @@ describe('OrganizationSettings', () => {
});
});
});
+
+ describe('when organization has avatar', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: { organization: { ...defaultProvide.organization, avatar: 'avatar.jpg' } },
+ });
+ });
+
+ describe('when avatar is explicitly removed', () => {
+ beforeEach(async () => {
+ await submitForm({ avatar: null });
+ await waitForPromises();
+ });
+
+ it('sets `avatar` argument to `null`', () => {
+ expect(successfulResponseHandler).toHaveBeenCalledWith({
+ input: {
+ id: 'gid://gitlab/Organizations::Organization/1',
+ name: 'Foo bar',
+ avatar: null,
+ },
+ });
+ });
+ });
+
+ describe('when avatar is not changed', () => {
+ beforeEach(async () => {
+ await submitForm({ avatar: 'avatar.jpg' });
+ await waitForPromises();
+ });
+
+ it('does not pass `avatar` argument', () => {
+ expect(successfulResponseHandler).toHaveBeenCalledWith({
+ input: {
+ id: 'gid://gitlab/Organizations::Organization/1',
+ name: 'Foo bar',
+ },
+ });
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/organizations/shared/components/new_edit_form_spec.js b/spec/frontend/organizations/shared/components/new_edit_form_spec.js
index 1fcfc20bf1a..4897a81fc1c 100644
--- a/spec/frontend/organizations/shared/components/new_edit_form_spec.js
+++ b/spec/frontend/organizations/shared/components/new_edit_form_spec.js
@@ -3,7 +3,13 @@ import { nextTick } from 'vue';
import NewEditForm from '~/organizations/shared/components/new_edit_form.vue';
import OrganizationUrlField from '~/organizations/shared/components/organization_url_field.vue';
-import { FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_PATH } from '~/organizations/shared/constants';
+import AvatarUploadDropzone from '~/vue_shared/components/upload_dropzone/avatar_upload_dropzone.vue';
+import {
+ FORM_FIELD_NAME,
+ FORM_FIELD_ID,
+ FORM_FIELD_PATH,
+ FORM_FIELD_AVATAR,
+} from '~/organizations/shared/constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
describe('NewEditForm', () => {
@@ -32,6 +38,7 @@ describe('NewEditForm', () => {
const findNameField = () => wrapper.findByLabelText('Organization name');
const findIdField = () => wrapper.findByLabelText('Organization ID');
const findUrlField = () => wrapper.findComponent(OrganizationUrlField);
+ const findAvatarField = () => wrapper.findComponent(AvatarUploadDropzone);
const setUrlFieldValue = async (value) => {
findUrlField().vm.$emit('input', value);
@@ -53,6 +60,32 @@ describe('NewEditForm', () => {
expect(findUrlField().exists()).toBe(true);
});
+ it('renders `Organization avatar` field', () => {
+ createComponent();
+
+ expect(findAvatarField().props()).toMatchObject({
+ value: null,
+ entity: { [FORM_FIELD_NAME]: '', [FORM_FIELD_PATH]: '', [FORM_FIELD_AVATAR]: null },
+ label: 'Organization avatar',
+ });
+ });
+
+ describe('when `Organization avatar` field is changed', () => {
+ const file = new File(['foo'], 'foo.jpg', {
+ type: 'text/plain',
+ });
+
+ beforeEach(() => {
+ window.URL.revokeObjectURL = jest.fn();
+ createComponent();
+ findAvatarField().vm.$emit('input', file);
+ });
+
+ it('updates `value` prop', () => {
+ expect(findAvatarField().props('value')).toEqual(file);
+ });
+ });
+
it('requires `Organization URL` field to be a minimum of two characters', async () => {
createComponent();
@@ -125,7 +158,9 @@ describe('NewEditForm', () => {
});
it('emits `submit` event with form values', () => {
- expect(wrapper.emitted('submit')).toEqual([[{ name: 'Foo bar', path: 'foo-bar' }]]);
+ expect(wrapper.emitted('submit')).toEqual([
+ [{ name: 'Foo bar', path: 'foo-bar', avatar: null }],
+ ]);
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
index 1b7338744e8..adbf4e1d371 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -858,6 +858,42 @@ describe('ReadyToMerge', () => {
});
});
+ describe('only allow merge if pipeline succeeds', () => {
+ beforeEach(() => {
+ const response = JSON.parse(JSON.stringify(readyToMergeResponse));
+ response.data.project.onlyAllowMergeIfPipelineSucceeds = true;
+ response.data.project.mergeRequest.headPipeline = {
+ id: 1,
+ active: true,
+ status: '',
+ path: '',
+ };
+
+ readyToMergeResponseSpy = jest.fn().mockResolvedValueOnce(response);
+ });
+
+ it('hides merge immediately dropdown when subscription returns', async () => {
+ createComponent({ mr: { id: 1 } });
+
+ await waitForPromises();
+
+ expect(findMergeImmediatelyDropdown().exists()).toBe(false);
+
+ mockedSubscription.next({
+ data: {
+ mergeRequestMergeStatusUpdated: {
+ ...readyToMergeResponse.data.project.mergeRequest,
+ headPipeline: { id: 1, active: true, status: '', path: '' },
+ },
+ },
+ });
+
+ await waitForPromises();
+
+ expect(findMergeImmediatelyDropdown().exists()).toBe(false);
+ });
+ });
+
describe('commit message', () => {
it('updates commit message from subscription', async () => {
createComponent({ mr: { id: 1 } });
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/avatar_upload_dropzone_spec.js b/spec/frontend/vue_shared/components/upload_dropzone/avatar_upload_dropzone_spec.js
new file mode 100644
index 00000000000..6313bf588a0
--- /dev/null
+++ b/spec/frontend/vue_shared/components/upload_dropzone/avatar_upload_dropzone_spec.js
@@ -0,0 +1,116 @@
+import { GlAvatar, GlButton, GlTruncate } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import AvatarUploadDropzone from '~/vue_shared/components/upload_dropzone/avatar_upload_dropzone.vue';
+import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
+import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
+
+describe('AvatarUploadDropzone', () => {
+ let wrapper;
+
+ const defaultPropsData = {
+ entity: { id: 1, name: 'Foo' },
+ value: null,
+ label: 'Avatar',
+ };
+
+ const file = new File(['foo'], 'foo.jpg', {
+ type: 'text/plain',
+ });
+ const file2 = new File(['bar'], 'bar.jpg', {
+ type: 'text/plain',
+ });
+ const blob = 'blob:http://127.0.0.1:3000/0046cf8c-ea21-4720-91ef-2e354d570c75';
+
+ const createComponent = ({ propsData = {} } = {}) => {
+ wrapper = shallowMountExtended(AvatarUploadDropzone, {
+ propsData: {
+ ...defaultPropsData,
+ ...propsData,
+ },
+ });
+ };
+
+ const findUploadDropzone = () => wrapper.findComponent(UploadDropzone);
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ beforeEach(() => {
+ window.URL.createObjectURL = jest.fn().mockImplementation(() => blob);
+ window.URL.revokeObjectURL = jest.fn();
+ });
+
+ it('renders `GlAvatar` with correct props', () => {
+ createComponent();
+
+ expect(wrapper.findComponent(GlAvatar).props()).toMatchObject({
+ entityId: defaultPropsData.entity.id,
+ entityName: defaultPropsData.entity.name,
+ shape: AVATAR_SHAPE_OPTION_RECT,
+ size: 96,
+ src: null,
+ });
+ });
+
+ it('renders label', () => {
+ createComponent();
+
+ expect(wrapper.findByText(defaultPropsData.label).exists()).toBe(true);
+ });
+
+ describe('when `value` prop is updated', () => {
+ beforeEach(() => {
+ createComponent();
+
+ // setProps is justified here because we are testing the component's
+ // reactive behavior which constitutes an exception
+ // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+ wrapper.setProps({ value: file });
+ });
+
+ it('updates `GlAvatar` `src` prop', () => {
+ expect(wrapper.findComponent(GlAvatar).props('src')).toBe(blob);
+ });
+
+ it('renders remove button', () => {
+ expect(findButton().exists()).toBe(true);
+ });
+
+ it('renders truncated file name', () => {
+ expect(wrapper.findComponent(GlTruncate).props('text')).toBe('foo.jpg');
+ });
+
+ it('does not render upload dropzone', () => {
+ expect(findUploadDropzone().exists()).toBe(false);
+ });
+
+ describe('when `value` prop is updated a second time', () => {
+ beforeEach(() => {
+ wrapper.setProps({ value: file2 });
+ });
+
+ it('revokes the object URL of the previous avatar', () => {
+ expect(window.URL.revokeObjectURL).toHaveBeenCalledWith(blob);
+ });
+ });
+
+ describe('when avatar is removed', () => {
+ beforeEach(() => {
+ findButton().vm.$emit('click');
+ });
+
+ it('emits `input` event with `null` payload', () => {
+ expect(wrapper.emitted('input')).toEqual([[null]]);
+ });
+ });
+ });
+
+ describe('when `UploadDropzone` emits `change` event', () => {
+ beforeEach(() => {
+ createComponent();
+ findUploadDropzone().vm.$emit('change', file);
+ });
+
+ it('emits `input` event', () => {
+ expect(wrapper.emitted('input')).toEqual([[file]]);
+ });
+ });
+});