diff --git a/webapp/src/components/kanban/__snapshots__/kanbanColumnHeader.test.tsx.snap b/webapp/src/components/kanban/__snapshots__/kanbanColumnHeader.test.tsx.snap
new file mode 100644
index 000000000..35526aa64
--- /dev/null
+++ b/webapp/src/components/kanban/__snapshots__/kanbanColumnHeader.test.tsx.snap
@@ -0,0 +1,469 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`src/components/kanban/kanbanColumnHeader return kanbanColumnHeader and click on menuwrapper 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`src/components/kanban/kanbanColumnHeader return kanbanColumnHeader and edit title 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`src/components/kanban/kanbanColumnHeader should match snapshot 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`src/components/kanban/kanbanColumnHeader should match snapshot readonly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/webapp/src/components/kanban/kanbanColumnHeader.test.tsx b/webapp/src/components/kanban/kanbanColumnHeader.test.tsx
new file mode 100644
index 000000000..7e6f7a3a9
--- /dev/null
+++ b/webapp/src/components/kanban/kanbanColumnHeader.test.tsx
@@ -0,0 +1,297 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+import React from 'react'
+import {fireEvent, render, screen, within} from '@testing-library/react'
+import {createIntl} from 'react-intl'
+import userEvent from '@testing-library/user-event'
+import {mocked} from 'ts-jest/utils'
+
+import Mutator from '../../mutator'
+import {wrapDNDIntl} from '../../testUtils'
+import {TestBlockFactory} from '../../test/testBlockFactory'
+import {IPropertyOption} from '../../blocks/board'
+
+import KanbanColumnHeader from './kanbanColumnHeader'
+jest.mock('../../mutator')
+const mockedMutator = mocked(Mutator, true)
+describe('src/components/kanban/kanbanColumnHeader', () => {
+ const intl = createIntl({locale: 'en-us'})
+ const board = TestBlockFactory.createBoard()
+ const activeView = TestBlockFactory.createBoardView(board)
+ const card = TestBlockFactory.createCard(board)
+ card.id = 'id1'
+ activeView.fields.kanbanCalculations = {
+ id1: {
+ calculation: 'countEmpty',
+ propertyId: '1',
+
+ },
+ }
+ const option:IPropertyOption = {
+ id: 'id1',
+ value: 'Title',
+ color: 'propColorDefault',
+ }
+ beforeAll(() => {
+ console.error = jest.fn()
+ })
+ beforeEach(jest.resetAllMocks)
+ test('should match snapshot', () => {
+ const {container} = render(wrapDNDIntl(
+ ,
+
+ ))
+ expect(container).toMatchSnapshot()
+ })
+ test('should match snapshot readonly', () => {
+ const {container} = render(wrapDNDIntl(
+ ,
+
+ ))
+ expect(container).toMatchSnapshot()
+ })
+ test('return kanbanColumnHeader and edit title', () => {
+ const mockedPropertyNameChanged = jest.fn()
+ const {container} = render(wrapDNDIntl(
+ ,
+
+ ))
+ const inputTitle = screen.getByRole('textbox', {name: option.value})
+ expect(inputTitle).toBeDefined()
+ fireEvent.change(inputTitle, {target: {value: ''}})
+ userEvent.type(inputTitle, 'New Title')
+ fireEvent.blur(inputTitle)
+ expect(mockedPropertyNameChanged).toBeCalledWith(option, 'New Title')
+ expect(container).toMatchSnapshot()
+ })
+ test('return kanbanColumnHeader and click on menuwrapper', () => {
+ const {container} = render(wrapDNDIntl(
+ ,
+
+ ))
+ const buttonMenuWrapper = screen.getByRole('button', {name: 'menuwrapper'})
+ expect(buttonMenuWrapper).toBeDefined()
+ userEvent.click(buttonMenuWrapper)
+ expect(container).toMatchSnapshot()
+ })
+ test('return kanbanColumnHeader, click on menuwrapper and click on hide menu', () => {
+ render(wrapDNDIntl(
+ ,
+
+ ))
+ const buttonMenuWrapper = screen.getByRole('button', {name: 'menuwrapper'})
+ expect(buttonMenuWrapper).toBeDefined()
+ userEvent.click(buttonMenuWrapper)
+ const buttonHide = within(buttonMenuWrapper).getByRole('button', {name: 'Hide'})
+ expect(buttonHide).toBeDefined()
+ userEvent.click(buttonHide)
+ expect(mockedMutator.hideViewColumn).toBeCalledTimes(1)
+ })
+ test('return kanbanColumnHeader, click on menuwrapper and click on delete menu', () => {
+ render(wrapDNDIntl(
+ ,
+
+ ))
+ const buttonMenuWrapper = screen.getByRole('button', {name: 'menuwrapper'})
+ expect(buttonMenuWrapper).toBeDefined()
+ userEvent.click(buttonMenuWrapper)
+ const buttonDelete = within(buttonMenuWrapper).getByRole('button', {name: 'Delete'})
+ expect(buttonDelete).toBeDefined()
+ userEvent.click(buttonDelete)
+ expect(mockedMutator.deletePropertyOption).toBeCalledTimes(1)
+ })
+ test('return kanbanColumnHeader, click on menuwrapper and click on blue color menu', () => {
+ render(wrapDNDIntl(
+ ,
+
+ ))
+ const buttonMenuWrapper = screen.getByRole('button', {name: 'menuwrapper'})
+ expect(buttonMenuWrapper).toBeDefined()
+ userEvent.click(buttonMenuWrapper)
+ const buttonBlueColor = within(buttonMenuWrapper).getByRole('button', {name: 'Select Blue Color'})
+ expect(buttonBlueColor).toBeDefined()
+ userEvent.click(buttonBlueColor)
+ expect(mockedMutator.changePropertyOptionColor).toBeCalledTimes(1)
+ })
+
+ test('return kanbanColumnHeader and click to add card', () => {
+ const mockedAddCard = jest.fn()
+ const {container} = render(wrapDNDIntl(
+ ,
+
+ ))
+ const buttonAddCard = container.querySelector('.AddIcon')?.parentElement
+ expect(buttonAddCard).toBeDefined()
+ userEvent.click(buttonAddCard!)
+ expect(mockedAddCard).toBeCalledTimes(1)
+ })
+ test('return kanbanColumnHeader and click KanbanCalculationMenu', () => {
+ const mockedCalculationMenuOpen = jest.fn()
+ render(wrapDNDIntl(
+ ,
+ ))
+ const buttonKanbanCalculation = screen.getByText(/0/i).parentElement
+ expect(buttonKanbanCalculation).toBeDefined()
+ userEvent.click(buttonKanbanCalculation!)
+ expect(mockedCalculationMenuOpen).toBeCalledTimes(1)
+ })
+ test('return kanbanColumnHeader and click count on KanbanCalculationMenu', () => {
+ render(wrapDNDIntl(
+ ,
+ ))
+ const menuCountEmpty = screen.getByText('Count')
+ expect(menuCountEmpty).toBeDefined()
+ userEvent.click(menuCountEmpty)
+ expect(mockedMutator.changeViewKanbanCalculations).toBeCalledTimes(1)
+ })
+})