From 8f1291a34d910428f40d104465887decc530acb7 Mon Sep 17 00:00:00 2001 From: mkzie2 Date: Fri, 3 Oct 2025 16:13:43 +0700 Subject: [PATCH 1/2] fix: Approver field becomes grayed out after going offline --- src/libs/actions/Workflow.ts | 2 +- tests/actions/WorkflowTest.ts | 129 ++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts index 547bf8ef0476..927aff1d0da7 100644 --- a/src/libs/actions/Workflow.ts +++ b/src/libs/actions/Workflow.ts @@ -98,7 +98,7 @@ function createApprovalWorkflow(policyID: string, approvalWorkflow: ApprovalWork onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null}])), + employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null, pendingFields: {submitsTo: null, forwardsTo: null}}])), }, }, ]; diff --git a/tests/actions/WorkflowTest.ts b/tests/actions/WorkflowTest.ts index 6e8314005ad8..f988e566c3a2 100644 --- a/tests/actions/WorkflowTest.ts +++ b/tests/actions/WorkflowTest.ts @@ -2,24 +2,36 @@ import Onyx from 'react-native-onyx'; import {INITIAL_APPROVAL_WORKFLOW} from '@libs/WorkflowUtils'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import {generatePolicyID} from '@src/libs/actions/Policy/Policy'; -import {clearApprovalWorkflowApprover, setApprovalWorkflowApprover} from '@src/libs/actions/Workflow'; +import {clearApprovalWorkflowApprover, createApprovalWorkflow, setApprovalWorkflowApprover} from '@src/libs/actions/Workflow'; import {calculateApprovers} from '@src/libs/WorkflowUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ApprovalWorkflowOnyx, Policy as PolicyType} from '@src/types/onyx'; +import type {ApprovalWorkflowOnyx, Policy, Policy as PolicyType} from '@src/types/onyx'; import type {Approver} from '@src/types/onyx/ApprovalWorkflow'; import createRandomPolicy from '../utils/collections/policies'; -import {getGlobalFetchMock} from '../utils/TestHelper'; +import {getGlobalFetchMock, getOnyxData} from '../utils/TestHelper'; import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; -jest.mock('@src/libs/WorkflowUtils', () => ({ - calculateApprovers: jest.fn(), -})); +jest.mock('@src/libs/WorkflowUtils', () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const actual = jest.requireActual('@src/libs/WorkflowUtils'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + ...actual, + calculateApprovers: jest.fn(), + } +}); const calculateApproversMock = calculateApprovers as jest.Mock; OnyxUpdateManager(); +const employee1Email = 'test1@gmail.com'; +const employee2Email = 'test2@gmail.com'; +const employee3Email = 'test3@gmail.com'; +const ownerEmail = 'owner@gmail.com'; + describe('actions/Workflow', () => { function getApprovalWorkflowState(): Promise { return new Promise((resolve) => { @@ -118,4 +130,109 @@ describe('actions/Workflow', () => { await waitForBatchedUpdates(); }); }); + + describe('createApprovalWorkflow', () => { + it('should clear pendingFields when the API is success', async () => { + mockFetch.pause(); + + const policy = { + "id": "123456789", + "name": "Mkzie2+bnmsn@gmail.com's Workspace", + "role": "admin", + "type": "corporate", + "owner": ownerEmail, + "employeeList": { + [ownerEmail]: { + "email": ownerEmail, + "forwardsTo": "", + "role": "admin", + "submitsTo": ownerEmail, + }, + [employee1Email]: { + "email": employee1Email, + "forwardsTo": "", + "role": "user", + "submitsTo": ownerEmail, + }, + [employee2Email]: { + "email": employee2Email, + "role": "user", + "submitsTo": ownerEmail, + "forwardsTo": "", + }, + [employee3Email]: { + "email": employee3Email, + "role": "user", + "submitsTo": ownerEmail, + "forwardsTo": "" + } + }, + + } as unknown as Policy; + + const approvalWorkflow = { + "members": [ + { + "displayName": employee1Email, + "email": employee1Email + } + ], + "approvers": [ + { + "email": employee1Email, + "displayName": employee1Email, + "isCircularReference": false + }, + { + "email": employee2Email, + "displayName": employee2Email, + "isCircularReference": false + } + ], + "availableMembers": [ + { + "email": ownerEmail, + "displayName": ownerEmail, + }, + { + "email": employee1Email, + "displayName": employee1Email, + }, + { + "email": employee2Email, + "displayName": employee2Email, + }, + { + "email": employee3Email, + "displayName": employee3Email, + } + ], + "usedApproverEmails": [ + ownerEmail + ], + "isDefault": false, + "action": "create", + "originalApprovers": [], + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); + await Onyx.merge(ONYXKEYS.SESSION, {authToken: '123456789'}); + await waitForBatchedUpdates(); + + createApprovalWorkflow(policy.id, approvalWorkflow); + await mockFetch.resume(); + + let updatedPolicy: Policy | undefined; + await getOnyxData({ + key: `${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, + callback: (val) => (updatedPolicy = val), + }) + + + expect(updatedPolicy?.employeeList?.[employee1Email]?.pendingFields).toBeUndefined(); + expect(updatedPolicy?.employeeList?.[employee2Email]?.pendingFields).toBeUndefined(); + }) + + + }) }); From f9245e43d58bde47c9af9bac1e0b0b2c9f71afd2 Mon Sep 17 00:00:00 2001 From: mkzie2 Date: Fri, 3 Oct 2025 16:32:44 +0700 Subject: [PATCH 2/2] run prettier --- src/libs/actions/Workflow.ts | 2 +- tests/actions/WorkflowTest.ts | 112 ++++++++++++++++------------------ 2 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts index 927aff1d0da7..639f427d5ea1 100644 --- a/src/libs/actions/Workflow.ts +++ b/src/libs/actions/Workflow.ts @@ -98,7 +98,7 @@ function createApprovalWorkflow(policyID: string, approvalWorkflow: ApprovalWork onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null, pendingFields: {submitsTo: null, forwardsTo: null}}])), + employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null, pendingFields: null}])), }, }, ]; diff --git a/tests/actions/WorkflowTest.ts b/tests/actions/WorkflowTest.ts index f988e566c3a2..b00e51b4924f 100644 --- a/tests/actions/WorkflowTest.ts +++ b/tests/actions/WorkflowTest.ts @@ -20,7 +20,7 @@ jest.mock('@src/libs/WorkflowUtils', () => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment ...actual, calculateApprovers: jest.fn(), - } + }; }); const calculateApproversMock = calculateApprovers as jest.Mock; @@ -136,83 +136,80 @@ describe('actions/Workflow', () => { mockFetch.pause(); const policy = { - "id": "123456789", - "name": "Mkzie2+bnmsn@gmail.com's Workspace", - "role": "admin", - "type": "corporate", - "owner": ownerEmail, - "employeeList": { + id: '123456789', + name: "Mkzie2+bnmsn@gmail.com's Workspace", + role: 'admin', + type: 'corporate', + owner: ownerEmail, + employeeList: { [ownerEmail]: { - "email": ownerEmail, - "forwardsTo": "", - "role": "admin", - "submitsTo": ownerEmail, + email: ownerEmail, + forwardsTo: '', + role: 'admin', + submitsTo: ownerEmail, }, [employee1Email]: { - "email": employee1Email, - "forwardsTo": "", - "role": "user", - "submitsTo": ownerEmail, + email: employee1Email, + forwardsTo: '', + role: 'user', + submitsTo: ownerEmail, }, [employee2Email]: { - "email": employee2Email, - "role": "user", - "submitsTo": ownerEmail, - "forwardsTo": "", + email: employee2Email, + role: 'user', + submitsTo: ownerEmail, + forwardsTo: '', }, [employee3Email]: { - "email": employee3Email, - "role": "user", - "submitsTo": ownerEmail, - "forwardsTo": "" - } + email: employee3Email, + role: 'user', + submitsTo: ownerEmail, + forwardsTo: '', + }, }, - } as unknown as Policy; const approvalWorkflow = { - "members": [ + members: [ { - "displayName": employee1Email, - "email": employee1Email - } + displayName: employee1Email, + email: employee1Email, + }, ], - "approvers": [ + approvers: [ { - "email": employee1Email, - "displayName": employee1Email, - "isCircularReference": false + email: employee1Email, + displayName: employee1Email, + isCircularReference: false, }, { - "email": employee2Email, - "displayName": employee2Email, - "isCircularReference": false - } + email: employee2Email, + displayName: employee2Email, + isCircularReference: false, + }, ], - "availableMembers": [ + availableMembers: [ { - "email": ownerEmail, - "displayName": ownerEmail, + email: ownerEmail, + displayName: ownerEmail, }, { - "email": employee1Email, - "displayName": employee1Email, + email: employee1Email, + displayName: employee1Email, }, { - "email": employee2Email, - "displayName": employee2Email, + email: employee2Email, + displayName: employee2Email, }, { - "email": employee3Email, - "displayName": employee3Email, - } - ], - "usedApproverEmails": [ - ownerEmail + email: employee3Email, + displayName: employee3Email, + }, ], - "isDefault": false, - "action": "create", - "originalApprovers": [], + usedApproverEmails: [ownerEmail], + isDefault: false, + action: 'create', + originalApprovers: [], }; await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); @@ -226,13 +223,10 @@ describe('actions/Workflow', () => { await getOnyxData({ key: `${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, callback: (val) => (updatedPolicy = val), - }) - + }); expect(updatedPolicy?.employeeList?.[employee1Email]?.pendingFields).toBeUndefined(); expect(updatedPolicy?.employeeList?.[employee2Email]?.pendingFields).toBeUndefined(); - }) - - - }) + }); + }); });