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:
Diffstat (limited to 'spec/frontend/issues/show/components/incidents')
-rw-r--r--spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js9
-rw-r--r--spec/frontend/issues/show/components/incidents/mock_data.js1
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js142
3 files changed, 127 insertions, 25 deletions
diff --git a/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js b/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
index 1286617d64a..6c923cae0cc 100644
--- a/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
+++ b/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
@@ -1,6 +1,6 @@
import VueApollo from 'vue-apollo';
import Vue from 'vue';
-import { GlDatepicker } from '@gitlab/ui';
+import { GlDatepicker, GlListboxItem } from '@gitlab/ui';
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';
@@ -27,6 +27,7 @@ const mockInputData = {
incidentId: 'gid://gitlab/Issue/1',
note: 'test',
occurredAt: '2020-07-08T00:00:00.000Z',
+ timelineEventTagNames: ['Start time'],
};
describe('Create Timeline events', () => {
@@ -51,9 +52,14 @@ describe('Create Timeline events', () => {
findHourInput().setValue(inputDate.getHours());
findMinuteInput().setValue(inputDate.getMinutes());
};
+ const findListboxItems = () => wrapper.findAllComponents(GlListboxItem);
+ const setEventTags = () => {
+ findListboxItems().at(0).vm.$emit('select', true);
+ };
const fillForm = () => {
setDatetime();
setNoteInput();
+ setEventTags();
};
function createMockApolloProvider() {
@@ -80,6 +86,7 @@ describe('Create Timeline events', () => {
provide: {
fullPath: 'group/project',
issuableId: '1',
+ glFeatures: { incidentEventTags: true },
},
apolloProvider,
});
diff --git a/spec/frontend/issues/show/components/incidents/mock_data.js b/spec/frontend/issues/show/components/incidents/mock_data.js
index 9accfcea791..6606bed1567 100644
--- a/spec/frontend/issues/show/components/incidents/mock_data.js
+++ b/spec/frontend/issues/show/components/incidents/mock_data.js
@@ -74,6 +74,7 @@ const mockUpdatedEvent = {
action: 'comment',
occurredAt: '2022-07-01T12:47:00Z',
createdAt: '2022-07-20T12:47:40Z',
+ timelineEventTags: [],
};
export const timelineEventsQueryListResponse = {
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
index d5b199cc790..f06d968a4c5 100644
--- a/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
+++ b/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
@@ -1,11 +1,15 @@
import VueApollo from 'vue-apollo';
import Vue, { nextTick } from 'vue';
-import { GlDatepicker } from '@gitlab/ui';
-import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
+import { GlDatepicker, GlListbox } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import TimelineEventsForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import { timelineFormI18n } from '~/issues/show/components/incidents/constants';
+import {
+ timelineFormI18n,
+ TIMELINE_EVENT_TAGS,
+ timelineEventTagsI18n,
+} from '~/issues/show/components/incidents/constants';
import { createAlert } from '~/flash';
import { useFakeDate } from 'helpers/fake_date';
@@ -17,17 +21,23 @@ const fakeDate = '2020-07-08T00:00:00.000Z';
const mockInputDate = new Date('2021-08-12');
+const mockTags = TIMELINE_EVENT_TAGS;
+
describe('Timeline events form', () => {
// July 8 2020
useFakeDate(fakeDate);
let wrapper;
- const mountComponent = ({ mountMethod = shallowMountExtended } = {}, props = {}) => {
+ const mountComponent = ({ mountMethod = mountExtended } = {}, props = {}, glFeatures = {}) => {
wrapper = mountMethod(TimelineEventsForm, {
+ provide: {
+ glFeatures,
+ },
propsData: {
showSaveAndAdd: true,
isEventProcessed: false,
...props,
+ tags: mockTags,
},
stubs: {
GlButton: true,
@@ -35,6 +45,10 @@ describe('Timeline events form', () => {
});
};
+ beforeEach(() => {
+ mountComponent();
+ });
+
afterEach(() => {
createAlert.mockReset();
wrapper.destroy();
@@ -48,16 +62,26 @@ describe('Timeline events form', () => {
const findDatePicker = () => wrapper.findComponent(GlDatepicker);
const findHourInput = () => wrapper.findByTestId('input-hours');
const findMinuteInput = () => wrapper.findByTestId('input-minutes');
- const setDatetime = () => {
- findDatePicker().vm.$emit('input', mockInputDate);
- findHourInput().setValue(5);
- findMinuteInput().setValue(45);
- };
+ const findTagDropdown = () => wrapper.findComponent(GlListbox);
const findTextarea = () => wrapper.findByTestId('input-note');
+ const findTextareaValue = () => findTextarea().element.value;
const findCountNumeric = (count) => wrapper.findByText(count);
const findCountVerbose = (count) => wrapper.findByText(`${count} characters remaining`);
const findCountHint = () => wrapper.findByText(timelineFormI18n.hint);
+ const setDatetime = () => {
+ findDatePicker().vm.$emit('input', mockInputDate);
+ findHourInput().setValue(5);
+ findMinuteInput().setValue(45);
+ };
+ const selectTags = async (tags) => {
+ findTagDropdown().vm.$emit(
+ 'select',
+ tags.map((x) => x.value),
+ );
+ await nextTick();
+ };
+ const selectOneTag = () => selectTags([mockTags[0]]);
const submitForm = async () => {
findSubmitButton().vm.$emit('click');
await waitForPromises();
@@ -90,23 +114,97 @@ describe('Timeline events form', () => {
]);
});
- describe('form button behaviour', () => {
+ describe('with incident_event_tag feature flag enabled', () => {
beforeEach(() => {
- mountComponent({ mountMethod: mountExtended });
+ mountComponent(
+ {},
+ {},
+ {
+ incidentEventTags: true,
+ },
+ );
+ });
+
+ describe('event tag dropdown', () => {
+ it('should render option list from provided array', () => {
+ expect(findTagDropdown().props('items')).toEqual(mockTags);
+ });
+
+ it('should allow to choose multiple tags', async () => {
+ await selectTags(mockTags);
+
+ expect(findTagDropdown().props('selected')).toEqual(mockTags.map((x) => x.value));
+ });
+
+ it('should show default option, when none is chosen', () => {
+ expect(findTagDropdown().props('toggleText')).toBe(timelineFormI18n.selectTags);
+ });
+
+ it('should show the tag, when one is selected', async () => {
+ await selectOneTag();
+
+ expect(findTagDropdown().props('toggleText')).toBe(timelineEventTagsI18n.startTime);
+ });
+
+ it('should show the number of selected tags, when more than one is selected', async () => {
+ await selectTags(mockTags);
+
+ expect(findTagDropdown().props('toggleText')).toBe('2 tags');
+ });
+
+ it('should be cleared when clear is triggered', async () => {
+ await selectTags(mockTags);
+
+ // This component expects the parent to call `clear`, so this is the only way to trigger this
+ wrapper.vm.clear();
+ await nextTick();
+
+ expect(findTagDropdown().props('toggleText')).toBe(timelineFormI18n.selectTags);
+ expect(findTagDropdown().props('selected')).toEqual([]);
+ });
+
+ it('should populate incident note with tags if a note was empty', async () => {
+ await selectTags(mockTags);
+
+ expect(findTextareaValue()).toBe(
+ `${timelineFormI18n.areaDefaultMessage} ${mockTags
+ .map((x) => x.value.toLowerCase())
+ .join(', ')}`,
+ );
+ });
+
+ it('should populate incident note with tag but allow to customise it', async () => {
+ await selectOneTag();
+
+ await findTextarea().setValue('my customised event note');
+
+ await nextTick();
+
+ expect(findTextareaValue()).toBe('my customised event note');
+ });
+
+ it('should not populate incident note with tag if it had a note', async () => {
+ await findTextarea().setValue('hello');
+ await selectOneTag();
+
+ expect(findTextareaValue()).toBe('hello');
+ });
});
+ });
+ describe('form button behaviour', () => {
it('should save event on submit', async () => {
await submitForm();
expect(wrapper.emitted()).toEqual({
- 'save-event': [[{ note: '', occurredAt: fakeDate }, false]],
+ 'save-event': [[{ note: '', occurredAt: fakeDate, timelineEventTags: [] }, false]],
});
});
it('should save event on "submit and add another"', async () => {
await submitFormAndAddAnother();
expect(wrapper.emitted()).toEqual({
- 'save-event': [[{ note: '', occurredAt: fakeDate }, true]],
+ 'save-event': [[{ note: '', occurredAt: fakeDate, timelineEventTags: [] }, true]],
});
});
@@ -145,10 +243,6 @@ describe('Timeline events form', () => {
});
describe('form character limit', () => {
- beforeEach(() => {
- mountComponent({ mountMethod: mountExtended });
- });
-
it('sets a character limit hint', () => {
expect(findCountHint().exists()).toBe(true);
});
@@ -172,32 +266,32 @@ describe('Timeline events form', () => {
});
describe('Delete button', () => {
- it('does not show the delete button if showDelete prop is false', () => {
- mountComponent({ mountMethod: mountExtended }, { showDelete: false });
+ it('does not show the delete button if isEditing prop is false', () => {
+ mountComponent({ mountMethod: mountExtended }, { isEditing: false });
expect(findDeleteButton().exists()).toBe(false);
});
- it('shows the delete button if showDelete prop is true', () => {
- mountComponent({ mountMethod: mountExtended }, { showDelete: true });
+ it('shows the delete button if isEditing prop is true', () => {
+ mountComponent({ mountMethod: mountExtended }, { isEditing: true });
expect(findDeleteButton().exists()).toBe(true);
});
it('disables the delete button if isEventProcessed prop is true', () => {
- mountComponent({ mountMethod: mountExtended }, { showDelete: true, isEventProcessed: true });
+ mountComponent({ mountMethod: mountExtended }, { isEditing: true, isEventProcessed: true });
expect(findDeleteButton().props('disabled')).toBe(true);
});
it('does not disable the delete button if isEventProcessed prop is false', () => {
- mountComponent({ mountMethod: mountExtended }, { showDelete: true, isEventProcessed: false });
+ mountComponent({ mountMethod: mountExtended }, { isEditing: true, isEventProcessed: false });
expect(findDeleteButton().props('disabled')).toBe(false);
});
it('emits delete event on click', () => {
- mountComponent({ mountMethod: mountExtended }, { showDelete: true, isEventProcessed: true });
+ mountComponent({ mountMethod: mountExtended }, { isEditing: true, isEventProcessed: true });
deleteForm();