From 068eb2838052f8dcea54d9d2844107d817a9127e Mon Sep 17 00:00:00 2001 From: Shubham Sharma Date: Mon, 9 Sep 2024 21:39:20 +0530 Subject: [PATCH 1/3] Reverted done status release --- __mocks__/handlers/task-details.handler.ts | 57 +++++++++++-- __tests__/Unit/Components/Tabs/Tab.test.tsx | 27 +++--- .../Components/Tasks/FilterDropdown.test.tsx | 82 +++++++++++++------ .../Components/Tasks/TaskDetails.test.tsx | 41 +++++++--- .../Tasks/TaskDetailsSection.test.tsx | 4 +- .../Unit/Components/Tasks/TaskSearch.test.tsx | 53 ++++++------ .../Tasks/TaskStatusEditMode.test.tsx | 2 +- .../taskDetails/TaskDetailsSection.tsx | 13 ++- src/components/tasks/TaskDropDown.tsx | 2 +- .../tasks/TaskSearch/FilterDropdown.tsx | 11 ++- src/interfaces/task.type.ts | 2 +- src/utils/getChangedStatusName.ts | 6 +- 12 files changed, 207 insertions(+), 93 deletions(-) diff --git a/__mocks__/handlers/task-details.handler.ts b/__mocks__/handlers/task-details.handler.ts index ec40f93b9..51062be60 100644 --- a/__mocks__/handlers/task-details.handler.ts +++ b/__mocks__/handlers/task-details.handler.ts @@ -2,6 +2,48 @@ import { rest } from 'msw'; const URL = process.env.NEXT_PUBLIC_BASE_URL; const taskDetailsHandler = [ + rest.get(`${URL}/tasks/12345/details`, (_, res, ctx) => { + try { + return res( + ctx.status(200), + ctx.json({ + message: 'task returned successfully', + taskData: { + id: '12345', + isNoteworthy: true, + lossRate: { + dinero: 0, + neelam: 0, + }, + purpose: 'This is a sample description', + endsOn: 1618790410, + title: 'test 1 for drag and drop', + status: 'COMPLETED', + assignee: 'ankur', + links: [], + dependsOn: [], + percentCompleted: 0, + type: 'feature', + priority: 'high', + featureUrl: 'https://www.sampleUrl.com', + startedOn: 1617062400, + completionAward: { + neelam: 0, + dinero: 110, + }, + github: { + issue: { + html_url: + 'https://github.com/sample-org/sample-repo/issues/000', + }, + }, + }, + }) + ); + } catch (error) { + return res(ctx.status(500), ctx.json({ error })); + } + }), rest.get(`${URL}/tasks/6KhcLU3yr45dzjQIVm0J/details`, (_, res, ctx) => { return res( ctx.status(200), @@ -19,8 +61,8 @@ const taskDetailsHandler = [ title: 'test 1 for drag and drop', status: 'assigned', assignee: 'ankur', - links: ['null'], - dependsOn: ['null'], + links: [], + dependsOn: [], percentCompleted: 0, type: 'feature', priority: 'high', @@ -32,9 +74,10 @@ const taskDetailsHandler = [ }, github: { issue: { - html_url:'https://github.com/sample-org/sample-repo/issues/000' - } - } + html_url: + 'https://github.com/sample-org/sample-repo/issues/000', + }, + }, }, }) ); @@ -55,8 +98,8 @@ const taskDetailsHandler = [ title: 'test 1 for drag and drop', status: 'assigned', assignee: 'ankur', - links: ['null'], - dependsOn: ['null'], + links: [], + dependsOn: [], percentCompleted: 0, type: 'feature', priority: 'high', diff --git a/__tests__/Unit/Components/Tabs/Tab.test.tsx b/__tests__/Unit/Components/Tabs/Tab.test.tsx index 4684516dd..6123d7c69 100644 --- a/__tests__/Unit/Components/Tabs/Tab.test.tsx +++ b/__tests__/Unit/Components/Tabs/Tab.test.tsx @@ -1,17 +1,16 @@ import Tabs from '@/components/Tabs'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, screen } from '@testing-library/react'; import { Tab, TABS, depreciatedTaskStatus, newTaskStatus, } from '@/interfaces/task.type'; -import { COMPLETED, DONE, AVAILABLE, UNASSIGNED } from '@/constants/constants'; +import { AVAILABLE, UNASSIGNED } from '@/constants/constants'; +import { renderWithRouter } from '@/test_utils/createMockRouter'; function changeName(name: string) { - if (name === COMPLETED) { - return DONE; - } else if (name === AVAILABLE) { + if (name === AVAILABLE) { return UNASSIGNED; } else { return name.split('_').join(' '); @@ -22,7 +21,7 @@ describe('Tabs Component', () => { const onSelectMock = jest.fn(); it('should render all the buttons', () => { - render( + renderWithRouter( { }); it('should render all the buttons when dev is true', () => { - render( + renderWithRouter( { }); it('check if selectTab() is called with right key', () => { - render( + renderWithRouter( { }); it('check if selectTab() is called with right key when dev is true', () => { - render( + renderWithRouter( { }); it('Check if correct button is selected', () => { - render( + renderWithRouter( ); - const completedBtn = screen.getByRole('button', { name: /DONE/i }); + const completedBtn = screen.getByRole('button', { name: /COMPLETED/i }); expect(completedBtn).toHaveClass('active'); }); it('Check if correct button is selected when dev is true', () => { - render( + renderWithRouter( { }); it('should render all tabs passed with correct text', () => { - render( + renderWithRouter( { }); it('should render all tabs passed with correct text when dev is true', () => { - render( + renderWithRouter( { test('renders the modal with correct title and buttons', () => { - render( + renderWithRouter( { }); test('renders the modal having overdue tab with correct title and buttons', () => { - render( + renderWithRouter( { }); test('renders the modal with correct title and buttons', () => { - render( + renderWithRouter( { const unassignedButton = screen.getByText(/unassigned/i); expect(unassignedButton).toBeInTheDocument(); - const doneButton = screen.getByText(/done/i); - expect(doneButton).toBeInTheDocument(); + const completedButton = screen.getByText(/completed/i); + expect(completedButton).toBeInTheDocument(); }); test('calls onSelect and onClose when a status button is clicked', () => { - render( + renderWithRouter( { }); test('calls onClose when the close button is clicked', () => { - render( + renderWithRouter( { expect(mockOnClose).toBeCalled(); }); test('calls onClose when clicked on outside', () => { - render( + renderWithRouter( { expect(mockOnClose).toBeCalled(); }); test('calls onClose when escape button is clicked', () => { - render( + renderWithRouter( { }); test('renders the modal with correct active tab', () => { - render( + renderWithRouter( { }); test('renders the modal with correct active tab', () => { - render( + renderWithRouter( ); - const doneButton = screen.getByText(/done/i); - expect(doneButton).toHaveClass('status-button-active'); + const completedButton = screen.getByText(/completed/i); + expect(completedButton).toHaveClass('status-button-active'); const unassignedButton = screen.getByText(/unassigned/i); expect(unassignedButton).not.toHaveClass('status-button-active'); }); test('render the filter model having BACKLOG tab with correct title and buttons', () => { - render( + renderWithRouter( { }); test('onSelect Function Gets Called When the Backlog Status button is Clicked', () => { - render( + renderWithRouter( { }); test('Selection of the Backlog Button', () => { - render( + renderWithRouter( { const backlogButton = screen.getByText(/backlog/i); expect(backlogButton).toHaveClass('status-button-active'); - const doneButton = screen.getByText(/done/i); - expect(doneButton).not.toHaveClass('status-button-active'); + const completedButton = screen.getByText(/completed/i); + expect(completedButton).not.toHaveClass('status-button-active'); + }); + + it('Renders Task tab Done, when dev flag is on', async () => { + renderWithRouter( + , + { + query: { dev: 'true' }, + } + ); + + const doneButton = screen.queryByText(/done/i); + const completedButton = screen.queryByText(/completed/i); + + expect(doneButton).toBeInTheDocument(); + expect(completedButton).toBeNull(); + }); + it('Renders Task status Completed, when dev flag is not on', async () => { + renderWithRouter( + + ); + const doneButton = screen.queryByText(/done/i); + const completedButton = screen.queryByText(/completed/i); + + expect(completedButton).toBeInTheDocument(); + expect(doneButton).toBeNull(); }); }); diff --git a/__tests__/Unit/Components/Tasks/TaskDetails.test.tsx b/__tests__/Unit/Components/Tasks/TaskDetails.test.tsx index 14a1f86f5..3ba9acd95 100644 --- a/__tests__/Unit/Components/Tasks/TaskDetails.test.tsx +++ b/__tests__/Unit/Components/Tasks/TaskDetails.test.tsx @@ -1,13 +1,4 @@ -import { - fireEvent, - queryByText, - render, - screen, - waitFor, - queryAllByText, - act, -} from '@testing-library/react'; -import { Router, useRouter } from 'next/router'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import TaskDetails, { Button, Textarea } from '@/components/taskDetails'; import TaskContainer from '@/components/taskDetails/TaskContainer'; import task from '@/interfaces/task.type'; @@ -21,15 +12,14 @@ import { ButtonProps, TextAreaProps } from '@/interfaces/taskDetails.type'; import { ToastContainer } from 'react-toastify'; import * as progressQueries from '@/app/services/progressesApi'; import Details from '@/components/taskDetails/Details'; -import { taskRequestErrorHandler } from '../../../../__mocks__/handlers/task-request.handler'; import { taskDetailsHandler } from '../../../../__mocks__/handlers/task-details.handler'; import { superUserSelfHandler } from '../../../../__mocks__/handlers/self.handler'; -import convertTimeStamp from '@/helperFunctions/convertTimeStamp'; const details = { url: 'https://realdevsquad.com/tasks/6KhcLU3yr45dzjQIVm0J/details', taskID: '6KhcLU3yr45dzjQIVm0J', extension_request_url: 'https://dashboard.realdevsquad.com/extension-requests?order=asc&q=taskId%3AzlwjJzKbGpqCoCTZMZQy', + completedTaskID: '12345', }; const server = setupServer(...handlers); @@ -224,6 +214,33 @@ describe('TaskDetails Page', () => { expect(getByText('ankur')).toBeInTheDocument(); }); }); + it('Renders Task status Done when task status is Completed, when dev flag is on', async () => { + const { getByText } = renderWithRouter( + + + , + { query: { dev: 'true' } } + ); + await waitFor(() => { + expect(getByText('Done')).toBeInTheDocument(); + }); + }); + it('Renders Task status Done as selected when task status is Completed, when dev flag is on in edit mode', async () => { + renderWithRouter( + + + , + { query: { dev: 'true' } } + ); + await waitFor(() => { + const editButton = screen.getByRole('button', { name: 'Edit' }); + fireEvent.click(editButton); + }); + const option: HTMLOptionElement = screen.getByTestId( + 'task-status-DONE' + ) as HTMLOptionElement; + expect(option.selected).toBeTruthy(); + }); }); it('Renders Task Ends-on Date', async () => { const { getAllByText } = renderWithRouter( diff --git a/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx b/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx index fb79a3caa..35179622b 100644 --- a/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx +++ b/__tests__/Unit/Components/Tasks/TaskDetailsSection.test.tsx @@ -77,10 +77,10 @@ describe('TaskDetailsSection Component', () => { ); const dropdown = screen.getByRole('combobox'); - fireEvent.change(dropdown, { target: { value: 'DONE' } }); + fireEvent.change(dropdown, { target: { value: 'IN_PROGRESS' } }); expect(mockHandleTaskStatusUpdate).toHaveBeenCalledWith({ - newStatus: 'DONE', + newStatus: 'IN_PROGRESS', }); }); diff --git a/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx b/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx index 20fa47cde..67e162ddb 100644 --- a/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx +++ b/__tests__/Unit/Components/Tasks/TaskSearch.test.tsx @@ -1,7 +1,8 @@ -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { screen, fireEvent, waitFor } from '@testing-library/react'; import TaskSearch from '@/components/tasks/TaskSearch/TaskSearch'; import { Provider } from 'react-redux'; import { store } from '@/app/store'; +import { renderWithRouter } from '@/test_utils/createMockRouter'; jest.mock('@/utils/getChangedStatusName', () => ({ getChangedStatusName: jest.fn((tab) => tab), @@ -20,7 +21,7 @@ describe('TaskSearch', () => { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { const onInputChange = jest.fn(); const onClickSearchButton = jest.fn(); test('renders search input with empty string if dev mode is enabled', () => { - render( + renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { test('should display suggestions based on typed key through user input', async () => { const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { const onSelect = jest.fn(); const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { }); test('should generate suggestion once clicked on option pill', async () => { - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { test('should set focus back to input if clicked in surrounding of it', async () => { const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { expect(searchInput).toHaveFocus(); }); test('should discard changes and set focus back to input if escape is pressed', async () => { - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { expect(suggestions).toBeNull(); }); test('should take 2 backspaces to remove a pill, if pressed in an empty input field', async () => { - render( + renderWithRouter( { expect(searchInput).toHaveFocus(); }); test('should delete the pill if entire value of its is cleared', async () => { - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { expect(isPillPresent).toBeNull(); }); test('should be able to traverse between options through arrow keys', async () => { - render( + renderWithRouter( { ); }); test('should be able to select options using ENTER key', async () => { - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { ); }); test('should fetch tasks if ENTER is pressed', async () => { - render( + renderWithRouter( { expect(suggestions).toBeNull(); }); it('should remove pill from UI if clicked on delete button', () => { - render( + renderWithRouter( { expect(searchInput).toHaveFocus(); }); test('should discard changes made in pill and set focus back to input if clicked outside of pill', async () => { - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { }); test('should be able to update pill value through keyboard', async () => { const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + renderWithRouter( { /> ); - const pillContent = getByTestId('pill-content'); + const pillContent = screen.getByTestId('pill-content'); fireEvent.click(pillContent); - const pillInput = getByTestId('pill-input'); + const pillInput = screen.getByTestId('pill-input'); fireEvent.change(pillInput, { target: { value: 'status:assigned' }, }); @@ -440,7 +441,7 @@ describe('Multi select task search in dev mode', () => { await waitFor( () => { fireEvent.keyDown(pillInput, { key: 'Enter', code: 'Enter' }); - const pillContent = getByTestId('pill-content'); + const pillContent = screen.getByTestId('pill-content'); expect(pillContent).toBeInTheDocument(); expect(pillContent).toHaveTextContent('status:assigned'); }, @@ -449,7 +450,7 @@ describe('Multi select task search in dev mode', () => { }); test('should display suggestions even if white space is present at the end', async () => { const onClickSearchButton = jest.fn(); - render( + renderWithRouter( { test('should be able to close suggestions if input is out of focus', async () => { const onClickSearchButton = jest.fn(); - const { getByTestId } = render( + const { getByTestId } = renderWithRouter( { const allTaskStatus = Object.entries(BACKEND_TASK_STATUS) .map(([name, status]) => [status, beautifyStatus(name)]) - .filter(([status]) => status !== 'BACKLOG'); + .filter(([status]) => status !== 'BACKLOG' && status !== 'DONE'); expect(allOptions).toEqual(allTaskStatus); }); diff --git a/src/components/taskDetails/TaskDetailsSection.tsx b/src/components/taskDetails/TaskDetailsSection.tsx index 8194d0e3b..31bc0d89a 100644 --- a/src/components/taskDetails/TaskDetailsSection.tsx +++ b/src/components/taskDetails/TaskDetailsSection.tsx @@ -4,6 +4,8 @@ import TaskDropDown from '../tasks/TaskDropDown'; import ProgressContainer from '../tasks/card/progressContainer'; import task, { taskStatusUpdateHandleProp } from '@/interfaces/task.type'; import styles from './task-details.module.scss'; +import { beautifyStatus } from '../tasks/card/TaskStatusEditMode'; +import { useRouter } from 'next/router'; interface TaskDetailsSectionProps { isEditing: boolean; @@ -26,6 +28,10 @@ export const TaskDetailsSection: React.FC = ({ handleTaskStatusUpdate, taskDetailsData, }) => { + const router = useRouter(); + + const { dev } = router.query; + const isDevMode = dev === 'true'; return (
@@ -35,9 +41,14 @@ export const TaskDetailsSection: React.FC = ({ onChange={handleTaskStatusUpdate} oldStatus={status} oldProgress={percentCompleted} + isDevMode={isDevMode} + key={status} /> ) : ( -
+
)}
!(isDevMode && key === 'COMPLETED') && - !(!isDevMode && key === 'BACKLOG') + !(!isDevMode && (key === 'BACKLOG' || key === 'DONE')) ); const isCurrentTaskStatusBlock = oldStatus === BACKEND_TASK_STATUS.BLOCKED; diff --git a/src/components/tasks/TaskSearch/FilterDropdown.tsx b/src/components/tasks/TaskSearch/FilterDropdown.tsx index 4b97f3cc5..880e7c9a2 100644 --- a/src/components/tasks/TaskSearch/FilterDropdown.tsx +++ b/src/components/tasks/TaskSearch/FilterDropdown.tsx @@ -1,6 +1,7 @@ import styles from './tasksearch.module.scss'; import { Tab, depreciatedTaskStatus } from '@/interfaces/task.type'; import { getChangedStatusName } from '@/utils/getChangedStatusName'; +import { useRouter } from 'next/router'; import { useEffect } from 'react'; type FilterModalProps = { @@ -24,6 +25,9 @@ const FilterDropdown = ({ return () => document.removeEventListener('keydown', onKeyDownHandler); }, []); + const router = useRouter(); + const isDevMode = router.query.dev === 'true'; + return ( <>
{tabs .filter( - (tab: Tab) => !depreciatedTaskStatus.includes(tab) + (tab: Tab) => + !depreciatedTaskStatus.includes(tab) && + !( + (isDevMode && tab === 'COMPLETED') || + (!isDevMode && tab === 'DONE') + ) ) .map((tab) => (