Commit 5ea9167b authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'ss/swimlane-sidebar' into 'master'

RUN AS-IF-FOSS Swimlanes Sidebar Container

See merge request gitlab-org/gitlab!38527
parents 52a000e4 00f7c443
<script> <script>
/* eslint-disable vue/require-default-prop */ import BoardCardLayout from './board_card_layout.vue';
import IssueCardInner from './issue_card_inner.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub'; import sidebarEventHub from '~/sidebar/event_hub';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
...@@ -8,7 +7,7 @@ import boardsStore from '../stores/boards_store'; ...@@ -8,7 +7,7 @@ import boardsStore from '../stores/boards_store';
export default { export default {
name: 'BoardsIssueCard', name: 'BoardsIssueCard',
components: { components: {
IssueCardInner, BoardCardLayout,
}, },
props: { props: {
list: { list: {
...@@ -21,80 +20,29 @@ export default { ...@@ -21,80 +20,29 @@ export default {
default: () => ({}), default: () => ({}),
required: false, required: false,
}, },
issueLinkBase: {
type: String,
default: '',
required: false,
},
disabled: {
type: Boolean,
default: false,
required: false,
},
index: {
type: Number,
default: 0,
required: false,
},
rootPath: {
type: String,
default: '',
required: false,
},
groupId: {
type: Number,
required: false,
},
},
data() {
return {
showDetail: false,
detailIssue: boardsStore.detail,
multiSelect: boardsStore.multiSelect,
};
},
computed: {
issueDetailVisible() {
return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
},
multiSelectVisible() {
return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
},
canMultiSelect() {
return gon.features && gon.features.multiSelectBoard;
},
}, },
methods: { methods: {
mouseDown() { // These are methods instead of computed's, because boardsStore is not reactive.
this.showDetail = true; isActive() {
return this.getActiveId() === this.issue.id;
}, },
mouseMove() { getActiveId() {
this.showDetail = false; return boardsStore.detail?.issue?.id;
}, },
showIssue(e) { showIssue({ isMultiSelect }) {
if (e.target.classList.contains('js-no-trigger')) return;
// If no issues are opened, close all sidebars first // If no issues are opened, close all sidebars first
if (!boardsStore.detail?.issue?.id) { if (!this.getActiveId()) {
sidebarEventHub.$emit('sidebar.closeAll'); sidebarEventHub.$emit('sidebar.closeAll');
} }
if (this.isActive()) {
eventHub.$emit('clearDetailIssue', isMultiSelect);
// If CMD or CTRL is clicked if (isMultiSelect) {
const isMultiSelect = this.canMultiSelect && (e.ctrlKey || e.metaKey);
if (this.showDetail || isMultiSelect) {
this.showDetail = false;
if (boardsStore.detail.issue && boardsStore.detail.issue.id === this.issue.id) {
eventHub.$emit('clearDetailIssue', isMultiSelect);
if (isMultiSelect) {
eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
}
} else {
eventHub.$emit('newDetailIssue', this.issue, isMultiSelect); eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
boardsStore.setListDetail(this.list);
} }
} else {
eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
boardsStore.setListDetail(this.list);
} }
}, },
}, },
...@@ -102,28 +50,12 @@ export default { ...@@ -102,28 +50,12 @@ export default {
</script> </script>
<template> <template>
<li <board-card-layout
:class="{
'multi-select': multiSelectVisible,
'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id,
'is-active': issueDetailVisible,
}"
:index="index"
:data-issue-id="issue.id"
data-qa-selector="board_card" data-qa-selector="board_card"
class="board-card p-3 rounded" :issue="issue"
@mousedown="mouseDown" :list="list"
@mousemove="mouseMove" :is-active="isActive()"
@mouseup="showIssue($event)" v-bind="$attrs"
> @show="showIssue"
<issue-card-inner />
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:group-id="groupId"
:root-path="rootPath"
:update-filters="true"
/>
</li>
</template> </template>
<script>
/* eslint-disable vue/require-default-prop */
import IssueCardInner from './issue_card_inner.vue';
import boardsStore from '../stores/boards_store';
export default {
name: 'BoardsIssueCard',
components: {
IssueCardInner,
},
props: {
list: {
type: Object,
default: () => ({}),
required: false,
},
issue: {
type: Object,
default: () => ({}),
required: false,
},
issueLinkBase: {
type: String,
default: '',
required: false,
},
disabled: {
type: Boolean,
default: false,
required: false,
},
index: {
type: Number,
default: 0,
required: false,
},
rootPath: {
type: String,
default: '',
required: false,
},
groupId: {
type: Number,
required: false,
},
isActive: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
showDetail: false,
multiSelect: boardsStore.multiSelect,
};
},
computed: {
multiSelectVisible() {
return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
},
canMultiSelect() {
return gon.features && gon.features.multiSelectBoard;
},
},
methods: {
mouseDown() {
this.showDetail = true;
},
mouseMove() {
this.showDetail = false;
},
showIssue(e) {
// Don't do anything if this happened on a no trigger element
if (e.target.classList.contains('js-no-trigger')) return;
const isMultiSelect = this.canMultiSelect && (e.ctrlKey || e.metaKey);
if (this.showDetail || isMultiSelect) {
this.showDetail = false;
this.$emit('show', { event: e, isMultiSelect });
}
},
},
};
</script>
<template>
<li
:class="{
'multi-select': multiSelectVisible,
'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id,
'is-active': isActive,
}"
:index="index"
:data-issue-id="issue.id"
data-testid="board_card"
class="board-card p-3 rounded"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)"
>
<issue-card-inner
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:group-id="groupId"
:root-path="rootPath"
:update-filters="true"
/>
</li>
</template>
<script> <script>
import { mapActions, mapState } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import { GlAlert } from '@gitlab/ui';
import BoardColumn from 'ee_else_ce/boards/components/board_column.vue'; import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
import { GlAlert } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
components: { components: {
BoardColumn, BoardColumn,
BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'),
EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'), EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
GlAlert, GlAlert,
}, },
...@@ -43,10 +44,8 @@ export default { ...@@ -43,10 +44,8 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['isShowingEpicsSwimlanes', 'boardLists', 'error']), ...mapState(['boardLists', 'error']),
isSwimlanesOn() { ...mapGetters(['isSwimlanesOn']),
return this.glFeatures.boardsWithSwimlanes && this.isShowingEpicsSwimlanes;
},
boardListsToUse() { boardListsToUse() {
return this.glFeatures.graphqlBoardLists ? this.boardLists : this.lists; return this.glFeatures.graphqlBoardLists ? this.boardLists : this.lists;
}, },
...@@ -86,15 +85,18 @@ export default { ...@@ -86,15 +85,18 @@ export default {
:board-id="boardId" :board-id="boardId"
/> />
</div> </div>
<epics-swimlanes
v-else <template v-else>
ref="swimlanes" <epics-swimlanes
:lists="boardListsToUse" ref="swimlanes"
:can-admin-list="canAdminList" :lists="boardLists"
:disabled="disabled" :can-admin-list="canAdminList"
:board-id="boardId" :disabled="disabled"
:group-id="groupId" :board-id="boardId"
:root-path="rootPath" :group-id="groupId"
/> :root-path="rootPath"
/>
<board-content-sidebar />
</template>
</div> </div>
</template> </template>
<script> <script>
import { GlDrawer, GlLabel } from '@gitlab/ui'; import { GlDrawer, GlLabel } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale'; import { __ } from '~/locale';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
import { isScopedLabel } from '~/lib/utils/common_utils'; import { isScopedLabel } from '~/lib/utils/common_utils';
import { inactiveId } from '~/boards/constants'; import { LIST } from '~/boards/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
// NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options. // NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options.
...@@ -26,7 +26,8 @@ export default { ...@@ -26,7 +26,8 @@ export default {
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
computed: { computed: {
...mapState(['activeId', 'boardLists']), ...mapGetters(['isSidebarOpen']),
...mapState(['activeId', 'sidebarType', 'boardLists']),
activeList() { activeList() {
/* /*
Warning: Though a computed property it is not reactive because we are Warning: Though a computed property it is not reactive because we are
...@@ -37,9 +38,6 @@ export default { ...@@ -37,9 +38,6 @@ export default {
} }
return boardsStore.state.lists.find(({ id }) => id === this.activeId); return boardsStore.state.lists.find(({ id }) => id === this.activeId);
}, },
isSidebarOpen() {
return this.activeId !== inactiveId;
},
activeListLabel() { activeListLabel() {
return this.activeList.label; return this.activeList.label;
}, },
...@@ -49,18 +47,18 @@ export default { ...@@ -49,18 +47,18 @@ export default {
listTypeTitle() { listTypeTitle() {
return this.$options.labelListText; return this.$options.labelListText;
}, },
showSidebar() {
return this.sidebarType === LIST;
},
}, },
created() { created() {
eventHub.$on('sidebar.closeAll', this.closeSidebar); eventHub.$on('sidebar.closeAll', this.unsetActiveId);
}, },
beforeDestroy() { beforeDestroy() {
eventHub.$off('sidebar.closeAll', this.closeSidebar); eventHub.$off('sidebar.closeAll', this.unsetActiveId);
}, },
methods: { methods: {
...mapActions(['setActiveId']), ...mapActions(['unsetActiveId']),
closeSidebar() {
this.setActiveId(inactiveId);
},
showScopedLabels(label) { showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label); return boardsStore.scopedLabels.enabled && isScopedLabel(label);
}, },
...@@ -70,10 +68,11 @@ export default { ...@@ -70,10 +68,11 @@ export default {
<template> <template>
<gl-drawer <gl-drawer
v-if="showSidebar"
class="js-board-settings-sidebar" class="js-board-settings-sidebar"
:open="isSidebarOpen" :open="isSidebarOpen"
:header-height="$options.headerHeight" :header-height="$options.headerHeight"
@close="closeSidebar" @close="unsetActiveId"
> >
<template #header>{{ $options.listSettingsText }}</template> <template #header>{{ $options.listSettingsText }}</template>
<template v-if="isSidebarOpen"> <template v-if="isSidebarOpen">
......
...@@ -15,6 +15,9 @@ export const ListType = { ...@@ -15,6 +15,9 @@ export const ListType = {
export const inactiveId = 0; export const inactiveId = 0;
export const ISSUABLE = 'issuable';
export const LIST = 'list';
export default { export default {
BoardType, BoardType,
ListType, ListType,
......
...@@ -5,7 +5,7 @@ import { __ } from '~/locale'; ...@@ -5,7 +5,7 @@ import { __ } from '~/locale';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { BoardType, ListType } from '~/boards/constants'; import { BoardType, ListType, inactiveId } from '~/boards/constants';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { formatListIssues, fullBoardId } from '../boards_util'; import { formatListIssues, fullBoardId } from '../boards_util';
import boardStore from '~/boards/stores/boards_store'; import boardStore from '~/boards/stores/boards_store';
...@@ -28,8 +28,12 @@ export default { ...@@ -28,8 +28,12 @@ export default {
commit(types.SET_INITIAL_BOARD_DATA, data); commit(types.SET_INITIAL_BOARD_DATA, data);
}, },
setActiveId({ commit }, id) { setActiveId({ commit }, { id, sidebarType }) {
commit(types.SET_ACTIVE_ID, id); commit(types.SET_ACTIVE_ID, { id, sidebarType });
},
unsetActiveId({ dispatch }) {
dispatch('setActiveId', { id: inactiveId, sidebarType: '' });
}, },
setFilters: ({ commit }, filters) => { setFilters: ({ commit }, filters) => {
......
import { inactiveId } from '../constants';
export default { export default {
getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'), getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
isSidebarOpen: state => state.activeId !== inactiveId,
isSwimlanesOn: state => {
if (!gon?.features?.boardsWithSwimlanes) {
return false;
}
return state.isShowingEpicsSwimlanes;
},
}; };
...@@ -19,8 +19,9 @@ export default { ...@@ -19,8 +19,9 @@ export default {
state.boardLists = lists; state.boardLists = lists;
}, },
[mutationTypes.SET_ACTIVE_ID](state, id) { [mutationTypes.SET_ACTIVE_ID](state, { id, sidebarType }) {
state.activeId = id; state.activeId = id;
state.sidebarType = sidebarType;
}, },
[mutationTypes.SET_FILTERS](state, filterParams) { [mutationTypes.SET_FILTERS](state, filterParams) {
......
...@@ -7,6 +7,7 @@ export default () => ({ ...@@ -7,6 +7,7 @@ export default () => ({
showPromotion: false, showPromotion: false,
isShowingLabels: true, isShowingLabels: true,
activeId: inactiveId, activeId: inactiveId,
sidebarType: '',
boardLists: [], boardLists: [],
issuesByListId: {}, issuesByListId: {},
isLoadingIssues: false, isLoadingIssues: false,
......
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlDrawer } from '@gitlab/ui';
import { ISSUABLE } from '~/boards/constants';
import { contentTop } from '~/lib/utils/common_utils';
export default {
headerHeight: `${contentTop()}px`,
components: {
GlDrawer,
},
computed: {
...mapGetters(['isSidebarOpen']),
...mapState(['sidebarType']),
showSidebar() {
return this.sidebarType === ISSUABLE;
},
},
methods: {
...mapActions(['unsetActiveId']),
},
};
</script>
<template>
<gl-drawer
v-if="showSidebar"
:open="isSidebarOpen"
:header-height="$options.headerHeight"
@close="unsetActiveId"
/>
</template>
...@@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex'; ...@@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex';
import BoardListHeaderFoss from '~/boards/components/board_list_header.vue'; import BoardListHeaderFoss from '~/boards/components/board_list_header.vue';
import { __, sprintf, s__ } from '~/locale'; import { __, sprintf, s__ } from '~/locale';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import { inactiveId } from '~/boards/constants'; import { inactiveId, LIST } from '~/boards/constants';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
export default { export default {
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
eventHub.$emit('sidebar.closeAll'); eventHub.$emit('sidebar.closeAll');
} }
this.setActiveId(this.list.id); this.setActiveId({ id: this.list.id, sidebarType: LIST });
}, },
}, },
}; };
......
...@@ -48,7 +48,7 @@ export default { ...@@ -48,7 +48,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(['setActiveId', 'updateListWipLimit']), ...mapActions(['unsetActiveId', 'updateListWipLimit']),
showInput() { showInput() {
this.edit = true; this.edit = true;
this.currentWipLimit = this.maxIssueCount > 0 ? this.maxIssueCount : null; this.currentWipLimit = this.maxIssueCount > 0 ? this.maxIssueCount : null;
...@@ -80,7 +80,7 @@ export default { ...@@ -80,7 +80,7 @@ export default {
boardsStoreEE.setMaxIssueCountOnList(id, wipLimit); boardsStoreEE.setMaxIssueCountOnList(id, wipLimit);
}) })
.catch(() => { .catch(() => {
this.setActiveId(0); this.unsetActiveId();
flash(__('Something went wrong while updating your list settings')); flash(__('Something went wrong while updating your list settings'));
}) })
.finally(() => { .finally(() => {
...@@ -96,7 +96,7 @@ export default { ...@@ -96,7 +96,7 @@ export default {
boardsStoreEE.setMaxIssueCountOnList(this.activeId, inactiveId); boardsStoreEE.setMaxIssueCountOnList(this.activeId, inactiveId);
}) })
.catch(() => { .catch(() => {
this.setActiveId(inactiveId); this.unsetActiveId();
flash(__('Something went wrong while updating your list settings')); flash(__('Something went wrong while updating your list settings'));
}) })
.finally(() => { .finally(() => {
......
<script> <script>
import { mapState, mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import BoardCardLayout from '~/boards/components/board_card_layout.vue';
import eventHub from '~/boards/eventhub'; import eventHub from '~/boards/eventhub';
import BoardCard from '~/boards/components/board_card.vue';
import BoardNewIssue from '~/boards/components/board_new_issue.vue'; import BoardNewIssue from '~/boards/components/board_new_issue.vue';
import { ISSUABLE } from '~/boards/constants';
export default { export default {
components: { components: {
BoardCard, BoardCardLayout,
BoardNewIssue, BoardNewIssue,
GlLoadingIcon, GlLoadingIcon,
}, },
...@@ -49,6 +51,9 @@ export default { ...@@ -49,6 +51,9 @@ export default {
showIssueForm: false, showIssueForm: false,
}; };
}, },
computed: {
...mapState(['activeId']),
},
created() { created() {
eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm); eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
}, },
...@@ -56,12 +61,19 @@ export default { ...@@ -56,12 +61,19 @@ export default {
eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm); eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
}, },
methods: { methods: {
...mapActions(['setActiveId']),
toggleForm() { toggleForm() {
this.showIssueForm = !this.showIssueForm; this.showIssueForm = !this.showIssueForm;
if (this.showIssueForm && this.isUnassignedIssuesLane) { if (this.showIssueForm && this.isUnassignedIssuesLane) {
this.$el.scrollIntoView(false); this.$el.scrollIntoView(false);
} }
}, },
isActiveIssue(issue) {
return this.activeId === issue.id;
},
showIssue(issue) {
this.setActiveId({ id: issue.id, sidebarType: ISSUABLE });
},
}, },
}; };
</script> </script>
...@@ -79,7 +91,7 @@ export default { ...@@ -79,7 +91,7 @@ export default {
:list="list" :list="list"
/> />
<ul v-if="list.isExpanded" class="gl-p-2 gl-m-0"> <ul v-if="list.isExpanded" class="gl-p-2 gl-m-0">
<board-card <board-card-layout
v-for="(issue, index) in issues" v-for="(issue, index) in issues"
ref="issue" ref="issue"
:key="issue.id" :key="issue.id"
...@@ -87,6 +99,8 @@ export default { ...@@ -87,6 +99,8 @@ export default {
:list="list" :list="list"
:issue="issue" :issue="issue"
:root-path="rootPath" :root-path="rootPath"
:is-active="isActiveIssue(issue)"
@show="showIssue(issue)"
/> />
</ul> </ul>
</div> </div>
......
import { shallowMount } from '@vue/test-utils';
import { GlDrawer } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import BoardContentSidebar from 'ee_component/boards/components/board_content_sidebar.vue';
import { createStore } from '~/boards/stores';
import { ISSUABLE } from '~/boards/constants';
describe('ee/BoardContentSidebar', () => {
let wrapper;
let store;
const createComponent = () => {
wrapper = shallowMount(BoardContentSidebar, {
store,
});
};
beforeEach(() => {
store = createStore();
store.state.sidebarType = ISSUABLE;
store.state.activeId = 1;
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('confirms we render GlDrawer', () => {
expect(wrapper.find(GlDrawer).exists()).toBe(true);
});
it('applies an open attribute', () => {
expect(wrapper.find(GlDrawer).props('open')).toBe(true);
});
describe('when we emit close', () => {
it('hides GlDrawer', async () => {
expect(wrapper.find(GlDrawer).props('open')).toBe(true);
wrapper.find(GlDrawer).vm.$emit('close');
await waitForPromises();
expect(wrapper.find(GlDrawer).exists()).toBe(false);
});
});
});
import Vuex from 'vuex'; import { shallowMount } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import BoardContentSidebar from 'ee/boards/components/board_content_sidebar.vue';
import { GlAlert } from '@gitlab/ui';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
import getters from 'ee/boards/stores/getters';
import { mockListsWithModel, mockIssuesByListId } from '../mock_data';
import BoardContent from '~/boards/components/board_content.vue'; import BoardContent from '~/boards/components/board_content.vue';
import { createStore } from '~/boards/stores';
const localVue = createLocalVue(); describe('ee/BoardContent', () => {
localVue.use(Vuex);
describe('BoardContent', () => {
let wrapper; let wrapper;
let store;
window.gon = { features: {} };
const defaultState = { const createComponent = () => {
isShowingEpicsSwimlanes: false,
boardLists: mockListsWithModel,
error: undefined,
issuesByListId: mockIssuesByListId,
};
const createStore = (state = defaultState) => {
return new Vuex.Store({
state,
actions: {
fetchIssuesForAllLists: () => {},
},
getters,
});
};
const createComponent = state => {
const store = createStore({
...defaultState,
...state,
});
wrapper = shallowMount(BoardContent, { wrapper = shallowMount(BoardContent, {
localVue, store,
propsData: { propsData: {
lists: mockListsWithModel, lists: [],
canAdminList: true, canAdminList: false,
groupId: 1,
disabled: false, disabled: false,
issueLinkBase: '/', issueLinkBase: '',
rootPath: '/', rootPath: '',
boardId: '1', boardId: '',
}, },
store, stubs: {
provide: { 'board-content-sidebar': BoardContentSidebar,
glFeatures: { boardsWithSwimlanes: true },
}, },
}); });
}; };
beforeEach(() => {
store = createStore();
});
afterEach(() => { afterEach(() => {
window.gon.features = {};
wrapper.destroy(); wrapper.destroy();
}); });
describe('Swimlanes off', () => { describe.each`
featureFlag | state | result
${true} | ${{ isShowingEpicsSwimlanes: true }} | ${true}
${true} | ${{ isShowingEpicsSwimlanes: false }} | ${false}
${false} | ${{ isShowingEpicsSwimlanes: true }} | ${false}
${false} | ${{ isShowingEpicsSwimlanes: false }} | ${false}
`('with featureFlag=$featureFlag and state=$state', ({ featureFlag, state, result }) => {
beforeEach(() => { beforeEach(() => {
gon.features.boardsWithSwimlanes = featureFlag;
Object.assign(store.state, state);
createComponent(); createComponent();
}); });
it('renders a BoardColumn component per list', () => { it(`renders BoardContentSidebar = ${result}`, () => {
expect(wrapper.findAll(BoardColumn)).toHaveLength(mockListsWithModel.length); expect(wrapper.find(BoardContentSidebar).exists()).toBe(result);
});
it('does not display EpicsSwimlanes component', () => {
expect(wrapper.contains(EpicsSwimlanes)).toBe(false);
expect(wrapper.contains(GlAlert)).toBe(false);
});
});
describe('Swimlanes on', () => {
beforeEach(() => {
createComponent({ isShowingEpicsSwimlanes: true });
});
it('does not display BoardColumn component', () => {
expect(wrapper.findAll(BoardColumn)).toHaveLength(0);
});
it('displays EpicsSwimlanes component', () => {
expect(wrapper.contains('.board-swimlanes')).toBe(true);
expect(wrapper.contains(GlAlert)).toBe(false);
});
it('displays alert if an error occurs when fetching swimlanes', () => {
createComponent({
isShowingEpicsSwimlanes: true,
error: 'An error occurred while fetching the board swimlanes. Please reload the page.',
});
expect(wrapper.contains(GlAlert)).toBe(true);
}); });
}); });
}); });
...@@ -7,7 +7,8 @@ import BoardSettingsWipLimit from 'ee_component/boards/components/board_settings ...@@ -7,7 +7,8 @@ import BoardSettingsWipLimit from 'ee_component/boards/components/board_settings
import BoardSettingsListTypes from 'ee_component/boards/components/board_settings_list_types.vue'; import BoardSettingsListTypes from 'ee_component/boards/components/board_settings_list_types.vue';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import { inactiveId } from '~/boards/constants'; import getters from '~/boards/stores/getters';
import { LIST } from '~/boards/constants';
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -21,11 +22,12 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -21,11 +22,12 @@ describe('ee/BoardSettingsSidebar', () => {
const listId = 1; const listId = 1;
let mock; let mock;
const createComponent = (state = { activeId: inactiveId }, actions = {}) => { const createComponent = (actions = {}) => {
storeActions = actions; storeActions = actions;
const store = new Vuex.Store({ const store = new Vuex.Store({
state, state: { sidebarType: LIST, activeId: listId },
getters,
actions: storeActions, actions: storeActions,
}); });
...@@ -57,7 +59,7 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -57,7 +59,7 @@ describe('ee/BoardSettingsSidebar', () => {
list_type: 'label', list_type: 'label',
}); });
createComponent({ activeId: listId }); createComponent();
expect(wrapper.find(BoardSettingsWipLimit).exists()).toBe(true); expect(wrapper.find(BoardSettingsWipLimit).exists()).toBe(true);
}); });
...@@ -73,7 +75,7 @@ describe('ee/BoardSettingsSidebar', () => { ...@@ -73,7 +75,7 @@ describe('ee/BoardSettingsSidebar', () => {
list_type: 'milestone', list_type: 'milestone',
}); });
createComponent({ activeId: listId }); createComponent();
expect(wrapper.find(BoardSettingsListTypes).exists()).toBe(true); expect(wrapper.find(BoardSettingsListTypes).exists()).toBe(true);
}); });
......
...@@ -285,7 +285,7 @@ describe('BoardSettingsWipLimit', () => { ...@@ -285,7 +285,7 @@ describe('BoardSettingsWipLimit', () => {
const spy = jest.fn().mockRejectedValue(); const spy = jest.fn().mockRejectedValue();
createComponent({ createComponent({
vuexState: { activeId: listId }, vuexState: { activeId: listId },
actions: { updateListWipLimit: spy, setActiveId: noop }, actions: { updateListWipLimit: spy, unsetActiveId: noop },
localState: { edit: true, currentWipLimit }, localState: { edit: true, currentWipLimit },
}); });
......
...@@ -4,15 +4,17 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -4,15 +4,17 @@ import { shallowMount } from '@vue/test-utils';
import IssuesLaneList from 'ee/boards/components/issues_lane_list.vue'; import IssuesLaneList from 'ee/boards/components/issues_lane_list.vue';
import { listObj } from 'jest/boards/mock_data'; import { listObj } from 'jest/boards/mock_data';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import BoardCard from '~/boards/components/board_card_layout.vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import BoardCard from '~/boards/components/board_card.vue';
import { mockIssues } from '../mock_data'; import { mockIssues } from '../mock_data';
import List from '~/boards/models/list'; import List from '~/boards/models/list';
import { createStore } from '~/boards/stores';
import { ListType } from '~/boards/constants'; import { ListType } from '~/boards/constants';
describe('IssuesLaneList', () => { describe('IssuesLaneList', () => {
let wrapper; let wrapper;
let axiosMock; let axiosMock;
let store;
beforeEach(() => { beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios); axiosMock = new AxiosMockAdapter(axios);
...@@ -48,6 +50,7 @@ describe('IssuesLaneList', () => { ...@@ -48,6 +50,7 @@ describe('IssuesLaneList', () => {
} }
wrapper = shallowMount(IssuesLaneList, { wrapper = shallowMount(IssuesLaneList, {
store,
propsData: { propsData: {
list, list,
issues: mockIssues, issues: mockIssues,
...@@ -65,6 +68,8 @@ describe('IssuesLaneList', () => { ...@@ -65,6 +68,8 @@ describe('IssuesLaneList', () => {
describe('if list is expanded', () => { describe('if list is expanded', () => {
beforeEach(() => { beforeEach(() => {
store = createStore();
createComponent(); createComponent();
}); });
...@@ -79,6 +84,8 @@ describe('IssuesLaneList', () => { ...@@ -79,6 +84,8 @@ describe('IssuesLaneList', () => {
describe('if list is collapsed', () => { describe('if list is collapsed', () => {
beforeEach(() => { beforeEach(() => {
store = createStore();
createComponent({ collapsed: true }); createComponent({ collapsed: true });
}); });
......
/* global List */
/* global ListLabel */
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/list';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import BoardCardLayout from '~/boards/components/board_card_layout.vue';
import issueCardInner from '~/boards/components/issue_card_inner.vue';
import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
describe('Board card layout', () => {
let wrapper;
let mock;
let list;
// this particular mount component needs to be used after the root beforeEach because it depends on list being initialized
const mountComponent = propsData => {
wrapper = shallowMount(BoardCardLayout, {
stubs: {
issueCardInner,
},
store,
propsData: {
list,
issue: list.issues[0],
issueLinkBase: '/',
disabled: false,
index: 0,
rootPath: '/',
...propsData,
},
});
};
const setupData = () => {
list = new List(listObj);
boardsStore.create();
boardsStore.detail.issue = {};
const label1 = new ListLabel({
id: 3,
title: 'testing 123',
color: '#000cff',
text_color: 'white',
description: 'test',
});
return waitForPromises().then(() => {
list.issues[0].labels.push(label1);
});
};
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
setMockEndpoints();
return setupData();
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
list = null;
mock.restore();
});
describe('mouse events', () => {
it('sets showDetail to true on mousedown', async () => {
mountComponent();
wrapper.trigger('mousedown');
await wrapper.vm.$nextTick();
expect(wrapper.vm.showDetail).toBe(true);
});
it('sets showDetail to false on mousemove', async () => {
mountComponent();
wrapper.trigger('mousedown');
await wrapper.vm.$nextTick();
expect(wrapper.vm.showDetail).toBe(true);
wrapper.trigger('mousemove');
await wrapper.vm.$nextTick();
expect(wrapper.vm.showDetail).toBe(false);
});
});
});
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* global ListAssignee */ /* global ListAssignee */
/* global ListLabel */ /* global ListLabel */
import { shallowMount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
...@@ -15,12 +15,12 @@ import '~/boards/models/assignee'; ...@@ -15,12 +15,12 @@ import '~/boards/models/assignee';
import '~/boards/models/list'; import '~/boards/models/list';
import store from '~/boards/stores'; import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue'; import BoardCard from '~/boards/components/board_card.vue';
import issueCardInner from '~/boards/components/issue_card_inner.vue'; import issueCardInner from '~/boards/components/issue_card_inner.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 { listObj, boardsMockInterceptor, setMockEndpoints } from './mock_data'; import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
describe('Board card', () => { describe('BoardCard', () => {
let wrapper; let wrapper;
let mock; let mock;
let list; let list;
...@@ -30,7 +30,7 @@ describe('Board card', () => { ...@@ -30,7 +30,7 @@ describe('Board card', () => {
// this particular mount component needs to be used after the root beforeEach because it depends on list being initialized // this particular mount component needs to be used after the root beforeEach because it depends on list being initialized
const mountComponent = propsData => { const mountComponent = propsData => {
wrapper = shallowMount(boardCard, { wrapper = mount(BoardCard, {
stubs: { stubs: {
issueCardInner, issueCardInner,
}, },
...@@ -47,7 +47,7 @@ describe('Board card', () => { ...@@ -47,7 +47,7 @@ describe('Board card', () => {
}); });
}; };
const setupData = () => { const setupData = async () => {
list = new List(listObj); list = new List(listObj);
boardsStore.create(); boardsStore.create();
boardsStore.detail.issue = {}; boardsStore.detail.issue = {};
...@@ -58,9 +58,9 @@ describe('Board card', () => { ...@@ -58,9 +58,9 @@ describe('Board card', () => {
text_color: 'white', text_color: 'white',
description: 'test', description: 'test',
}); });
return waitForPromises().then(() => { await waitForPromises();
list.issues[0].labels.push(label1);
}); list.issues[0].labels.push(label1);
}; };
beforeEach(() => { beforeEach(() => {
...@@ -79,7 +79,7 @@ describe('Board card', () => { ...@@ -79,7 +79,7 @@ describe('Board card', () => {
it('when details issue is empty does not show the element', () => { it('when details issue is empty does not show the element', () => {
mountComponent(); mountComponent();
expect(wrapper.classes()).not.toContain('is-active'); expect(wrapper.find('[data-testid="board_card"').classes()).not.toContain('is-active');
}); });
it('when detailIssue is equal to card issue shows the element', () => { it('when detailIssue is equal to card issue shows the element', () => {
...@@ -124,29 +124,6 @@ describe('Board card', () => { ...@@ -124,29 +124,6 @@ describe('Board card', () => {
}); });
describe('mouse events', () => { describe('mouse events', () => {
it('sets showDetail to true on mousedown', () => {
mountComponent();
wrapper.trigger('mousedown');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.showDetail).toBe(true);
});
});
it('sets showDetail to false on mousemove', () => {
mountComponent();
wrapper.trigger('mousedown');
return wrapper.vm
.$nextTick()
.then(() => {
expect(wrapper.vm.showDetail).toBe(true);
wrapper.trigger('mousemove');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(wrapper.vm.showDetail).toBe(false);
});
});
it('does not set detail issue if showDetail is false', () => { it('does not set detail issue if showDetail is false', () => {
mountComponent(); mountComponent();
expect(boardsStore.detail.issue).toEqual({}); expect(boardsStore.detail.issue).toEqual({});
...@@ -219,6 +196,9 @@ describe('Board card', () => { ...@@ -219,6 +196,9 @@ describe('Board card', () => {
boardsStore.detail.issue = {}; boardsStore.detail.issue = {};
mountComponent(); mountComponent();
// sets conditional so that event is emitted.
wrapper.trigger('mousedown');
wrapper.trigger('mouseup'); wrapper.trigger('mouseup');
expect(sidebarEventHub.$emit).toHaveBeenCalledWith('sidebar.closeAll'); expect(sidebarEventHub.$emit).toHaveBeenCalledWith('sidebar.closeAll');
......
...@@ -3,6 +3,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils'; ...@@ -3,6 +3,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue'; import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import BoardColumn from 'ee_else_ce/boards/components/board_column.vue'; import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
import getters from 'ee_else_ce/boards/stores/getters';
import { mockListsWithModel } from '../mock_data'; import { mockListsWithModel } from '../mock_data';
import BoardContent from '~/boards/components/board_content.vue'; import BoardContent from '~/boards/components/board_content.vue';
...@@ -20,6 +21,7 @@ describe('BoardContent', () => { ...@@ -20,6 +21,7 @@ describe('BoardContent', () => {
const createStore = (state = defaultState) => { const createStore = (state = defaultState) => {
return new Vuex.Store({ return new Vuex.Store({
getters,
state, state,
actions: { actions: {
fetchIssuesForAllLists: () => {}, fetchIssuesForAllLists: () => {},
......
...@@ -6,8 +6,9 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; ...@@ -6,8 +6,9 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDrawer, GlLabel } from '@gitlab/ui'; import { GlDrawer, GlLabel } from '@gitlab/ui';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue'; import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import { createStore } from '~/boards/stores';
import sidebarEventHub from '~/sidebar/event_hub'; import sidebarEventHub from '~/sidebar/event_hub';
import { inactiveId } from '~/boards/constants'; import { inactiveId, LIST } from '~/boards/constants';
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -16,19 +17,12 @@ localVue.use(Vuex); ...@@ -16,19 +17,12 @@ localVue.use(Vuex);
describe('BoardSettingsSidebar', () => { describe('BoardSettingsSidebar', () => {
let wrapper; let wrapper;
let mock; let mock;
let storeActions; let store;
const labelTitle = 'test'; const labelTitle = 'test';
const labelColor = '#FFFF'; const labelColor = '#FFFF';
const listId = 1; const listId = 1;
const createComponent = (state = { activeId: inactiveId }, actions = {}) => { const createComponent = () => {
storeActions = actions;
const store = new Vuex.Store({
state,
actions: storeActions,
});
wrapper = shallowMount(BoardSettingsSidebar, { wrapper = shallowMount(BoardSettingsSidebar, {
store, store,
localVue, localVue,
...@@ -38,6 +32,9 @@ describe('BoardSettingsSidebar', () => { ...@@ -38,6 +32,9 @@ describe('BoardSettingsSidebar', () => {
const findDrawer = () => wrapper.find(GlDrawer); const findDrawer = () => wrapper.find(GlDrawer);
beforeEach(() => { beforeEach(() => {
store = createStore();
store.state.activeId = inactiveId;
store.state.sidebarType = LIST;
boardsStore.create(); boardsStore.create();
}); });
...@@ -46,114 +43,125 @@ describe('BoardSettingsSidebar', () => { ...@@ -46,114 +43,125 @@ describe('BoardSettingsSidebar', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('finds a GlDrawer component', () => { describe('when sidebarType is "list"', () => {
createComponent(); it('finds a GlDrawer component', () => {
createComponent();
expect(findDrawer().exists()).toBe(true); expect(findDrawer().exists()).toBe(true);
}); });
describe('on close', () => { describe('on close', () => {
it('calls closeSidebar', async () => { it('closes the sidebar', async () => {
const spy = jest.fn(); createComponent();
createComponent({ activeId: inactiveId }, { setActiveId: spy });
findDrawer().vm.$emit('close'); findDrawer().vm.$emit('close');
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(storeActions.setActiveId).toHaveBeenCalledWith( expect(wrapper.find(GlDrawer).exists()).toBe(false);
expect.anything(), });
inactiveId,
undefined,
);
});
it('calls closeSidebar on sidebar.closeAll event', async () => { it('closes the sidebar when emitting the correct event', async () => {
createComponent({ activeId: inactiveId }, { setActiveId: jest.fn() }); createComponent();
sidebarEventHub.$emit('sidebar.closeAll'); sidebarEventHub.$emit('sidebar.closeAll');
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(storeActions.setActiveId).toHaveBeenCalledWith( expect(wrapper.find(GlDrawer).exists()).toBe(false);
expect.anything(), });
inactiveId,
undefined,
);
}); });
});
describe('when activeId is zero', () => { describe('when activeId is zero', () => {
it('renders GlDrawer with open false', () => { it('renders GlDrawer with open false', () => {
createComponent(); createComponent();
expect(findDrawer().props('open')).toBe(false); expect(findDrawer().props('open')).toBe(false);
});
}); });
});
describe('when activeId is greater than zero', () => { describe('when activeId is greater than zero', () => {
beforeEach(() => { beforeEach(() => {
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
boardsStore.addList({
id: listId,
label: { title: labelTitle, color: labelColor },
list_type: 'label',
});
store.state.activeId = 1;
store.state.sidebarType = LIST;
});
boardsStore.addList({ afterEach(() => {
id: listId, boardsStore.removeList(listId);
label: { title: labelTitle, color: labelColor },
list_type: 'label',
}); });
});
afterEach(() => { it('renders GlDrawer with open false', () => {
boardsStore.removeList(listId); createComponent();
expect(findDrawer().props('open')).toBe(true);
});
}); });
it('renders GlDrawer with open false', () => { describe('when activeId is in boardsStore', () => {
createComponent({ activeId: 1 }); beforeEach(() => {
mock = new MockAdapter(axios);
expect(findDrawer().props('open')).toBe(true); boardsStore.addList({
}); id: listId,
}); label: { title: labelTitle, color: labelColor },
list_type: 'label',
});
describe('when activeId is in boardsStore', () => { store.state.activeId = listId;
beforeEach(() => { store.state.sidebarType = LIST;
mock = new MockAdapter(axios);
boardsStore.addList({ createComponent();
id: listId,
label: { title: labelTitle, color: labelColor },
list_type: 'label',
}); });
createComponent({ activeId: listId }); afterEach(() => {
}); mock.restore();
});
afterEach(() => { it('renders label title', () => {
mock.restore(); expect(findLabel().props('title')).toBe(labelTitle);
}); });
it('renders label title', () => { it('renders label background color', () => {
expect(findLabel().props('title')).toBe(labelTitle); expect(findLabel().props('backgroundColor')).toBe(labelColor);
});
}); });
it('renders label background color', () => { describe('when activeId is not in boardsStore', () => {
expect(findLabel().props('backgroundColor')).toBe(labelColor); beforeEach(() => {
}); mock = new MockAdapter(axios);
});
describe('when activeId is not in boardsStore', () => { boardsStore.addList({ id: listId, label: { title: labelTitle, color: labelColor } });
beforeEach(() => {
mock = new MockAdapter(axios); store.state.activeId = inactiveId;
boardsStore.addList({ id: listId, label: { title: labelTitle, color: labelColor } }); createComponent();
});
afterEach(() => {
mock.restore();
});
createComponent({ activeId: inactiveId }); it('does not render GlLabel', () => {
expect(findLabel().exists()).toBe(false);
});
}); });
});
afterEach(() => { describe('when sidebarType is not List', () => {
mock.restore(); beforeEach(() => {
store.state.sidebarType = '';
createComponent();
}); });
it('does not render GlLabel', () => { it('does not render GlDrawer', () => {
expect(findLabel().exists()).toBe(false); expect(findDrawer().exists()).toBe(false);
}); });
}); });
}); });
...@@ -53,9 +53,9 @@ describe('setActiveId', () => { ...@@ -53,9 +53,9 @@ describe('setActiveId', () => {
testAction( testAction(
actions.setActiveId, actions.setActiveId,
1, { id: 1, sidebarType: 'something' },
state, state,
[{ type: types.SET_ACTIVE_ID, payload: 1 }], [{ type: types.SET_ACTIVE_ID, payload: { id: 1, sidebarType: 'something' } }],
[], [],
done, done,
); );
......
import getters from '~/boards/stores/getters'; import getters from '~/boards/stores/getters';
import { inactiveId } from '~/boards/constants';
describe('Boards - Getters', () => { describe('Boards - Getters', () => {
describe('getLabelToggleState', () => { describe('getLabelToggleState', () => {
...@@ -18,4 +19,76 @@ describe('Boards - Getters', () => { ...@@ -18,4 +19,76 @@ describe('Boards - Getters', () => {
expect(getters.getLabelToggleState(state)).toBe('off'); expect(getters.getLabelToggleState(state)).toBe('off');
}); });
}); });
describe('isSidebarOpen', () => {
it('returns true when activeId is not equal to 0', () => {
const state = {
activeId: 1,
};
expect(getters.isSidebarOpen(state)).toBe(true);
});
it('returns false when activeId is equal to 0', () => {
const state = {
activeId: inactiveId,
};
expect(getters.isSidebarOpen(state)).toBe(false);
});
});
describe('isSwimlanesOn', () => {
afterEach(() => {
window.gon = { features: {} };
});
describe('when boardsWithSwimlanes is true', () => {
beforeEach(() => {
window.gon = { features: { boardsWithSwimlanes: true } };
});
describe('when isShowingEpicsSwimlanes is true', () => {
it('returns true', () => {
const state = {
isShowingEpicsSwimlanes: true,
};
expect(getters.isSwimlanesOn(state)).toBe(true);
});
});
describe('when isShowingEpicsSwimlanes is false', () => {
it('returns false', () => {
const state = {
isShowingEpicsSwimlanes: false,
};
expect(getters.isSwimlanesOn(state)).toBe(false);
});
});
});
describe('when boardsWithSwimlanes is false', () => {
describe('when isShowingEpicsSwimlanes is true', () => {
it('returns false', () => {
const state = {
isShowingEpicsSwimlanes: true,
};
expect(getters.isSwimlanesOn(state)).toBe(false);
});
});
describe('when isShowingEpicsSwimlanes is false', () => {
it('returns false', () => {
const state = {
isShowingEpicsSwimlanes: false,
};
expect(getters.isSwimlanesOn(state)).toBe(false);
});
});
});
});
}); });
...@@ -55,12 +55,18 @@ describe('Board Store Mutations', () => { ...@@ -55,12 +55,18 @@ describe('Board Store Mutations', () => {
}); });
describe('SET_ACTIVE_ID', () => { describe('SET_ACTIVE_ID', () => {
it('updates activeListId to be the value that is passed', () => { const expected = { id: 1, sidebarType: '' };
const expectedId = 1;
mutations.SET_ACTIVE_ID(state, expectedId); beforeEach(() => {
mutations.SET_ACTIVE_ID(state, expected);
});
it('updates aciveListId to be the value that is passed', () => {
expect(state.activeId).toBe(expected.id);
});
expect(state.activeId).toBe(expectedId); it('updates sidebarType to be the value that is passed', () => {
expect(state.sidebarType).toBe(expected.sidebarType);
}); });
}); });
......
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