diff options
Diffstat (limited to 'spec/frontend/boards')
-rw-r--r-- | spec/frontend/boards/board_list_helper.js | 66 | ||||
-rw-r--r-- | spec/frontend/boards/board_list_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_column_spec.js | 88 | ||||
-rw-r--r-- | spec/frontend/boards/components/board_list_header_spec.js | 166 | ||||
-rw-r--r-- | spec/frontend/boards/stores/actions_spec.js | 17 | ||||
-rw-r--r-- | spec/frontend/boards/stores/mutations_spec.js | 147 |
6 files changed, 339 insertions, 147 deletions
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js new file mode 100644 index 00000000000..b51a82f2a35 --- /dev/null +++ b/spec/frontend/boards/board_list_helper.js @@ -0,0 +1,66 @@ +/* global List */ +/* global ListIssue */ + +import MockAdapter from 'axios-mock-adapter'; +import Vue from 'vue'; +import Sortable from 'sortablejs'; +import axios from '~/lib/utils/axios_utils'; +import BoardList from '~/boards/components/board_list.vue'; + +import '~/boards/models/issue'; +import '~/boards/models/list'; +import { listObj, boardsMockInterceptor } from './mock_data'; +import store from '~/boards/stores'; +import boardsStore from '~/boards/stores/boards_store'; + +window.Sortable = Sortable; + +export default function createComponent({ + done, + listIssueProps = {}, + componentProps = {}, + listProps = {}, +}) { + const el = document.createElement('div'); + + document.body.appendChild(el); + const mock = new MockAdapter(axios); + mock.onAny().reply(boardsMockInterceptor); + boardsStore.create(); + + const BoardListComp = Vue.extend(BoardList); + const list = new List({ ...listObj, ...listProps }); + const issue = new ListIssue({ + title: 'Testing', + id: 1, + iid: 1, + confidential: false, + labels: [], + assignees: [], + ...listIssueProps, + }); + if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesSize')) { + list.issuesSize = 1; + } + list.issues.push(issue); + + const component = new BoardListComp({ + el, + store, + propsData: { + disabled: false, + list, + issues: list.issues, + loading: false, + issueLinkBase: '/issues', + rootPath: '/', + ...componentProps, + }, + }).$mount(); + + Vue.nextTick(() => { + done(); + }); + + return { component, mock }; +} diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js index fa21053e2de..3a64b004847 100644 --- a/spec/frontend/boards/board_list_spec.js +++ b/spec/frontend/boards/board_list_spec.js @@ -118,7 +118,7 @@ describe('Board list component', () => { }); it('shows new issue form after eventhub event', () => { - eventHub.$emit(`hide-issue-form-${component.list.id}`); + eventHub.$emit(`toggle-issue-form-${component.list.id}`); return Vue.nextTick().then(() => { expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull(); diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js index 7cf6ec913b4..6853fe2559d 100644 --- a/spec/frontend/boards/components/board_column_spec.js +++ b/spec/frontend/boards/components/board_column_spec.js @@ -70,37 +70,6 @@ describe('Board Column Component', () => { const isExpandable = () => wrapper.classes('is-expandable'); const isCollapsed = () => wrapper.classes('is-collapsed'); - const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' }); - - describe('Add issue button', () => { - const hasNoAddButton = [ListType.promotion, ListType.blank, ListType.closed]; - const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee]; - - it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => { - createComponent({ listType }); - - expect(findAddIssueButton().exists()).toBe(false); - }); - - it.each(hasAddButton)('does render when List Type is `%s`', listType => { - createComponent({ listType }); - - expect(findAddIssueButton().exists()).toBe(true); - }); - - it('has a test for each list type', () => { - Object.values(ListType).forEach(value => { - expect([...hasAddButton, ...hasNoAddButton]).toContain(value); - }); - }); - - it('does render when logged out', () => { - createComponent(); - - expect(findAddIssueButton().exists()).toBe(true); - }); - }); - describe('Given different list types', () => { it('is expandable when List Type is `backlog`', () => { createComponent({ listType: ListType.backlog }); @@ -109,64 +78,17 @@ describe('Board Column Component', () => { }); }); - describe('expanding / collapsing the column', () => { - it('does not collapse when clicking the header', () => { - createComponent(); - expect(isCollapsed()).toBe(false); - wrapper.find('.board-header').trigger('click'); + describe('expanded / collaped column', () => { + it('has class is-collapsed when list is collapsed', () => { + createComponent({ collapsed: false }); - return wrapper.vm.$nextTick().then(() => { - expect(isCollapsed()).toBe(false); - }); - }); - - it('collapses expanded Column when clicking the collapse icon', () => { - createComponent(); expect(wrapper.vm.list.isExpanded).toBe(true); - wrapper.find('.board-title-caret').trigger('click'); - - return wrapper.vm.$nextTick().then(() => { - expect(isCollapsed()).toBe(true); - }); }); - it('expands collapsed Column when clicking the expand icon', () => { + it('does not have class is-collapsed when list is expanded', () => { createComponent({ collapsed: true }); - expect(isCollapsed()).toBe(true); - wrapper.find('.board-title-caret').trigger('click'); - - return wrapper.vm.$nextTick().then(() => { - expect(isCollapsed()).toBe(false); - }); - }); - - it("when logged in it calls list update and doesn't set localStorage", () => { - jest.spyOn(List.prototype, 'update'); - window.gon.current_user_id = 1; - - createComponent({ withLocalStorage: false }); - wrapper.find('.board-title-caret').trigger('click'); - - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.list.update).toHaveBeenCalledTimes(1); - expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null); - }); - }); - - it("when logged out it doesn't call list update and sets localStorage", () => { - jest.spyOn(List.prototype, 'update'); - - createComponent(); - - wrapper.find('.board-title-caret').trigger('click'); - - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.list.update).toHaveBeenCalledTimes(0); - expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe( - String(wrapper.vm.list.isExpanded), - ); - }); + expect(isCollapsed()).toBe(true); }); }); }); diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js new file mode 100644 index 00000000000..95673da1c56 --- /dev/null +++ b/spec/frontend/boards/components/board_list_header_spec.js @@ -0,0 +1,166 @@ +import Vue from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import AxiosMockAdapter from 'axios-mock-adapter'; + +import BoardListHeader from '~/boards/components/board_list_header.vue'; +import List from '~/boards/models/list'; +import { ListType } from '~/boards/constants'; +import axios from '~/lib/utils/axios_utils'; + +import { TEST_HOST } from 'helpers/test_constants'; +import { listObj } from 'jest/boards/mock_data'; + +describe('Board List Header Component', () => { + let wrapper; + let axiosMock; + + beforeEach(() => { + window.gon = {}; + axiosMock = new AxiosMockAdapter(axios); + axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] }); + }); + + afterEach(() => { + axiosMock.restore(); + + wrapper.destroy(); + + localStorage.clear(); + }); + + const createComponent = ({ + listType = ListType.backlog, + collapsed = false, + withLocalStorage = true, + } = {}) => { + const boardId = '1'; + + const listMock = { + ...listObj, + list_type: listType, + collapsed, + }; + + if (listType === ListType.assignee) { + delete listMock.label; + listMock.user = {}; + } + + // Making List reactive + const list = Vue.observable(new List(listMock)); + + if (withLocalStorage) { + localStorage.setItem( + `boards.${boardId}.${list.type}.${list.id}.expanded`, + (!collapsed).toString(), + ); + } + + wrapper = shallowMount(BoardListHeader, { + propsData: { + boardId, + disabled: false, + issueLinkBase: '/', + rootPath: '/', + list, + }, + }); + }; + + const isCollapsed = () => !wrapper.props().list.isExpanded; + const isExpanded = () => wrapper.vm.list.isExpanded; + + const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' }); + const findCaret = () => wrapper.find('.board-title-caret'); + + describe('Add issue button', () => { + const hasNoAddButton = [ListType.promotion, ListType.blank, ListType.closed]; + const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee]; + + it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => { + createComponent({ listType }); + + expect(findAddIssueButton().exists()).toBe(false); + }); + + it.each(hasAddButton)('does render when List Type is `%s`', listType => { + createComponent({ listType }); + + expect(findAddIssueButton().exists()).toBe(true); + }); + + it('has a test for each list type', () => { + Object.values(ListType).forEach(value => { + expect([...hasAddButton, ...hasNoAddButton]).toContain(value); + }); + }); + + it('does render when logged out', () => { + createComponent(); + + expect(findAddIssueButton().exists()).toBe(true); + }); + }); + + describe('expanding / collapsing the column', () => { + it('does not collapse when clicking the header', () => { + createComponent(); + + expect(isCollapsed()).toBe(false); + wrapper.find('[data-testid="board-list-header"]').vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(isCollapsed()).toBe(false); + }); + }); + + it('collapses expanded Column when clicking the collapse icon', () => { + createComponent(); + + expect(isExpanded()).toBe(true); + findCaret().vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(isCollapsed()).toBe(true); + }); + }); + + it('expands collapsed Column when clicking the expand icon', () => { + createComponent({ collapsed: true }); + + expect(isCollapsed()).toBe(true); + findCaret().vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(isCollapsed()).toBe(false); + }); + }); + + it("when logged in it calls list update and doesn't set localStorage", () => { + jest.spyOn(List.prototype, 'update'); + window.gon.current_user_id = 1; + + createComponent({ withLocalStorage: false }); + + findCaret().vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.list.update).toHaveBeenCalledTimes(1); + expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(null); + }); + }); + + it("when logged out it doesn't call list update and sets localStorage", () => { + jest.spyOn(List.prototype, 'update'); + + createComponent(); + + findCaret().vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.list.update).not.toHaveBeenCalled(); + expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded())); + }); + }); + }); +}); diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index d23393db60d..0debca1310a 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -1,4 +1,6 @@ import actions from '~/boards/stores/actions'; +import * as types from '~/boards/stores/mutation_types'; +import testAction from 'helpers/vuex_action_helper'; const expectNotImplemented = action => { it('is not implemented', () => { @@ -7,7 +9,20 @@ const expectNotImplemented = action => { }; describe('setEndpoints', () => { - expectNotImplemented(actions.setEndpoints); + it('sets endpoints object', () => { + const mockEndpoints = { + foo: 'bar', + bar: 'baz', + }; + + return testAction( + actions.setEndpoints, + mockEndpoints, + {}, + [{ type: types.SET_ENDPOINTS, payload: mockEndpoints }], + [], + ); + }); }); describe('fetchLists', () => { diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js index aa477766978..bc57c30b354 100644 --- a/spec/frontend/boards/stores/mutations_spec.js +++ b/spec/frontend/boards/stores/mutations_spec.js @@ -1,4 +1,6 @@ import mutations from '~/boards/stores/mutations'; +import * as types from '~/boards/stores/mutation_types'; +import defaultState from '~/boards/stores/state'; const expectNotImplemented = action => { it('is not implemented', () => { @@ -6,86 +8,107 @@ const expectNotImplemented = action => { }); }; -describe('SET_ENDPOINTS', () => { - expectNotImplemented(mutations.SET_ENDPOINTS); -}); +describe('Board Store Mutations', () => { + let state; -describe('REQUEST_ADD_LIST', () => { - expectNotImplemented(mutations.REQUEST_ADD_LIST); -}); + beforeEach(() => { + state = defaultState(); + }); -describe('RECEIVE_ADD_LIST_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_ADD_LIST_SUCCESS); -}); + describe('SET_ENDPOINTS', () => { + it('Should set initial Boards data to state', () => { + const endpoints = { + boardsEndpoint: '/boards/', + recentBoardsEndpoint: '/boards/', + listsEndpoint: '/boards/lists', + bulkUpdatePath: '/boards/bulkUpdate', + boardId: 1, + fullPath: 'gitlab-org', + }; + + mutations[types.SET_ENDPOINTS](state, endpoints); + + expect(state.endpoints).toEqual(endpoints); + }); + }); -describe('RECEIVE_ADD_LIST_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_ADD_LIST_ERROR); -}); + describe('REQUEST_ADD_LIST', () => { + expectNotImplemented(mutations.REQUEST_ADD_LIST); + }); -describe('REQUEST_UPDATE_LIST', () => { - expectNotImplemented(mutations.REQUEST_UPDATE_LIST); -}); + describe('RECEIVE_ADD_LIST_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_ADD_LIST_SUCCESS); + }); -describe('RECEIVE_UPDATE_LIST_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_SUCCESS); -}); + describe('RECEIVE_ADD_LIST_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_ADD_LIST_ERROR); + }); -describe('RECEIVE_UPDATE_LIST_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_ERROR); -}); + describe('REQUEST_UPDATE_LIST', () => { + expectNotImplemented(mutations.REQUEST_UPDATE_LIST); + }); -describe('REQUEST_REMOVE_LIST', () => { - expectNotImplemented(mutations.REQUEST_REMOVE_LIST); -}); + describe('RECEIVE_UPDATE_LIST_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_SUCCESS); + }); -describe('RECEIVE_REMOVE_LIST_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_SUCCESS); -}); + describe('RECEIVE_UPDATE_LIST_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_ERROR); + }); -describe('RECEIVE_REMOVE_LIST_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR); -}); + describe('REQUEST_REMOVE_LIST', () => { + expectNotImplemented(mutations.REQUEST_REMOVE_LIST); + }); -describe('REQUEST_ADD_ISSUE', () => { - expectNotImplemented(mutations.REQUEST_ADD_ISSUE); -}); + describe('RECEIVE_REMOVE_LIST_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_SUCCESS); + }); -describe('RECEIVE_ADD_ISSUE_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_SUCCESS); -}); + describe('RECEIVE_REMOVE_LIST_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR); + }); -describe('RECEIVE_ADD_ISSUE_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_ERROR); -}); + describe('REQUEST_ADD_ISSUE', () => { + expectNotImplemented(mutations.REQUEST_ADD_ISSUE); + }); -describe('REQUEST_MOVE_ISSUE', () => { - expectNotImplemented(mutations.REQUEST_MOVE_ISSUE); -}); + describe('RECEIVE_ADD_ISSUE_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_SUCCESS); + }); -describe('RECEIVE_MOVE_ISSUE_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_SUCCESS); -}); + describe('RECEIVE_ADD_ISSUE_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_ERROR); + }); -describe('RECEIVE_MOVE_ISSUE_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_ERROR); -}); + describe('REQUEST_MOVE_ISSUE', () => { + expectNotImplemented(mutations.REQUEST_MOVE_ISSUE); + }); -describe('REQUEST_UPDATE_ISSUE', () => { - expectNotImplemented(mutations.REQUEST_UPDATE_ISSUE); -}); + describe('RECEIVE_MOVE_ISSUE_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_SUCCESS); + }); -describe('RECEIVE_UPDATE_ISSUE_SUCCESS', () => { - expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_SUCCESS); -}); + describe('RECEIVE_MOVE_ISSUE_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_ERROR); + }); -describe('RECEIVE_UPDATE_ISSUE_ERROR', () => { - expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR); -}); + describe('REQUEST_UPDATE_ISSUE', () => { + expectNotImplemented(mutations.REQUEST_UPDATE_ISSUE); + }); -describe('SET_CURRENT_PAGE', () => { - expectNotImplemented(mutations.SET_CURRENT_PAGE); -}); + describe('RECEIVE_UPDATE_ISSUE_SUCCESS', () => { + expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_SUCCESS); + }); -describe('TOGGLE_EMPTY_STATE', () => { - expectNotImplemented(mutations.TOGGLE_EMPTY_STATE); + describe('RECEIVE_UPDATE_ISSUE_ERROR', () => { + expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR); + }); + + describe('SET_CURRENT_PAGE', () => { + expectNotImplemented(mutations.SET_CURRENT_PAGE); + }); + + describe('TOGGLE_EMPTY_STATE', () => { + expectNotImplemented(mutations.TOGGLE_EMPTY_STATE); + }); }); |