Fix progress numbers on playbook runs (#8998)

* Fix progress numbers on playbook runs

* Update checkList for checklist
This commit is contained in:
Daniel Espino García 2025-07-18 12:10:49 +02:00 committed by GitHub
parent 5a034aa51f
commit 6678003def
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 103 deletions

View file

@ -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(<Checklist {...props}/>);
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(<Checklist {...props}/>);
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(<Checklist {...props}/>);
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(<Checklist {...props}/>);
@ -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(<Checklist {...props}/>);
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(<Checklist {...props}/>);
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(<Checklist {...props}/>);
expect(progressBar.props.progress).toBe(100);

View file

@ -71,6 +71,7 @@ type Props = {
playbookRunId: string;
isFinished: boolean;
isParticipant: boolean;
checklistProgress: ReturnType<typeof getChecklistProgress>;
}
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);
}, []);

View file

@ -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) {

View file

@ -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)),
};
});