Skip to content

Commit

Permalink
Merge pull request Expensify#50258 from callstack-internal/gedu/openA…
Browse files Browse the repository at this point in the history
…pp_conflict_resolver

[NoQA] Request conflict resolution for OpenApp
  • Loading branch information
mountiny authored Oct 11, 2024
2 parents 096e25c + 4fd3707 commit e4969b2
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 18 deletions.
23 changes: 5 additions & 18 deletions src/libs/actions/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {OnyxData} from '@src/types/onyx/Request';
import {setShouldForceOffline} from './Network';
import * as PersistedRequests from './PersistedRequests';
import * as Policy from './Policy/Policy';
import resolveDuplicationConflictAction from './RequestConflictUtils';
import * as Session from './Session';
import Timing from './Timing';

Expand Down Expand Up @@ -255,7 +256,9 @@ function getOnyxDataForOpenOrReconnect(isOpenApp = false): OnyxData {
function openApp() {
return getPolicyParamsForOpenOrReconnect().then((policyParams: PolicyParamsForOpenOrReconnect) => {
const params: OpenAppParams = {enablePriorityModeFilter: true, ...policyParams};
return API.write(WRITE_COMMANDS.OPEN_APP, params, getOnyxDataForOpenOrReconnect(true));
return API.write(WRITE_COMMANDS.OPEN_APP, params, getOnyxDataForOpenOrReconnect(true), {
checkAndFixConflictingRequest: (persistedRequests) => resolveDuplicationConflictAction(persistedRequests, WRITE_COMMANDS.OPEN_APP),
});
});
}

Expand Down Expand Up @@ -284,23 +287,7 @@ function reconnectApp(updateIDFrom: OnyxEntry<number> = 0) {
}

API.write(WRITE_COMMANDS.RECONNECT_APP, params, getOnyxDataForOpenOrReconnect(), {
checkAndFixConflictingRequest: (persistedRequests) => {
const index = persistedRequests.findIndex((request) => request.command === WRITE_COMMANDS.RECONNECT_APP);
if (index === -1) {
return {
conflictAction: {
type: 'push',
},
};
}

return {
conflictAction: {
type: 'replace',
index,
},
};
},
checkAndFixConflictingRequest: (persistedRequests) => resolveDuplicationConflictAction(persistedRequests, WRITE_COMMANDS.RECONNECT_APP),
});
});
}
Expand Down
30 changes: 30 additions & 0 deletions src/libs/actions/RequestConflictUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type {WriteCommand} from '@libs/API/types';
import type OnyxRequest from '@src/types/onyx/Request';
import type {ConflictActionData} from '@src/types/onyx/Request';

/**
* Resolves duplication conflicts between persisted requests and a given command.
*
* This method checks if a specific command exists within a list of persisted requests.
* - If the command is not found, it suggests adding the command to the list, indicating a 'push' action.
* - If the command is found, it suggests updating the existing entry, indicating a 'replace' action at the found index.
*/
function resolveDuplicationConflictAction(persistedRequests: OnyxRequest[], commandToFind: WriteCommand): ConflictActionData {
const index = persistedRequests.findIndex((request) => request.command === commandToFind);
if (index === -1) {
return {
conflictAction: {
type: 'push',
},
};
}

return {
conflictAction: {
type: 'replace',
index,
},
};
}

export default resolveDuplicationConflictAction;
37 changes: 37 additions & 0 deletions tests/actions/SessionTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,41 @@ describe('Session', () => {

expect(PersistedRequests.getAll().length).toBe(0);
});

test('OpenApp should push request to the queue', async () => {
await TestHelper.signInWithTestUser();
await Onyx.set(ONYXKEYS.NETWORK, {isOffline: true});

App.openApp();

await waitForBatchedUpdates();

expect(PersistedRequests.getAll().length).toBe(1);
expect(PersistedRequests.getAll().at(0)?.command).toBe(WRITE_COMMANDS.OPEN_APP);

await Onyx.set(ONYXKEYS.NETWORK, {isOffline: false});

await waitForBatchedUpdates();

expect(PersistedRequests.getAll().length).toBe(0);
});

test('OpenApp should replace same requests from the queue', async () => {
await TestHelper.signInWithTestUser();
await Onyx.set(ONYXKEYS.NETWORK, {isOffline: true});

App.openApp();
App.openApp();
App.openApp();
App.openApp();

await waitForBatchedUpdates();

expect(PersistedRequests.getAll().length).toBe(1);
expect(PersistedRequests.getAll().at(0)?.command).toBe(WRITE_COMMANDS.OPEN_APP);

await Onyx.set(ONYXKEYS.NETWORK, {isOffline: false});

expect(PersistedRequests.getAll().length).toBe(0);
});
});
21 changes: 21 additions & 0 deletions tests/unit/RequestConflictUtilsTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import resolveDuplicationConflictAction from '@libs/actions/RequestConflictUtils';
import type {WriteCommand} from '@libs/API/types';

describe('RequestConflictUtils', () => {
it.each([['OpenApp'], ['ReconnectApp']])('resolveDuplicationConflictAction when %s do not exist in the queue should push %i', (command) => {
const persistedRequests = [{command: 'OpenReport'}, {command: 'AddComment'}, {command: 'CloseAccount'}];
const commandToFind = command as WriteCommand;
const result = resolveDuplicationConflictAction(persistedRequests, commandToFind);
expect(result).toEqual({conflictAction: {type: 'push'}});
});

it.each([
['OpenApp', 0],
['ReconnectApp', 2],
])('resolveDuplicationConflictAction when %s exist in the queue should replace at index %i', (command, index) => {
const persistedRequests = [{command: 'OpenApp'}, {command: 'AddComment'}, {command: 'ReconnectApp'}];
const commandToFind = command as WriteCommand;
const result = resolveDuplicationConflictAction(persistedRequests, commandToFind);
expect(result).toEqual({conflictAction: {type: 'replace', index}});
});
});

0 comments on commit e4969b2

Please sign in to comment.