summaryrefslogtreecommitdiff
path: root/spec/frontend/work_items/components/work_item_description_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/work_items/components/work_item_description_spec.js')
-rw-r--r--spec/frontend/work_items/components/work_item_description_spec.js295
1 files changed, 163 insertions, 132 deletions
diff --git a/spec/frontend/work_items/components/work_item_description_spec.js b/spec/frontend/work_items/components/work_item_description_spec.js
index 0691fe25e0d..c79b049442d 100644
--- a/spec/frontend/work_items/components/work_item_description_spec.js
+++ b/spec/frontend/work_items/components/work_item_description_spec.js
@@ -8,21 +8,23 @@ import EditedAt from '~/issues/show/components/edited.vue';
import { updateDraft } from '~/lib/utils/autosave';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import WorkItemDescription from '~/work_items/components/work_item_description.vue';
+import WorkItemDescriptionRendered from '~/work_items/components/work_item_description_rendered.vue';
import { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import workItemDescriptionSubscription from '~/work_items/graphql/work_item_description.subscription.graphql';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
+import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
import {
updateWorkItemMutationResponse,
+ workItemDescriptionSubscriptionResponse,
workItemResponseFactory,
workItemQueryResponse,
+ projectWorkItemResponse,
} from '../mock_data';
-jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
- return {
- confirmAction: jest.fn(),
- };
-});
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
jest.mock('~/lib/utils/autosave');
const workItemId = workItemQueryResponse.data.workItem.id;
@@ -33,12 +35,22 @@ describe('WorkItemDescription', () => {
Vue.use(VueApollo);
const mutationSuccessHandler = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
+ const subscriptionHandler = jest.fn().mockResolvedValue(workItemDescriptionSubscriptionResponse);
+ const workItemByIidResponseHandler = jest.fn().mockResolvedValue(projectWorkItemResponse);
+ let workItemResponseHandler;
+ let workItemsMvc2;
- const findEditButton = () => wrapper.find('[data-testid="edit-description"]');
const findMarkdownField = () => wrapper.findComponent(MarkdownField);
+ const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
+ const findRenderedDescription = () => wrapper.findComponent(WorkItemDescriptionRendered);
const findEditedAt = () => wrapper.findComponent(EditedAt);
- const editDescription = (newText) => wrapper.find('textarea').setValue(newText);
+ const editDescription = (newText) => {
+ if (workItemsMvc2) {
+ return findMarkdownEditor().vm.$emit('input', newText);
+ }
+ return wrapper.find('textarea').setValue(newText);
+ };
const clickCancel = () => wrapper.find('[data-testid="cancel"]').vm.$emit('click');
const clickSave = () => wrapper.find('[data-testid="save-description"]').vm.$emit('click', {});
@@ -48,18 +60,30 @@ describe('WorkItemDescription', () => {
canUpdate = true,
workItemResponse = workItemResponseFactory({ canUpdate }),
isEditing = false,
+ fetchByIid = false,
} = {}) => {
- const workItemResponseHandler = jest.fn().mockResolvedValue(workItemResponse);
+ workItemResponseHandler = jest.fn().mockResolvedValue(workItemResponse);
const { id } = workItemQueryResponse.data.workItem;
wrapper = shallowMount(WorkItemDescription, {
apolloProvider: createMockApollo([
[workItemQuery, workItemResponseHandler],
[updateWorkItemMutation, mutationHandler],
+ [workItemDescriptionSubscription, subscriptionHandler],
+ [workItemByIidQuery, workItemByIidResponseHandler],
]),
propsData: {
workItemId: id,
fullPath: 'test-project-path',
+ queryVariables: {
+ id: workItemId,
+ },
+ fetchByIid,
+ },
+ provide: {
+ glFeatures: {
+ workItemsMvc2,
+ },
},
stubs: {
MarkdownField,
@@ -69,7 +93,7 @@ describe('WorkItemDescription', () => {
await waitForPromises();
if (isEditing) {
- findEditButton().vm.$emit('click');
+ findRenderedDescription().vm.$emit('startEditing');
await nextTick();
}
@@ -79,171 +103,178 @@ describe('WorkItemDescription', () => {
wrapper.destroy();
});
- describe('Edit button', () => {
- it('is not visible when canUpdate = false', async () => {
- await createComponent({
- canUpdate: false,
+ describe.each([true, false])(
+ 'editing description with workItemsMvc2 %workItemsMvc2Enabled',
+ (workItemsMvc2Enabled) => {
+ beforeEach(() => {
+ beforeEach(() => {
+ workItemsMvc2 = workItemsMvc2Enabled;
+ });
});
- expect(findEditButton().exists()).toBe(false);
- });
+ describe('editing description', () => {
+ it('shows edited by text', async () => {
+ const lastEditedAt = '2022-09-21T06:18:42Z';
+ const lastEditedBy = {
+ name: 'Administrator',
+ webPath: '/root',
+ };
- it('toggles edit mode', async () => {
- await createComponent({
- canUpdate: true,
- });
+ await createComponent({
+ workItemResponse: workItemResponseFactory({
+ lastEditedAt,
+ lastEditedBy,
+ }),
+ });
- findEditButton().vm.$emit('click');
+ expect(findEditedAt().props()).toEqual({
+ updatedAt: lastEditedAt,
+ updatedByName: lastEditedBy.name,
+ updatedByPath: lastEditedBy.webPath,
+ });
+ });
- await nextTick();
+ it('does not show edited by text', async () => {
+ await createComponent();
- expect(findMarkdownField().exists()).toBe(true);
- });
- });
+ expect(findEditedAt().exists()).toBe(false);
+ });
- describe('editing description', () => {
- it('shows edited by text', async () => {
- const lastEditedAt = '2022-09-21T06:18:42Z';
- const lastEditedBy = {
- name: 'Administrator',
- webPath: '/root',
- };
-
- await createComponent({
- workItemResponse: workItemResponseFactory({
- lastEditedAt,
- lastEditedBy,
- }),
- });
+ it('cancels when clicking cancel', async () => {
+ await createComponent({
+ isEditing: true,
+ });
- expect(findEditedAt().props()).toEqual({
- updatedAt: lastEditedAt,
- updatedByName: lastEditedBy.name,
- updatedByPath: lastEditedBy.webPath,
- });
- });
+ clickCancel();
- it('does not show edited by text', async () => {
- await createComponent();
+ await nextTick();
- expect(findEditedAt().exists()).toBe(false);
- });
+ expect(confirmAction).not.toHaveBeenCalled();
+ expect(findMarkdownField().exists()).toBe(false);
+ });
- it('cancels when clicking cancel', async () => {
- await createComponent({
- isEditing: true,
- });
+ it('prompts for confirmation when clicking cancel after changes', async () => {
+ await createComponent({
+ isEditing: true,
+ });
- clickCancel();
+ editDescription('updated desc');
- await nextTick();
+ clickCancel();
- expect(confirmAction).not.toHaveBeenCalled();
- expect(findMarkdownField().exists()).toBe(false);
- });
+ await nextTick();
- it('prompts for confirmation when clicking cancel after changes', async () => {
- await createComponent({
- isEditing: true,
- });
+ expect(confirmAction).toHaveBeenCalled();
+ });
- editDescription('updated desc');
+ it('calls update widgets mutation', async () => {
+ const updatedDesc = 'updated desc';
- clickCancel();
+ await createComponent({
+ isEditing: true,
+ });
- await nextTick();
+ editDescription(updatedDesc);
- expect(confirmAction).toHaveBeenCalled();
- });
+ clickSave();
- it('calls update widgets mutation', async () => {
- await createComponent({
- isEditing: true,
- });
+ await waitForPromises();
- editDescription('updated desc');
+ expect(mutationSuccessHandler).toHaveBeenCalledWith({
+ input: {
+ id: workItemId,
+ descriptionWidget: {
+ description: updatedDesc,
+ },
+ },
+ });
+ });
- clickSave();
+ it('tracks editing description', async () => {
+ await createComponent({
+ isEditing: true,
+ markdownPreviewPath: '/preview',
+ });
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- await waitForPromises();
+ clickSave();
- expect(mutationSuccessHandler).toHaveBeenCalledWith({
- input: {
- id: workItemId,
- descriptionWidget: {
- description: 'updated desc',
- },
- },
- });
- });
+ await waitForPromises();
- it('tracks editing description', async () => {
- await createComponent({
- isEditing: true,
- markdownPreviewPath: '/preview',
- });
- const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_description', {
+ category: TRACKING_CATEGORY_SHOW,
+ label: 'item_description',
+ property: 'type_Task',
+ });
+ });
- clickSave();
+ it('emits error when mutation returns error', async () => {
+ const error = 'eror';
- await waitForPromises();
+ await createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockResolvedValue({
+ data: {
+ workItemUpdate: {
+ workItem: {},
+ errors: [error],
+ },
+ },
+ }),
+ });
- expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_description', {
- category: TRACKING_CATEGORY_SHOW,
- label: 'item_description',
- property: 'type_Task',
- });
- });
+ editDescription('updated desc');
- it('emits error when mutation returns error', async () => {
- const error = 'eror';
+ clickSave();
- await createComponent({
- isEditing: true,
- mutationHandler: jest.fn().mockResolvedValue({
- data: {
- workItemUpdate: {
- workItem: {},
- errors: [error],
- },
- },
- }),
- });
+ await waitForPromises();
- editDescription('updated desc');
+ expect(wrapper.emitted('error')).toEqual([[error]]);
+ });
- clickSave();
+ it('emits error when mutation fails', async () => {
+ const error = 'eror';
- await waitForPromises();
+ await createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockRejectedValue(new Error(error)),
+ });
- expect(wrapper.emitted('error')).toEqual([[error]]);
- });
+ editDescription('updated desc');
- it('emits error when mutation fails', async () => {
- const error = 'eror';
+ clickSave();
- await createComponent({
- isEditing: true,
- mutationHandler: jest.fn().mockRejectedValue(new Error(error)),
- });
+ await waitForPromises();
- editDescription('updated desc');
+ expect(wrapper.emitted('error')).toEqual([[error]]);
+ });
- clickSave();
+ it('autosaves description', async () => {
+ await createComponent({
+ isEditing: true,
+ });
- await waitForPromises();
+ editDescription('updated desc');
- expect(wrapper.emitted('error')).toEqual([[error]]);
- });
+ expect(updateDraft).toHaveBeenCalled();
+ });
+ });
+
+ it('calls the global ID work item query when `fetchByIid` prop is false', async () => {
+ createComponent({ fetchByIid: false });
+ await waitForPromises();
- it('autosaves description', async () => {
- await createComponent({
- isEditing: true,
+ expect(workItemResponseHandler).toHaveBeenCalled();
+ expect(workItemByIidResponseHandler).not.toHaveBeenCalled();
});
- editDescription('updated desc');
+ it('calls the IID work item query when when `fetchByIid` prop is true', async () => {
+ createComponent({ fetchByIid: true });
+ await waitForPromises();
- expect(updateDraft).toHaveBeenCalled();
- });
- });
+ expect(workItemResponseHandler).not.toHaveBeenCalled();
+ expect(workItemByIidResponseHandler).toHaveBeenCalled();
+ });
+ },
+ );
});