Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make OpenApp a write command #37062

Merged
merged 6 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const WRITE_COMMANDS = {
SET_WORKSPACE_APPROVAL_MODE: 'SetWorkspaceApprovalMode',
DISMISS_REFERRAL_BANNER: 'DismissReferralBanner',
UPDATE_PREFERRED_LOCALE: 'UpdatePreferredLocale',
OPEN_APP: 'OpenApp',
RECONNECT_APP: 'ReconnectApp',
OPEN_PROFILE: 'OpenProfile',
HANDLE_RESTRICTED_EVENT: 'HandleRestrictedEvent',
Expand Down Expand Up @@ -158,6 +159,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.DISMISS_REFERRAL_BANNER]: Parameters.DismissReferralBannerParams;
[WRITE_COMMANDS.UPDATE_PREFERRED_LOCALE]: Parameters.UpdatePreferredLocaleParams;
[WRITE_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams;
[WRITE_COMMANDS.OPEN_APP]: Parameters.OpenAppParams;
[WRITE_COMMANDS.OPEN_PROFILE]: Parameters.OpenProfileParams;
[WRITE_COMMANDS.HANDLE_RESTRICTED_EVENT]: Parameters.HandleRestrictedEventParams;
[WRITE_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams;
Expand Down Expand Up @@ -301,7 +303,6 @@ type WriteCommandParameters = {
};

const READ_COMMANDS = {
OPEN_APP: 'OpenApp',
OPEN_REIMBURSEMENT_ACCOUNT_PAGE: 'OpenReimbursementAccountPage',
OPEN_WORKSPACE_VIEW: 'OpenWorkspaceView',
GET_MAPBOX_ACCESS_TOKEN: 'GetMapboxAccessToken',
Expand Down Expand Up @@ -335,7 +336,6 @@ const READ_COMMANDS = {
type ReadCommand = ValueOf<typeof READ_COMMANDS>;

type ReadCommandParameters = {
[READ_COMMANDS.OPEN_APP]: Parameters.OpenAppParams;
[READ_COMMANDS.OPEN_REIMBURSEMENT_ACCOUNT_PAGE]: Parameters.OpenReimbursementAccountPageParams;
[READ_COMMANDS.OPEN_WORKSPACE_VIEW]: Parameters.OpenWorkspaceViewParams;
[READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN]: EmptyObject;
Expand Down
4 changes: 2 additions & 2 deletions src/libs/HttpUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {RequestType} from '@src/types/onyx/Request';
import type Response from '@src/types/onyx/Response';
import * as NetworkActions from './actions/Network';
import * as UpdateRequired from './actions/UpdateRequired';
import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS} from './API/types';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from './API/types';
import * as ApiUtils from './ApiUtils';
import HttpsError from './Errors/HttpsError';

Expand All @@ -31,7 +31,7 @@ let cancellationController = new AbortController();
/**
* The API commands that require the skew calculation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably unrelated, but I am completely confused about what a "skew calculation" refers to here. I see these changes, but did not have an opportunity to make sense of them yet.

*/
const addSkewList: string[] = [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, READ_COMMANDS.OPEN_APP];
const addSkewList: string[] = [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, WRITE_COMMANDS.OPEN_APP];

/**
* Regex to get API command from the command
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Middleware/SaveResponseInOnyx.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as MemoryOnlyKeys from '@userActions/MemoryOnlyKeys/MemoryOnlyKeys';
import * as OnyxUpdates from '@userActions/OnyxUpdates';
import CONST from '@src/CONST';
Expand All @@ -7,7 +7,7 @@ import type Middleware from './types';

// If we're executing any of these requests, we don't need to trigger our OnyxUpdates flow to update the current data even if our current value is out of
// date because all these requests are updating the app to the most current state.
const requestsToIgnoreLastUpdateID: string[] = [READ_COMMANDS.OPEN_APP, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, SIDE_EFFECT_REQUEST_COMMANDS.GET_MISSING_ONYX_MESSAGES];
const requestsToIgnoreLastUpdateID: string[] = [WRITE_COMMANDS.OPEN_APP, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, SIDE_EFFECT_REQUEST_COMMANDS.GET_MISSING_ONYX_MESSAGES];

const SaveResponseInOnyx: Middleware = (requestResponse, request) =>
requestResponse.then((response = {}) => {
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Network/NetworkStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Onyx from 'react-native-onyx';
import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import ONYXKEYS from '@src/ONYXKEYS';
import type Credentials from '@src/types/onyx/Credentials';

Expand Down Expand Up @@ -96,7 +96,7 @@ function getAuthToken(): string | null {
}

function isSupportRequest(command: string): boolean {
return [READ_COMMANDS.OPEN_APP, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT].some((cmd) => cmd === command);
return [WRITE_COMMANDS.OPEN_APP, SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP, SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT].some((cmd) => cmd === command);
}

function getSupportAuthToken(): string | null {
Expand Down
4 changes: 2 additions & 2 deletions src/libs/actions/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
ReconnectAppParams,
UpdatePreferredLocaleParams,
} from '@libs/API/parameters';
import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as Browser from '@libs/Browser';
import DateUtils from '@libs/DateUtils';
import Log from '@libs/Log';
Expand Down Expand Up @@ -211,7 +211,7 @@ function openApp() {
getPolicyParamsForOpenOrReconnect().then((policyParams: PolicyParamsForOpenOrReconnect) => {
const params: OpenAppParams = {enablePriorityModeFilter: true, ...policyParams};

API.read(READ_COMMANDS.OPEN_APP, params, getOnyxDataForOpenOrReconnect(true));
API.write(WRITE_COMMANDS.OPEN_APP, params, getOnyxDataForOpenOrReconnect(true));
});
}

Expand Down
25 changes: 12 additions & 13 deletions tests/unit/NetworkTest.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Onyx from 'react-native-onyx';
import _ from 'underscore';
import CONST from '../../src/CONST';
import * as App from '../../src/libs/actions/App';
import OnyxUpdateManager from '../../src/libs/actions/OnyxUpdateManager';
import * as PersistedRequests from '../../src/libs/actions/PersistedRequests';
import * as PersonalDetails from '../../src/libs/actions/PersonalDetails';
import * as Session from '../../src/libs/actions/Session';
import HttpUtils from '../../src/libs/HttpUtils';
import Log from '../../src/libs/Log';
Expand Down Expand Up @@ -101,8 +101,7 @@ describe('NetworkTests', () => {
);

// This should first trigger re-authentication and then a Failed to fetch
App.confirmReadyToOpenApp();
App.openApp();
PersonalDetails.openPersonalDetails();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see we just picked a flow arbitrarily to confirm the re-auth behavior? Looks good!

return waitForBatchedUpdates()
.then(() => Onyx.set(ONYXKEYS.NETWORK, {isOffline: false}))
.then(() => {
Expand All @@ -113,11 +112,11 @@ describe('NetworkTests', () => {
return waitForBatchedUpdates();
})
.then(() => {
// Then we will eventually have 3 calls to chatList and 2 calls to Authenticate
const callsToOpenApp = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'OpenApp');
// Then we will eventually have 1 call to OpenPersonalDetailsPage and 1 calls to Authenticate
const callsToOpenPersonalDetails = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'OpenPersonalDetailsPage');
const callsToAuthenticate = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'Authenticate');

expect(callsToOpenApp.length).toBe(1);
expect(callsToOpenPersonalDetails.length).toBe(1);
expect(callsToAuthenticate.length).toBe(1);
});
});
Expand All @@ -137,7 +136,7 @@ describe('NetworkTests', () => {
HttpUtils.xhr = jest.fn();
HttpUtils.xhr

// And mock the first call to OpenApp return with an expired session code
// And mock the first call to openPersonalDetails return with an expired session code
.mockImplementationOnce(() =>
Promise.resolve({
jsonCode: CONST.JSON_CODE.NOT_AUTHENTICATED,
Expand Down Expand Up @@ -165,20 +164,20 @@ describe('NetworkTests', () => {
}),
);

// And then make 3 API requests in quick succession with an expired authToken and handle the response
// And then make 3 API READ requests in quick succession with an expired authToken and handle the response
// It doesn't matter which requests these are really as all the response is mocked we just want to see
// that we get re-authenticated
App.openApp();
App.openApp();
App.openApp();
PersonalDetails.openPersonalDetails();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to use a READ command here to make the test pass. It seems like this behaves differently when we call a write command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this scenario though of a write command with an expired authToken and I was re-authenticated properly.

Copy link
Contributor

@tgolen tgolen Feb 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please update the comment above here that says "make 3 API requests" to specifically say that they are READ requests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On it.

PersonalDetails.openPersonalDetails();
PersonalDetails.openPersonalDetails();
return waitForBatchedUpdates();
})
.then(() => {
// We should expect to see the three calls to OpenApp, but only one call to Authenticate.
// And we should also see the reconnection callbacks triggered.
const callsToOpenApp = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'OpenApp');
const callsToOpenPersonalDetails = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'OpenPersonalDetailsPage');
const callsToAuthenticate = _.filter(HttpUtils.xhr.mock.calls, ([command]) => command === 'Authenticate');
expect(callsToOpenApp.length).toBe(3);
expect(callsToOpenPersonalDetails.length).toBe(3);
expect(callsToAuthenticate.length).toBe(1);
expect(reconnectionCallbacksSpy.mock.calls.length).toBe(3);
});
Expand Down
Loading