Skip to content
Snippets Groups Projects
Commit a82efcb5 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo :two:
Browse files

Merge branch '344060-split-create-timeline-event-from-form' into 'master'

Split Create timeline event from Timeline Event form

See merge request !93545
parents 2761b8fc 4e767d1b
No related branches found
No related tags found
2 merge requests!96059Draft: Add GraphQL query for deployment details,!93545Split Create timeline event from Timeline Event form
Pipeline #615364589 passed
import { s__ } from '~/locale';
import { __, s__ } from '~/locale';
export const timelineTabI18n = Object.freeze({
title: s__('Incident|Timeline'),
......@@ -12,6 +12,9 @@ export const timelineFormI18n = Object.freeze({
'Incident|Something went wrong while creating the incident timeline event.',
),
areaPlaceholder: s__('Incident|Timeline text...'),
save: __('Save'),
cancel: __('Cancel'),
description: __('Description'),
saveAndAdd: s__('Incident|Save and add another event'),
areaLabel: s__('Incident|Timeline text'),
});
......
<script>
import { produce } from 'immer';
import { sortBy } from 'lodash';
import { sprintf } from '~/locale';
import { createAlert } from '~/flash';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPE_ISSUE } from '~/graphql_shared/constants';
import { timelineFormI18n } from './constants';
import TimelineEventsForm from './timeline_events_form.vue';
import CreateTimelineEvent from './graphql/queries/create_timeline_event.mutation.graphql';
import getTimelineEvents from './graphql/queries/get_timeline_events.query.graphql';
export default {
name: 'CreateTimelineEvent',
i18n: timelineFormI18n,
components: {
TimelineEventsForm,
},
inject: ['fullPath', 'issuableId'],
props: {
hasTimelineEvents: {
type: Boolean,
required: true,
},
},
data() {
return { createTimelineEventActive: false };
},
methods: {
clearForm() {
this.$refs.eventForm.clear();
},
focusDate() {
this.$refs.eventForm.focusDate();
},
updateCache(store, { data }) {
const { timelineEvent: event, errors } = data?.timelineEventCreate || {};
if (errors.length) {
return;
}
const variables = {
incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
fullPath: this.fullPath,
};
const sourceData = store.readQuery({
query: getTimelineEvents,
variables,
});
const newData = produce(sourceData, (draftData) => {
const { nodes: draftEventList } = draftData.project.incidentManagementTimelineEvents;
draftEventList.push(event);
// ISOStrings sort correctly in lexical order
const sortedEvents = sortBy(draftEventList, 'occurredAt');
draftData.project.incidentManagementTimelineEvents.nodes = sortedEvents;
});
store.writeQuery({
query: getTimelineEvents,
variables,
data: newData,
});
},
createIncidentTimelineEvent(eventDetails, addAnotherEvent = false) {
this.createTimelineEventActive = true;
return this.$apollo
.mutate({
mutation: CreateTimelineEvent,
variables: {
input: {
incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
note: eventDetails.note,
occurredAt: eventDetails.occurredAt,
},
},
update: this.updateCache,
})
.then(({ data = {} }) => {
this.createTimelineEventActive = false;
const errors = data.timelineEventCreate?.errors;
if (errors.length) {
createAlert({
message: sprintf(this.$options.i18n.createError, { error: errors.join('. ') }, false),
});
return;
}
if (addAnotherEvent) {
this.$refs.eventForm.clear();
} else {
this.$emit('hide-new-timeline-events-form');
}
})
.catch((error) => {
createAlert({
message: this.$options.i18n.createErrorGeneric,
captureError: true,
error,
});
});
},
},
};
</script>
<template>
<timeline-events-form
ref="eventForm"
:is-event-processed="createTimelineEventActive"
:has-timeline-events="hasTimelineEvents"
@save-event="createIncidentTimelineEvent"
@cancel="$emit('hide-new-timeline-events-form')"
/>
</template>
<script>
import { GlDatepicker, GlFormInput, GlFormGroup, GlButton, GlIcon } from '@gitlab/ui';
import { produce } from 'immer';
import { sortBy } from 'lodash';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPE_ISSUE } from '~/graphql_shared/constants';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { createAlert } from '~/flash';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import { sprintf } from '~/locale';
import { getUtcShiftedDateNow } from './utils';
import { timelineFormI18n } from './constants';
import CreateTimelineEvent from './graphql/queries/create_timeline_event.mutation.graphql';
import getTimelineEvents from './graphql/queries/get_timeline_events.query.graphql';
import { getUtcShiftedDateNow } from './utils';
export default {
name: 'IncidentTimelineEventForm',
name: 'TimelineEventsForm',
restrictedToolBarItems: [
'quote',
'strikethrough',
......@@ -38,112 +29,55 @@ export default {
directives: {
autofocusonshow,
},
inject: ['fullPath', 'issuableId'],
props: {
hasTimelineEvents: {
type: Boolean,
required: true,
},
isEventProcessed: {
type: Boolean,
required: true,
},
},
data() {
// Create shifted date to force the datepicker to format in UTC
const utcShiftedDate = getUtcShiftedDateNow();
// if occurredAt is undefined, returns "now" in UTC
const placeholderDate = getUtcShiftedDateNow();
return {
currentDate: utcShiftedDate,
currentHour: utcShiftedDate.getHours(),
currentMinute: utcShiftedDate.getMinutes(),
timelineText: '',
createTimelineEventActive: false,
placeholderDate,
hourPickerInput: placeholderDate.getHours(),
minutePickerInput: placeholderDate.getMinutes(),
datepickerTextInput: null,
};
},
computed: {
occurredAt() {
const [years, months, days] = this.datepickerTextInput.split('-');
const utcDate = new Date(
Date.UTC(years, months - 1, days, this.hourPickerInput, this.minutePickerInput),
);
return utcDate.toISOString();
},
},
methods: {
clear() {
const utcShiftedDate = getUtcShiftedDateNow();
this.currentDate = utcShiftedDate;
this.currentHour = utcShiftedDate.getHours();
this.currentMinute = utcShiftedDate.getMinutes();
},
hideIncidentTimelineEventForm() {
this.$emit('hide-incident-timeline-event-form');
const utcShiftedDateNow = getUtcShiftedDateNow();
this.placeholderDate = utcShiftedDateNow;
this.hourPickerInput = utcShiftedDateNow.getHours();
this.minutePickerInput = utcShiftedDateNow.getMinutes();
this.timelineText = '';
},
focusDate() {
this.$refs.datepicker.$el.focus();
},
updateCache(store, { data }) {
const { timelineEvent: event, errors } = data?.timelineEventCreate || {};
if (errors.length) {
return;
}
const variables = {
incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
fullPath: this.fullPath,
handleSave(addAnotherEvent) {
const eventDetails = {
note: this.timelineText,
occurredAt: this.occurredAt,
};
const sourceData = store.readQuery({
query: getTimelineEvents,
variables,
});
const newData = produce(sourceData, (draftData) => {
const { nodes: draftEventList } = draftData.project.incidentManagementTimelineEvents;
draftEventList.push(event);
// ISOStrings sort correctly in lexical order
const sortedEvents = sortBy(draftEventList, 'occurredAt');
draftData.project.incidentManagementTimelineEvents.nodes = sortedEvents;
});
store.writeQuery({
query: getTimelineEvents,
variables,
data: newData,
});
},
createIncidentTimelineEvent(addOneEvent) {
this.createTimelineEventActive = true;
return this.$apollo
.mutate({
mutation: CreateTimelineEvent,
variables: {
input: {
incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
note: this.timelineText,
occurredAt: this.createDateString(),
},
},
update: this.updateCache,
})
.then(({ data = {} }) => {
const errors = data.timelineEventCreate?.errors;
if (errors.length) {
createAlert({
message: sprintf(this.$options.i18n.createError, { error: errors.join('. ') }, false),
});
}
})
.catch((error) => {
createAlert({
message: this.$options.i18n.createErrorGeneric,
captureError: true,
error,
});
})
.finally(() => {
this.createTimelineEventActive = false;
this.timelineText = '';
if (addOneEvent) {
this.hideIncidentTimelineEventForm();
}
});
},
createDateString() {
const [years, months, days] = this.datepickerTextInput.split('-');
const utcDate = new Date(
Date.UTC(years, months - 1, days, this.currentHour, this.currentMinute),
);
return utcDate.toISOString();
this.$emit('save-event', eventDetails, addAnotherEvent);
},
},
};
......@@ -165,7 +99,7 @@ export default {
class="gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row datetime-picker"
>
<gl-form-group :label="__('Date')" class="gl-mt-5 gl-mr-5">
<gl-datepicker id="incident-date" #default="{ formattedDate }" v-model="currentDate">
<gl-datepicker id="incident-date" #default="{ formattedDate }" v-model="placeholderDate">
<gl-form-input
id="incident-date"
ref="datepicker"
......@@ -184,7 +118,7 @@ export default {
<label label-for="timeline-input-hours" class="sr-only"></label>
<gl-form-input
id="timeline-input-hours"
v-model="currentHour"
v-model="hourPickerInput"
data-testid="input-hours"
size="xs"
type="number"
......@@ -194,7 +128,7 @@ export default {
<label label-for="timeline-input-minutes" class="sr-only"></label>
<gl-form-input
id="timeline-input-minutes"
v-model="currentMinute"
v-model="minutePickerInput"
class="gl-ml-3"
data-testid="input-minutes"
size="xs"
......@@ -223,9 +157,10 @@ export default {
<textarea
v-model="timelineText"
class="note-textarea js-gfm-input js-autosize markdown-area"
data-testid="input-note"
dir="auto"
data-supports-quick-actions="false"
:aria-label="__('Description')"
:aria-label="$options.i18n.description"
:placeholder="$options.i18n.areaPlaceholder"
>
</textarea>
......@@ -238,26 +173,22 @@ export default {
variant="confirm"
category="primary"
class="gl-mr-3"
:loading="createTimelineEventActive"
@click="createIncidentTimelineEvent(true)"
:loading="isEventProcessed"
@click="handleSave(false)"
>
{{ __('Save') }}
{{ $options.i18n.save }}
</gl-button>
<gl-button
variant="confirm"
category="secondary"
class="gl-mr-3 gl-ml-n2"
:loading="createTimelineEventActive"
@click="createIncidentTimelineEvent(false)"
:loading="isEventProcessed"
@click="handleSave(true)"
>
{{ $options.i18n.saveAndAdd }}
</gl-button>
<gl-button
class="gl-ml-n2"
:disabled="createTimelineEventActive"
@click="hideIncidentTimelineEventForm"
>
{{ __('Cancel') }}
<gl-button class="gl-ml-n2" :disabled="isEventProcessed" @click="$emit('cancel')">
{{ $options.i18n.cancel }}
</gl-button>
<div class="gl-border-b gl-pt-5"></div>
</gl-form-group>
......
......@@ -7,7 +7,7 @@ import getTimelineEvents from './graphql/queries/get_timeline_events.query.graph
import { displayAndLogError } from './utils';
import { timelineTabI18n } from './constants';
import IncidentTimelineEventForm from './timeline_events_form.vue';
import CreateTimelineEvent from './create_timeline_event.vue';
import IncidentTimelineEventsList from './timeline_events_list.vue';
export default {
......@@ -16,7 +16,7 @@ export default {
GlEmptyState,
GlLoadingIcon,
GlTab,
IncidentTimelineEventForm,
CreateTimelineEvent,
IncidentTimelineEventsList,
},
i18n: timelineTabI18n,
......@@ -61,10 +61,10 @@ export default {
this.isEventFormVisible = false;
},
async showEventForm() {
this.$refs.eventForm.clear();
this.$refs.createEventForm.clearForm();
this.isEventFormVisible = true;
await this.$nextTick();
this.$refs.eventForm.focusDate();
this.$refs.createEventForm.focusDate();
},
},
};
......@@ -82,14 +82,15 @@ export default {
v-if="hasTimelineEvents"
:timeline-event-loading="timelineEventLoading"
:timeline-events="timelineEvents"
@hide-new-timeline-events-form="hideEventForm"
/>
<incident-timeline-event-form
<create-timeline-event
v-show="isEventFormVisible"
ref="eventForm"
ref="createEventForm"
:has-timeline-events="hasTimelineEvents"
class="timeline-event-note timeline-event-note-form"
:class="{ 'gl-pl-0': !hasTimelineEvents }"
@hide-incident-timeline-event-form="hideEventForm"
@hide-new-timeline-events-form="hideEventForm"
/>
<gl-button v-if="canUpdate" variant="default" class="gl-mb-3 gl-mt-7" @click="showEventForm">
{{ $options.i18n.addEventButton }}
......
import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { GlDatepicker } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import CreateTimelineEvent from '~/issues/show/components/incidents/create_timeline_event.vue';
import TimelineEventsForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import createTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/create_timeline_event.mutation.graphql';
import getTimelineEvents from '~/issues/show/components/incidents/graphql/queries/get_timeline_events.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createAlert } from '~/flash';
import { useFakeDate } from 'helpers/fake_date';
import {
timelineEventsCreateEventResponse,
timelineEventsCreateEventError,
mockGetTimelineData,
} from './mock_data';
Vue.use(VueApollo);
jest.mock('~/flash');
const fakeDate = '2020-07-08T00:00:00.000Z';
const mockInputData = {
incidentId: 'gid://gitlab/Issue/1',
note: 'test',
occurredAt: '2020-07-08T00:00:00.000Z',
};
describe('Create Timeline events', () => {
useFakeDate(fakeDate);
let wrapper;
let responseSpy;
let apolloProvider;
const findSubmitButton = () => wrapper.findByText(__('Save'));
const findSubmitAndAddButton = () =>
wrapper.findByText(s__('Incident|Save and add another event'));
const findCancelButton = () => wrapper.findByText(__('Cancel'));
const findDatePicker = () => wrapper.findComponent(GlDatepicker);
const findNoteInput = () => wrapper.findByTestId('input-note');
const setNoteInput = () => {
const textarea = findNoteInput().element;
textarea.value = mockInputData.note;
textarea.dispatchEvent(new Event('input'));
};
const findHourInput = () => wrapper.findByTestId('input-hours');
const findMinuteInput = () => wrapper.findByTestId('input-minutes');
const setDatetime = () => {
const inputDate = new Date(mockInputData.occurredAt);
findDatePicker().vm.$emit('input', inputDate);
findHourInput().vm.$emit('input', inputDate.getHours());
findMinuteInput().vm.$emit('input', inputDate.getMinutes());
};
const fillForm = () => {
setDatetime();
setNoteInput();
};
function createMockApolloProvider() {
const requestHandlers = [[createTimelineEventMutation, responseSpy]];
const mockApollo = createMockApollo(requestHandlers);
mockApollo.clients.defaultClient.cache.writeQuery({
query: getTimelineEvents,
data: mockGetTimelineData,
variables: {
fullPath: 'group/project',
incidentId: 'gid://gitlab/Issue/1',
},
});
return mockApollo;
}
const mountComponent = () => {
wrapper = mountExtended(CreateTimelineEvent, {
propsData: {
hasTimelineEvents: true,
},
provide: {
fullPath: 'group/project',
issuableId: '1',
},
apolloProvider,
});
};
beforeEach(() => {
responseSpy = jest.fn().mockResolvedValue(timelineEventsCreateEventResponse);
apolloProvider = createMockApolloProvider();
});
afterEach(() => {
createAlert.mockReset();
wrapper.destroy();
});
describe('createIncidentTimelineEvent', () => {
const closeFormEvent = { 'hide-new-timeline-events-form': [[]] };
const expectedData = {
input: mockInputData,
};
beforeEach(() => {
mountComponent();
fillForm();
});
describe('on submit', () => {
beforeEach(async () => {
findSubmitButton().trigger('click');
await waitForPromises();
});
it('should call the mutation with the right variables', () => {
expect(responseSpy).toHaveBeenCalledWith(expectedData);
});
it('should close the form on successful addition', () => {
expect(wrapper.emitted()).toEqual(closeFormEvent);
});
});
describe('on submit and add', () => {
beforeEach(async () => {
findSubmitAndAddButton().trigger('click');
await waitForPromises();
});
it('should keep the form open for save and add another', () => {
expect(wrapper.emitted()).toEqual({});
});
});
describe('on cancel', () => {
beforeEach(async () => {
findCancelButton().trigger('click');
await waitForPromises();
});
it('should close the form', () => {
expect(wrapper.emitted()).toEqual(closeFormEvent);
});
});
});
describe('error handling', () => {
it('should show an error when submission returns an error', async () => {
const expectedAlertArgs = {
message: `Error creating incident timeline event: ${timelineEventsCreateEventError.data.timelineEventCreate.errors[0]}`,
};
responseSpy.mockResolvedValueOnce(timelineEventsCreateEventError);
mountComponent();
findSubmitButton().trigger('click');
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 creating the incident timeline event.',
};
responseSpy.mockRejectedValueOnce();
mountComponent();
findSubmitButton().trigger('click');
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
});
it('should keep the form open on failed addition', async () => {
responseSpy.mockResolvedValueOnce(timelineEventsCreateEventError);
mountComponent();
await wrapper.findComponent(TimelineEventsForm).vm.$emit('save-event', mockInputData);
await waitForPromises;
expect(wrapper.emitted()).toEqual({});
});
});
});
......@@ -72,10 +72,14 @@ export const timelineEventsQueryEmptyResponse = {
};
export const timelineEventsCreateEventResponse = {
timelineEvent: {
...mockEvents[0],
data: {
timelineEventCreate: {
timelineEvent: {
...mockEvents[0],
},
errors: [],
},
},
errors: [],
};
export const timelineEventsCreateEventError = {
......@@ -103,3 +107,21 @@ const timelineEventDeleteData = (errors = []) => {
export const timelineEventsDeleteEventResponse = timelineEventDeleteData();
export const timelineEventsDeleteEventError = timelineEventDeleteData(['Item does not exist']);
export const mockGetTimelineData = {
project: {
id: 'gid://gitlab/Project/19',
incidentManagementTimelineEvents: {
nodes: [
{
id: 'gid://gitlab/IncidentManagement::TimelineEvent/8',
note: 'another one2',
noteHtml: '<p>another one2</p>',
action: 'comment',
occurredAt: '2022-07-01T12:47:00Z',
createdAt: '2022-07-20T12:47:40Z',
},
],
},
},
};
......@@ -3,49 +3,33 @@ import Vue, { nextTick } from 'vue';
import { GlDatepicker } from '@gitlab/ui';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import IncidentTimelineEventForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import createTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/create_timeline_event.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import TimelineEventsForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import { createAlert } from '~/flash';
import { useFakeDate } from 'helpers/fake_date';
import { timelineEventsCreateEventResponse, timelineEventsCreateEventError } from './mock_data';
Vue.use(VueApollo);
jest.mock('~/flash');
const addEventResponse = jest.fn().mockResolvedValue(timelineEventsCreateEventResponse);
function createMockApolloProvider(response = addEventResponse) {
const requestHandlers = [[createTimelineEventMutation, response]];
return createMockApollo(requestHandlers);
}
const fakeDate = '2020-07-08T00:00:00.000Z';
describe('Timeline events form', () => {
// July 8 2020
useFakeDate(2020, 6, 8);
useFakeDate(fakeDate);
let wrapper;
const mountComponent = ({ mockApollo, mountMethod = shallowMountExtended, stubs }) => {
wrapper = mountMethod(IncidentTimelineEventForm, {
const mountComponent = ({ mountMethod = shallowMountExtended }) => {
wrapper = mountMethod(TimelineEventsForm, {
propsData: {
hasTimelineEvents: true,
isEventProcessed: false,
},
provide: {
fullPath: 'group/project',
issuableId: '1',
},
apolloProvider: mockApollo,
stubs,
});
};
afterEach(() => {
addEventResponse.mockReset();
createAlert.mockReset();
if (wrapper) {
wrapper.destroy();
}
wrapper.destroy();
});
const findSubmitButton = () => wrapper.findByText('Save');
......@@ -75,24 +59,28 @@ describe('Timeline events form', () => {
};
describe('form button behaviour', () => {
const closeFormEvent = { 'hide-incident-timeline-event-form': [[]] };
beforeEach(() => {
mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
mountComponent({ mountMethod: mountExtended });
});
it('should close the form on submit', async () => {
it('should save event on submit', async () => {
await submitForm();
expect(wrapper.emitted()).toEqual(closeFormEvent);
expect(wrapper.emitted()).toEqual({
'save-event': [[{ note: '', occurredAt: fakeDate }, false]],
});
});
it('should not close the form on "submit and add another"', async () => {
it('should save event on "submit and add another"', async () => {
await submitFormAndAddAnother();
expect(wrapper.emitted()).toEqual({});
expect(wrapper.emitted()).toEqual({
'save-event': [[{ note: '', occurredAt: fakeDate }, true]],
});
});
it('should close the form on cancel', async () => {
it('should emit cancel on cancel', async () => {
await cancelForm();
expect(wrapper.emitted()).toEqual(closeFormEvent);
expect(wrapper.emitted()).toEqual({ cancel: [[]] });
});
it('should clear the form', async () => {
......@@ -111,71 +99,4 @@ describe('Timeline events form', () => {
expect(findMinuteInput().element.value).toBe('0');
});
});
describe('addTimelineEventQuery', () => {
const expectedData = {
input: {
incidentId: 'gid://gitlab/Issue/1',
note: '',
occurredAt: '2020-07-08T00:00:00.000Z',
},
};
let mockApollo;
beforeEach(() => {
mockApollo = createMockApolloProvider();
mountComponent({ mockApollo, mountMethod: mountExtended });
});
it('should call the mutation with the right variables', async () => {
await submitForm();
expect(addEventResponse).toHaveBeenCalledWith(expectedData);
});
it('should call the mutation with user selected variables', async () => {
const expectedUserSelectedData = {
input: {
...expectedData.input,
occurredAt: '2021-08-12T05:45:00.000Z',
},
};
setDatetime();
await nextTick();
await submitForm();
expect(addEventResponse).toHaveBeenCalledWith(expectedUserSelectedData);
});
});
describe('error handling', () => {
it('should show an error when submission returns an error', async () => {
const expectedAlertArgs = {
message: 'Error creating incident timeline event: Create error',
};
addEventResponse.mockResolvedValueOnce(timelineEventsCreateEventError);
mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
await submitForm();
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 creating the incident timeline event.',
};
addEventResponse.mockRejectedValueOnce();
mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
await submitForm();
expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
});
});
});
......@@ -5,7 +5,7 @@ import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_help
import waitForPromises from 'helpers/wait_for_promises';
import TimelineEventsTab from '~/issues/show/components/incidents/timeline_events_tab.vue';
import IncidentTimelineEventsList from '~/issues/show/components/incidents/timeline_events_list.vue';
import IncidentTimelineEventForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import CreateTimelineEvent from '~/issues/show/components/incidents/create_timeline_event.vue';
import timelineEventsQuery from '~/issues/show/components/incidents/graphql/queries/get_timeline_events.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createAlert } from '~/flash';
......@@ -53,7 +53,7 @@ describe('TimelineEventsTab', () => {
const findLoadingSpinner = () => wrapper.findComponent(GlLoadingIcon);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findTimelineEventsList = () => wrapper.findComponent(IncidentTimelineEventsList);
const findTimelineEventForm = () => wrapper.findComponent(IncidentTimelineEventForm);
const findCreateTimelineEvent = () => wrapper.findComponent(CreateTimelineEvent);
const findAddEventButton = () => wrapper.findByText(timelineTabI18n.addEventButton);
describe('Timeline events tab', () => {
......@@ -143,18 +143,18 @@ describe('TimelineEventsTab', () => {
});
it('should not show a form by default', () => {
expect(findTimelineEventForm().isVisible()).toBe(false);
expect(findCreateTimelineEvent().isVisible()).toBe(false);
});
it('should show a form when button is clicked', async () => {
await findAddEventButton().trigger('click');
expect(findTimelineEventForm().isVisible()).toBe(true);
expect(findCreateTimelineEvent().isVisible()).toBe(true);
});
it('should clear the form when button is clicked', async () => {
const mockClear = jest.fn();
wrapper.vm.$refs.eventForm.clear = mockClear;
wrapper.vm.$refs.createEventForm.clearForm = mockClear;
await findAddEventButton().trigger('click');
......@@ -165,9 +165,9 @@ describe('TimelineEventsTab', () => {
// open the form
await findAddEventButton().trigger('click');
await findTimelineEventForm().vm.$emit('hide-incident-timeline-event-form');
await findCreateTimelineEvent().vm.$emit('hide-new-timeline-events-form');
expect(findTimelineEventForm().isVisible()).toBe(false);
expect(findCreateTimelineEvent().isVisible()).toBe(false);
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment