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