Commit c71dad2e authored by Florie Guibert's avatar Florie Guibert Committed by Simon Knox

Board refactor - Decouple boardsStore from GraphQL boards

Duplicate components to help decouple boardsStore
parent 1e1b44a0
<script> <script>
import IssueCardInner from './issue_card_inner.vue'; import IssueCardInner from './issue_card_inner.vue';
import IssueCardInnerDeprecated from './issue_card_inner_deprecated.vue';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
export default { export default {
name: 'BoardsIssueCard', name: 'BoardsIssueCard',
components: { components: {
IssueCardInner, IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated,
}, },
props: { props: {
list: { list: {
......
<script> <script>
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner'; import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import { sprintf, __, n__ } from '~/locale'; import { sprintf, __, n__ } from '~/locale';
...@@ -8,9 +8,10 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; ...@@ -8,9 +8,10 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.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 IssueDueDate from './issue_due_date.vue'; import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue'; import IssueTimeEstimate from './issue_time_estimate.vue';
import boardsStore from '../stores/boards_store'; import eventHub from '../eventhub';
import { isScopedLabel } from '~/lib/utils/common_utils'; import { isScopedLabel } from '~/lib/utils/common_utils';
import { ListType } from '../constants'; import { ListType } from '../constants';
import { updateHistory } from '~/lib/utils/url_utility';
export default { export default {
components: { components: {
...@@ -42,7 +43,7 @@ export default { ...@@ -42,7 +43,7 @@ export default {
default: false, default: false,
}, },
}, },
inject: ['groupId', 'rootPath'], inject: ['groupId', 'rootPath', 'scopedLabelsAvailable'],
data() { data() {
return { return {
limitBeforeCounter: 2, limitBeforeCounter: 2,
...@@ -52,6 +53,16 @@ export default { ...@@ -52,6 +53,16 @@ export default {
}, },
computed: { computed: {
...mapState(['isShowingLabels']), ...mapState(['isShowingLabels']),
cappedAssignees() {
// e.g. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return this.issue.assignees.slice(0, this.maxRender);
}
return this.issue.assignees.slice(0, this.limitBeforeCounter);
},
numberOverLimit() { numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter; return this.issue.assignees.length - this.limitBeforeCounter;
}, },
...@@ -98,19 +109,10 @@ export default { ...@@ -98,19 +109,10 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(['performSearch']),
isIndexLessThanlimit(index) { isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter; return index < this.limitBeforeCounter;
}, },
shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
return index < this.limitBeforeCounter;
},
assigneeUrl(assignee) { assigneeUrl(assignee) {
if (!assignee) return ''; if (!assignee) return '';
return `${this.rootPath}${assignee.username}`; return `${this.rootPath}${assignee.username}`;
...@@ -118,6 +120,9 @@ export default { ...@@ -118,6 +120,9 @@ export default {
avatarUrlTitle(assignee) { avatarUrlTitle(assignee) {
return sprintf(__(`Avatar for %{assigneeName}`), { assigneeName: assignee.name }); return sprintf(__(`Avatar for %{assigneeName}`), { assigneeName: assignee.name });
}, },
avatarUrl(assignee) {
return assignee.avatarUrl || assignee.avatar || gon.default_avatar_url;
},
showLabel(label) { showLabel(label) {
if (!label.id) return false; if (!label.id) return false;
return true; return true;
...@@ -133,13 +138,19 @@ export default { ...@@ -133,13 +138,19 @@ export default {
}, },
filterByLabel(label) { filterByLabel(label) {
if (!this.updateFilters) return; if (!this.updateFilters) return;
const labelTitle = encodeURIComponent(label.title); const filterPath = window.location.search ? `${window.location.search}&` : '?';
const filter = `label_name[]=${labelTitle}`; const filter = `label_name[]=${encodeURIComponent(label.title)}`;
boardsStore.toggleFilter(filter); if (!filterPath.includes(filter)) {
updateHistory({
url: `${filterPath}${filter}`,
});
this.performSearch();
eventHub.$emit('updateTokens');
}
}, },
showScopedLabel(label) { showScopedLabel(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label); return this.scopedLabelsAvailable && isScopedLabel(label);
}, },
}, },
}; };
...@@ -222,12 +233,11 @@ export default { ...@@ -222,12 +233,11 @@ export default {
</div> </div>
<div class="board-card-assignee gl-display-flex"> <div class="board-card-assignee gl-display-flex">
<user-avatar-link <user-avatar-link
v-for="(assignee, index) in issue.assignees" v-for="assignee in cappedAssignees"
v-if="shouldRenderAssignee(index)"
:key="assignee.id" :key="assignee.id"
:link-href="assigneeUrl(assignee)" :link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)" :img-alt="avatarUrlTitle(assignee)"
:img-src="assignee.avatarUrl || assignee.avatar || assignee.avatar_url" :img-src="avatarUrl(assignee)"
:img-size="24" :img-size="24"
class="js-no-trigger" class="js-no-trigger"
tooltip-placement="bottom" tooltip-placement="bottom"
......
<script>
import { sortBy } from 'lodash';
import { mapState } from 'vuex';
import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import { sprintf, __, n__ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate_deprecated.vue';
import boardsStore from '../stores/boards_store';
import { isScopedLabel } from '~/lib/utils/common_utils';
export default {
components: {
GlLabel,
GlIcon,
UserAvatarLink,
TooltipOnTruncate,
IssueDueDate,
IssueTimeEstimate,
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [issueCardInner],
props: {
issue: {
type: Object,
required: true,
},
list: {
type: Object,
required: false,
default: () => ({}),
},
updateFilters: {
type: Boolean,
required: false,
default: false,
},
},
inject: ['groupId', 'rootPath'],
data() {
return {
limitBeforeCounter: 2,
maxRender: 3,
maxCounter: 99,
};
},
computed: {
...mapState(['isShowingLabels']),
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
assigneeCounterTooltip() {
const { numberOverLimit, maxCounter } = this;
const count = numberOverLimit > maxCounter ? maxCounter : numberOverLimit;
return sprintf(__('%{count} more assignees'), { count });
},
assigneeCounterLabel() {
if (this.numberOverLimit > this.maxCounter) {
return `${this.maxCounter}+`;
}
return `+${this.numberOverLimit}`;
},
shouldRenderCounter() {
if (this.issue.assignees.length <= this.maxRender) {
return false;
}
return this.issue.assignees.length > this.numberOverLimit;
},
issueId() {
if (this.issue.iid) {
return `#${this.issue.iid}`;
}
return false;
},
showLabelFooter() {
return this.isShowingLabels && this.issue.labels.find(this.showLabel);
},
issueReferencePath() {
const { referencePath, groupId } = this.issue;
return !groupId ? referencePath.split('#')[0] : null;
},
orderedLabels() {
return sortBy(this.issue.labels.filter(this.isNonListLabel), 'title');
},
blockedLabel() {
if (this.issue.blockedByCount) {
return n__(`Blocked by %d issue`, `Blocked by %d issues`, this.issue.blockedByCount);
}
return __('Blocked issue');
},
},
methods: {
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
return index < this.limitBeforeCounter;
},
assigneeUrl(assignee) {
if (!assignee) return '';
return `${this.rootPath}${assignee.username}`;
},
avatarUrlTitle(assignee) {
return sprintf(__(`Avatar for %{assigneeName}`), { assigneeName: assignee.name });
},
showLabel(label) {
if (!label.id) return false;
return true;
},
isNonListLabel(label) {
return label.id && !(this.list.type === 'label' && this.list.title === label.title);
},
filterByLabel(label) {
if (!this.updateFilters) return;
const labelTitle = encodeURIComponent(label.title);
const filter = `label_name[]=${labelTitle}`;
boardsStore.toggleFilter(filter);
},
showScopedLabel(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
},
},
};
</script>
<template>
<div>
<div class="gl-display-flex" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0">
<gl-icon
v-if="issue.blocked"
v-gl-tooltip
name="issue-block"
:title="blockedLabel"
class="issue-blocked-icon gl-mr-2"
:aria-label="blockedLabel"
data-testid="issue-blocked-icon"
/>
<gl-icon
v-if="issue.confidential"
v-gl-tooltip
name="eye-slash"
:title="__('Confidential')"
class="confidential-icon gl-mr-2"
:aria-label="__('Confidential')"
/>
<a
:href="issue.path || issue.webUrl || ''"
:title="issue.title"
class="js-no-trigger"
@mousemove.stop
>{{ issue.title }}</a
>
</h4>
</div>
<div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
<template v-for="label in orderedLabels">
<gl-label
:key="label.id"
:background-color="label.color"
:title="label.title"
:description="label.description"
size="sm"
:scoped="showScopedLabel(label)"
@click="filterByLabel(label)"
/>
</template>
</div>
<div
class="board-card-footer gl-display-flex gl-justify-content-space-between gl-align-items-flex-end"
>
<div
class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden js-board-card-number-container"
>
<span
v-if="issue.referencePath"
class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3"
>
<tooltip-on-truncate
v-if="issueReferencePath"
:title="issueReferencePath"
placement="bottom"
class="board-issue-path gl-text-truncate gl-font-weight-bold"
>{{ issueReferencePath }}</tooltip-on-truncate
>
#{{ issue.iid }}
</span>
<span class="board-info-items gl-mt-3 gl-display-inline-block">
<issue-due-date
v-if="issue.dueDate"
:date="issue.dueDate"
:closed="issue.closed || Boolean(issue.closedAt)"
/>
<issue-time-estimate v-if="issue.timeEstimate" :estimate="issue.timeEstimate" />
<issue-card-weight
v-if="validIssueWeight"
:weight="issue.weight"
@click="filterByWeight(issue.weight)"
/>
</span>
</div>
<div class="board-card-assignee gl-display-flex">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
v-if="shouldRenderAssignee(index)"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
:img-src="assignee.avatarUrl || assignee.avatar || assignee.avatar_url"
:img-size="24"
class="js-no-trigger"
tooltip-placement="bottom"
>
<span class="js-assignee-tooltip">
<span class="gl-font-weight-bold gl-display-block">{{ __('Assignee') }}</span>
{{ assignee.name }}
<span class="text-white-50">@{{ assignee.username }}</span>
</span>
</user-avatar-link>
<span
v-if="shouldRenderCounter"
v-gl-tooltip
:title="assigneeCounterTooltip"
class="avatar-counter"
data-placement="bottom"
>{{ assigneeCounterLabel }}</span
>
</div>
</div>
</div>
</template>
<script> <script>
import { GlTooltip, GlIcon } from '@gitlab/ui'; import { GlTooltip, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility'; import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
import boardsStore from '../stores/boards_store';
export default { export default {
i18n: {
timeEstimate: __('Time estimate'),
},
components: { components: {
GlIcon, GlIcon,
GlTooltip, GlTooltip,
...@@ -14,17 +17,18 @@ export default { ...@@ -14,17 +17,18 @@ export default {
required: true, required: true,
}, },
}, },
data() { inject: ['timeTrackingLimitToHours'],
return {
limitToHours: boardsStore.timeTracking.limitToHours,
};
},
computed: { computed: {
title() { title() {
return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }), true); return stringifyTime(
parseSeconds(this.estimate, { limitToHours: this.timeTrackingLimitToHours }),
true,
);
}, },
timeEstimate() { timeEstimate() {
return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours })); return stringifyTime(
parseSeconds(this.estimate, { limitToHours: this.timeTrackingLimitToHours }),
);
}, },
}, },
}; };
...@@ -33,16 +37,16 @@ export default { ...@@ -33,16 +37,16 @@ export default {
<template> <template>
<span> <span>
<span ref="issueTimeEstimate" class="board-card-info card-number"> <span ref="issueTimeEstimate" class="board-card-info card-number">
<gl-icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{ <gl-icon name="hourglass" class="board-card-info-icon" />
timeEstimate <time class="board-card-info-text">{{ timeEstimate }}</time>
}}</time>
</span> </span>
<gl-tooltip <gl-tooltip
:target="() => $refs.issueTimeEstimate" :target="() => $refs.issueTimeEstimate"
placement="bottom" placement="bottom"
class="js-issue-time-estimate" class="js-issue-time-estimate"
> >
<span class="bold d-block">{{ __('Time estimate') }}</span> {{ title }} <span class="gl-font-weight-bold gl-display-block">{{ $options.i18n.timeEstimate }}</span>
{{ title }}
</gl-tooltip> </gl-tooltip>
</span> </span>
</template> </template>
<script>
import { GlTooltip, GlIcon } from '@gitlab/ui';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
import boardsStore from '../stores/boards_store';
export default {
components: {
GlIcon,
GlTooltip,
},
props: {
estimate: {
type: Number,
required: true,
},
},
data() {
return {
limitToHours: boardsStore.timeTracking.limitToHours,
};
},
computed: {
title() {
return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }), true);
},
timeEstimate() {
return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }));
},
},
};
</script>
<template>
<span>
<span ref="issueTimeEstimate" class="board-card-info card-number">
<gl-icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
timeEstimate
}}</time>
</span>
<gl-tooltip
:target="() => $refs.issueTimeEstimate"
placement="bottom"
class="js-issue-time-estimate"
>
<span class="bold d-block">{{ __('Time estimate') }}</span> {{ title }}
</gl-tooltip>
</span>
</template>
...@@ -117,16 +117,9 @@ export default () => { ...@@ -117,16 +117,9 @@ export default () => {
}, },
}, },
created() { created() {
const endpoints = { this.setInitialBoardData({
boardsEndpoint: this.boardsEndpoint,
recentBoardsEndpoint: this.recentBoardsEndpoint,
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
boardId: $boardApp.dataset.boardId, boardId: $boardApp.dataset.boardId,
fullPath: $boardApp.dataset.fullPath, fullPath: $boardApp.dataset.fullPath,
};
this.setInitialBoardData({
...endpoints,
boardType: this.parent, boardType: this.parent,
disabled: this.disabled, disabled: this.disabled,
boardConfig: { boardConfig: {
...@@ -141,7 +134,14 @@ export default () => { ...@@ -141,7 +134,14 @@ export default () => {
: null, : null,
}, },
}); });
boardsStore.setEndpoints(endpoints); boardsStore.setEndpoints({
boardsEndpoint: this.boardsEndpoint,
recentBoardsEndpoint: this.recentBoardsEndpoint,
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
boardId: $boardApp.dataset.boardId,
fullPath: $boardApp.dataset.fullPath,
});
boardsStore.rootPath = this.boardsEndpoint; boardsStore.rootPath = this.boardsEndpoint;
eventHub.$on('updateTokens', this.updateTokens); eventHub.$on('updateTokens', this.updateTokens);
......
...@@ -78,8 +78,7 @@ export default { ...@@ -78,8 +78,7 @@ export default {
}, },
fetchLists: ({ commit, state, dispatch }) => { fetchLists: ({ commit, state, dispatch }) => {
const { endpoints, boardType, filterParams } = state; const { boardType, filterParams, fullPath, boardId } = state;
const { fullPath, boardId } = endpoints;
const variables = { const variables = {
fullPath, fullPath,
...@@ -106,7 +105,7 @@ export default { ...@@ -106,7 +105,7 @@ export default {
}, },
createList: ({ state, commit, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => { createList: ({ state, commit, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => {
const { boardId } = state.endpoints; const { boardId } = state;
gqlClient gqlClient
.mutate({ .mutate({
...@@ -135,8 +134,7 @@ export default { ...@@ -135,8 +134,7 @@ export default {
}, },
fetchLabels: ({ state, commit }, searchTerm) => { fetchLabels: ({ state, commit }, searchTerm) => {
const { endpoints, boardType } = state; const { fullPath, boardType } = state;
const { fullPath } = endpoints;
const variables = { const variables = {
fullPath, fullPath,
...@@ -227,8 +225,7 @@ export default { ...@@ -227,8 +225,7 @@ export default {
fetchIssuesForList: ({ state, commit }, { listId, fetchNext = false }) => { fetchIssuesForList: ({ state, commit }, { listId, fetchNext = false }) => {
commit(types.REQUEST_ISSUES_FOR_LIST, { listId, fetchNext }); commit(types.REQUEST_ISSUES_FOR_LIST, { listId, fetchNext });
const { endpoints, boardType, filterParams } = state; const { fullPath, boardId, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
const variables = { const variables = {
fullPath, fullPath,
...@@ -271,7 +268,7 @@ export default { ...@@ -271,7 +268,7 @@ export default {
const originalIndex = fromList.indexOf(Number(issueId)); const originalIndex = fromList.indexOf(Number(issueId));
commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId }); commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId });
const { boardId } = state.endpoints; const { boardId } = state;
const [fullProjectPath] = issuePath.split(/[#]/); const [fullProjectPath] = issuePath.split(/[#]/);
gqlClient gqlClient
...@@ -357,9 +354,9 @@ export default { ...@@ -357,9 +354,9 @@ export default {
createNewIssue: ({ commit, state }, issueInput) => { createNewIssue: ({ commit, state }, issueInput) => {
const input = issueInput; const input = issueInput;
const { boardType, endpoints } = state; const { boardType, fullPath } = state;
if (boardType === BoardType.project) { if (boardType === BoardType.project) {
input.projectPath = endpoints.fullPath; input.projectPath = fullPath;
} }
return gqlClient return gqlClient
......
...@@ -32,8 +32,9 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter ...@@ -32,8 +32,9 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
export default { export default {
[mutationTypes.SET_INITIAL_BOARD_DATA](state, data) { [mutationTypes.SET_INITIAL_BOARD_DATA](state, data) {
const { boardType, disabled, boardConfig, ...endpoints } = data; const { boardType, disabled, boardId, fullPath, boardConfig } = data;
state.endpoints = endpoints; state.boardId = boardId;
state.fullPath = fullPath;
state.boardType = boardType; state.boardType = boardType;
state.disabled = disabled; state.disabled = disabled;
state.boardConfig = boardConfig; state.boardConfig = boardConfig;
......
...@@ -45,8 +45,7 @@ export const gqlClient = createGqClient( ...@@ -45,8 +45,7 @@ export const gqlClient = createGqClient(
); );
const fetchAndFormatListIssues = (state, extraVariables) => { const fetchAndFormatListIssues = (state, extraVariables) => {
const { endpoints, boardType, filterParams } = state; const { fullPath, boardId, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
const variables = { const variables = {
fullPath, fullPath,
...@@ -126,8 +125,7 @@ export default { ...@@ -126,8 +125,7 @@ export default {
}, },
fetchEpicsSwimlanes({ state, commit, dispatch }, { withLists = true, endCursor = null }) { fetchEpicsSwimlanes({ state, commit, dispatch }, { withLists = true, endCursor = null }) {
const { endpoints, boardType, filterParams } = state; const { fullPath, boardId, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
const variables = { const variables = {
fullPath, fullPath,
...@@ -176,9 +174,7 @@ export default { ...@@ -176,9 +174,7 @@ export default {
}, },
updateBoardEpicUserPreferences({ commit, state }, { epicId, collapsed }) { updateBoardEpicUserPreferences({ commit, state }, { epicId, collapsed }) {
const { const { boardId } = state;
endpoints: { boardId },
} = state;
const variables = { const variables = {
boardId: fullBoardId(boardId), boardId: fullBoardId(boardId),
...@@ -394,7 +390,7 @@ export default { ...@@ -394,7 +390,7 @@ export default {
epicId, epicId,
}); });
const { boardId } = state.endpoints; const { boardId } = state;
const [fullProjectPath] = issuePath.split(/[#]/); const [fullProjectPath] = issuePath.split(/[#]/);
gqlClient gqlClient
......
import { GlLabel } from '@gitlab/ui'; import { GlLabel } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import IssueCardWeight from 'ee/boards/components/issue_card_weight.vue'; import IssueCardWeight from 'ee/boards/components/issue_card_weight.vue';
import ListIssueEE from 'ee/boards/models/issue';
import IssueCardInner from '~/boards/components/issue_card_inner.vue'; import IssueCardInner from '~/boards/components/issue_card_inner.vue';
import ListLabel from '~/boards/models/label';
import defaultStore from '~/boards/stores'; import defaultStore from '~/boards/stores';
describe('Issue card component', () => { describe('Issue card component', () => {
...@@ -22,6 +20,7 @@ describe('Issue card component', () => { ...@@ -22,6 +20,7 @@ describe('Issue card component', () => {
provide: { provide: {
groupId: null, groupId: null,
rootPath: '/', rootPath: '/',
scopedLabelsAvailable: false,
}, },
}); });
}; };
...@@ -31,7 +30,7 @@ describe('Issue card component', () => { ...@@ -31,7 +30,7 @@ describe('Issue card component', () => {
id: 300, id: 300,
position: 0, position: 0,
title: 'Test', title: 'Test',
list_type: 'label', listType: 'label',
label: { label: {
id: 5000, id: 5000,
title: 'Testing', title: 'Testing',
...@@ -41,19 +40,19 @@ describe('Issue card component', () => { ...@@ -41,19 +40,19 @@ describe('Issue card component', () => {
}, },
}; };
issue = new ListIssueEE({ issue = {
title: 'Testing', title: 'Testing',
id: 1, id: 1,
iid: 1, iid: 1,
confidential: false, confidential: false,
labels: [list.label], labels: [list.label],
assignees: [], assignees: [],
reference_path: '#1', referencePath: '#1',
real_path: '/test/1', webUrl: '/test/1',
weight: 1, weight: 1,
blocked: true, blocked: true,
blockedByCount: 2, blockedByCount: 2,
}); };
}); });
afterEach(() => { afterEach(() => {
...@@ -63,15 +62,15 @@ describe('Issue card component', () => { ...@@ -63,15 +62,15 @@ describe('Issue card component', () => {
describe('labels', () => { describe('labels', () => {
beforeEach(() => { beforeEach(() => {
const label1 = new ListLabel({ const label1 = {
id: 3, id: 3,
title: 'testing 123', title: 'testing 123',
color: '#000cff', color: '#000cff',
text_color: 'white', textColor: 'white',
description: 'test', description: 'test',
}); };
issue.addLabel(label1); issue.labels = [...issue.labels, label1];
}); });
it.each` it.each`
...@@ -79,14 +78,15 @@ describe('Issue card component', () => { ...@@ -79,14 +78,15 @@ describe('Issue card component', () => {
${'GroupLabel'} | ${'Group label'} | ${'shows group labels on group boards'} ${'GroupLabel'} | ${'Group label'} | ${'shows group labels on group boards'}
${'ProjectLabel'} | ${'Project label'} | ${'shows project labels on group boards'} ${'ProjectLabel'} | ${'Project label'} | ${'shows project labels on group boards'}
`('$desc', ({ type, title }) => { `('$desc', ({ type, title }) => {
issue.addLabel( issue.labels = [
new ListLabel({ ...issue.labels,
{
id: 9001, id: 9001,
type, type,
title, title,
color: '#000000', color: '#000000',
}), },
); ];
createComponent({ groupId: 1 }); createComponent({ groupId: 1 });
......
...@@ -137,10 +137,8 @@ describe('performSearch', () => { ...@@ -137,10 +137,8 @@ describe('performSearch', () => {
describe('fetchEpicsSwimlanes', () => { describe('fetchEpicsSwimlanes', () => {
const state = { const state = {
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: 1,
},
filterParams: {}, filterParams: {},
boardType: 'group', boardType: 'group',
}; };
...@@ -230,9 +228,7 @@ describe('fetchEpicsSwimlanes', () => { ...@@ -230,9 +228,7 @@ describe('fetchEpicsSwimlanes', () => {
describe('updateBoardEpicUserPreferences', () => { describe('updateBoardEpicUserPreferences', () => {
const state = { const state = {
endpoints: {
boardId: 1, boardId: 1,
},
}; };
const queryResponse = (collapsed = false) => ({ const queryResponse = (collapsed = false) => ({
...@@ -392,10 +388,8 @@ describe('fetchIssuesForEpic', () => { ...@@ -392,10 +388,8 @@ describe('fetchIssuesForEpic', () => {
const epicId = mockEpic.id; const epicId = mockEpic.id;
const state = { const state = {
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: 1,
},
filterParams: {}, filterParams: {},
boardType: 'group', boardType: 'group',
}; };
...@@ -463,10 +457,8 @@ describe('toggleEpicSwimlanes', () => { ...@@ -463,10 +457,8 @@ describe('toggleEpicSwimlanes', () => {
const state = { const state = {
isShowingEpicsSwimlanes: false, isShowingEpicsSwimlanes: false,
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: 1,
},
}; };
return testAction( return testAction(
...@@ -495,10 +487,8 @@ describe('toggleEpicSwimlanes', () => { ...@@ -495,10 +487,8 @@ describe('toggleEpicSwimlanes', () => {
const state = { const state = {
isShowingEpicsSwimlanes: true, isShowingEpicsSwimlanes: true,
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: 1,
},
}; };
return testAction( return testAction(
...@@ -635,7 +625,8 @@ describe('moveIssue', () => { ...@@ -635,7 +625,8 @@ describe('moveIssue', () => {
}; };
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: 1,
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: mockLists, boardLists: mockLists,
......
...@@ -38,6 +38,7 @@ describe('Board card layout', () => { ...@@ -38,6 +38,7 @@ describe('Board card layout', () => {
provide: { provide: {
groupId: null, groupId: null,
rootPath: '/', rootPath: '/',
scopedLabelsAvailable: false,
}, },
}); });
}; };
......
...@@ -45,6 +45,7 @@ describe('BoardCard', () => { ...@@ -45,6 +45,7 @@ describe('BoardCard', () => {
provide: { provide: {
groupId: null, groupId: null,
rootPath: '/', rootPath: '/',
scopedLabelsAvailable: false,
}, },
}); });
}; };
......
import { shallowMount } from '@vue/test-utils';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate_deprecated.vue';
import boardsStore from '~/boards/stores/boards_store';
describe('Issue Time Estimate component', () => {
let wrapper;
beforeEach(() => {
boardsStore.create();
});
afterEach(() => {
wrapper.destroy();
});
describe('when limitToHours is false', () => {
beforeEach(() => {
boardsStore.timeTracking.limitToHours = false;
wrapper = shallowMount(IssueTimeEstimate, {
propsData: {
estimate: 374460,
},
});
});
it('renders the correct time estimate', () => {
expect(
wrapper
.find('time')
.text()
.trim(),
).toEqual('2w 3d 1m');
});
it('renders expanded time estimate in tooltip', () => {
expect(wrapper.find('.js-issue-time-estimate').text()).toContain('2 weeks 3 days 1 minute');
});
it('prevents tooltip xss', done => {
const alertSpy = jest.spyOn(window, 'alert');
wrapper.setProps({ estimate: 'Foo <script>alert("XSS")</script>' });
wrapper.vm.$nextTick(() => {
expect(alertSpy).not.toHaveBeenCalled();
expect(
wrapper
.find('time')
.text()
.trim(),
).toEqual('0m');
expect(wrapper.find('.js-issue-time-estimate').text()).toContain('0m');
done();
});
});
});
describe('when limitToHours is true', () => {
beforeEach(() => {
boardsStore.timeTracking.limitToHours = true;
wrapper = shallowMount(IssueTimeEstimate, {
propsData: {
estimate: 374460,
},
});
});
it('renders the correct time estimate', () => {
expect(
wrapper
.find('time')
.text()
.trim(),
).toEqual('104h 1m');
});
it('renders expanded time estimate in tooltip', () => {
expect(wrapper.find('.js-issue-time-estimate').text()).toContain('104 hours 1 minute');
});
});
});
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue'; import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
import boardsStore from '~/boards/stores/boards_store';
describe('Issue Time Estimate component', () => { describe('Issue Time Estimate component', () => {
let wrapper; let wrapper;
beforeEach(() => {
boardsStore.create();
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
describe('when limitToHours is false', () => { describe('when limitToHours is false', () => {
beforeEach(() => { beforeEach(() => {
boardsStore.timeTracking.limitToHours = false;
wrapper = shallowMount(IssueTimeEstimate, { wrapper = shallowMount(IssueTimeEstimate, {
propsData: { propsData: {
estimate: 374460, estimate: 374460,
}, },
provide: {
timeTrackingLimitToHours: false,
},
}); });
}); });
...@@ -55,11 +52,13 @@ describe('Issue Time Estimate component', () => { ...@@ -55,11 +52,13 @@ describe('Issue Time Estimate component', () => {
describe('when limitToHours is true', () => { describe('when limitToHours is true', () => {
beforeEach(() => { beforeEach(() => {
boardsStore.timeTracking.limitToHours = true;
wrapper = shallowMount(IssueTimeEstimate, { wrapper = shallowMount(IssueTimeEstimate, {
propsData: { propsData: {
estimate: 374460, estimate: 374460,
}, },
provide: {
timeTrackingLimitToHours: true,
},
}); });
}); });
......
...@@ -6,7 +6,7 @@ import '~/boards/models/assignee'; ...@@ -6,7 +6,7 @@ import '~/boards/models/assignee';
import '~/boards/models/issue'; import '~/boards/models/issue';
import '~/boards/models/list'; import '~/boards/models/list';
import { GlLabel } from '@gitlab/ui'; import { GlLabel } from '@gitlab/ui';
import IssueCardInner from '~/boards/components/issue_card_inner.vue'; import IssueCardInner from '~/boards/components/issue_card_inner_deprecated.vue';
import { listObj } from './mock_data'; import { listObj } from './mock_data';
import store from '~/boards/stores'; import store from '~/boards/stores';
......
import { mount } from '@vue/test-utils';
import { range } from 'lodash';
import { GlLabel } from '@gitlab/ui';
import IssueCardInner from '~/boards/components/issue_card_inner.vue';
import { mockLabelList } from './mock_data';
import defaultStore from '~/boards/stores';
import eventHub from '~/boards/eventhub';
import { updateHistory } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/boards/eventhub');
describe('Issue card component', () => {
const user = {
id: 1,
name: 'testing 123',
username: 'test',
avatarUrl: 'test_image',
};
const label1 = {
id: 3,
title: 'testing 123',
color: '#000CFF',
textColor: 'white',
description: 'test',
};
let wrapper;
let issue;
let list;
const createWrapper = (props = {}, store = defaultStore) => {
wrapper = mount(IssueCardInner, {
store,
propsData: {
list,
issue,
...props,
},
stubs: {
GlLabel: true,
},
provide: {
groupId: null,
rootPath: '/',
scopedLabelsAvailable: false,
},
});
};
beforeEach(() => {
list = mockLabelList;
issue = {
title: 'Testing',
id: 1,
iid: 1,
confidential: false,
labels: [list.label],
assignees: [],
referencePath: '#1',
webUrl: '/test/1',
weight: 1,
};
createWrapper({ issue, list });
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
jest.clearAllMocks();
});
it('renders issue title', () => {
expect(wrapper.find('.board-card-title').text()).toContain(issue.title);
});
it('includes issue base in link', () => {
expect(wrapper.find('.board-card-title a').attributes('href')).toContain('/test');
});
it('includes issue title on link', () => {
expect(wrapper.find('.board-card-title a').attributes('title')).toBe(issue.title);
});
it('does not render confidential icon', () => {
expect(wrapper.find('.confidential-icon').exists()).toBe(false);
});
it('does not render blocked icon', () => {
expect(wrapper.find('.issue-blocked-icon').exists()).toBe(false);
});
it('renders issue ID with #', () => {
expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.id}`);
});
it('does not render assignee', () => {
expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
});
describe('confidential issue', () => {
beforeEach(() => {
wrapper.setProps({
issue: {
...wrapper.props('issue'),
confidential: true,
},
});
});
it('renders confidential icon', () => {
expect(wrapper.find('.confidential-icon').exists()).toBe(true);
});
});
describe('with assignee', () => {
describe('with avatar', () => {
beforeEach(() => {
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees: [user],
updateData(newData) {
Object.assign(this, newData);
},
},
});
});
it('renders assignee', () => {
expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(true);
});
it('sets title', () => {
expect(wrapper.find('.js-assignee-tooltip').text()).toContain(`${user.name}`);
});
it('sets users path', () => {
expect(wrapper.find('.board-card-assignee a').attributes('href')).toBe('/test');
});
it('renders avatar', () => {
expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
});
it('renders the avatar using avatarUrl property', async () => {
wrapper.props('issue').updateData({
...wrapper.props('issue'),
assignees: [
{
id: '1',
name: 'test',
state: 'active',
username: 'test_name',
avatarUrl: 'test_image_from_avatar_url',
},
],
});
await wrapper.vm.$nextTick();
expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
'test_image_from_avatar_url?width=24',
);
});
});
describe('with default avatar', () => {
beforeEach(() => {
global.gon.default_avatar_url = 'default_avatar';
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees: [
{
id: 1,
name: 'testing 123',
username: 'test',
},
],
},
});
});
afterEach(() => {
global.gon.default_avatar_url = null;
});
it('displays defaults avatar if users avatar is null', () => {
expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
'default_avatar?width=24',
);
});
});
});
describe('multiple assignees', () => {
beforeEach(() => {
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees: [
{
id: 2,
name: 'user2',
username: 'user2',
avatarUrl: 'test_image',
},
{
id: 3,
name: 'user3',
username: 'user3',
avatarUrl: 'test_image',
},
{
id: 4,
name: 'user4',
username: 'user4',
avatarUrl: 'test_image',
},
],
},
});
});
it('renders all three assignees', () => {
expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(3);
});
describe('more than three assignees', () => {
beforeEach(() => {
const { assignees } = wrapper.props('issue');
assignees.push({
id: 5,
name: 'user5',
username: 'user5',
avatarUrl: 'test_image',
});
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees,
},
});
});
it('renders more avatar counter', () => {
expect(
wrapper
.find('.board-card-assignee .avatar-counter')
.text()
.trim(),
).toEqual('+2');
});
it('renders two assignees', () => {
expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(2);
});
it('renders 99+ avatar counter', async () => {
const assignees = [
...wrapper.props('issue').assignees,
...range(5, 103).map(i => ({
id: i,
name: 'name',
username: 'username',
avatarUrl: 'test_image',
})),
];
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees,
},
});
await wrapper.vm.$nextTick();
expect(
wrapper
.find('.board-card-assignee .avatar-counter')
.text()
.trim(),
).toEqual('99+');
});
});
});
describe('labels', () => {
beforeEach(() => {
wrapper.setProps({ issue: { ...issue, labels: [list.label, label1] } });
});
it('does not render list label but renders all other labels', () => {
expect(wrapper.findAll(GlLabel).length).toBe(1);
const label = wrapper.find(GlLabel);
expect(label.props('title')).toEqual(label1.title);
expect(label.props('description')).toEqual(label1.description);
expect(label.props('backgroundColor')).toEqual(label1.color);
});
it('does not render label if label does not have an ID', async () => {
wrapper.setProps({ issue: { ...issue, labels: [label1, { title: 'closed' }] } });
await wrapper.vm.$nextTick();
expect(wrapper.findAll(GlLabel).length).toBe(1);
expect(wrapper.text()).not.toContain('closed');
});
});
describe('blocked', () => {
beforeEach(() => {
wrapper.setProps({
issue: {
...wrapper.props('issue'),
blocked: true,
},
});
});
it('renders blocked icon if issue is blocked', () => {
expect(wrapper.find('.issue-blocked-icon').exists()).toBe(true);
});
});
describe('filterByLabel method', () => {
beforeEach(() => {
delete window.location;
wrapper.setProps({
updateFilters: true,
});
});
describe('when selected label is not in the filter', () => {
beforeEach(() => {
jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
window.location = { search: '' };
wrapper.vm.filterByLabel(label1);
});
it('calls updateHistory', () => {
expect(updateHistory).toHaveBeenCalledTimes(1);
});
it('dispatches performSearch vuex action', () => {
expect(wrapper.vm.performSearch).toHaveBeenCalledTimes(1);
});
it('emits updateTokens event', () => {
expect(eventHub.$emit).toHaveBeenCalledTimes(1);
expect(eventHub.$emit).toHaveBeenCalledWith('updateTokens');
});
});
describe('when selected label is already in the filter', () => {
beforeEach(() => {
jest.spyOn(wrapper.vm, 'performSearch').mockImplementation(() => {});
window.location = { search: '?label_name[]=testing%20123' };
wrapper.vm.filterByLabel(label1);
});
it('does not call updateHistory', () => {
expect(updateHistory).not.toHaveBeenCalled();
});
it('does not dispatch performSearch vuex action', () => {
expect(wrapper.vm.performSearch).not.toHaveBeenCalled();
});
it('does not emit updateTokens event', () => {
expect(eventHub.$emit).not.toHaveBeenCalled();
});
});
});
});
...@@ -108,10 +108,8 @@ describe('setActiveId', () => { ...@@ -108,10 +108,8 @@ describe('setActiveId', () => {
describe('fetchLists', () => { describe('fetchLists', () => {
const state = { const state = {
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: '1',
},
filterParams: {}, filterParams: {},
boardType: 'group', boardType: 'group',
}; };
...@@ -201,7 +199,8 @@ describe('createList', () => { ...@@ -201,7 +199,8 @@ describe('createList', () => {
); );
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: [{ type: 'closed' }], boardLists: [{ type: 'closed' }],
...@@ -230,7 +229,8 @@ describe('createList', () => { ...@@ -230,7 +229,8 @@ describe('createList', () => {
); );
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: [{ type: 'closed' }], boardLists: [{ type: 'closed' }],
...@@ -255,7 +255,8 @@ describe('moveList', () => { ...@@ -255,7 +255,8 @@ describe('moveList', () => {
}; };
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: initialBoardListsState, boardLists: initialBoardListsState,
...@@ -297,7 +298,8 @@ describe('moveList', () => { ...@@ -297,7 +298,8 @@ describe('moveList', () => {
}; };
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: initialBoardListsState, boardLists: initialBoardListsState,
...@@ -330,7 +332,8 @@ describe('updateList', () => { ...@@ -330,7 +332,8 @@ describe('updateList', () => {
}); });
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: [{ type: 'closed' }], boardLists: [{ type: 'closed' }],
...@@ -429,10 +432,8 @@ describe('fetchIssuesForList', () => { ...@@ -429,10 +432,8 @@ describe('fetchIssuesForList', () => {
const listId = mockLists[0].id; const listId = mockLists[0].id;
const state = { const state = {
endpoints: {
fullPath: 'gitlab-org', fullPath: 'gitlab-org',
boardId: 1, boardId: '1',
},
filterParams: {}, filterParams: {},
boardType: 'group', boardType: 'group',
}; };
...@@ -530,7 +531,8 @@ describe('moveIssue', () => { ...@@ -530,7 +531,8 @@ describe('moveIssue', () => {
}; };
const state = { const state = {
endpoints: { fullPath: 'gitlab-org', boardId: '1' }, fullPath: 'gitlab-org',
boardId: '1',
boardType: 'group', boardType: 'group',
disabled: false, disabled: false,
boardLists: mockLists, boardLists: mockLists,
...@@ -582,7 +584,7 @@ describe('moveIssue', () => { ...@@ -582,7 +584,7 @@ describe('moveIssue', () => {
mutation: issueMoveListMutation, mutation: issueMoveListMutation,
variables: { variables: {
projectPath: getProjectPath(mockIssue.referencePath), projectPath: getProjectPath(mockIssue.referencePath),
boardId: fullBoardId(state.endpoints.boardId), boardId: fullBoardId(state.boardId),
iid: mockIssue.iid, iid: mockIssue.iid,
fromListId: 1, fromListId: 1,
toListId: 2, toListId: 2,
...@@ -724,9 +726,7 @@ describe('setAssignees', () => { ...@@ -724,9 +726,7 @@ describe('setAssignees', () => {
describe('createNewIssue', () => { describe('createNewIssue', () => {
const state = { const state = {
boardType: 'group', boardType: 'group',
endpoints: {
fullPath: 'gitlab-org/gitlab', fullPath: 'gitlab-org/gitlab',
},
}; };
it('should return issue from API on success', async () => { it('should return issue from API on success', async () => {
......
...@@ -23,14 +23,8 @@ describe('Board Store Mutations', () => { ...@@ -23,14 +23,8 @@ describe('Board Store Mutations', () => {
describe('SET_INITIAL_BOARD_DATA', () => { describe('SET_INITIAL_BOARD_DATA', () => {
it('Should set initial Boards data to state', () => { it('Should set initial Boards data to state', () => {
const endpoints = { const boardId = 1;
boardsEndpoint: '/boards/', const fullPath = 'gitlab-org';
recentBoardsEndpoint: '/boards/',
listsEndpoint: '/boards/lists',
bulkUpdatePath: '/boards/bulkUpdate',
boardId: 1,
fullPath: 'gitlab-org',
};
const boardType = 'group'; const boardType = 'group';
const disabled = false; const disabled = false;
const boardConfig = { const boardConfig = {
...@@ -38,13 +32,15 @@ describe('Board Store Mutations', () => { ...@@ -38,13 +32,15 @@ describe('Board Store Mutations', () => {
}; };
mutations[types.SET_INITIAL_BOARD_DATA](state, { mutations[types.SET_INITIAL_BOARD_DATA](state, {
...endpoints, boardId,
fullPath,
boardType, boardType,
disabled, disabled,
boardConfig, boardConfig,
}); });
expect(state.endpoints).toEqual(endpoints); expect(state.boardId).toEqual(boardId);
expect(state.fullPath).toEqual(fullPath);
expect(state.boardType).toEqual(boardType); expect(state.boardType).toEqual(boardType);
expect(state.disabled).toEqual(disabled); expect(state.disabled).toEqual(disabled);
expect(state.boardConfig).toEqual(boardConfig); expect(state.boardConfig).toEqual(boardConfig);
......
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