Skip to content

Commit

Permalink
Merge pull request #23457 from neonbhai/23221-onyxMigrationForPreviou…
Browse files Browse the repository at this point in the history
…sReportActionID

Onyx Migration for checkPreviousReportActionID
  • Loading branch information
roryabraham authored Aug 8, 2023
2 parents c91d5fd + 6608631 commit c08d588
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
67 changes: 67 additions & 0 deletions src/libs/migrations/CheckForPreviousReportActionID.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import _ from 'underscore';
import Onyx from 'react-native-onyx';
import Log from '../Log';
import ONYXKEYS from '../../ONYXKEYS';

/**
* @returns {Promise<Object>}
*/
function getReportActionsFromOnyx() {
return new Promise((resolve) => {
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
return resolve(allReportActions);
},
});
});
}

/**
* This migration checks for the 'previousReportActionID' key in the first valid reportAction of a report in Onyx.
* If the key is not found then all reportActions for all reports are removed from Onyx.
*
* @returns {Promise<void>}
*/
export default function () {
return getReportActionsFromOnyx().then((allReportActions) => {
if (_.isEmpty(allReportActions)) {
Log.info(`[Migrate Onyx] Skipped migration CheckForPreviousReportActionID because there were no reportActions`);
return;
}

let firstValidValue;
_.some(_.values(allReportActions), (reportActions) =>
_.some(_.values(reportActions), (reportActionData) => {
if (_.has(reportActionData, 'reportActionID')) {
firstValidValue = reportActionData;
return true;
}

return false;
}),
);

if (_.isUndefined(firstValidValue)) {
Log.info(`[Migrate Onyx] Skipped migration CheckForPreviousReportActionID because there were no valid reportActions`);
return;
}

if (_.has(firstValidValue, 'previousReportActionID')) {
Log.info(`[Migrate Onyx] CheckForPreviousReportActionID Migration: previousReportActionID found. Migration complete`);
return;
}

// If previousReportActionID not found:
Log.info(`[Migrate Onyx] CheckForPreviousReportActionID Migration: removing all reportActions because previousReportActionID not found in the first valid reportAction`);

const onyxData = {};
_.each(allReportActions, (reportAction, onyxKey) => {
onyxData[onyxKey] = {};
});

return Onyx.multiSet(onyxData);
});
}
171 changes: 171 additions & 0 deletions tests/unit/MigrationTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import AddLastVisibleActionCreated from '../../src/libs/migrations/AddLastVisibl
import MoveToIndexedDB from '../../src/libs/migrations/MoveToIndexedDB';
import KeyReportActionsByReportActionID from '../../src/libs/migrations/KeyReportActionsByReportActionID';
import PersonalDetailsByAccountID from '../../src/libs/migrations/PersonalDetailsByAccountID';
import CheckForPreviousReportActionID from '../../src/libs/migrations/CheckForPreviousReportActionID';
import ONYXKEYS from '../../src/ONYXKEYS';

jest.mock('../../src/libs/getPlatform');
Expand Down Expand Up @@ -639,4 +640,174 @@ describe('Migrations', () => {
});
}));
});

describe('CheckForPreviousReportActionID', () => {
it("Should work even if there's no reportAction data in Onyx", () =>
CheckForPreviousReportActionID().then(() =>
expect(LogSpy).toHaveBeenCalledWith('[Migrate Onyx] Skipped migration CheckForPreviousReportActionID because there were no reportActions'),
));

it('Should remove all report actions given that a previousReportActionID does not exist', () =>
Onyx.multiSet({
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: {
1: {
reportActionID: 1,
},
2: {
reportActionID: 2,
},
},
})
.then(CheckForPreviousReportActionID)
.then(() => {
expect(LogSpy).toHaveBeenCalledWith(
'[Migrate Onyx] CheckForPreviousReportActionID Migration: removing all reportActions because previousReportActionID not found in the first valid reportAction',
);
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction = {};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction);
},
});
}));

it('Should not remove any report action given that previousReportActionID exists in first valid report action', () =>
Onyx.multiSet({
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: {
1: {
reportActionID: 1,
previousReportActionID: 0,
},
2: {
reportActionID: 2,
previousReportActionID: 1,
},
},
})
.then(CheckForPreviousReportActionID)
.then(() => {
expect(LogSpy).toHaveBeenCalledWith('[Migrate Onyx] CheckForPreviousReportActionID Migration: previousReportActionID found. Migration complete');
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction = {
1: {
reportActionID: 1,
previousReportActionID: 0,
},
2: {
reportActionID: 2,
previousReportActionID: 1,
},
};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction);
},
});
}));

it('Should skip zombie report actions and proceed to remove all reportActions given that a previousReportActionID does not exist', () =>
Onyx.multiSet({
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: {},
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]: null,
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]: null,
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]: {
1: {
reportActionID: 1,
},
2: {
reportActionID: 2,
},
},
})
.then(CheckForPreviousReportActionID)
.then(() => {
expect(LogSpy).toHaveBeenCalledWith(
'[Migrate Onyx] CheckForPreviousReportActionID Migration: removing all reportActions because previousReportActionID not found in the first valid reportAction',
);
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction = {};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toMatchObject(expectedReportAction);
},
});
}));

it('Should skip zombie report actions and should not remove any report action given that previousReportActionID exists in first valid report action', () =>
Onyx.multiSet({
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: {},
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]: null,
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]: null,
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]: {
1: {
reportActionID: 1,
previousReportActionID: 10,
},
2: {
reportActionID: 2,
previousReportActionID: 23,
},
},
})
.then(CheckForPreviousReportActionID)
.then(() => {
expect(LogSpy).toHaveBeenCalledWith('[Migrate Onyx] CheckForPreviousReportActionID Migration: previousReportActionID found. Migration complete');
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction1 = {};
const expectedReportAction4 = {
1: {
reportActionID: 1,
previousReportActionID: 10,
},
2: {
reportActionID: 2,
previousReportActionID: 23,
},
};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toMatchObject(expectedReportAction1);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toBeNull();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toBeNull();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toMatchObject(expectedReportAction4);
},
});
}));

it('Should skip if no valid reportActions', () =>
Onyx.multiSet({
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: null,
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]: {},
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]: {},
[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]: null,
})
.then(CheckForPreviousReportActionID)
.then(() => {
expect(LogSpy).toHaveBeenCalledWith('[Migrate Onyx] Skipped migration CheckForPreviousReportActionID because there were no valid reportActions');
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (allReportActions) => {
Onyx.disconnect(connectionID);
const expectedReportAction = {};
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]).toBeNull();
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]).toMatchObject(expectedReportAction);
expect(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]).toBeNull();
},
});
}));
});
});

0 comments on commit c08d588

Please sign in to comment.