diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-13 21:09:27 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-13 21:09:27 +0300 |
commit | 5248c5e2212b8e42b28b23e6839d69db0006829b (patch) | |
tree | f989d4b4cd06fc5dc28c024a5f230b42b0af179b /spec/frontend/admin | |
parent | 0d55697d64b5f053bbd0f69da2962e7478097de3 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/admin')
3 files changed, 255 insertions, 0 deletions
diff --git a/spec/frontend/admin/broadcast_messages/components/datetime_picker_spec.js b/spec/frontend/admin/broadcast_messages/components/datetime_picker_spec.js new file mode 100644 index 00000000000..291c3aed1cf --- /dev/null +++ b/spec/frontend/admin/broadcast_messages/components/datetime_picker_spec.js @@ -0,0 +1,46 @@ +import { mount } from '@vue/test-utils'; +import { GlDatepicker } from '@gitlab/ui'; +import DatetimePicker from '~/admin/broadcast_messages/components/datetime_picker.vue'; + +describe('DatetimePicker', () => { + let wrapper; + + const toDate = (day, time) => new Date(`${day}T${time}:00.000Z`); + const findDatepicker = () => wrapper.findComponent(GlDatepicker); + const findTimepicker = () => wrapper.findComponent('[data-testid="time-picker"]'); + + const testDay = '2022-03-22'; + const testTime = '01:23'; + + function createComponent() { + wrapper = mount(DatetimePicker, { + propsData: { + value: toDate(testDay, testTime), + }, + }); + } + + beforeEach(() => { + createComponent(); + }); + + it('renders the Date in the datepicker and timepicker inputs', () => { + expect(findDatepicker().props().value).toEqual(toDate(testDay, testTime)); + expect(findTimepicker().element.value).toEqual(testTime); + }); + + it('emits Date with the new day/old time when the date picker changes', () => { + const newDay = '1992-06-30'; + const newTime = '08:00'; + + findDatepicker().vm.$emit('input', toDate(newDay, newTime)); + expect(wrapper.emitted().input).toEqual([[toDate(newDay, testTime)]]); + }); + + it('emits Date with the old day/new time when the time picker changes', () => { + const newTime = '08:00'; + + findTimepicker().vm.$emit('input', newTime); + expect(wrapper.emitted().input).toEqual([[toDate(testDay, newTime)]]); + }); +}); diff --git a/spec/frontend/admin/broadcast_messages/components/message_form_spec.js b/spec/frontend/admin/broadcast_messages/components/message_form_spec.js new file mode 100644 index 00000000000..88ea79f38b3 --- /dev/null +++ b/spec/frontend/admin/broadcast_messages/components/message_form_spec.js @@ -0,0 +1,201 @@ +import { mount } from '@vue/test-utils'; +import { GlBroadcastMessage, GlForm } from '@gitlab/ui'; +import AxiosMockAdapter from 'axios-mock-adapter'; +import { createAlert } from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import httpStatus from '~/lib/utils/http_status'; +import MessageForm from '~/admin/broadcast_messages/components/message_form.vue'; +import { + BROADCAST_MESSAGES_PATH, + TYPE_BANNER, + TYPE_NOTIFICATION, + THEMES, +} from '~/admin/broadcast_messages/constants'; +import waitForPromises from 'helpers/wait_for_promises'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import { MOCK_TARGET_ACCESS_LEVELS } from '../mock_data'; + +jest.mock('~/flash'); + +describe('MessageForm', () => { + let wrapper; + let axiosMock; + + const defaultProps = { + message: 'zzzzzzz', + broadcastType: TYPE_BANNER, + theme: THEMES[0].value, + dismissable: false, + targetPath: '', + targetAccessLevels: [], + startsAt: new Date(), + endsAt: new Date(), + }; + + const findPreview = () => extendedWrapper(wrapper.findComponent(GlBroadcastMessage)); + const findThemeSelect = () => wrapper.findComponent('[data-testid=theme-select]'); + const findDismissable = () => wrapper.findComponent('[data-testid=dismissable-checkbox]'); + const findTargetRoles = () => wrapper.findComponent('[data-testid=target-roles-checkboxes]'); + const findSubmitButton = () => wrapper.findComponent('[data-testid=submit-button]'); + const findForm = () => wrapper.findComponent(GlForm); + + function createComponent({ broadcastMessage = {}, glFeatures = {} }) { + wrapper = mount(MessageForm, { + provide: { + glFeatures, + targetAccessLevelOptions: MOCK_TARGET_ACCESS_LEVELS, + }, + propsData: { + broadcastMessage: { + ...defaultProps, + ...broadcastMessage, + }, + }, + }); + } + + beforeEach(() => { + axiosMock = new AxiosMockAdapter(axios); + }); + + afterEach(() => { + axiosMock.restore(); + createAlert.mockClear(); + }); + + describe('the message preview', () => { + it('renders the preview with the user selected theme', () => { + const theme = 'blue'; + createComponent({ broadcastMessage: { theme } }); + expect(findPreview().props().theme).toEqual(theme); + }); + + it('renders the placeholder text when the user message is blank', () => { + createComponent({ broadcastMessage: { message: ' ' } }); + expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.messagePlaceholder); + }); + }); + + describe('theme select dropdown', () => { + it('renders for Banners', () => { + createComponent({ broadcastMessage: { broadcastType: TYPE_BANNER } }); + expect(findThemeSelect().exists()).toBe(true); + }); + + it('does not render for Notifications', () => { + createComponent({ broadcastMessage: { broadcastType: TYPE_NOTIFICATION } }); + expect(findThemeSelect().exists()).toBe(false); + }); + }); + + describe('dismissable checkbox', () => { + it('renders for Banners', () => { + createComponent({ broadcastMessage: { broadcastType: TYPE_BANNER } }); + expect(findDismissable().exists()).toBe(true); + }); + + it('does not render for Notifications', () => { + createComponent({ broadcastMessage: { broadcastType: TYPE_NOTIFICATION } }); + expect(findDismissable().exists()).toBe(false); + }); + }); + + describe('target roles checkboxes', () => { + it('renders when roleTargetedBroadcastMessages feature is enabled', () => { + createComponent({ glFeatures: { roleTargetedBroadcastMessages: true } }); + expect(findTargetRoles().exists()).toBe(true); + }); + + it('does not render when roleTargetedBroadcastMessages feature is disabled', () => { + createComponent({ glFeatures: { roleTargetedBroadcastMessages: false } }); + expect(findTargetRoles().exists()).toBe(false); + }); + }); + + describe('form submit button', () => { + it('renders the "add" text when the message is not persisted', () => { + createComponent({ broadcastMessage: { id: undefined } }); + expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.add); + }); + + it('renders the "update" text when the message is persisted', () => { + createComponent({ broadcastMessage: { id: 100 } }); + expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.update); + }); + + it('is disabled when the user message is blank', () => { + createComponent({ broadcastMessage: { message: ' ' } }); + expect(findSubmitButton().props().disabled).toBe(true); + }); + + it('is not disabled when the user message is present', () => { + createComponent({ broadcastMessage: { message: 'alsdjfkldsj' } }); + expect(findSubmitButton().props().disabled).toBe(false); + }); + }); + + describe('form submission', () => { + const defaultPayload = { + message: defaultProps.message, + broadcast_type: defaultProps.broadcastType, + theme: defaultProps.theme, + dismissable: defaultProps.dismissable, + target_path: defaultProps.targetPath, + target_access_levels: defaultProps.targetAccessLevels, + starts_at: defaultProps.startsAt, + ends_at: defaultProps.endsAt, + }; + + it('sends a create request for a new message form', async () => { + createComponent({ broadcastMessage: { id: undefined } }); + findForm().vm.$emit('submit', { preventDefault: () => {} }); + await waitForPromises(); + + expect(axiosMock.history.post).toHaveLength(1); + expect(axiosMock.history.post[0]).toMatchObject({ + url: BROADCAST_MESSAGES_PATH, + data: JSON.stringify(defaultPayload), + }); + }); + + it('shows an error alert if the create request fails', async () => { + createComponent({ broadcastMessage: { id: undefined } }); + axiosMock.onPost(BROADCAST_MESSAGES_PATH).replyOnce(httpStatus.BAD_REQUEST); + findForm().vm.$emit('submit', { preventDefault: () => {} }); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith( + expect.objectContaining({ + message: wrapper.vm.$options.i18n.addError, + }), + ); + }); + + it('sends an update request for a persisted message form', async () => { + const id = 1337; + createComponent({ broadcastMessage: { id } }); + findForm().vm.$emit('submit', { preventDefault: () => {} }); + await waitForPromises(); + + expect(axiosMock.history.patch).toHaveLength(1); + expect(axiosMock.history.patch[0]).toMatchObject({ + url: `${BROADCAST_MESSAGES_PATH}/${id}`, + data: JSON.stringify(defaultPayload), + }); + }); + + it('shows an error alert if the update request fails', async () => { + const id = 1337; + createComponent({ broadcastMessage: { id } }); + axiosMock.onPost(`${BROADCAST_MESSAGES_PATH}/${id}`).replyOnce(httpStatus.BAD_REQUEST); + findForm().vm.$emit('submit', { preventDefault: () => {} }); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith( + expect.objectContaining({ + message: wrapper.vm.$options.i18n.updateError, + }), + ); + }); + }); +}); diff --git a/spec/frontend/admin/broadcast_messages/mock_data.js b/spec/frontend/admin/broadcast_messages/mock_data.js index 8dd98c2319d..2e20b5cf638 100644 --- a/spec/frontend/admin/broadcast_messages/mock_data.js +++ b/spec/frontend/admin/broadcast_messages/mock_data.js @@ -15,3 +15,11 @@ export const generateMockMessages = (n) => [...Array(n).keys()].map((id) => generateMockMessage(id + 1)); export const MOCK_MESSAGES = generateMockMessages(5).map((id) => generateMockMessage(id)); + +export const MOCK_TARGET_ACCESS_LEVELS = [ + ['Guest', 10], + ['Reporter', 20], + ['Developer', 30], + ['Maintainer', 40], + ['Owner', 50], +]; |