Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Expensify/App into amal-fix-archive…
Browse files Browse the repository at this point in the history
…d-member-view
  • Loading branch information
Amal Nazeem committed Apr 25, 2022
2 parents f989a4a + 16b130b commit 728e933
Show file tree
Hide file tree
Showing 18 changed files with 296 additions and 131 deletions.
42 changes: 21 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"dom-serializer": "^0.2.2",
"domhandler": "^4.3.0",
"dotenv": "^8.2.0",
"expensify-common": "git+https://github.com/Expensify/expensify-common.git#f77bb4710c13d01153716df7fb087b637ba3b8bd",
"expensify-common": "git+https://github.com/Expensify/expensify-common.git#15237e012770048e8413dc08d4c36bc12304f3e8",
"fbjs": "^3.0.2",
"file-loader": "^6.0.0",
"html-entities": "^1.3.1",
Expand All @@ -71,7 +71,7 @@
"moment-timezone": "^0.5.31",
"onfido-sdk-ui": "^6.15.2",
"prop-types": "^15.7.2",
"pusher-js": "^7.0.0",
"pusher-js": "^7.0.6",
"react": "^17.0.2",
"react-collapse": "^5.1.0",
"react-dom": "^17.0.2",
Expand Down
5 changes: 5 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ const CONST = {
REQUEST_CANCELLED: 'AbortError',
FAILED_TO_FETCH: 'Failed to fetch',
ENSURE_BUGBOT: 'ENSURE_BUGBOT',
PUSHER_ERROR: 'PusherError',
WEB_SOCKET_ERROR: 'WebSocketError',
NETWORK_REQUEST_FAILED: 'Network request failed',
SAFARI_DOCUMENT_LOAD_ABORTED: 'cancelled',
FIREFOX_DOCUMENT_LOAD_ABORTED: 'NetworkError when attempting to fetch resource.',
Expand Down Expand Up @@ -675,6 +677,9 @@ const CONST = {
this.EMAIL.ADMIN,
];
},

// There's a limit of 60k characters in Auth - https://github.com/Expensify/Auth/blob/198d59547f71fdee8121325e8bc9241fc9c3236a/auth/lib/Request.h#L28
MAX_COMMENT_LENGTH: 60_000,
};

export default CONST;
90 changes: 90 additions & 0 deletions src/components/TestToolMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import styles from '../styles/styles';
import Switch from './Switch';
import Text from './Text';
import * as User from '../libs/actions/User';
import * as Network from '../libs/actions/Network';
import * as Session from '../libs/actions/Session';
import ONYXKEYS from '../ONYXKEYS';
import Button from './Button';
import * as NetworkStore from '../libs/Network/NetworkStore';
import TestToolRow from './TestToolRow';

const propTypes = {
/** User object in Onyx */
user: PropTypes.shape({
/** Whether we should use the staging version of the secure API server */
shouldUseSecureStaging: PropTypes.bool,
}),

/** Network object in Onyx */
network: PropTypes.shape({
/** Whether we should fail all network requests */
shouldFailAllRequests: PropTypes.bool,
}),
};

const defaultProps = {
user: {
shouldUseSecureStaging: false,
},
network: {
shouldFailAllRequests: false,
},
};

const TestToolMenu = props => (
<>
<Text style={[styles.formLabel]} numberOfLines={1}>
Test Preferences
</Text>

{/* Option to switch from using the staging secure endpoint or the production secure endpoint.
This enables QA and internal testers to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. */}
<TestToolRow title="Use Secure Staging Server">
<Switch
isOn={props.user.shouldUseSecureStaging || false}
onToggle={() => User.setShouldUseSecureStaging(!props.user.shouldUseSecureStaging)}
/>
</TestToolRow>

{/* When toggled all network requests will fail. */}
<TestToolRow title="Simulate failing network requests">
<Switch
isOn={props.network.shouldFailAllRequests || false}
onToggle={() => Network.setShouldFailAllRequests(!props.network.shouldFailAllRequests)}
/>
</TestToolRow>

{/* Instantly invalidates a user's local authToken. Useful for testing flows related to reauthentication. */}
<TestToolRow title="Authentication status">
<Button
small
text="Invalidate"
onPress={() => NetworkStore.setAuthToken('pizza')}
/>
</TestToolRow>

{/* Invalidate stored user auto-generated credentials. Useful for manually testing sign out logic. */}
<TestToolRow title="Device credentials">
<Button
small
text="Destroy"
onPress={() => Session.invalidateCredentials()}
/>
</TestToolRow>
</>
);

TestToolMenu.propTypes = propTypes;
TestToolMenu.defaultProps = defaultProps;
export default withOnyx({
user: {
key: ONYXKEYS.USER,
},
network: {
key: ONYXKEYS.NETWORK,
},
})(TestToolMenu);
29 changes: 29 additions & 0 deletions src/components/TestToolRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import styles from '../styles/styles';
import Text from './Text';

const propTypes = {
/** Title of control */
title: PropTypes.string.isRequired,

/** Control component jsx */
children: PropTypes.node.isRequired,
};

