From 8d390d164034f1a4c8dd9f793b5c9462f5d7cf10 Mon Sep 17 00:00:00 2001 From: Lukas Eipert <leipert@gitlab.com> Date: Wed, 1 Apr 2020 16:30:12 +0200 Subject: [PATCH] Promotions now don't show unnecessary header Previously promotion columns did show unnecessary headers (adding issues and WIP config). This adds a check and proper tests. --- .../boards/components/board_column.vue | 3 +- .../boards/mixins/is_wip_limits.js | 2 +- .../boards/components/board_column_spec.js | 118 ++++++++++++++++++ .../boards/components/board_column_spec.js | 49 ++++++-- spec/frontend/boards/list_spec.js | 2 +- 5 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 ee/spec/frontend/boards/components/board_column_spec.js diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue index 7cad4e8537a..183f478de25 100644 --- a/app/assets/javascripts/boards/components/board_column.vue +++ b/app/assets/javascripts/boards/components/board_column.vue @@ -80,7 +80,8 @@ export default { return ( !this.disabled && this.list.type !== ListType.closed && - this.list.type !== ListType.blank + this.list.type !== ListType.blank && + this.list.type !== ListType.promotion ); }, issuesTooltip() { diff --git a/ee/app/assets/javascripts/boards/mixins/is_wip_limits.js b/ee/app/assets/javascripts/boards/mixins/is_wip_limits.js index 512e0045c2a..66d6025d8d1 100644 --- a/ee/app/assets/javascripts/boards/mixins/is_wip_limits.js +++ b/ee/app/assets/javascripts/boards/mixins/is_wip_limits.js @@ -1,7 +1,7 @@ export default { computed: { isWipLimitsOn() { - return gon.features.wipLimits; + return Boolean(gon?.features?.wipLimits); }, }, }; diff --git a/ee/spec/frontend/boards/components/board_column_spec.js b/ee/spec/frontend/boards/components/board_column_spec.js new file mode 100644 index 00000000000..d3f1e1fea6a --- /dev/null +++ b/ee/spec/frontend/boards/components/board_column_spec.js @@ -0,0 +1,118 @@ +import Vue from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import AxiosMockAdapter from 'axios-mock-adapter'; + +import Board from 'ee/boards/components/board_column.vue'; +import List from '~/boards/models/list'; +import { ListType } from '~/boards/constants'; +import axios from '~/lib/utils/axios_utils'; + +import { TEST_HOST } from 'helpers/test_constants'; +import { listObj } from 'jest/boards/mock_data'; + +describe('Board Column Component', () => { + let wrapper; + let axiosMock; + + beforeEach(() => { + window.gon = {}; + axiosMock = new AxiosMockAdapter(axios); + axiosMock.onGet(`${TEST_HOST}/lists/1/issues`).reply(200, { issues: [] }); + }); + + afterEach(() => { + axiosMock.restore(); + + wrapper.destroy(); + + localStorage.clear(); + }); + + const createComponent = ({ + listType = ListType.backlog, + collapsed = false, + withLocalStorage = true, + } = {}) => { + const boardId = '1'; + + const listMock = { + ...listObj, + list_type: listType, + collapsed, + }; + + if (listType === ListType.assignee) { + delete listMock.label; + listMock.user = {}; + } + + // Making List reactive + const list = Vue.observable(new List(listMock)); + + if (withLocalStorage) { + localStorage.setItem( + `boards.${boardId}.${list.type}.${list.id}.expanded`, + (!collapsed).toString(), + ); + } + + wrapper = shallowMount(Board, { + propsData: { + boardId, + disabled: false, + issueLinkBase: '/', + rootPath: '/', + list, + }, + }); + }; + + const findSettingsButton = () => wrapper.find({ ref: 'settingsBtn' }); + + describe('Settings Button', () => { + it.each(Object.values(ListType))( + 'when feature flag is off: does not render for List Type `%s`', + listType => { + window.gon = { + features: { + wipLimits: false, + }, + }; + createComponent({ listType }); + + expect(findSettingsButton().exists()).toBe(false); + }, + ); + + describe('when feature flag is on', () => { + const hasSettings = [ListType.assignee, ListType.milestone, ListType.label]; + const hasNoSettings = [ListType.backlog, ListType.blank, ListType.closed, ListType.promotion]; + + beforeEach(() => { + window.gon = { + features: { + wipLimits: true, + }, + }; + }); + + it.each(hasSettings)('does render for List Type `%s`', listType => { + createComponent({ listType }); + + expect(findSettingsButton().exists()).toBe(true); + }); + + it.each(hasNoSettings)('does not render for List Type `%s`', listType => { + createComponent({ listType }); + + expect(findSettingsButton().exists()).toBe(false); + }); + + it('has a test for each list type', () => { + Object.values(ListType).forEach(value => { + expect([...hasSettings, ...hasNoSettings]).toContain(value); + }); + }); + }); + }); +}); diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js index de6c3fed249..7cf6ec913b4 100644 --- a/spec/frontend/boards/components/board_column_spec.js +++ b/spec/frontend/boards/components/board_column_spec.js @@ -4,6 +4,7 @@ import AxiosMockAdapter from 'axios-mock-adapter'; import Board from '~/boards/components/board_column.vue'; import List from '~/boards/models/list'; +import { ListType } from '~/boards/constants'; import axios from '~/lib/utils/axios_utils'; import { TEST_HOST } from 'helpers/test_constants'; @@ -28,20 +29,25 @@ describe('Board Column Component', () => { }); const createComponent = ({ - listType = 'backlog', + listType = ListType.backlog, collapsed = false, withLocalStorage = true, } = {}) => { const boardId = '1'; + const listMock = { + ...listObj, + list_type: listType, + collapsed, + }; + + if (listType === ListType.assignee) { + delete listMock.label; + listMock.user = {}; + } + // Making List reactive - const list = Vue.observable( - new List({ - ...listObj, - list_type: listType, - collapsed, - }), - ); + const list = Vue.observable(new List(listMock)); if (withLocalStorage) { localStorage.setItem( @@ -64,23 +70,40 @@ describe('Board Column Component', () => { const isExpandable = () => wrapper.classes('is-expandable'); const isCollapsed = () => wrapper.classes('is-collapsed'); + const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' }); + describe('Add issue button', () => { - it('does not render when List Type is `blank`', () => { - createComponent({ listType: 'blank' }); + const hasNoAddButton = [ListType.promotion, ListType.blank, ListType.closed]; + const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee]; + + it.each(hasNoAddButton)('does not render when List Type is `%s`', listType => { + createComponent({ listType }); - expect(wrapper.find('.issue-count-badge-add-button').exists()).toBe(false); + expect(findAddIssueButton().exists()).toBe(false); + }); + + it.each(hasAddButton)('does render when List Type is `%s`', listType => { + createComponent({ listType }); + + expect(findAddIssueButton().exists()).toBe(true); + }); + + it('has a test for each list type', () => { + Object.values(ListType).forEach(value => { + expect([...hasAddButton, ...hasNoAddButton]).toContain(value); + }); }); it('does render when logged out', () => { createComponent(); - expect(wrapper.find('.issue-count-badge-add-button').exists()).toBe(true); + expect(findAddIssueButton().exists()).toBe(true); }); }); describe('Given different list types', () => { it('is expandable when List Type is `backlog`', () => { - createComponent({ listType: 'backlog' }); + createComponent({ listType: ListType.backlog }); expect(isExpandable()).toBe(true); }); diff --git a/spec/frontend/boards/list_spec.js b/spec/frontend/boards/list_spec.js index 92e1ed03610..b30281f8df5 100644 --- a/spec/frontend/boards/list_spec.js +++ b/spec/frontend/boards/list_spec.js @@ -56,7 +56,7 @@ describe('List model', () => { label: { id: 1, title: 'test', - color: 'red', + color: '#ff0000', text_color: 'white', }, }); -- 2.30.9