From 9f46488805e86b1bc341ea1620b866016c2ce5ed Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 20 May 2020 14:34:42 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-0-stable-ee --- .../frontend/notes/components/comment_form_spec.js | 7 +- .../notes/components/discussion_actions_spec.js | 2 +- .../notes/components/discussion_counter_spec.js | 9 +-- .../notes/components/discussion_filter_spec.js | 4 +- .../notes/components/discussion_notes_spec.js | 2 +- spec/frontend/notes/components/note_form_spec.js | 8 +- spec/frontend/notes/components/note_header_spec.js | 94 ++++++++++++++++++---- .../notes/components/noteable_discussion_spec.js | 2 +- spec/frontend/notes/components/notes_app_spec.js | 2 +- 9 files changed, 94 insertions(+), 36 deletions(-) (limited to 'spec/frontend/notes/components') diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index a2c7f0b3767..dc68c4371aa 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -9,12 +9,7 @@ import CommentForm from '~/notes/components/comment_form.vue'; import * as constants from '~/notes/constants'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import { keyboardDownEvent } from '../../issue_show/helpers'; -import { - loggedOutnoteableData, - notesDataMock, - userDataMock, - noteableDataMock, -} from '../../notes/mock_data'; +import { loggedOutnoteableData, notesDataMock, userDataMock, noteableDataMock } from '../mock_data'; jest.mock('autosize'); jest.mock('~/commons/nav/user_merge_requests'); diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js index 5101b81e3ee..44dc148933c 100644 --- a/spec/frontend/notes/components/discussion_actions_spec.js +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -1,5 +1,5 @@ import { shallowMount, mount } from '@vue/test-utils'; -import { discussionMock } from '../../notes/mock_data'; +import { discussionMock } from '../mock_data'; import DiscussionActions from '~/notes/components/discussion_actions.vue'; import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue'; diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js index 77603c16f82..04535aa17c5 100644 --- a/spec/frontend/notes/components/discussion_counter_spec.js +++ b/spec/frontend/notes/components/discussion_counter_spec.js @@ -75,15 +75,14 @@ describe('DiscussionCounter component', () => { }); it.each` - title | resolved | isActive | icon | groupLength - ${'not allResolved'} | ${false} | ${false} | ${'check-circle'} | ${3} - ${'allResolved'} | ${true} | ${true} | ${'check-circle-filled'} | ${1} - `('renders correctly if $title', ({ resolved, isActive, icon, groupLength }) => { + title | resolved | isActive | groupLength + ${'not allResolved'} | ${false} | ${false} | ${3} + ${'allResolved'} | ${true} | ${true} | ${1} + `('renders correctly if $title', ({ resolved, isActive, groupLength }) => { updateStore({ resolvable: true, resolved }); wrapper = shallowMount(DiscussionCounter, { store, localVue }); expect(wrapper.find(`.is-active`).exists()).toBe(isActive); - expect(wrapper.find({ name: icon }).exists()).toBe(true); expect(wrapper.findAll('[role="group"').length).toBe(groupLength); }); }); diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js index b8d2d721443..7f042c0e9de 100644 --- a/spec/frontend/notes/components/discussion_filter_spec.js +++ b/spec/frontend/notes/components/discussion_filter_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import createEventHub from '~/helpers/event_hub_factory'; import Vuex from 'vuex'; import { createLocalVue, mount } from '@vue/test-utils'; @@ -132,7 +132,7 @@ describe('DiscussionFilter component', () => { }); describe('Merge request tabs', () => { - eventHub = new Vue(); + eventHub = createEventHub(); beforeEach(() => { window.mrTabs = { diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js index 81773752037..5a10deefd09 100644 --- a/spec/frontend/notes/components/discussion_notes_spec.js +++ b/spec/frontend/notes/components/discussion_notes_spec.js @@ -7,7 +7,7 @@ import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue' import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue'; import SystemNote from '~/vue_shared/components/notes/system_note.vue'; import createStore from '~/notes/stores'; -import { noteableDataMock, discussionMock, notesDataMock } from '../../notes/mock_data'; +import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data'; describe('DiscussionNotes', () => { let wrapper; diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js index bccac03126c..8270c148fb5 100644 --- a/spec/frontend/notes/components/note_form_spec.js +++ b/spec/frontend/notes/components/note_form_spec.js @@ -161,18 +161,18 @@ describe('issue_note_form component', () => { describe('actions', () => { it('should be possible to cancel', () => { - // TODO: do not spy on vm - jest.spyOn(wrapper.vm, 'cancelHandler'); + const cancelHandler = jest.fn(); wrapper.setProps({ ...props, isEditing: true, }); + wrapper.setMethods({ cancelHandler }); return wrapper.vm.$nextTick().then(() => { - const cancelButton = wrapper.find('.note-edit-cancel'); + const cancelButton = wrapper.find('[data-testid="cancel"]'); cancelButton.trigger('click'); - expect(wrapper.vm.cancelHandler).toHaveBeenCalled(); + expect(cancelHandler).toHaveBeenCalledWith(true); }); }); diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js index d477de69716..2bb08b60569 100644 --- a/spec/frontend/notes/components/note_header_spec.js +++ b/spec/frontend/notes/components/note_header_spec.js @@ -1,7 +1,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Vuex from 'vuex'; import NoteHeader from '~/notes/components/note_header.vue'; -import GitlabTeamMemberBadge from '~/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'; const localVue = createLocalVue(); localVue.use(Vuex); @@ -18,6 +18,7 @@ describe('NoteHeader component', () => { const findActionText = () => wrapper.find({ ref: 'actionText' }); const findTimestampLink = () => wrapper.find({ ref: 'noteTimestampLink' }); const findTimestamp = () => wrapper.find({ ref: 'noteTimestamp' }); + const findConfidentialIndicator = () => wrapper.find('[data-testid="confidentialIndicator"]'); const findSpinner = () => wrapper.find({ ref: 'spinner' }); const author = { @@ -140,20 +141,6 @@ describe('NoteHeader component', () => { }); }); - test.each` - props | expected | message1 | message2 - ${{ author: { ...author, is_gitlab_employee: true } }} | ${true} | ${'renders'} | ${'true'} - ${{ author: { ...author, is_gitlab_employee: false } }} | ${false} | ${"doesn't render"} | ${'false'} - ${{ author }} | ${false} | ${"doesn't render"} | ${'undefined'} - `( - '$message1 GitLab team member badge when `is_gitlab_employee` is $message2', - ({ props, expected }) => { - createComponent(props); - - expect(wrapper.find(GitlabTeamMemberBadge).exists()).toBe(expected); - }, - ); - describe('loading spinner', () => { it('shows spinner when showSpinner is true', () => { createComponent(); @@ -179,4 +166,81 @@ describe('NoteHeader component', () => { expect(findTimestamp().exists()).toBe(true); }); }); + + describe('author username link', () => { + it('proxies `mouseenter` event to author name link', () => { + createComponent({ author }); + + const dispatchEvent = jest.spyOn(wrapper.vm.$refs.authorNameLink, 'dispatchEvent'); + + wrapper.find({ ref: 'authorUsernameLink' }).trigger('mouseenter'); + + expect(dispatchEvent).toHaveBeenCalledWith(new Event('mouseenter')); + }); + + it('proxies `mouseleave` event to author name link', () => { + createComponent({ author }); + + const dispatchEvent = jest.spyOn(wrapper.vm.$refs.authorNameLink, 'dispatchEvent'); + + wrapper.find({ ref: 'authorUsernameLink' }).trigger('mouseleave'); + + expect(dispatchEvent).toHaveBeenCalledWith(new Event('mouseleave')); + }); + }); + + describe('when author status tooltip is opened', () => { + it('removes `title` attribute from emoji to prevent duplicate tooltips', () => { + createComponent({ + author: { + ...author, + status_tooltip_html: + '"🏀"', + }, + }); + + return nextTick().then(() => { + const authorStatus = wrapper.find({ ref: 'authorStatus' }); + authorStatus.trigger('mouseenter'); + + expect(authorStatus.find('gl-emoji').attributes('title')).toBeUndefined(); + }); + }); + }); + + describe('when author username link is hovered', () => { + it('toggles hover specific CSS classes on author name link', done => { + createComponent({ author }); + + const authorUsernameLink = wrapper.find({ ref: 'authorUsernameLink' }); + const authorNameLink = wrapper.find({ ref: 'authorNameLink' }); + + authorUsernameLink.trigger('mouseenter'); + + nextTick(() => { + expect(authorNameLink.classes()).toContain('hover'); + expect(authorNameLink.classes()).toContain('text-underline'); + + authorUsernameLink.trigger('mouseleave'); + + nextTick(() => { + expect(authorNameLink.classes()).not.toContain('hover'); + expect(authorNameLink.classes()).not.toContain('text-underline'); + + done(); + }); + }); + }); + }); + + describe('with confidentiality indicator', () => { + it.each` + status | condition + ${true} | ${'shows'} + ${false} | ${'hides'} + `('$condition icon indicator when isConfidential is $status', ({ status }) => { + createComponent({ isConfidential: status }); + expect(findConfidentialIndicator().exists()).toBe(status); + }); + }); }); diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js index b91f599f158..b14ec2a65be 100644 --- a/spec/frontend/notes/components/noteable_discussion_spec.js +++ b/spec/frontend/notes/components/noteable_discussion_spec.js @@ -138,7 +138,7 @@ describe('noteable_discussion component', () => { describe('signout widget', () => { beforeEach(() => { - originalGon = Object.assign({}, window.gon); + originalGon = { ...window.gon }; window.gon = window.gon || {}; }); diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index e22dd85f221..fbfba2efb1d 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -10,7 +10,7 @@ import createStore from '~/notes/stores'; import * as constants from '~/notes/constants'; import '~/behaviors/markdown/render_gfm'; // TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-foss/issues/62491) -import * as mockData from '../../notes/mock_data'; +import * as mockData from '../mock_data'; import * as urlUtility from '~/lib/utils/url_utility'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; -- cgit v1.2.3