Commit f15f3477 authored by Illya Klymov's avatar Illya Klymov

Merge branch '118609-design-comment-edit-comment-text' into 'master'

Resolve "Design Comment: Edit Comment text"

See merge request gitlab-org/gitlab!30479
parents ed06dfc8 0496b76b
...@@ -103,7 +103,13 @@ export default { ...@@ -103,7 +103,13 @@ export default {
class="design-discussion bordered-box position-relative" class="design-discussion bordered-box position-relative"
data-qa-selector="design_discussion_content" data-qa-selector="design_discussion_content"
> >
<design-note v-for="note in discussion.notes" :key="note.id" :note="note" /> <design-note
v-for="note in discussion.notes"
:key="note.id"
:note="note"
:markdown-preview-path="markdownPreviewPath"
@error="$emit('updateNoteError', $event)"
/>
<div class="reply-wrapper"> <div class="reply-wrapper">
<reply-placeholder <reply-placeholder
v-if="!isFormRendered" v-if="!isFormRendered"
......
<script> <script>
import { ApolloMutation } from 'vue-apollo';
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DesignReplyForm from './design_reply_form.vue';
import { findNoteId } from '../../utils/design_management_utils'; import { findNoteId } from '../../utils/design_management_utils';
import { hasErrors } from '../../utils/cache_update';
export default { export default {
components: { components: {
UserAvatarLink, UserAvatarLink,
TimelineEntryItem, TimelineEntryItem,
TimeAgoTooltip, TimeAgoTooltip,
DesignReplyForm,
ApolloMutation,
GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
}, },
props: { props: {
note: { note: {
type: Object, type: Object,
required: true, required: true,
}, },
markdownPreviewPath: {
type: String,
required: false,
default: '',
},
},
data() {
return {
noteText: this.note.body,
isEditing: false,
};
}, },
computed: { computed: {
author() { author() {
...@@ -26,12 +48,31 @@ export default { ...@@ -26,12 +48,31 @@ export default {
isNoteLinked() { isNoteLinked() {
return this.$route.hash === `#note_${this.noteAnchorId}`; return this.$route.hash === `#note_${this.noteAnchorId}`;
}, },
mutationPayload() {
return {
id: this.note.id,
body: this.noteText,
};
},
}, },
mounted() { mounted() {
if (this.isNoteLinked) { if (this.isNoteLinked) {
this.$refs.anchor.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' }); this.$refs.anchor.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' });
} }
}, },
methods: {
hideForm() {
this.isEditing = false;
this.noteText = this.note.body;
},
onDone({ data }) {
this.hideForm();
if (hasErrors(data.updateNote)) {
this.$emit('error', data.errors[0]);
}
},
},
updateNoteMutation,
}; };
</script> </script>
...@@ -43,6 +84,8 @@ export default { ...@@ -43,6 +84,8 @@ export default {
:img-alt="author.username" :img-alt="author.username"
:img-size="40" :img-size="40"
/> />
<div class="d-flex justify-content-between">
<div>
<a <a
v-once v-once
:href="author.webUrl" :href="author.webUrl"
...@@ -63,6 +106,43 @@ export default { ...@@ -63,6 +106,43 @@ export default {
</a> </a>
</template> </template>
</span> </span>
<div class="note-text md" data-qa-selector="note_content" v-html="note.bodyHtml"></div> </div>
<button
v-if="!isEditing"
v-gl-tooltip
type="button"
title="Edit comment"
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
@click="isEditing = true"
>
<gl-icon name="pencil" class="link-highlight" />
</button>
</div>
<div
v-if="!isEditing"
class="note-text js-note-text md"
data-qa-selector="note_content"
v-html="note.bodyHtml"
></div>
<apollo-mutation
v-else
#default="{ mutate, loading }"
:mutation="$options.updateNoteMutation"
:variables="{
input: mutationPayload,
}"
@error="$emit('error', $event)"
@done="onDone"
>
<design-reply-form
v-model="noteText"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
:is-new-comment="false"
class="mt-5"
@submitForm="mutate"
@cancelForm="hideForm"
/>
</apollo-mutation>
</timeline-entry-item> </timeline-entry-item>
</template> </template>
<script> <script>
import { GlDeprecatedButton, GlModal } from '@gitlab/ui'; import { GlDeprecatedButton, GlModal } from '@gitlab/ui';
import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { s__ } from '~/locale';
export default { export default {
name: 'DesignReplyForm', name: 'DesignReplyForm',
...@@ -23,11 +24,42 @@ export default { ...@@ -23,11 +24,42 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
isNewComment: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
formText: this.value,
};
}, },
computed: { computed: {
hasValue() { hasValue() {
return this.value.trim().length > 0; return this.value.trim().length > 0;
}, },
modalSettings() {
if (this.isNewComment) {
return {
title: s__('DesignManagement|Cancel comment confirmation'),
okTitle: s__('DesignManagement|Discard comment'),
cancelTitle: s__('DesignManagement|Keep comment'),
content: s__('DesignManagement|Are you sure you want to cancel creating this comment?'),
};
}
return {
title: s__('DesignManagement|Cancel comment update confirmation'),
okTitle: s__('DesignManagement|Cancel changes'),
cancelTitle: s__('DesignManagement|Keep changes'),
content: s__('DesignManagement|Are you sure you want to cancel changes to this comment?'),
};
},
buttonText() {
return this.isNewComment
? s__('DesignManagement|Comment')
: s__('DesignManagement|Save comment');
},
}, },
mounted() { mounted() {
this.$refs.textarea.focus(); this.$refs.textarea.focus();
...@@ -37,7 +69,7 @@ export default { ...@@ -37,7 +69,7 @@ export default {
if (this.hasValue) this.$emit('submitForm'); if (this.hasValue) this.$emit('submitForm');
}, },
cancelComment() { cancelComment() {
if (this.hasValue) { if (this.hasValue && this.formText !== this.value) {
this.$refs.cancelCommentModal.show(); this.$refs.cancelCommentModal.show();
} else { } else {
this.$emit('cancelForm'); this.$emit('cancelForm');
...@@ -85,7 +117,7 @@ export default { ...@@ -85,7 +117,7 @@ export default {
data-qa-selector="save_comment_button" data-qa-selector="save_comment_button"
@click="$emit('submitForm')" @click="$emit('submitForm')"
> >
{{ __('Comment') }} {{ buttonText }}
</gl-deprecated-button> </gl-deprecated-button>
<gl-deprecated-button ref="cancelButton" @click="cancelComment">{{ <gl-deprecated-button ref="cancelButton" @click="cancelComment">{{
__('Cancel') __('Cancel')
...@@ -94,12 +126,12 @@ export default { ...@@ -94,12 +126,12 @@ export default {
<gl-modal <gl-modal
ref="cancelCommentModal" ref="cancelCommentModal"
ok-variant="danger" ok-variant="danger"
:title="s__('DesignManagement|Cancel comment confirmation')" :title="modalSettings.title"
:ok-title="s__('DesignManagement|Discard comment')" :ok-title="modalSettings.okTitle"
:cancel-title="s__('DesignManagement|Keep comment')" :cancel-title="modalSettings.cancelTitle"
modal-id="cancel-comment-modal" modal-id="cancel-comment-modal"
@ok="$emit('cancelForm')" @ok="$emit('cancelForm')"
>{{ s__('DesignManagement|Are you sure you want to cancel creating this comment?') }} >{{ modalSettings.content }}
</gl-modal> </gl-modal>
</form> </form>
</template> </template>
#import "../fragments/designNote.fragment.graphql"
mutation updateNote($input: UpdateNoteInput!) {
updateNote(input: $input) {
note {
...DesignNote
}
errors
}
}
...@@ -32,6 +32,7 @@ import { ...@@ -32,6 +32,7 @@ import {
UPDATE_IMAGE_DIFF_NOTE_ERROR, UPDATE_IMAGE_DIFF_NOTE_ERROR,
DESIGN_NOT_FOUND_ERROR, DESIGN_NOT_FOUND_ERROR,
DESIGN_VERSION_NOT_EXIST_ERROR, DESIGN_VERSION_NOT_EXIST_ERROR,
UPDATE_NOTE_ERROR,
designDeletionError, designDeletionError,
} from '../../utils/error_messages'; } from '../../utils/error_messages';
import { DESIGNS_ROUTE_NAME } from '../../router/constants'; import { DESIGNS_ROUTE_NAME } from '../../router/constants';
...@@ -231,6 +232,9 @@ export default { ...@@ -231,6 +232,9 @@ export default {
onCreateImageDiffNoteError(e) { onCreateImageDiffNoteError(e) {
this.onError(ADD_IMAGE_DIFF_NOTE_ERROR, e); this.onError(ADD_IMAGE_DIFF_NOTE_ERROR, e);
}, },
onUpdateNoteError(e) {
this.onError(UPDATE_NOTE_ERROR, e);
},
onDesignDiscussionError(e) { onDesignDiscussionError(e) {
this.onError(ADD_DISCUSSION_COMMENT_ERROR, e); this.onError(ADD_DISCUSSION_COMMENT_ERROR, e);
}, },
...@@ -329,6 +333,7 @@ export default { ...@@ -329,6 +333,7 @@ export default {
:discussion-index="index + 1" :discussion-index="index + 1"
:markdown-preview-path="markdownPreviewPath" :markdown-preview-path="markdownPreviewPath"
@error="onDesignDiscussionError" @error="onDesignDiscussionError"
@updateNoteError="onUpdateNoteError"
/> />
<apollo-mutation <apollo-mutation
v-if="annotationCoordinates" v-if="annotationCoordinates"
...@@ -345,7 +350,7 @@ export default { ...@@ -345,7 +350,7 @@ export default {
v-model="comment" v-model="comment"
:is-saving="loading" :is-saving="loading"
:markdown-preview-path="markdownPreviewPath" :markdown-preview-path="markdownPreviewPath"
@submitForm="mutate()" @submitForm="mutate"
@cancelForm="closeCommentForm" @cancelForm="closeCommentForm"
/> />
</apollo-mutation> </apollo-mutation>
......
...@@ -214,7 +214,7 @@ const onError = (data, message) => { ...@@ -214,7 +214,7 @@ const onError = (data, message) => {
throw new Error(data.errors); throw new Error(data.errors);
}; };
const hasErrors = ({ errors = [] }) => errors?.length; export const hasErrors = ({ errors = [] }) => errors?.length;
/** /**
* Updates a store after design deletion * Updates a store after design deletion
......
...@@ -12,6 +12,8 @@ export const UPDATE_IMAGE_DIFF_NOTE_ERROR = s__( ...@@ -12,6 +12,8 @@ export const UPDATE_IMAGE_DIFF_NOTE_ERROR = s__(
'DesignManagement|Could not update discussion. Please try again.', 'DesignManagement|Could not update discussion. Please try again.',
); );
export const UPDATE_NOTE_ERROR = s__('DesignManagement|Could not update note. Please try again.');
export const UPLOAD_DESIGN_ERROR = s__( export const UPLOAD_DESIGN_ERROR = s__(
'DesignManagement|Error uploading a new design. Please try again.', 'DesignManagement|Error uploading a new design. Please try again.',
); );
......
---
title: 'Resolve Design Comment: Edit Comment text'
merge_request: 30479
author:
type: added
...@@ -7220,15 +7220,27 @@ msgstr "" ...@@ -7220,15 +7220,27 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version." msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "" msgstr ""
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
msgid "DesignManagement|Are you sure you want to cancel creating this comment?" msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "" msgstr ""
msgid "DesignManagement|Are you sure you want to delete the selected designs?" msgid "DesignManagement|Are you sure you want to delete the selected designs?"
msgstr "" msgstr ""
msgid "DesignManagement|Cancel changes"
msgstr ""
msgid "DesignManagement|Cancel comment confirmation" msgid "DesignManagement|Cancel comment confirmation"
msgstr "" msgstr ""
msgid "DesignManagement|Cancel comment update confirmation"
msgstr ""
msgid "DesignManagement|Comment"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again." msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "" msgstr ""
...@@ -7238,6 +7250,9 @@ msgstr "" ...@@ -7238,6 +7250,9 @@ msgstr ""
msgid "DesignManagement|Could not update discussion. Please try again." msgid "DesignManagement|Could not update discussion. Please try again."
msgstr "" msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
msgid "DesignManagement|Delete" msgid "DesignManagement|Delete"
msgstr "" msgstr ""
...@@ -7265,12 +7280,18 @@ msgstr "" ...@@ -7265,12 +7280,18 @@ msgstr ""
msgid "DesignManagement|Go to previous design" msgid "DesignManagement|Go to previous design"
msgstr "" msgstr ""
msgid "DesignManagement|Keep changes"
msgstr ""
msgid "DesignManagement|Keep comment" msgid "DesignManagement|Keep comment"
msgstr "" msgstr ""
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead" msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "" msgstr ""
msgid "DesignManagement|Save comment"
msgstr ""
msgid "DesignManagement|Select all" msgid "DesignManagement|Select all"
msgstr "" msgstr ""
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
exports[`Design note component should match the snapshot 1`] = ` exports[`Design note component should match the snapshot 1`] = `
<timeline-entry-item-stub <timeline-entry-item-stub
class="design-note note-form" class="design-note note-form"
id="note_undefined" id="note_123"
> >
<user-avatar-link-stub <user-avatar-link-stub
imgalt="" imgalt=""
...@@ -16,6 +16,10 @@ exports[`Design note component should match the snapshot 1`] = ` ...@@ -16,6 +16,10 @@ exports[`Design note component should match the snapshot 1`] = `
username="" username=""
/> />
<div
class="d-flex justify-content-between"
>
<div>
<a <a
class="js-user-link" class="js-user-link"
data-user-id="author-id" data-user-id="author-id"
...@@ -42,24 +46,25 @@ exports[`Design note component should match the snapshot 1`] = ` ...@@ -42,24 +46,25 @@ exports[`Design note component should match the snapshot 1`] = `
class="system-note-message" class="system-note-message"
/> />
<span <!---->
class="system-note-separator" </span>
/> </div>
<a <button
class="note-timestamp system-note-separator" class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
href="#note_undefined" title="Edit comment"
type="button"
> >
<time-ago-tooltip-stub <gl-icon-stub
cssclass="" class="link-highlight"
time="2019-07-26T15:02:20Z" name="pencil"
tooltipplacement="bottom" size="16"
/> />
</a> </button>
</span> </div>
<div <div
class="note-text md" class="note-text js-note-text md"
data-qa-selector="note_content" data-qa-selector="note_content"
/> />
</timeline-entry-item-stub> </timeline-entry-item-stub>
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design reply form component renders button text as "Comment" when creating a comment 1`] = `
"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
<!---->
Comment
</button>"
`;
exports[`Design reply form component renders button text as "Save comment" when creating a comment 1`] = `
"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
<!---->
Save comment
</button>"
`;
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
import DesignNote from '~/design_management/components/design_notes/design_note.vue'; import DesignNote from '~/design_management/components/design_notes/design_note.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
const scrollIntoViewMock = jest.fn(); const scrollIntoViewMock = jest.fn();
const note = {
id: 'gid://gitlab/DiffNote/123',
author: {
id: 'author-id',
},
body: 'test',
};
HTMLElement.prototype.scrollIntoView = scrollIntoViewMock; HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
const $route = { const $route = {
hash: '#note_123', hash: '#note_123',
}; };
const mutate = jest.fn().mockResolvedValue({ data: { updateNote: {} } });
describe('Design note component', () => { describe('Design note component', () => {
let wrapper; let wrapper;
const findUserAvatar = () => wrapper.find(UserAvatarLink); const findUserAvatar = () => wrapper.find(UserAvatarLink);
const findUserLink = () => wrapper.find('.js-user-link'); const findUserLink = () => wrapper.find('.js-user-link');
const findReplyForm = () => wrapper.find(DesignReplyForm);
const findEditButton = () => wrapper.find('.js-note-edit');
const findNoteContent = () => wrapper.find('.js-note-text');
function createComponent(props = {}) { function createComponent(props = {}, data = { isEditing: false }) {
wrapper = shallowMount(DesignNote, { wrapper = shallowMount(DesignNote, {
propsData: { propsData: {
note: {}, note: {},
...props, ...props,
}, },
data() {
return {
...data,
};
},
mocks: { mocks: {
$route, $route,
$apollo: {
mutate,
},
},
stubs: {
ApolloMutation,
}, },
}); });
} }
...@@ -34,13 +59,7 @@ describe('Design note component', () => { ...@@ -34,13 +59,7 @@ describe('Design note component', () => {
it('should match the snapshot', () => { it('should match the snapshot', () => {
createComponent({ createComponent({
note: { note,
id: '1',
createdAt: '2019-07-26T15:02:20Z',
author: {
id: 'author-id',
},
},
}); });
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
...@@ -48,12 +67,7 @@ describe('Design note component', () => { ...@@ -48,12 +67,7 @@ describe('Design note component', () => {
it('should render an author', () => { it('should render an author', () => {
createComponent({ createComponent({
note: { note,
id: '1',
author: {
id: 'author-id',
},
},
}); });
expect(findUserAvatar().exists()).toBe(true); expect(findUserAvatar().exists()).toBe(true);
...@@ -63,11 +77,8 @@ describe('Design note component', () => { ...@@ -63,11 +77,8 @@ describe('Design note component', () => {
it('should render a time ago tooltip if note has createdAt property', () => { it('should render a time ago tooltip if note has createdAt property', () => {
createComponent({ createComponent({
note: { note: {
id: '1', ...note,
createdAt: '2019-07-26T15:02:20Z', createdAt: '2019-07-26T15:02:20Z',
author: {
id: 'author-id',
},
}, },
}); });
...@@ -76,14 +87,61 @@ describe('Design note component', () => { ...@@ -76,14 +87,61 @@ describe('Design note component', () => {
it('should trigger a scrollIntoView method', () => { it('should trigger a scrollIntoView method', () => {
createComponent({ createComponent({
note: { note,
id: 'gid://gitlab/DiffNote/123',
author: {
id: 'author-id',
},
},
}); });
expect(scrollIntoViewMock).toHaveBeenCalled(); expect(scrollIntoViewMock).toHaveBeenCalled();
}); });
it('should open an edit form on edit button click', () => {
createComponent({
note,
});
findEditButton().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(findReplyForm().exists()).toBe(true);
expect(findNoteContent().exists()).toBe(false);
});
});
describe('when edit form is rendered', () => {
beforeEach(() => {
createComponent(
{
note,
},
{ isEditing: true },
);
});
it('should not render note content and should render reply form', () => {
expect(findNoteContent().exists()).toBe(false);
expect(findReplyForm().exists()).toBe(true);
});
it('hides the form on hideForm event', () => {
findReplyForm().vm.$emit('cancelForm');
return wrapper.vm.$nextTick().then(() => {
expect(findReplyForm().exists()).toBe(false);
expect(findNoteContent().exists()).toBe(true);
});
});
it('calls a mutation on submitForm event and hides a form', () => {
findReplyForm().vm.$emit('submitForm');
expect(mutate).toHaveBeenCalled();
return mutate()
.then(() => {
return wrapper.vm.$nextTick();
})
.then(() => {
expect(findReplyForm().exists()).toBe(false);
expect(findNoteContent().exists()).toBe(true);
});
});
});
}); });
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue'; import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
const showModal = jest.fn();
const GlModal = {
template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
methods: {
show: showModal,
},
};
describe('Design reply form component', () => { describe('Design reply form component', () => {
let wrapper; let wrapper;
...@@ -16,6 +25,7 @@ describe('Design reply form component', () => { ...@@ -16,6 +25,7 @@ describe('Design reply form component', () => {
isSaving: false, isSaving: false,
...props, ...props,
}, },
stubs: { GlModal },
}); });
} }
...@@ -29,6 +39,18 @@ describe('Design reply form component', () => { ...@@ -29,6 +39,18 @@ describe('Design reply form component', () => {
expect(findTextarea().element).toEqual(document.activeElement); expect(findTextarea().element).toEqual(document.activeElement);
}); });
it('renders button text as "Comment" when creating a comment', () => {
createComponent();
expect(findSubmitButton().html()).toMatchSnapshot();
});
it('renders button text as "Save comment" when creating a comment', () => {
createComponent({ isNewComment: false });
expect(findSubmitButton().html()).toMatchSnapshot();
});
describe('when form has no text', () => { describe('when form has no text', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ createComponent({
...@@ -120,16 +142,34 @@ describe('Design reply form component', () => { ...@@ -120,16 +142,34 @@ describe('Design reply form component', () => {
}); });
}); });
it('opens confirmation modal on pressing Escape button', () => { it('emits cancelForm event on Escape key if text was not changed', () => {
findTextarea().trigger('keyup.esc'); findTextarea().trigger('keyup.esc');
expect(findModal().exists()).toBe(true); expect(wrapper.emitted('cancelForm')).toBeTruthy();
}); });
it('opens confirmation modal on Cancel button click', () => { it('opens confirmation modal on Escape key when text has changed', () => {
findCancelButton().vm.$emit('click'); wrapper.setProps({ value: 'test2' });
expect(findModal().exists()).toBe(true); return wrapper.vm.$nextTick().then(() => {
findTextarea().trigger('keyup.esc');
expect(showModal).toHaveBeenCalled();
});
});
it('emits cancelForm event on Cancel button click if text was not changed', () => {
findCancelButton().trigger('click');
expect(wrapper.emitted('cancelForm')).toBeTruthy();
});
it('opens confirmation modal on Cancel button click when text has changed', () => {
wrapper.setProps({ value: 'test2' });
return wrapper.vm.$nextTick().then(() => {
findCancelButton().trigger('click');
expect(showModal).toHaveBeenCalled();
});
}); });
it('emits cancelForm event on modal Ok button click', () => { it('emits cancelForm event on modal Ok button click', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment