import { GlLabel } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; import Vue from 'vue'; import Vuex from 'vuex'; import BoardCard from '~/boards/components/board_card.vue'; import BoardCardInner from '~/boards/components/board_card_inner.vue'; import { inactiveId } from '~/boards/constants'; import { mockLabelList, mockIssue } from '../mock_data'; describe('Board card', () => { let wrapper; let store; let mockActions; Vue.use(Vuex); const createStore = ({ initialState = {} } = {}) => { mockActions = { toggleBoardItem: jest.fn(), toggleBoardItemMultiSelection: jest.fn(), performSearch: jest.fn(), }; store = new Vuex.Store({ state: { activeId: inactiveId, selectedBoardItems: [], ...initialState, }, actions: mockActions, getters: { isEpicBoard: () => false, isProjectBoard: () => false, }, }); }; // this particular mount component needs to be used after the root beforeEach because it depends on list being initialized const mountComponent = ({ propsData = {}, provide = {}, mountFn = shallowMount, stubs = { BoardCardInner }, item = mockIssue, } = {}) => { wrapper = mountFn(BoardCard, { stubs, store, propsData: { list: mockLabelList, item, disabled: false, index: 0, ...propsData, }, provide: { groupId: null, rootPath: '/', scopedLabelsAvailable: false, ...provide, }, }); }; const selectCard = async () => { wrapper.trigger('mouseup'); await wrapper.vm.$nextTick(); }; const multiSelectCard = async () => { wrapper.trigger('mouseup', { ctrlKey: true }); await wrapper.vm.$nextTick(); }; beforeEach(() => { window.gon = { features: {} }; }); afterEach(() => { wrapper.destroy(); wrapper = null; store = null; }); describe('when GlLabel is clicked in BoardCardInner', () => { it('doesnt call toggleBoardItem', () => { createStore({ initialState: { isShowingLabels: true } }); mountComponent({ mountFn: mount, stubs: {} }); wrapper.find(GlLabel).trigger('mouseup'); expect(mockActions.toggleBoardItem).toHaveBeenCalledTimes(0); }); }); it('should not highlight the card by default', async () => { createStore(); mountComponent(); expect(wrapper.classes()).not.toContain('is-active'); expect(wrapper.classes()).not.toContain('multi-select'); }); it('should highlight the card with a correct style when selected', async () => { createStore({ initialState: { activeId: mockIssue.id, }, }); mountComponent(); expect(wrapper.classes()).toContain('is-active'); expect(wrapper.classes()).not.toContain('multi-select'); }); it('should highlight the card with a correct style when multi-selected', async () => { createStore({ initialState: { activeId: inactiveId, selectedBoardItems: [mockIssue], }, }); mountComponent(); expect(wrapper.classes()).toContain('multi-select'); expect(wrapper.classes()).not.toContain('is-active'); }); describe('when mouseup event is called on the card', () => { beforeEach(() => { createStore(); mountComponent(); }); describe('when not using multi-select', () => { it('should call vuex action "toggleBoardItem" with correct parameters', async () => { await selectCard(); expect(mockActions.toggleBoardItem).toHaveBeenCalledTimes(1); expect(mockActions.toggleBoardItem).toHaveBeenCalledWith(expect.any(Object), { boardItem: mockIssue, }); }); }); describe('when using multi-select', () => { beforeEach(() => { window.gon = { features: { boardMultiSelect: true } }; }); it('should call vuex action "multiSelectBoardItem" with correct parameters', async () => { await multiSelectCard(); expect(mockActions.toggleBoardItemMultiSelection).toHaveBeenCalledTimes(1); expect(mockActions.toggleBoardItemMultiSelection).toHaveBeenCalledWith( expect.any(Object), mockIssue, ); }); }); }); describe('when card is loading', () => { it('card is disabled and user cannot drag', () => { createStore(); mountComponent({ item: { ...mockIssue, isLoading: true } }); expect(wrapper.classes()).toContain('is-disabled'); expect(wrapper.classes()).not.toContain('user-can-drag'); }); }); describe('when card is not loading', () => { it('user can drag', () => { createStore(); mountComponent(); expect(wrapper.classes()).not.toContain('is-disabled'); expect(wrapper.classes()).toContain('user-can-drag'); }); }); });