diff options
Diffstat (limited to 'spec/frontend/sidebar')
27 files changed, 380 insertions, 56 deletions
diff --git a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap index e295c587d70..846f45345e7 100644 --- a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap +++ b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap @@ -3,7 +3,7 @@ exports[`SidebarTodo template renders component container element with proper data attributes 1`] = ` <button aria-label="Mark as done" - class="btn btn-default btn-todo issuable-header-btn float-right" + class="gl-button btn btn-default btn-todo issuable-header-btn float-right" data-issuable-id="1" data-issuable-type="epic" type="button" diff --git a/spec/frontend/sidebar/assignee_title_spec.js b/spec/frontend/sidebar/assignee_title_spec.js index 9f5d51c7795..3079cb28406 100644 --- a/spec/frontend/sidebar/assignee_title_spec.js +++ b/spec/frontend/sidebar/assignee_title_spec.js @@ -1,5 +1,5 @@ -import { shallowMount } from '@vue/test-utils'; import { GlLoadingIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import Component from '~/sidebar/components/assignees/assignee_title.vue'; diff --git a/spec/frontend/sidebar/assignees_realtime_spec.js b/spec/frontend/sidebar/assignees_realtime_spec.js index 1c62c52dc67..0fab6a29f71 100644 --- a/spec/frontend/sidebar/assignees_realtime_spec.js +++ b/spec/frontend/sidebar/assignees_realtime_spec.js @@ -1,9 +1,9 @@ -import { shallowMount } from '@vue/test-utils'; import ActionCable from '@rails/actioncable'; +import { shallowMount } from '@vue/test-utils'; +import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql'; import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import Mock from './mock_data'; -import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql'; jest.mock('@rails/actioncable', () => { const mockConsumer = { diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js index 23e82171fe9..74dce499999 100644 --- a/spec/frontend/sidebar/assignees_spec.js +++ b/spec/frontend/sidebar/assignees_spec.js @@ -1,6 +1,6 @@ +import { GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { trimText } from 'helpers/text_helper'; -import { GlIcon } from '@gitlab/ui'; import UsersMockHelper from 'helpers/user_mock_data_helper'; import Assignee from '~/sidebar/components/assignees/assignees.vue'; import UsersMock from './mock_data'; diff --git a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js index 03d1ac3ab8d..5a3a152d201 100644 --- a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js +++ b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js @@ -1,7 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import { TEST_HOST } from 'helpers/test_constants'; -import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue'; import AssigneeAvatar from '~/sidebar/components/assignees/assignee_avatar.vue'; +import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue'; import userDataMock from '../../user_data_mock'; const TOOLTIP_PLACEMENT = 'bottom'; @@ -79,4 +79,34 @@ describe('AssigneeAvatarLink component', () => { }); }, ); + + describe.each` + tooltipHasName | availability | canMerge | expected + ${true} | ${'Busy'} | ${false} | ${'Root (Busy) (cannot merge)'} + ${true} | ${'Busy'} | ${true} | ${'Root (Busy)'} + ${true} | ${''} | ${false} | ${'Root (cannot merge)'} + ${true} | ${''} | ${true} | ${'Root'} + ${false} | ${'Busy'} | ${false} | ${'Cannot merge'} + ${false} | ${'Busy'} | ${true} | ${''} + ${false} | ${''} | ${false} | ${'Cannot merge'} + ${false} | ${''} | ${true} | ${''} + `( + "with tooltipHasName=$tooltipHasName and availability='$availability' and canMerge=$canMerge", + ({ tooltipHasName, availability, canMerge, expected }) => { + beforeEach(() => { + createComponent({ + tooltipHasName, + user: { + ...userDataMock(), + can_merge: canMerge, + availability, + }, + }); + }); + + it('sets tooltip to $expected', () => { + expect(findTooltipText()).toBe(expected); + }); + }, + ); }); diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js index 8e158c99971..5aa8264b98c 100644 --- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js @@ -1,8 +1,8 @@ -import { shallowMount } from '@vue/test-utils'; import { GlIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import UsersMockHelper from 'helpers/user_mock_data_helper'; -import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue'; import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue'; +import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue'; const DEFAULT_MAX_COUNTER = 99; @@ -187,4 +187,26 @@ describe('CollapsedAssigneeList component', () => { expect(findAvatarCounter().text()).toEqual(`${DEFAULT_MAX_COUNTER}+`); }); }); + + const [busyUser] = UsersMockHelper.createNumberRandomUsers(1); + const [canMergeUser] = UsersMockHelper.createNumberRandomUsers(1); + busyUser.availability = 'busy'; + canMergeUser.can_merge = true; + + describe.each` + users | busy | canMerge | expected + ${[busyUser, canMergeUser]} | ${1} | ${1} | ${`${busyUser.name} (Busy), ${canMergeUser.name} (1/2 can merge)`} + ${[busyUser]} | ${1} | ${0} | ${`${busyUser.name} (Busy) (cannot merge)`} + ${[canMergeUser]} | ${0} | ${1} | ${`${canMergeUser.name}`} + ${[]} | ${0} | ${0} | ${'Assignee(s)'} + `( + 'with $users.length users, $busy is busy and $canMerge that can merge', + ({ users, expected }) => { + it('generates the tooltip text', () => { + createComponent({ users }); + + expect(getTooltipTitle()).toEqual(expected); + }); + }, + ); }); diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js index ee1f8ed8d2b..b49e6255923 100644 --- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js +++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; -import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue'; import AssigneeAvatar from '~/sidebar/components/assignees/assignee_avatar.vue'; +import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue'; +import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue'; import userDataMock from '../../user_data_mock'; const TEST_USER = userDataMock(); @@ -18,6 +19,9 @@ describe('CollapsedAssignee assignee component', () => { wrapper = shallowMount(CollapsedAssignee, { propsData, + stubs: { + UserNameWithStatus, + }, }); } diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js new file mode 100644 index 00000000000..4ee12838491 --- /dev/null +++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js @@ -0,0 +1,120 @@ +import { GlLoadingIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; + +describe('boards sidebar remove issue', () => { + let wrapper; + + const findLoader = () => wrapper.find(GlLoadingIcon); + const findEditButton = () => wrapper.find('[data-testid="edit-button"]'); + const findTitle = () => wrapper.find('[data-testid="title"]'); + const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]'); + const findExpanded = () => wrapper.find('[data-testid="expanded-content"]'); + + const createComponent = ({ props = {}, slots = {}, canUpdate = false } = {}) => { + wrapper = shallowMount(SidebarEditableItem, { + attachTo: document.body, + provide: { canUpdate }, + propsData: props, + slots, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('template', () => { + it('renders title', () => { + const title = 'Sidebar item title'; + createComponent({ props: { title } }); + + expect(findTitle().text()).toBe(title); + }); + + it('hides edit button, loader and expanded content by default', () => { + createComponent(); + + expect(findEditButton().exists()).toBe(false); + expect(findLoader().exists()).toBe(false); + expect(findExpanded().isVisible()).toBe(false); + }); + + it('shows "None" if empty collapsed slot', () => { + createComponent(); + + expect(findCollapsed().text()).toBe('None'); + }); + + it('renders collapsed content by default', () => { + const slots = { collapsed: '<div>Collapsed content</div>' }; + createComponent({ slots }); + + expect(findCollapsed().text()).toBe('Collapsed content'); + }); + + it('shows edit button if can update', () => { + createComponent({ canUpdate: true }); + + expect(findEditButton().exists()).toBe(true); + }); + + it('shows loading icon if loading', () => { + createComponent({ props: { loading: true } }); + + expect(findLoader().exists()).toBe(true); + }); + + it('shows expanded content and hides collapsed content when clicking edit button', async () => { + const slots = { default: '<div>Select item</div>' }; + createComponent({ canUpdate: true, slots }); + findEditButton().vm.$emit('click'); + + await wrapper.vm.$nextTick; + + expect(findCollapsed().isVisible()).toBe(false); + expect(findExpanded().isVisible()).toBe(true); + }); + }); + + describe('collapsing an item by offclicking', () => { + beforeEach(async () => { + createComponent({ canUpdate: true }); + findEditButton().vm.$emit('click'); + await wrapper.vm.$nextTick(); + }); + + it('hides expanded section and displays collapsed section', async () => { + expect(findExpanded().isVisible()).toBe(true); + document.body.click(); + + await wrapper.vm.$nextTick(); + + expect(findCollapsed().isVisible()).toBe(true); + expect(findExpanded().isVisible()).toBe(false); + }); + }); + + it('emits open when edit button is clicked and edit is initailized to false', async () => { + createComponent({ canUpdate: true }); + + findEditButton().vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + expect(wrapper.emitted().open.length).toBe(1); + }); + + it('does not emits events when collapsing with false `emitEvent`', async () => { + createComponent({ canUpdate: true }); + + findEditButton().vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + wrapper.vm.collapse({ emitEvent: false }); + + expect(wrapper.emitted().close).toBeUndefined(); + }); +}); diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js index da69f56d442..7e81df1d7d2 100644 --- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js @@ -1,8 +1,8 @@ import { mount } from '@vue/test-utils'; import { TEST_HOST } from 'helpers/test_constants'; import UsersMockHelper from 'helpers/user_mock_data_helper'; -import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue'; import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue'; +import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue'; import userDataMock from '../../user_data_mock'; const DEFAULT_RENDER_COUNT = 5; diff --git a/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js b/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js new file mode 100644 index 00000000000..9483c6624c5 --- /dev/null +++ b/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js @@ -0,0 +1,51 @@ +import { GlSprintf } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { AVAILABILITY_STATUS } from '~/set_status_modal/utils'; +import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue'; + +const name = 'Goku'; +const containerClasses = 'gl-cool-class gl-over-9000'; + +describe('UserNameWithStatus', () => { + let wrapper; + + function createComponent(props = {}) { + return shallowMount(UserNameWithStatus, { + propsData: { name, containerClasses, ...props }, + stubs: { + GlSprintf, + }, + }); + } + + beforeEach(() => { + wrapper = createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('will render the users name', () => { + expect(wrapper.html()).toContain(name); + }); + + it('will not render "Busy"', () => { + expect(wrapper.html()).not.toContain('Busy'); + }); + + it('will render all relevant containerClasses', () => { + const classes = wrapper.find('span').classes().join(' '); + expect(classes).toBe(containerClasses); + }); + + describe(`with availability="${AVAILABILITY_STATUS.BUSY}"`, () => { + beforeEach(() => { + wrapper = createComponent({ availability: AVAILABILITY_STATUS.BUSY }); + }); + + it('will render "Busy"', () => { + expect(wrapper.html()).toContain('Goku (Busy)'); + }); + }); +}); diff --git a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js index b9132fa4450..704847f65bf 100644 --- a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js +++ b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js @@ -1,7 +1,7 @@ -import { mount } from '@vue/test-utils'; import { getByText } from '@testing-library/dom'; -import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import { mount } from '@vue/test-utils'; import CopyEmailToClipboard from '~/sidebar/components/copy_email_to_clipboard.vue'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; describe('CopyEmailToClipboard component', () => { const sampleEmail = 'sample+email@test.com'; diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js new file mode 100644 index 00000000000..7c67149b517 --- /dev/null +++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js @@ -0,0 +1,91 @@ +import { shallowMount } from '@vue/test-utils'; +import { TEST_HOST } from 'helpers/test_constants'; +import ReviewerAvatarLink from '~/sidebar/components/reviewers/reviewer_avatar_link.vue'; +import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue'; +import userDataMock from '../../user_data_mock'; + +describe('UncollapsedReviewerList component', () => { + let wrapper; + + function createComponent(props = {}) { + const propsData = { + users: [], + rootPath: TEST_HOST, + ...props, + }; + + wrapper = shallowMount(UncollapsedReviewerList, { + propsData, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + describe('single reviewer', () => { + beforeEach(() => { + const user = userDataMock(); + + createComponent({ + users: [user], + }); + }); + + it('only has one user', () => { + expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(1); + }); + + it('shows one user with avatar, username and author name', () => { + expect(wrapper.text()).toContain(`@root`); + }); + + it('renders re-request loading icon', async () => { + await wrapper.setData({ loadingStates: { 1: 'loading' } }); + + expect(wrapper.find('[data-testid="re-request-button"]').props('loading')).toBe(true); + }); + + it('renders re-request success icon', async () => { + await wrapper.setData({ loadingStates: { 1: 'success' } }); + + expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true); + }); + }); + + describe('multiple reviewers', () => { + beforeEach(() => { + const user = userDataMock(); + + createComponent({ + users: [user, { ...user, id: 2, username: 'hello-world' }], + }); + }); + + it('only has one user', () => { + expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(2); + }); + + it('shows one user with avatar, username and author name', () => { + expect(wrapper.text()).toContain(`@root`); + expect(wrapper.text()).toContain(`@hello-world`); + }); + + it('renders re-request loading icon', async () => { + await wrapper.setData({ loadingStates: { 2: 'loading' } }); + + expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(2); + expect(wrapper.findAll('[data-testid="re-request-button"]').at(1).props('loading')).toBe( + true, + ); + }); + + it('renders re-request success icon', async () => { + await wrapper.setData({ loadingStates: { 2: 'success' } }); + + expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(1); + expect(wrapper.findAll('[data-testid="re-request-success"]').length).toBe(1); + expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/sidebar/components/severity/severity_spec.js b/spec/frontend/sidebar/components/severity/severity_spec.js index ba7cea0919c..1e4624e4dcd 100644 --- a/spec/frontend/sidebar/components/severity/severity_spec.js +++ b/spec/frontend/sidebar/components/severity/severity_spec.js @@ -1,7 +1,7 @@ -import { shallowMount } from '@vue/test-utils'; import { GlIcon } from '@gitlab/ui'; -import SeverityToken from '~/sidebar/components/severity/severity.vue'; +import { shallowMount } from '@vue/test-utils'; import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants'; +import SeverityToken from '~/sidebar/components/severity/severity.vue'; describe('SeverityToken', () => { let wrapper; diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js index fa40d75d4e9..747d370e1cf 100644 --- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js +++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js @@ -1,11 +1,11 @@ -import { shallowMount } from '@vue/test-utils'; import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; import createFlash from '~/flash'; -import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue'; -import SeverityToken from '~/sidebar/components/severity/severity.vue'; -import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql'; import { INCIDENT_SEVERITY, ISSUABLE_TYPES } from '~/sidebar/components/severity/constants'; +import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql'; +import SeverityToken from '~/sidebar/components/severity/severity.vue'; +import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue'; jest.mock('~/flash'); diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js index 0b6a2e6ceb9..4d03aedf1be 100644 --- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js +++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js @@ -1,6 +1,6 @@ -import { createMockDirective } from 'helpers/vue_mock_directive'; import { mount } from '@vue/test-utils'; import { stubTransition } from 'helpers/stub_transition'; +import { createMockDirective } from 'helpers/vue_mock_directive'; import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue'; describe('Issuable Time Tracker', () => { diff --git a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js index 8c868205295..427e3a89c29 100644 --- a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js +++ b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js @@ -1,9 +1,9 @@ import { shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; +import { deprecatedCreateFlash as flash } from '~/flash'; +import createStore from '~/notes/stores'; import EditFormButtons from '~/sidebar/components/confidential/edit_form_buttons.vue'; import eventHub from '~/sidebar/event_hub'; -import createStore from '~/notes/stores'; -import { deprecatedCreateFlash as flash } from '~/flash'; jest.mock('~/sidebar/event_hub', () => ({ $emit: jest.fn() })); jest.mock('~/flash'); diff --git a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js index bc2df9305d0..93a6401b1fc 100644 --- a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js +++ b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js @@ -1,10 +1,10 @@ import { shallowMount } from '@vue/test-utils'; -import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; -import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue'; -import EditForm from '~/sidebar/components/confidential/edit_form.vue'; +import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import createStore from '~/notes/stores'; import * as types from '~/notes/stores/mutation_types'; +import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue'; +import EditForm from '~/sidebar/components/confidential/edit_form.vue'; jest.mock('~/flash'); jest.mock('~/sidebar/services/sidebar_service'); diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js index a14ca711204..49283ea99cf 100644 --- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js +++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils'; -import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue'; -import eventHub from '~/sidebar/event_hub'; import { deprecatedCreateFlash as flash } from '~/flash'; -import createStore from '~/notes/stores'; import { createStore as createMrStore } from '~/mr_notes/stores'; +import createStore from '~/notes/stores'; +import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue'; +import eventHub from '~/sidebar/event_hub'; import { ISSUABLE_TYPE_ISSUE, ISSUABLE_TYPE_MR } from './constants'; jest.mock('~/sidebar/event_hub', () => ({ $emit: jest.fn() })); diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js index 92cdba4f1f2..1743e114bb0 100644 --- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js +++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js @@ -1,10 +1,10 @@ import { shallowMount } from '@vue/test-utils'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; -import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue'; -import EditForm from '~/sidebar/components/lock/edit_form.vue'; -import createStore from '~/notes/stores'; import { createStore as createMrStore } from '~/mr_notes/stores'; +import createStore from '~/notes/stores'; +import EditForm from '~/sidebar/components/lock/edit_form.vue'; +import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue'; import { ISSUABLE_TYPE_ISSUE, ISSUABLE_TYPE_MR } from './constants'; describe('IssuableLockForm', () => { diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js index cbd36040579..3c250be5d5e 100644 --- a/spec/frontend/sidebar/reviewer_title_spec.js +++ b/spec/frontend/sidebar/reviewer_title_spec.js @@ -1,5 +1,5 @@ -import { shallowMount } from '@vue/test-utils'; import { GlLoadingIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import Component from '~/sidebar/components/reviewers/reviewer_title.vue'; diff --git a/spec/frontend/sidebar/reviewers_spec.js b/spec/frontend/sidebar/reviewers_spec.js index 91f28e85f3b..fc24b51287f 100644 --- a/spec/frontend/sidebar/reviewers_spec.js +++ b/spec/frontend/sidebar/reviewers_spec.js @@ -1,6 +1,6 @@ +import { GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { trimText } from 'helpers/text_helper'; -import { GlIcon } from '@gitlab/ui'; import UsersMockHelper from 'helpers/user_mock_data_helper'; import Reviewer from '~/sidebar/components/reviewers/reviewers.vue'; import UsersMock from './mock_data'; @@ -114,8 +114,7 @@ describe('Reviewer component', () => { editable: true, }); - expect(wrapper.findAll('.user-item').length).toBe(users.length); - expect(wrapper.find('.user-list-more').exists()).toBe(false); + expect(wrapper.findAll('[data-testid="reviewer"]').length).toBe(users.length); }); it('shows sorted reviewer where "can merge" users are sorted first', () => { @@ -144,10 +143,10 @@ describe('Reviewer component', () => { users, }); - const userItems = wrapper.findAll('.user-list .user-item a'); + const userItems = wrapper.findAll('[data-testid="reviewer"]'); expect(userItems.length).toBe(3); - expect(userItems.at(0).attributes('title')).toBe(users[2].name); + expect(userItems.at(0).find('a').attributes('title')).toBe(users[2].name); }); it('passes the sorted reviewers to the collapsed-reviewer-list', () => { diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js index f1c13a5f818..e737b57e33d 100644 --- a/spec/frontend/sidebar/sidebar_assignees_spec.js +++ b/spec/frontend/sidebar/sidebar_assignees_spec.js @@ -1,11 +1,11 @@ import { shallowMount } from '@vue/test-utils'; -import AxiosMockAdapter from 'axios-mock-adapter'; import axios from 'axios'; -import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue'; +import AxiosMockAdapter from 'axios-mock-adapter'; import Assigness from '~/sidebar/components/assignees/assignees.vue'; import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue'; -import SidebarMediator from '~/sidebar/sidebar_mediator'; +import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue'; import SidebarService from '~/sidebar/services/sidebar_service'; +import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; import Mock from './mock_data'; diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js index 24bb5a8e916..6a7758ace40 100644 --- a/spec/frontend/sidebar/sidebar_move_issue_spec.js +++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js @@ -1,10 +1,10 @@ -import $ from 'jquery'; import MockAdapter from 'axios-mock-adapter'; +import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; +import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue'; +import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; -import SidebarService from '~/sidebar/services/sidebar_service'; -import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue'; import Mock from './mock_data'; describe('SidebarMoveIssue', () => { diff --git a/spec/frontend/sidebar/sidebar_subscriptions_spec.js b/spec/frontend/sidebar/sidebar_subscriptions_spec.js index 18aaeabe3dd..d900fde7e70 100644 --- a/spec/frontend/sidebar/sidebar_subscriptions_spec.js +++ b/spec/frontend/sidebar/sidebar_subscriptions_spec.js @@ -1,7 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import SidebarSubscriptions from '~/sidebar/components/subscriptions/sidebar_subscriptions.vue'; -import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarService from '~/sidebar/services/sidebar_service'; +import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; import Mock from './mock_data'; diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js index 043ffd972da..e7ae59e26cf 100644 --- a/spec/frontend/sidebar/subscriptions_spec.js +++ b/spec/frontend/sidebar/subscriptions_spec.js @@ -1,17 +1,20 @@ +import { GlToggle } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue'; import eventHub from '~/sidebar/event_hub'; -import ToggleButton from '~/vue_shared/components/toggle_button.vue'; describe('Subscriptions', () => { let wrapper; - const findToggleButton = () => wrapper.find(ToggleButton); + const findToggleButton = () => wrapper.findComponent(GlToggle); const mountComponent = (propsData) => - shallowMount(Subscriptions, { - propsData, - }); + extendedWrapper( + shallowMount(Subscriptions, { + propsData, + }), + ); afterEach(() => { wrapper.destroy(); @@ -24,7 +27,7 @@ describe('Subscriptions', () => { subscribed: undefined, }); - expect(findToggleButton().attributes('isloading')).toBe('true'); + expect(findToggleButton().props('isLoading')).toBe(true); }); it('is toggled "off" when currently not subscribed', () => { @@ -32,7 +35,7 @@ describe('Subscriptions', () => { subscribed: false, }); - expect(findToggleButton().attributes('value')).toBeFalsy(); + expect(findToggleButton().props('value')).toBe(false); }); it('is toggled "on" when currently subscribed', () => { @@ -40,7 +43,7 @@ describe('Subscriptions', () => { subscribed: true, }); - expect(findToggleButton().attributes('value')).toBe('true'); + expect(findToggleButton().props('value')).toBe(true); }); it('toggleSubscription method emits `toggleSubscription` event on eventHub and Component', () => { @@ -93,14 +96,16 @@ describe('Subscriptions', () => { }); it('sets the correct display text', () => { - expect(wrapper.find('.issuable-header-text').text()).toContain(subscribeDisabledDescription); + expect(wrapper.findByTestId('subscription-title').text()).toContain( + subscribeDisabledDescription, + ); expect(wrapper.find({ ref: 'tooltip' }).attributes('title')).toBe( subscribeDisabledDescription, ); }); it('does not render the toggle button', () => { - expect(wrapper.find('.js-issuable-subscribe-button').exists()).toBe(false); + expect(findToggleButton().exists()).toBe(false); }); }); }); diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js index 4adfaf7ad7b..ff6da3abad0 100644 --- a/spec/frontend/sidebar/todo_spec.js +++ b/spec/frontend/sidebar/todo_spec.js @@ -1,5 +1,5 @@ -import { shallowMount } from '@vue/test-utils'; import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue'; @@ -26,7 +26,7 @@ describe('SidebarTodo', () => { it.each` state | classes - ${false} | ${['btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']} + ${false} | ${['gl-button', 'btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']} ${true} | ${['btn-blank', 'btn-todo', 'sidebar-collapsed-icon', 'dont-change-state']} `('returns todo button classes for when `collapsed` prop is `$state`', ({ state, classes }) => { createComponent({ collapsed: state }); @@ -35,7 +35,7 @@ describe('SidebarTodo', () => { it.each` isTodo | iconClass | label | icon - ${false} | ${''} | ${'Add a To-Do'} | ${'todo-add'} + ${false} | ${''} | ${'Add a to do'} | ${'todo-add'} ${true} | ${'todo-undone'} | ${'Mark as done'} | ${'todo-done'} `( 'renders proper button when `isTodo` prop is `$isTodo`', diff --git a/spec/frontend/sidebar/user_data_mock.js b/spec/frontend/sidebar/user_data_mock.js index df90a65f6f9..41d0331f34a 100644 --- a/spec/frontend/sidebar/user_data_mock.js +++ b/spec/frontend/sidebar/user_data_mock.js @@ -8,4 +8,6 @@ export default () => ({ username: 'root', web_url: `${TEST_HOST}/root`, can_merge: true, + can_update_merge_request: true, + reviewed: true, }); |