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>2021-02-05 18:09:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-05 18:09:28 +0300
commit4046c3447e0a01fe48e224e72e12b27859b92822 (patch)
tree63b8293134d5cc6030abc7a5d2aeb34a34f54925 /spec/frontend/notifications
parent64f7eb2b37aebbb713463b2f6971b13191c1b0db (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/notifications')
-rw-r--r--spec/frontend/notifications/components/custom_notifications_modal_spec.js267
-rw-r--r--spec/frontend/notifications/components/notifications_dropdown_spec.js34
2 files changed, 301 insertions, 0 deletions
diff --git a/spec/frontend/notifications/components/custom_notifications_modal_spec.js b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
new file mode 100644
index 00000000000..192fc194015
--- /dev/null
+++ b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
@@ -0,0 +1,267 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf, GlModal, GlFormGroup, GlFormCheckbox, GlLoadingIcon } from '@gitlab/ui';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import httpStatus from '~/lib/utils/http_status';
+import CustomNotificationsModal from '~/notifications/components/custom_notifications_modal.vue';
+import { i18n } from '~/notifications/constants';
+
+const mockNotificationSettingsResponses = {
+ default: {
+ level: 'custom',
+ events: {
+ new_release: true,
+ new_note: false,
+ },
+ },
+ updated: {
+ level: 'custom',
+ events: {
+ new_release: true,
+ new_note: true,
+ },
+ },
+};
+
+const mockToastShow = jest.fn();
+
+describe('CustomNotificationsModal', () => {
+ let wrapper;
+ let mockAxios;
+
+ function createComponent(options = {}) {
+ const { injectedProperties = {}, props = {} } = options;
+ return extendedWrapper(
+ shallowMount(CustomNotificationsModal, {
+ props: {
+ ...props,
+ },
+ provide: {
+ ...injectedProperties,
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ stubs: {
+ GlModal,
+ GlFormGroup,
+ GlFormCheckbox,
+ },
+ }),
+ );
+ }
+
+ const findModalBodyDescription = () => wrapper.find(GlSprintf);
+ const findAllCheckboxes = () => wrapper.findAll(GlFormCheckbox);
+ const findCheckboxAt = (index) => findAllCheckboxes().at(index);
+
+ beforeEach(() => {
+ gon.api_version = 'v4';
+ mockAxios = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mockAxios.restore();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('displays the body title and the body message', () => {
+ expect(wrapper.findByTestId('modalBodyTitle').text()).toBe(
+ i18n.customNotificationsModal.bodyTitle,
+ );
+ expect(findModalBodyDescription().attributes('message')).toContain(
+ i18n.customNotificationsModal.bodyMessage,
+ );
+ });
+
+ describe('checkbox items', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: true },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it.each`
+ index | eventId | eventName | enabled | loading
+ ${0} | ${'new_release'} | ${'New release'} | ${true} | ${false}
+ ${1} | ${'new_note'} | ${'New note'} | ${false} | ${true}
+ `(
+ 'renders a checkbox for "$eventName" with checked=$enabled',
+ async ({ index, eventName, enabled, loading }) => {
+ const checkbox = findCheckboxAt(index);
+ expect(checkbox.text()).toContain(eventName);
+ expect(checkbox.vm.$attrs.checked).toBe(enabled);
+ expect(checkbox.find(GlLoadingIcon).exists()).toBe(loading);
+ },
+ );
+ });
+ });
+
+ describe('API calls', () => {
+ describe('load notification settings', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'get');
+ });
+
+ it.each`
+ projectId | groupId | endpointUrl | notificationType | condition
+ ${1} | ${null} | ${'/api/v4/projects/1/notification_settings'} | ${'project'} | ${'a projectId is given'}
+ ${null} | ${1} | ${'/api/v4/groups/1/notification_settings'} | ${'group'} | ${'a groupId is given'}
+ ${null} | ${null} | ${'/api/v4/notification_settings'} | ${'global'} | ${'neither projectId nor groupId are given'}
+ `(
+ 'requests $notificationType notification settings when $condition',
+ async ({ projectId, groupId, endpointUrl }) => {
+ const injectedProperties = {
+ projectId,
+ groupId,
+ };
+
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ wrapper = createComponent({ injectedProperties });
+
+ wrapper.find(GlModal).vm.$emit('show');
+
+ await waitForPromises();
+
+ expect(axios.get).toHaveBeenCalledWith(endpointUrl);
+ },
+ );
+
+ it('updates the loading state and the events property', async () => {
+ const endpointUrl = '/api/v4/notification_settings';
+
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ wrapper = createComponent();
+
+ wrapper.find(GlModal).vm.$emit('show');
+ expect(wrapper.vm.isLoading).toBe(true);
+
+ await waitForPromises();
+
+ expect(axios.get).toHaveBeenCalledWith(endpointUrl);
+ expect(wrapper.vm.isLoading).toBe(false);
+ expect(wrapper.vm.events).toEqual([
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ]);
+ });
+
+ it('shows a toast message when the request fails', async () => {
+ mockAxios.onGet('/api/v4/notification_settings').reply(httpStatus.NOT_FOUND, {});
+ wrapper = createComponent();
+
+ wrapper.find(GlModal).vm.$emit('show');
+
+ await waitForPromises();
+
+ expect(
+ mockToastShow,
+ ).toHaveBeenCalledWith(
+ 'An error occured while loading the notification settings. Please try again.',
+ { type: 'error' },
+ );
+ });
+ });
+
+ describe('update notification settings', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'put');
+ });
+
+ it.each`
+ projectId | groupId | endpointUrl | notificationType | condition
+ ${1} | ${null} | ${'/api/v4/projects/1/notification_settings'} | ${'project'} | ${'a projectId is given'}
+ ${null} | ${1} | ${'/api/v4/groups/1/notification_settings'} | ${'group'} | ${'a groupId is given'}
+ ${null} | ${null} | ${'/api/v4/notification_settings'} | ${'global'} | ${'neither projectId nor groupId are given'}
+ `(
+ 'updates the $notificationType notification settings when $condition and the user clicks the checkbox ',
+ async ({ projectId, groupId, endpointUrl }) => {
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ mockAxios
+ .onPut(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.updated);
+
+ const injectedProperties = {
+ projectId,
+ groupId,
+ };
+
+ wrapper = createComponent({ injectedProperties });
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ findCheckboxAt(1).vm.$emit('change', true);
+
+ await waitForPromises();
+
+ expect(axios.put).toHaveBeenCalledWith(endpointUrl, {
+ new_note: true,
+ });
+
+ expect(wrapper.vm.events).toEqual([
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: true, name: 'New note', loading: false },
+ ]);
+ },
+ );
+
+ it('shows a toast message when the request fails', async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.NOT_FOUND, {});
+ wrapper = createComponent();
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ findCheckboxAt(1).vm.$emit('change', true);
+
+ await waitForPromises();
+
+ expect(
+ mockToastShow,
+ ).toHaveBeenCalledWith(
+ 'An error occured while updating the notification settings. Please try again.',
+ { type: 'error' },
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notifications/components/notifications_dropdown_spec.js b/spec/frontend/notifications/components/notifications_dropdown_spec.js
index 2fe8e9c677e..37926f6f1bc 100644
--- a/spec/frontend/notifications/components/notifications_dropdown_spec.js
+++ b/spec/frontend/notifications/components/notifications_dropdown_spec.js
@@ -7,6 +7,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import httpStatus from '~/lib/utils/http_status';
import NotificationsDropdown from '~/notifications/components/notifications_dropdown.vue';
import NotificationsDropdownItem from '~/notifications/components/notifications_dropdown_item.vue';
+import CustomNotificationsModal from '~/notifications/components/custom_notifications_modal.vue';
const mockDropdownItems = ['global', 'watch', 'participating', 'mention', 'disabled'];
const mockToastShow = jest.fn();
@@ -14,17 +15,26 @@ const mockToastShow = jest.fn();
describe('NotificationsDropdown', () => {
let wrapper;
let mockAxios;
+ let glModalDirective;
function createComponent(injectedProperties = {}) {
+ glModalDirective = jest.fn();
+
return shallowMount(NotificationsDropdown, {
stubs: {
GlButtonGroup,
GlDropdown,
GlDropdownItem,
NotificationsDropdownItem,
+ CustomNotificationsModal,
},
directives: {
GlTooltip: createMockDirective(),
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
},
provide: {
dropdownItems: mockDropdownItems,
@@ -94,6 +104,19 @@ describe('NotificationsDropdown', () => {
expect(findButton().text()).toBe('');
});
+
+ it('opens the modal when the user clicks the button', async () => {
+ jest.spyOn(axios, 'put');
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.OK, {});
+
+ wrapper = createComponent({
+ initialNotificationLevel: 'custom',
+ });
+
+ findButton().vm.$emit('click');
+
+ expect(glModalDirective).toHaveBeenCalled();
+ });
});
describe('when notification level is not "custom"', () => {
@@ -236,5 +259,16 @@ describe('NotificationsDropdown', () => {
{ type: 'error' },
);
});
+
+ it('opens the modal when the user clicks on the "Custom" dropdown item', async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.OK, {});
+ wrapper = createComponent();
+
+ const mockModalShow = jest.spyOn(wrapper.vm.$refs.customNotificationsModal, 'open');
+
+ await clickDropdownItemAt(5);
+
+ expect(mockModalShow).toHaveBeenCalled();
+ });
});
});