diff --git a/__tests__/Unit/Components/Tasks/FilterModal.test.tsx b/__tests__/Unit/Components/Tasks/FilterDropdown.test.tsx similarity index 88% rename from __tests__/Unit/Components/Tasks/FilterModal.test.tsx rename to __tests__/Unit/Components/Tasks/FilterDropdown.test.tsx index 53c020799..d2fac2583 100644 --- a/__tests__/Unit/Components/Tasks/FilterModal.test.tsx +++ b/__tests__/Unit/Components/Tasks/FilterDropdown.test.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { Tab } from '@/interfaces/task.type'; -import FilterModal from '@/components/tasks/TaskSearch/FilterModal'; +import FilterDropdown from '@/components/tasks/TaskSearch/FilterDropdown'; const mockOnSelect = jest.fn(); const mockOnClose = jest.fn(); -describe('FilterModal', () => { +describe('FilterDropdown', () => { test('renders the modal with correct title and buttons', () => { render( - { test('renders the modal having overdue tab with correct title and buttons', () => { render( - { expect(overdueButton).toBeInTheDocument(); }); - test('renders the modal with correct title and buttons when dev is true', () => { + test('renders the modal with correct title and buttons', () => { render( - { test('calls onSelect and onClose when a status button is clicked', () => { render( - { test('calls onClose when the close button is clicked', () => { render( - { }); test('calls onClose when clicked on outside', () => { render( - ); @@ -138,12 +136,11 @@ describe('FilterModal', () => { }); test('calls onClose when escape button is clicked', () => { render( - ); @@ -154,7 +151,7 @@ describe('FilterModal', () => { test('renders the modal with correct active tab', () => { render( - { expect(inProgressButton).not.toHaveClass('status-button-active'); }); - test('renders the modal with correct active tab when dev is true', () => { + test('renders the modal with correct active tab', () => { render( - { expect(unassignedButton).not.toHaveClass('status-button-active'); }); - test('render the filter model having BACKLOG tab with correct title and buttons when dev is true', () => { + test('render the filter model having BACKLOG tab with correct title and buttons', () => { render( - { expect(backlogButton).toBeInTheDocument(); }); - test('onSelect Function Gets Called When the Backlog Status button is Clicked when dev is true', () => { + test('onSelect Function Gets Called When the Backlog Status button is Clicked', () => { render( - { expect(mockOnSelect).toHaveBeenCalledWith(Tab.BACKLOG); }); - test('Selection of the Backlog Button when dev is true', () => { + test('Selection of the Backlog Button', () => { render( - { const mockOnClickHandler = jest.fn(); diff --git a/__tests__/Unit/Components/Tasks/Options.test.tsx b/__tests__/Unit/Components/Tasks/Options.test.tsx index c3badfb9b..7d8fe4e89 100644 --- a/__tests__/Unit/Components/Tasks/Options.test.tsx +++ b/__tests__/Unit/Components/Tasks/Options.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { render, fireEvent } from '@testing-library/react'; -import Options from '@/components/tasks/TaskSearchDev/Suggestion/Options'; +import Options from '@/components/tasks/TaskSearch/Suggestion/Options'; import { TaskSearchOption } from '@/interfaces/searchOptions.type'; describe('Option component', () => { diff --git a/__tests__/Unit/Components/Tasks/Pill.test.tsx b/__tests__/Unit/Components/Tasks/Pill.test.tsx index 7b9e73c41..f697ef1de 100644 --- a/__tests__/Unit/Components/Tasks/Pill.test.tsx +++ b/__tests__/Unit/Components/Tasks/Pill.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import RenderPills, { PillProps, -} from '@/components/tasks/TaskSearchDev/Suggestion/Pill'; +} from '@/components/tasks/TaskSearch/Suggestion/Pill'; describe('RenderPills', () => { const setNewPillValue = jest.fn(); diff --git a/__tests__/Unit/Components/Tasks/TaskDates.test.tsx b/__tests__/Unit/Components/Tasks/TaskDates.test.tsx new file mode 100644 index 000000000..2c507b7c6 --- /dev/null +++ b/__tests__/Unit/Components/Tasks/TaskDates.test.tsx @@ -0,0 +1,28 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { TaskDates } from '@/components/taskDetails/TaskDates'; + +const mockSetNewEndOnDate = jest.fn(); +const mockHandleBlurOfEndsOn = jest.fn(); + +describe('TaskDates Component', () => { + it('should render input field for End On date when in editing mode', () => { + render( + + ); + + const input = screen.getByTestId('endsOnTaskDetails'); + expect(input).toBeInTheDocument(); + fireEvent.blur(input); + expect(mockHandleBlurOfEndsOn).toHaveBeenCalled(); + }); +}); diff --git a/__tests__/Unit/Components/Tasks/TaskDependency.test.tsx b/__tests__/Unit/Components/Tasks/TaskDependency.test.tsx deleted file mode 100644 index a1a300776..000000000 --- a/__tests__/Unit/Components/Tasks/TaskDependency.test.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import React from 'react'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { renderWithRouter } from '@/test_utils/createMockRouter'; -import TaskDependency from '@/components/taskDetails/taskDependency'; -import { taskDetailsHandler } from '../../../../__mocks__/handlers/task-details.handler'; -import { filterTaskHandler } from '../../../../__mocks__/handlers/tasks.handler'; -import { setupServer } from 'msw/node'; -import { Provider } from 'react-redux'; -import { store } from '@/app/store'; -import { TaskDependencyIds } from '../../../../__mocks__/db/tasks'; -import { useGetAllTasksQuery } from '@/app/services/tasksApi'; - -const setEditedTaskDetails = jest.fn(); -const mockNavigateToTask = jest.fn(); - -jest.mock('@/app/services/tasksApi'); -const mockedUseGetAllTasksQuery = useGetAllTasksQuery as jest.MockedFunction< - typeof useGetAllTasksQuery ->; - -describe('TaskDependency', () => { - const server = setupServer(...taskDetailsHandler); - beforeAll(() => server.listen()); - afterEach(() => server.resetHandlers()); - afterAll(() => server.close()); - - it('should select/unselect a task when checkbox is clicked', async () => { - mockedUseGetAllTasksQuery.mockReturnValue({ - data: { - tasks: [ - { id: 'task1', title: 'Test Task 1' }, - { id: 'task2', title: 'Test Task 2' }, - ], - }, - isLoading: false, - isError: false, - refetch: jest.fn(), - }); - const { container } = renderWithRouter( - - - - ); - const checkboxes = container.querySelectorAll('input[type="checkbox"]'); - const firstCheckbox = checkboxes[0] as HTMLInputElement; - expect(firstCheckbox.checked).toBe(false); - fireEvent.click(firstCheckbox); - await waitFor(() => { - expect(firstCheckbox.checked).toBe(true); - }); - fireEvent.click(firstCheckbox); - await waitFor(() => { - expect(firstCheckbox.checked).toBe(false); - }); - }); - - it('should render loading state when searching for tasks', async () => { - server.use(filterTaskHandler); - const { getByText } = renderWithRouter( - - - - ); - const loadingText = await waitFor(() => getByText('Loading...')); - expect(loadingText).toBeInTheDocument(); - }); - - it('should render DependencyList when isEditing is false', async () => { - const { queryByRole, getByTestId } = renderWithRouter( - - - , - { push: mockNavigateToTask } - ); - - const textarea = queryByRole('textbox'); - expect(textarea).toBeNull(); - - await waitFor(() => { - const dependencyList = getByTestId('dependency-list'); - expect(dependencyList).toBeInTheDocument(); - }); - }); -}); diff --git a/__tests__/Unit/Components/Tasks/TaskDescription.test.tsx b/__tests__/Unit/Components/Tasks/TaskDescription.test.tsx new file mode 100644 index 000000000..c2b8363a3 --- /dev/null +++ b/__tests__/Unit/Components/Tasks/TaskDescription.test.tsx @@ -0,0 +1,55 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { TaskDescription } from '@/components/taskDetails/TaskDescription'; + +const mockHandleChange = jest.fn(); + +describe('TaskDescription Component', () => { + it('should renders the task description when not editing', () => { + render( + + ); + expect(screen.getByText('Test Purpose')).toBeInTheDocument(); + }); + + it('should renders "No description available" when purpose is empty', () => { + render( + + ); + expect( + screen.getByText('No description available') + ).toBeInTheDocument(); + }); + + it('should renders textarea when in editing mode', () => { + render( + + ); + expect(screen.getByTestId('purpose-textarea')).toBeInTheDocument(); + }); + + it('should calls handleChange when textarea value changes', () => { + render( + + ); + fireEvent.change(screen.getByTestId('purpose-textarea'), { + target: { value: 'New Purpose' }, + }); + expect(mockHandleChange).toHaveBeenCalled(); + }); +}); diff --git a/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx b/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx new file mode 100644 index 000000000..fb79a3caa --- /dev/null +++ b/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx @@ -0,0 +1,97 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import { TaskDetailsSection } from '@/components/taskDetails/TaskDetailsSection'; +import '@testing-library/jest-dom/extend-expect'; +import { TASK } from '../../../../__mocks__/db/tasks'; +import { useRouter } from 'next/router'; +import { api } from '@/app/services/api'; + +jest.mock('next/router', () => ({ + useRouter: jest.fn(), +})); + +const createMockStore = () => { + return configureStore({ + reducer: { + user: (state = { roles: {} }) => state, + [api.reducerPath]: api.reducer, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(api.middleware), + }); +}; + +describe('TaskDetailsSection Component', () => { + const mockHandleTaskStatusUpdate = jest.fn(); + const mockRouter = { + query: { dev: true }, + }; + + beforeEach(() => { + (useRouter as jest.Mock).mockReturnValue(mockRouter); + }); + + const defaultProps = { + isEditing: false, + type: TASK.type, + priority: TASK.priority, + status: TASK.status, + link: TASK.featureUrl, + percentCompleted: TASK.percentCompleted, + handleTaskStatusUpdate: mockHandleTaskStatusUpdate, + taskDetailsData: TASK, + }; + + it('should render task details correctly when not in editing mode', () => { + render( + + + + ); + + expect(screen.getByText(TASK.type)).toBeInTheDocument(); + expect(screen.getByText(TASK.priority)).toBeInTheDocument(); + expect(screen.getByText(TASK.status)).toBeInTheDocument(); + + const linkElement = screen.getByRole('link', { + name: /open github issue/i, + }); + expect(linkElement).toHaveAttribute('href', TASK.featureUrl); + }); + + it('should render task status dropdown when in editing mode', () => { + render( + + + + ); + expect(screen.getByRole('combobox')).toBeInTheDocument(); + expect(screen.queryByText(TASK.status)).toBeNull(); + }); + + it('should call handleTaskStatusUpdate when task status is changed', () => { + render( + + + + ); + const dropdown = screen.getByRole('combobox'); + fireEvent.change(dropdown, { target: { value: 'DONE' } }); + + expect(mockHandleTaskStatusUpdate).toHaveBeenCalledWith({ + newStatus: 'DONE', + }); + }); + + it('should render progress container correctly', () => { + render( + + + + ); + expect( + screen.getByText(`${TASK.percentCompleted}%`) + ).toBeInTheDocument(); + }); +}); diff --git a/__tests__/Unit/Components/Tasks/TaskHeader.test.tsx b/__tests__/Unit/Components/Tasks/TaskHeader.test.tsx new file mode 100644 index 000000000..bda23da68 --- /dev/null +++ b/__tests__/Unit/Components/Tasks/TaskHeader.test.tsx @@ -0,0 +1,61 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { TaskHeader } from '@/components/taskDetails/TaskHeader'; +import { ButtonProps } from '@/interfaces/taskDetails.type'; + +const mockSetIsEditing = jest.fn(); +const mockOnSave = jest.fn(); +const mockOnCancel = jest.fn(); +const mockHandleChange = jest.fn(); + +const renderTaskHeader = (isEditing = false) => { + return render( + + ); +}; + +describe('TaskHeader Component', () => { + it('should renders the task title correctly when not editing', () => { + renderTaskHeader(false); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'Edit' }) + ).toBeInTheDocument(); + }); + + it('should renders textarea for title when in editing mode', () => { + renderTaskHeader(true); + expect(screen.getByTestId('title-textarea')).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'Save' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'Cancel' }) + ).toBeInTheDocument(); + }); + + it('should calls setIsEditing with true when Edit button is clicked', () => { + renderTaskHeader(false); + fireEvent.click(screen.getByRole('button', { name: 'Edit' })); + expect(mockSetIsEditing).toHaveBeenCalledWith(true); + }); + + it('should calls onSave when Save button is clicked', () => { + renderTaskHeader(true); + fireEvent.click(screen.getByRole('button', { name: 'Save' })); + expect(mockOnSave).toHaveBeenCalled(); + }); + + it('should calls onCancel when Cancel button is clicked', () => { + renderTaskHeader(true); + fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + expect(mockOnCancel).toHaveBeenCalled(); + }); +}); diff --git a/__tests__/Unit/Components/Tasks/TaskParticipants.test.tsx b/__tests__/Unit/Components/Tasks/TaskParticipants.test.tsx new file mode 100644 index 000000000..d0e9c6fc9 --- /dev/null +++ b/__tests__/Unit/Components/Tasks/TaskParticipants.test.tsx @@ -0,0 +1,49 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { TaskParticipants } from '@/components/taskDetails/TaskParticipants'; +import { Provider } from 'react-redux'; +import { store } from '@/app/store'; + +const mockHandleAssignment = jest.fn(); +const mockHandleAssigneSelect = jest.fn(); +const mockSetShowSuggestion = jest.fn(); + +const renderWithProvider = (ui: React.ReactElement) => { + return render({ui}); +}; + +describe('TaskParticipants Component', () => { + it('should render the assignee name correctly when not editing', () => { + renderWithProvider( + + ); + + expect(screen.getByText('John Doe')).toBeInTheDocument(); + }); + + it('should render the Suggestions component when editing', () => { + renderWithProvider( + + ); + + const input = screen.getByRole('textbox'); + expect(input).toBeInTheDocument(); + fireEvent.change(input, { target: { value: 'Jane Doe' } }); + expect(mockHandleAssignment).toHaveBeenCalled(); + }); +}); diff --git a/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx b/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx index 341af2a53..20fa47cde 100644 --- a/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx +++ b/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx @@ -1,7 +1,5 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import TaskSearch from '@/components/tasks/TaskSearch/TaskSearch'; -import { Tab } from '@/interfaces/task.type'; -import TaskSearchDev from '@/components/tasks/TaskSearchDev/TaskSearchDev'; import { Provider } from 'react-redux'; import { store } from '@/app/store'; @@ -18,54 +16,14 @@ jest.mock('@/app/services/usersApi', () => ({ })); describe('TaskSearch', () => { - test('renders the search input', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - - const searchInput = screen.getByTestId('search-input'); - expect(searchInput).toBeInTheDocument(); - }); - - test('calls onClickSearchButton when Search button is clicked', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - const searchInput = screen.getByTestId('search-input'); - fireEvent.change(searchInput, { target: { value: 'is:active' } }); - const searchButton = screen.getByText('Search'); - fireEvent.click(searchButton); - expect(onClickSearchButton).toHaveBeenCalledTimes(1); - }); - test('opens the filter modal when the Filter button is clicked', () => { const onSelect = jest.fn(); - const onInputChange = jest.fn(); const onClickSearchButton = jest.fn(); render( ); @@ -76,71 +34,31 @@ describe('TaskSearch', () => { expect(modalTitle).toBeInTheDocument(); }); - test('calls onInputChange when the search input value changes', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - - const searchInput = screen.getByTestId('search-input'); - fireEvent.change(searchInput, { target: { value: 'is:merged' } }); - expect(onInputChange).toHaveBeenCalledWith('is:merged'); - }); - - test('calls onInputChange when the search input value changes when dev is true', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - - const searchInput = screen.getByTestId('search-input'); - fireEvent.change(searchInput, { target: { value: 'is:done' } }); - expect(onInputChange).toHaveBeenCalledWith('is:done'); - }); - test('calls onSelect when the any one filter button is clicked', () => { const onSelect = jest.fn(); - const onInputChange = jest.fn(); const onClickSearchButton = jest.fn(); render( ); const filterButton = screen.getByText('Filter'); fireEvent.click(filterButton); - const assignedButton = screen.getByText(/assigned/i); + const assignedButton = screen.getByText('ASSIGNED'); fireEvent.click(assignedButton); expect(onSelect).toHaveBeenCalledWith('ASSIGNED'); }); - test('calls onSelect when the any one filter button is clicked and dev is true', () => { + test('calls onSelect when the any one filter button is clicked', () => { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); render( - { expect(onSelect).toHaveBeenCalledWith('UNASSIGNED'); }); - test('calls onClickSearchButton when enter key is pressed', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - - const searchInput = screen.getByTestId('search-input'); - fireEvent.change(searchInput, { target: { value: 'is:merged' } }); - fireEvent.keyDown(searchInput, { key: 'Enter', code: 'Enter' }); - expect(onClickSearchButton).toBeCalled(); - }); - - test('Should not display status:all in search bar in dev mode', () => { + test('Should not display status:all in search bar', () => { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); render( - { expect(onSelect).toHaveBeenCalledWith('ALL'); expect(screen.queryByText('status:all')).not.toBeInTheDocument(); }); - test('Should display status:all in search bar', () => { - const onSelect = jest.fn(); - const onInputChange = jest.fn(); - const onClickSearchButton = jest.fn(); - - render( - - ); - - const filterButton = screen.getByText('Filter'); - fireEvent.click(filterButton); - const blockedButton = screen.getByRole('button', { name: /all/i }); - fireEvent.click(blockedButton); - expect(onSelect).toHaveBeenCalledWith('ALL'); - expect(screen.getByDisplayValue('status:all')).toBeInTheDocument(); - }); }); describe('Multi select task search in dev mode', () => { @@ -226,7 +102,7 @@ describe('Multi select task search in dev mode', () => { test('renders search input with empty string if dev mode is enabled', () => { render( - { const { getByTestId } = render( - { const onClickSearchButton = jest.fn(); render( - { const { getByTestId } = render( - { const onClickSearchButton = jest.fn(); const { getByTestId } = render( - { test('should generate suggestion once clicked on option pill', async () => { const { getByTestId } = render( - { const onClickSearchButton = jest.fn(); const { getByTestId } = render( - { test('should discard changes and set focus back to input if escape is pressed', async () => { const { getByTestId } = render( - { test('should take 2 backspaces to remove a pill, if pressed in an empty input field', async () => { render( - { test('should delete the pill if entire value of its is cleared', async () => { const { getByTestId } = render( - { test('should be able to traverse between options through arrow keys', async () => { render( - { test('should be able to select options using ENTER key', async () => { const { getByTestId } = render( - { test('should fetch tasks if ENTER is pressed', async () => { render( - { it('should remove pill from UI if clicked on delete button', () => { render( - { test('should discard changes made in pill and set focus back to input if clicked outside of pill', async () => { const { getByTestId } = render( - { const onClickSearchButton = jest.fn(); const { getByTestId } = render( - { const onClickSearchButton = jest.fn(); render( - { const onClickSearchButton = jest.fn(); const { getByTestId } = render( - { global.dispatchEvent(new Event('resize')); }; - test('renders tabs component', async () => { - setWindowInnerWidth(breakpointToShowTabs); - - renderWithRouter( - - - - ); - - expect(screen.getByText(/loading/i)).toBeInTheDocument(); - - await screen.findByTestId('tabs'); - }); - - test('select tab and set active', async () => { - setWindowInnerWidth(breakpointToShowTabs); - renderWithRouter( - - - , - { - query: { section: 'unassigned' }, - } - ); - await screen.findByTestId('tabs'); - const tabsContainer = within( - screen.getByTestId('status-tabs-container') - ); - const assignedButton = tabsContainer.getByRole('button', { - name: 'UNASSIGNED', - }); - expect(assignedButton).toHaveTextContent('UNASSIGNED'); - await screen.findByText(NO_TASKS_FOUND_MESSAGE); - expect(screen.getByText(NO_TASKS_FOUND_MESSAGE)).toBeInTheDocument(); - }); - test('displays "No tasks found" message when there are no tasks', async () => { server.use(noTasksFoundHandler); const { findByText } = renderWithRouter( @@ -108,124 +72,6 @@ describe('tasks content', () => { expect(task).toBeInTheDocument(); }); - test('Selecting a tab pushes into query params', async () => { - setWindowInnerWidth(breakpointToShowTabs); - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { push: mockPushFunction } - ); - - await screen.findByTestId('tabs'); - const tabsContainer = within( - screen.getByTestId('status-tabs-container') - ); - const inProgressBtn = tabsContainer.getByRole('button', { - name: /IN PROGRESS/i, - }); - expect(inProgressBtn).toHaveClass('tabButton'); - const unassignedButton = tabsContainer.getByRole('button', { - name: /UNASSIGNED/i, - }); - fireEvent.click(unassignedButton); - expect(mockPushFunction).toBeCalledTimes(1); - expect(mockPushFunction).toBeCalledWith({ - query: { - q: 'status:available', - }, - }); - }); - - test('should show status-tabs-container after 450px of screen width', async () => { - setWindowInnerWidth(breakpointToShowTabs); - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { push: mockPushFunction } - ); - - await screen.findByTestId('tabs'); - const tabsContainer = screen.getByTestId('status-tabs-container'); - const tabStyles = getComputedStyle(tabsContainer); - expect(tabStyles.display).toBe('block'); - }); - - test('should show status-select-container 450px below status-tabs-container', async () => { - setWindowInnerWidth(breakpointToShowSelect); - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { push: mockPushFunction } - ); - await screen.findByTestId('status-select-container'); - const selectContainer = screen.getByTestId('status-select-container'); - const selectStyles = getComputedStyle(selectContainer); - - expect(selectStyles.display).toBe('block'); - }); - - test('Selecting a value from dropdown pushes into query params', async () => { - setWindowInnerWidth(breakpointToShowSelect); - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { push: mockPushFunction } - ); - - await screen.findByTestId('status-select-container'); - const selectContainer = screen?.getByTestId( - 'selected-option-container' - ); - - fireEvent.click(selectContainer); - fireEvent.keyDown(selectContainer, { - key: 'ArrowDown', - code: 'ArrowDown', - }); - - fireEvent.keyDown(selectContainer, { - key: 'Enter', - code: 'Enter', - }); - - expect(mockPushFunction).toBeCalledTimes(1); - expect(mockPushFunction).toBeCalledWith({ - query: { - q: 'status:in-progress', - }, - }); - }); - - test('searchButtonHandler when search button is clicked', async () => { - setWindowInnerWidth(breakpointToShowTabs); - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { push: mockPushFunction } - ); - - const searchButton = await screen.findByTestId('search-button'); - fireEvent.click(searchButton); - await waitFor(() => { - expect(mockPushFunction).toBeCalledTimes(1); - }); - expect(mockPushFunction).toBeCalledWith({ - query: { - q: 'status:all', - }, - }); - }); - test('setInputValue when input value is changed', async () => { setWindowInnerWidth(breakpointToShowTabs); const mockPushFunction = jest.fn(); @@ -239,34 +85,4 @@ describe('tasks content', () => { fireEvent.change(searchInput, { target: { value: 'test' } }); expect(searchInput).toHaveValue('test'); }); - - test('Query param should be changed when tab is selected', async () => { - const mockPushFunction = jest.fn(); - renderWithRouter( - - - , - { - push: mockPushFunction, - query: { - q: 'status:all assignee:satyam Add', - }, - } - ); - - await screen.findByTestId('tabs'); - const tabsContainer = within( - screen.getByTestId('status-tabs-container') - ); - const assignedButton = tabsContainer.getByRole('button', { - name: 'ASSIGNED', - }); - fireEvent.click(assignedButton); - expect(mockPushFunction).toBeCalledTimes(1); - expect(mockPushFunction).toBeCalledWith({ - query: { - q: 'status:assigned assignee:satyam Add', - }, - }); - }); }); diff --git a/src/components/taskDetails/TaskDates.tsx b/src/components/taskDetails/TaskDates.tsx new file mode 100644 index 000000000..d04ee30f5 --- /dev/null +++ b/src/components/taskDetails/TaskDates.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import Details from './Details'; +import styles from './task-details.module.scss'; +import { TASK_EXTENSION_REQUEST_URL } from '@/constants/url'; +import convertTimeStamp from '@/helperFunctions/convertTimeStamp'; + +interface TaskDatesProps { + isEditing: boolean; + isUserAuthorized: boolean; + startedOn: string; + endsOn: number; + newEndOnDate: string; + setNewEndOnDate: (date: string) => void; + handleBlurOfEndsOn: () => void; + isExtensionRequestPending: boolean; + taskId: string; +} + +export const TaskDates: React.FC = ({ + isEditing, + isUserAuthorized, + startedOn, + endsOn, + newEndOnDate, + setNewEndOnDate, + handleBlurOfEndsOn, + isExtensionRequestPending, + taskId, +}) => { + const formattedEndsOn = endsOn ? convertTimeStamp(endsOn) : 'TBD'; + + return ( + <> +
+
+
+
+ {isExtensionRequestPending && ( +
+ )} + {!isExtensionRequestPending && ( +
+ )} + {isEditing && isUserAuthorized && ( + setNewEndOnDate(e.target.value)} + onBlur={handleBlurOfEndsOn} + value={newEndOnDate} + data-testid="endsOnTaskDetails" + className={styles.inputField} + /> + )} +
+ + ); +}; diff --git a/src/components/taskDetails/TaskDescription.tsx b/src/components/taskDetails/TaskDescription.tsx new file mode 100644 index 000000000..66318b26b --- /dev/null +++ b/src/components/taskDetails/TaskDescription.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Textarea } from './index'; +import styles from './task-details.module.scss'; + +interface TaskDescriptionProps { + isEditing: boolean; + purpose: string; + handleChange: (event: React.ChangeEvent) => void; +} + +export const TaskDescription: React.FC = ({ + isEditing, + purpose, + handleChange, +}) => { + if (isEditing) { + return ( +