From 6678003def9e6dfe5228898d943a51c8388fad9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Fri, 18 Jul 2025 12:10:49 +0200 Subject: [PATCH] Fix progress numbers on playbook runs (#8998) * Fix progress numbers on playbook runs * Update checkList for checklist --- .../playbook_run/checklist/checklist.test.tsx | 118 +++--------------- .../playbook_run/checklist/checklist.tsx | 9 +- .../playbook_run/checklist/index.test.tsx | 18 +++ .../screens/playbook_run/checklist/index.ts | 8 ++ 4 files changed, 50 insertions(+), 103 deletions(-) diff --git a/app/products/playbooks/screens/playbook_run/checklist/checklist.test.tsx b/app/products/playbooks/screens/playbook_run/checklist/checklist.test.tsx index 2cf7e7556..ffbff4eca 100644 --- a/app/products/playbooks/screens/playbook_run/checklist/checklist.test.tsx +++ b/app/products/playbooks/screens/playbook_run/checklist/checklist.test.tsx @@ -49,11 +49,20 @@ describe('Checklist', () => { playbookRunId: 'run-id-1', isFinished: false, isParticipant: true, + checklistProgress: { + skipped: false, + completed: 0, + totalNumber: 0, + progress: 0, + }, }; } it('renders checklist header correctly', () => { const props = getBaseProps(); + props.checklistProgress.completed = 1; + props.checklistProgress.totalNumber = 2; + const {getByText} = renderWithIntl(); expect(getByText('Test Checklist')).toBeTruthy(); @@ -93,40 +102,16 @@ describe('Checklist', () => { it('shows correct progress for completed and skippeditems', () => { const props = getBaseProps(); - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: 'closed', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: 'closed', - }), - ]; + props.checklistProgress.completed = 2; + props.checklistProgress.totalNumber = 2; const {getByText, rerender} = renderWithIntl(); expect(getByText('2 / 2 done')).toBeTruthy(); - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: 'closed', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: '', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-3', - title: 'Item 3', - state: 'skipped', - }), - ]; + props.checklistProgress.completed = 1; + props.checklistProgress.totalNumber = 2; + rerender(); expect(getByText('1 / 2 done')).toBeTruthy(); @@ -220,23 +205,7 @@ describe('Checklist', () => { it('passes the correct props to the ProgressBar', () => { const props = getBaseProps(); props.isFinished = false; - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: '', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: '', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-3', - title: 'Item 3', - state: '', - }), - ]; + props.checklistProgress.progress = 0; const {getByTestId, rerender} = renderWithIntl(); @@ -245,67 +214,14 @@ describe('Checklist', () => { expect(progressBar.props.isActive).toBe(true); props.isFinished = true; - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: 'closed', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: '', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-3', - title: 'Item 3', - state: '', - }), - ]; - rerender(); + props.checklistProgress.progress = 50; - expect(progressBar.props.progress).toBe(33); - expect(progressBar.props.isActive).toBe(false); - - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: 'closed', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: 'skipped', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-3', - title: 'Item 3', - state: '', - }), - ]; rerender(); expect(progressBar.props.progress).toBe(50); expect(progressBar.props.isActive).toBe(false); - props.items = [ - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-1', - title: 'Item 1', - state: 'closed', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-2', - title: 'Item 2', - state: 'skipped', - }), - TestHelper.fakePlaybookChecklistItemModel({ - id: 'item-3', - title: 'Item 3', - state: 'closed', - }), - ]; + props.checklistProgress.progress = 100; rerender(); expect(progressBar.props.progress).toBe(100); diff --git a/app/products/playbooks/screens/playbook_run/checklist/checklist.tsx b/app/products/playbooks/screens/playbook_run/checklist/checklist.tsx index 840ecee3d..55cac37a5 100644 --- a/app/products/playbooks/screens/playbook_run/checklist/checklist.tsx +++ b/app/products/playbooks/screens/playbook_run/checklist/checklist.tsx @@ -71,6 +71,7 @@ type Props = { playbookRunId: string; isFinished: boolean; isParticipant: boolean; + checklistProgress: ReturnType; } const Checklist = ({ @@ -81,6 +82,12 @@ const Checklist = ({ playbookRunId, isFinished, isParticipant, + checklistProgress: { + skipped, + completed, + totalNumber, + progress, + }, }: Props) => { const [expanded, setExpanded] = useState(true); const theme = useTheme(); @@ -88,8 +95,6 @@ const Checklist = ({ const height = useSharedValue(0); const windowDimensions = useWindowDimensions(); - const {skipped, completed, totalNumber, progress} = useMemo(() => getChecklistProgress(items), [items]); - const toggleExpanded = useCallback(() => { setExpanded((prev) => !prev); }, []); diff --git a/app/products/playbooks/screens/playbook_run/checklist/index.test.tsx b/app/products/playbooks/screens/playbook_run/checklist/index.test.tsx index b9ee8446d..5106b1fcc 100644 --- a/app/products/playbooks/screens/playbook_run/checklist/index.test.tsx +++ b/app/products/playbooks/screens/playbook_run/checklist/index.test.tsx @@ -4,6 +4,7 @@ import React, {type ComponentProps} from 'react'; import DatabaseManager from '@database/manager'; +import {getChecklistProgress} from '@playbooks/utils/progress'; import {renderWithEverything, waitFor} from '@test/intl-test-helper'; import TestHelper from '@test/test_helper'; @@ -20,10 +21,20 @@ jest.mocked(ChecklistComponent).mockImplementation( (props) => React.createElement('Checklist', {testID: 'checklist', ...props}), ); +jest.mock('@playbooks/utils/progress'); + const serverUrl = 'server-url'; describe('Checklist', () => { const checklistId = 'checklist-id'; + const mockProgressReturn = { + skipped: false, + completed: 0, + totalNumber: 0, + progress: 0, + }; + + jest.mocked(getChecklistProgress).mockReturnValue(mockProgressReturn); let database: Database; let operator: ServerDataOperator; @@ -65,6 +76,8 @@ describe('Checklist', () => { expect(checklist).toBeTruthy(); expect(checklist.props.checklist).toBe(props.checklist); expect(checklist.props.items).toBe(props.checklist.items); + expect(checklist.props.checklistProgress).toBe(mockProgressReturn); + expect(getChecklistProgress).toHaveBeenCalledWith(props.checklist.items); }); }); @@ -105,6 +118,11 @@ describe('Checklist', () => { expect(checklist.props.checklist.id).toBe(props.checklist.id); expect(checklist.props.items[0].id).toBe(itemsIds[1]); expect(checklist.props.items[1].id).toBe(itemsIds[0]); + expect(checklist.props.checklistProgress).toBe(mockProgressReturn); + expect(getChecklistProgress).toHaveBeenCalledWith([ + expect.objectContaining({id: itemsIds[1]}), + expect.objectContaining({id: itemsIds[0]}), + ]); database.write(async () => { if ('update' in props.checklist) { diff --git a/app/products/playbooks/screens/playbook_run/checklist/index.ts b/app/products/playbooks/screens/playbook_run/checklist/index.ts index 6c35b6e96..b9a748df4 100644 --- a/app/products/playbooks/screens/playbook_run/checklist/index.ts +++ b/app/products/playbooks/screens/playbook_run/checklist/index.ts @@ -5,6 +5,7 @@ import {withDatabase, withObservables} from '@nozbe/watermelondb/react'; import {combineLatest, distinctUntilChanged, of as of$, switchMap} from 'rxjs'; import {areItemsOrdersEqual} from '@playbooks/utils/items_order'; +import {getChecklistProgress} from '@playbooks/utils/progress'; import Checklist from './checklist'; @@ -39,15 +40,22 @@ const enhanced = withObservables(['checklist'], ({checklist}: OwnProps) => { }), distinctUntilChanged((a, b) => areItemsOrdersEqual(getIds(a), getIds(b))), ); + + const checklistProgress = items.pipe( + switchMap((i) => of$(getChecklistProgress(i))), + ); + return { checklist: observedChecklist, items: sortedItems, + checklistProgress, }; } return { checklist: of$(checklist), items: of$(checklist.items), + checklistProgress: of$(getChecklistProgress(checklist.items)), }; });