const TestToolRow = props => (
<View style={[styles.flexRow, styles.mb6, styles.justifyContentBetween, styles.alignItemsCenter]}>
<View style={styles.flex4}>
<Text>
{props.title}
</Text>
</View>
<View style={[styles.flex1, styles.alignItemsEnd]}>
{props.children}
</View>
</View>
);

TestToolRow.propTypes = propTypes;
export default TestToolRow;
13 changes: 13 additions & 0 deletions src/libs/HttpUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ Onyx.connect({
callback: val => shouldUseSecureStaging = (val && _.isBoolean(val.shouldUseSecureStaging)) ? val.shouldUseSecureStaging : false,
});

let shouldFailAllRequests = false;
Onyx.connect({
key: ONYXKEYS.NETWORK,
callback: val => shouldFailAllRequests = (val && _.isBoolean(val.shouldFailAllRequests)) ? val.shouldFailAllRequests : false,
});

// We use the AbortController API to terminate pending request in `cancelPendingRequests`
let cancellationController = new AbortController();

Expand All @@ -32,6 +38,13 @@ function processHTTPRequest(url, method = 'get', body = null, canCancel = true)
body,
})
.then((response) => {
// Test mode where all requests will succeed in the server, but fail to return a response
if (shouldFailAllRequests) {
throw new HttpsError({
message: CONST.ERROR.FAILED_TO_FETCH,
});
}

if (!response.ok) {
throw new HttpsError({
message: response.statusText,
Expand Down
1 change: 1 addition & 0 deletions src/libs/Log.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function LogCommand(parameters) {
function serverLoggingCallback(logger, params) {
const requestParams = params;
requestParams.shouldProcessImmediately = false;
requestParams.shouldRetry = false;
requestParams.expensifyCashAppVersion = `expensifyCash[${getPlatform()}]${version}`;
if (requestParams.parameters) {
requestParams.parameters = JSON.stringify(params.parameters);
Expand Down
18 changes: 9 additions & 9 deletions src/libs/Pusher/pusher.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,15 @@ function subscribe(
onResubscribe();
});

channel.bind('pusher:subscription_error', (status) => {
if (status === 403) {
Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', {
channelName,
status,
});
}

reject(status);
channel.bind('pusher:subscription_error', (data = {}) => {
const {type, error, status} = data;
Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', {
channelName,
status,
type,
error,
});
reject(error);
});
} else {
bindEventToChannel(channel, eventName, eventCallback, isChunked);
Expand Down
29 changes: 22 additions & 7 deletions src/libs/PusherConnectionManager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import lodashGet from 'lodash/get';
import * as Pusher from './Pusher/pusher';
import * as Session from './actions/Session';
import Log from './Log';
import CONST from '../CONST';

function init() {
/**
Expand All @@ -16,24 +18,37 @@ function init() {
}));

/**
* Events that happen on the pusher socket are used to determine if the app is online or offline.
* The offline setting is stored in Onyx so the rest of the app has access to it.
*
* @params {string} eventName
*/
Pusher.registerSocketEventCallback((eventName, data) => {
Pusher.registerSocketEventCallback((eventName, error) => {
switch (eventName) {
case 'error':
Log.info('[PusherConnectionManager] error event', false, {error: data});
Session.reauthenticatePusher();
case 'error': {
const errorType = lodashGet(error, 'type');
const code = lodashGet(error, 'data.code');
if (errorType === CONST.ERROR.PUSHER_ERROR && code === 1006) {
// 1006 code happens when a websocket connection is closed. There may or may not be a reason attached indicating why the connection was closed.
// https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5
Log.hmmm('[PusherConnectionManager] Channels Error 1006', {error});
} else if (errorType === CONST.ERROR.PUSHER_ERROR && code === 4201) {
// This means the connection was closed because Pusher did not recieve a reply from the client when it pinged them for a response
// https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/#4200-4299
Log.hmmm('[PusherConnectionManager] Pong reply not received', {error});
} else if (errorType === CONST.ERROR.WEB_SOCKET_ERROR) {
// It's not clear why some errors are wrapped in a WebSocketError type - this error could mean different things depending on the contents.
Log.hmmm('[PusherConnectionManager] WebSocketError', {error});
} else {
Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} [PusherConnectionManager] Unknown error event`, {error});
}
break;
}
case 'connected':
Log.info('[PusherConnectionManager] connected event');
break;
case 'disconnected':
Log.info('[PusherConnectionManager] disconnected event');
break;
default:
Log.info('[PusherConnectionManager] unhandled event', false, {eventName});
break;
}
});
Expand Down
9 changes: 9 additions & 0 deletions src/libs/actions/Network.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ function setIsOffline(isOffline) {
Onyx.merge(ONYXKEYS.NETWORK, {isOffline});
}

/**
* Test tool that will fail all network requests when enabled
* @param {Boolean} shouldFailAllRequests
*/
function setShouldFailAllRequests(shouldFailAllRequests) {
Onyx.merge(ONYXKEYS.NETWORK, {shouldFailAllRequests});
}

export {
setIsLoadingAfterReconnect,
setIsOffline,
setShouldFailAllRequests,
};
Loading

0 comments on commit 728e933

Please sign in to comment.