diff options
Diffstat (limited to 'spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js')
-rw-r--r-- | spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js | 157 |
1 files changed, 110 insertions, 47 deletions
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js index 4d2d53c990e..dff1c429d07 100644 --- a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js +++ b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js @@ -3,16 +3,24 @@ import VueApollo from 'vue-apollo'; import Vue from 'vue'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import IncidentTimelineEventList from '~/issues/show/components/incidents/timeline_events_list.vue'; -import IncidentTimelineEventListItem from '~/issues/show/components/incidents/timeline_events_item.vue'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import IncidentTimelineEventItem from '~/issues/show/components/incidents/timeline_events_item.vue'; +import EditTimelineEvent from '~/issues/show/components/incidents/edit_timeline_event.vue'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import deleteTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/delete_timeline_event.mutation.graphql'; +import editTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/edit_timeline_event.mutation.graphql'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { useFakeDate } from 'helpers/fake_date'; import { createAlert } from '~/flash'; import { mockEvents, timelineEventsDeleteEventResponse, timelineEventsDeleteEventError, + timelineEventsEditEventResponse, + timelineEventsEditEventError, + fakeDate, + fakeEventData, + mockInputData, } from './mock_data'; Vue.use(VueApollo); @@ -20,83 +28,73 @@ Vue.use(VueApollo); jest.mock('~/flash'); jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'); -const deleteEventResponse = jest.fn(); - -function createMockApolloProvider() { - deleteEventResponse.mockResolvedValue(timelineEventsDeleteEventResponse); - const requestHandlers = [[deleteTimelineEventMutation, deleteEventResponse]]; - return createMockApollo(requestHandlers); -} - const mockConfirmAction = ({ confirmed }) => { confirmAction.mockResolvedValueOnce(confirmed); }; describe('IncidentTimelineEventList', () => { + useFakeDate(fakeDate); let wrapper; + const deleteResponseSpy = jest.fn().mockResolvedValue(timelineEventsDeleteEventResponse); + const editResponseSpy = jest.fn().mockResolvedValue(timelineEventsEditEventResponse); - const mountComponent = (mockApollo) => { - const apollo = mockApollo ? { apolloProvider: mockApollo } : {}; + const requestHandlers = [ + [deleteTimelineEventMutation, deleteResponseSpy], + [editTimelineEventMutation, editResponseSpy], + ]; + const apolloProvider = createMockApollo(requestHandlers); - wrapper = shallowMountExtended(IncidentTimelineEventList, { + const mountComponent = () => { + wrapper = mountExtended(IncidentTimelineEventList, { + propsData: { + timelineEvents: mockEvents, + }, provide: { fullPath: 'group/project', issuableId: '1', + canUpdateTimelineEvent: true, }, - propsData: { - timelineEvents: mockEvents, - }, - ...apollo, + apolloProvider, }); }; const findTimelineEventGroups = () => wrapper.findAllByTestId('timeline-group'); - const findItems = (base = wrapper) => base.findAll(IncidentTimelineEventListItem); + const findItems = (base = wrapper) => base.findAllComponents(IncidentTimelineEventItem); const findFirstTimelineEventGroup = () => findTimelineEventGroups().at(0); const findSecondTimelineEventGroup = () => findTimelineEventGroups().at(1); const findDates = () => wrapper.findAllByTestId('event-date'); const clickFirstDeleteButton = async () => { - findItems() - .at(0) - .vm.$emit('delete', { ...mockEvents[0] }); + findItems().at(0).vm.$emit('delete', { fakeEventData }); await waitForPromises(); }; + const clickFirstEditButton = async () => { + findItems().at(0).vm.$emit('edit'); + await waitForPromises(); + }; + beforeEach(() => { + mountComponent(); + }); + afterEach(() => { - confirmAction.mockReset(); - deleteEventResponse.mockReset(); wrapper.destroy(); }); describe('template', () => { it('groups items correctly', () => { - mountComponent(); - expect(findTimelineEventGroups()).toHaveLength(2); expect(findItems(findFirstTimelineEventGroup())).toHaveLength(1); expect(findItems(findSecondTimelineEventGroup())).toHaveLength(2); }); - it('sets the isLastItem prop correctly', () => { - mountComponent(); - - expect(findItems().at(0).props('isLastItem')).toBe(false); - expect(findItems().at(1).props('isLastItem')).toBe(false); - expect(findItems().at(2).props('isLastItem')).toBe(true); - }); - it('sets the event props correctly', () => { - mountComponent(); - expect(findItems().at(1).props('occurredAt')).toBe(mockEvents[1].occurredAt); expect(findItems().at(1).props('action')).toBe(mockEvents[1].action); expect(findItems().at(1).props('noteHtml')).toBe(mockEvents[1].noteHtml); }); it('formats dates correctly', () => { - mountComponent(); - expect(findDates().at(0).text()).toBe('2022-03-22'); expect(findDates().at(1).text()).toBe('2022-03-23'); }); @@ -110,8 +108,6 @@ describe('IncidentTimelineEventList', () => { describe(timezone, () => { beforeEach(() => { timezoneMock.register(timezone); - - mountComponent(); }); afterEach(() => { @@ -131,12 +127,9 @@ describe('IncidentTimelineEventList', () => { it('should delete when button is clicked', async () => { const expectedVars = { input: { id: mockEvents[0].id } }; - - mountComponent(createMockApolloProvider()); - await clickFirstDeleteButton(); - expect(deleteEventResponse).toHaveBeenCalledWith(expectedVars); + expect(deleteResponseSpy).toHaveBeenCalledWith(expectedVars); }); it('should show an error when delete returns an error', async () => { @@ -144,8 +137,7 @@ describe('IncidentTimelineEventList', () => { message: 'Error deleting incident timeline event: Item does not exist', }; - mountComponent(createMockApolloProvider()); - deleteEventResponse.mockResolvedValue(timelineEventsDeleteEventError); + deleteResponseSpy.mockResolvedValue(timelineEventsDeleteEventError); await clickFirstDeleteButton(); @@ -158,8 +150,7 @@ describe('IncidentTimelineEventList', () => { error: new Error(), message: 'Something went wrong while deleting the incident timeline event.', }; - mountComponent(createMockApolloProvider()); - deleteEventResponse.mockRejectedValueOnce(); + deleteResponseSpy.mockRejectedValueOnce(); await clickFirstDeleteButton(); @@ -167,4 +158,76 @@ describe('IncidentTimelineEventList', () => { }); }); }); + + describe('Edit Functionality', () => { + beforeEach(() => { + mountComponent(); + clickFirstEditButton(); + }); + + const findEditEvent = () => wrapper.findComponent(EditTimelineEvent); + const mockSaveData = { ...fakeEventData, ...mockInputData }; + + describe('editTimelineEvent', () => { + it('should call the mutation with the right variables', async () => { + await findEditEvent().vm.$emit('handle-save-edit', mockSaveData); + await waitForPromises(); + + expect(editResponseSpy).toHaveBeenCalledWith({ + input: mockSaveData, + }); + }); + + it('should close the form on successful addition', async () => { + await findEditEvent().vm.$emit('handle-save-edit', mockSaveData); + await waitForPromises(); + + expect(findEditEvent().exists()).toBe(false); + }); + + it('should close the form on cancel', async () => { + await findEditEvent().vm.$emit('hide-edit'); + await waitForPromises(); + + expect(findEditEvent().exists()).toBe(false); + }); + }); + + describe('error handling', () => { + it('should show an error when submission returns an error', async () => { + const expectedAlertArgs = { + message: `Error updating incident timeline event: ${timelineEventsEditEventError.data.timelineEventUpdate.errors[0]}`, + }; + editResponseSpy.mockResolvedValueOnce(timelineEventsEditEventError); + + await findEditEvent().vm.$emit('handle-save-edit', mockSaveData); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs); + }); + + it('should show an error when submission fails', async () => { + const expectedAlertArgs = { + captureError: true, + error: new Error(), + message: 'Something went wrong while updating the incident timeline event.', + }; + editResponseSpy.mockRejectedValueOnce(); + + await findEditEvent().vm.$emit('handle-save-edit', mockSaveData); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs); + }); + + it('should keep the form open on failed addition', async () => { + editResponseSpy.mockResolvedValueOnce(timelineEventsEditEventError); + + await findEditEvent().vm.$emit('handle-save-edit', mockSaveData); + await waitForPromises(); + + expect(findEditEvent().exists()).toBe(true); + }); + }); + }); }); |