Skip to content

Commit

Permalink
Merge pull request #8713 from Expensify/marcaaron-reauthenticationTools
Browse files Browse the repository at this point in the history
Add test tools to make it easier to test Network/reauthentication logic
  • Loading branch information
marcochavezf authored Apr 25, 2022
2 parents c308f6b + e4baae1 commit be7fd88
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 22 deletions.
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
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,
};
5 changes: 5 additions & 0 deletions src/libs/actions/Session/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ function setPassword(password, validateCode, accountID) {
});
}

function invalidateCredentials() {
Onyx.merge(ONYXKEYS.CREDENTIALS, {autoGeneratedLogin: '', autoGeneratedPassword: ''});
}

/**
* Clear the credentials and partial sign in session so the user can taken back to first Login step
*/
Expand Down Expand Up @@ -496,4 +500,5 @@ export {
reauthenticatePusher,
setShouldShowComposeInput,
changePasswordAndSignIn,
invalidateCredentials,
};
25 changes: 3 additions & 22 deletions src/pages/settings/PreferencesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize
import compose from '../../libs/compose';
import Picker from '../../components/Picker';
import withEnvironment, {environmentPropTypes} from '../../components/withEnvironment';
import TestToolMenu from '../../components/TestToolMenu';

const propTypes = {
/** The chat priority mode */
Expand Down Expand Up @@ -99,28 +100,8 @@ const PreferencesPage = (props) => {
<LocalePicker />
</View>

{/* If we are in the staging environment then we have the 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 */}
{props.environment === CONST.ENVIRONMENT.STAGING && (
<>
<Text style={[styles.formLabel]} numberOfLines={1}>
Test Preferences
</Text>
<View style={[styles.flexRow, styles.mb6, styles.justifyContentBetween]}>
<View style={styles.flex4}>
<Text>
Use Secure Staging Server
</Text>
</View>
<View style={[styles.flex1, styles.alignItemsEnd]}>
<Switch
isOn={props.user.shouldUseSecureStaging || false}
onToggle={User.setShouldUseSecureStaging}
/>
</View>
</View>
</>
)}
{/* If we are in the staging environment then we enable additional test features */}
{props.environment === CONST.ENVIRONMENT.STAGING && <TestToolMenu />}
</View>
</ScrollView>
</ScreenWrapper>
Expand Down

0 comments on commit be7fd88

Please sign in to comment.