Skip to content
This repository has been archived by the owner on May 8, 2024. It is now read-only.

Added TestFairy code examples #74

Closed
wants to merge 4 commits into from
Closed
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"react-native-screens": "^2.16.1",
"react-native-signature-canvas": "^3.3.0",
"react-native-splash-screen": "^3.2.0",
"react-native-testfairy": "^2.44.0",
"react-native-vector-icons": "^7.1.0",
"react-native-webview": "^11.0.2",
"react-navigation": "^4.4.3",
Expand Down
29 changes: 29 additions & 0 deletions src/js/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import SwagLabsStatusBar from './components/StatusBar';
import SplashScreen from 'react-native-splash-screen';
import QuickActions from 'react-native-quick-actions';
import { IS_IOS, SCREENS } from './config/Constants';
import TestFairy from 'react-native-testfairy';

QuickActions.setShortcutItems([
{
Expand Down Expand Up @@ -37,6 +38,34 @@ QuickActions.setShortcutItems([

export default class App extends Component {
componentDidMount() {
// We call stop to support hot-swap during development. This call will be ignored silently for the initial app launch.
TestFairy.stop();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Launch a TestFairy session. The session url will be in the logs for you to navigate.
// Optionally, specify a private cloud endpoint if it applies to you.
//
// When TestFairy launches a session, these will be listened collected until the session is stopped or app is closed:
//
// - logs
// - crashes
// - video recording
// - http network events
// - feedbacks via forms launched when the users shakes their device
// - custom attributes set in the code w/ TestFairy.setAttribute()
// - events sent in the code w/ TestFairy.addEvent()
//
// and many others.
//
// All of this data will be available in your TestFairy web dashboard as well as the REST API.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TestFairy.setServerEndpoint("https://your.privatecloud.example.com") // Private cloud only
TestFairy.begin('SDK-gLeZiE9i');
// TestFairy.installFeedbackHandler('SDK-gLeZiE9i'); // Swap this line with the above if you don't want to record a session but still need the shake gesture detection for the feedbacks.

// Hide splash screen once the component mounts
SplashScreen.hide();
}

Expand Down
13 changes: 12 additions & 1 deletion src/js/Router.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import QrCodeScanner from './screens/QrCodeScanner';
import DrawerLinks from './components/DrawerLinks';
import GeoLocation from './screens/GeoLocation';
import Drawing from './screens/Drawing';
import TestFairy from 'react-native-testfairy';

enableScreens();

Expand Down Expand Up @@ -94,7 +95,17 @@ const prefix = 'swaglabs://';
export default class NavigationContainer extends Component {
render() {
return (
<Router uriPrefix={ prefix }/>
<Router uriPrefix={ prefix } onNavigationStateChange={ this.onNavigationStateChange } />
);
}

onNavigationStateChange(previousState, newState, action) {
if (newState.routes.length > 0) {
let newScreen = newState.routes[0].routes[newState.routes[0].routes.length - 1];
if (newScreen) {
// This helps TestFairy to show curent screen name in the session timeline
TestFairy.setScreenName(newScreen.routeName);
}
}
}
}
4 changes: 4 additions & 0 deletions src/js/screens/CheckoutComplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Footer from '../components/Footer';
import ActionButton from '../components/ActionButton';
import SecondaryHeader from '../components/SecondaryHeader';
import { handleQuickActionsNavigation } from '../config/QuickActionsNavigation';
import TestFairy from 'react-native-testfairy';

export default class CheckoutComplete extends Component {
constructor(props) {
Expand All @@ -17,6 +18,9 @@ export default class CheckoutComplete extends Component {

componentDidMount() {
handleQuickActionsNavigation(this.props.navigation);

// Mark important moments in time to be able to later search them in the web dashboard
TestFairy.addEvent('Checkout complete');
}

render() {
Expand Down
11 changes: 10 additions & 1 deletion src/js/screens/CheckoutScreenTwo.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import SectionHeader from '../components/SectionHeader';
import CartItem from '../components/CartItem';
import SecondaryHeader from '../components/SecondaryHeader';
import { handleQuickActionsNavigation } from '../config/QuickActionsNavigation';
import TestFairy from 'react-native-testfairy';

export default class CheckoutScreenTwo extends Component {
constructor(props) {
Expand All @@ -35,6 +36,9 @@ export default class CheckoutScreenTwo extends Component {
if (!Credentials.isProblemUser()) {
// Wipe out our shopping cart
ShoppingCart.resetCart();

// Mark important moments in time to be able to later search them in the web dashboard.
TestFairy.addEvent('Problematic user');
}

// Checkout complete, redirect to our order complete page
Expand Down Expand Up @@ -92,7 +96,12 @@ export default class CheckoutScreenTwo extends Component {
<View style={ styles.button_container }>
<ArrowButton
title={ I18n.t('checkoutPageTwo.cancelButton') }
onPress={ () => this.props.navigation.navigate(SCREENS.INVENTORY_LIST) }
onPress={ () => {
// Mark important moments in time to be able to later search them in the web dashboard
TestFairy.addEvent('Checkout canceled');

this.props.navigation.navigate(SCREENS.INVENTORY_LIST);
} }
/>
<Divider style={ styles.button_divider }/>
<ProceedButton
Expand Down
10 changes: 10 additions & 0 deletions src/js/screens/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import InputError from '../components/InputError';
import ErrorMessageContainer from '../components/ErrorMessageContainer';
import BiometryButton from '../components/BiometryButton';
import { handleQuickActionsNavigation } from '../config/QuickActionsNavigation';
import TestFairy from 'react-native-testfairy';

export default class Login extends Component {
static navigationOptions = {
Expand Down Expand Up @@ -57,6 +58,10 @@ export default class Login extends Component {
}

handleQuickActionsNavigation(this.props.navigation);

// Hide these child components in the screenshots to respect privacy
TestFairy.hideView('username');
TestFairy.hideView('password');
}

resetState() {
Expand Down Expand Up @@ -105,6 +110,9 @@ export default class Login extends Component {
return this.setState({ error: I18n.t('login.errors.lockedOut') });
}

// Identify the user to be able to filter sessions and feedbacks via the web dashboard
TestFairy.setUserId(this.state.username);

return this.successfulLogin();
}

Expand Down Expand Up @@ -194,13 +202,15 @@ export default class Login extends Component {
style={ styles.swag_logo_image }
/>
<InputError
nativeID={ 'username' }
placeholder={ 'login.username' }
value={ this.state.username }
onChangeText={ this.handleUserChange }
error={ this.state.usernameError }
/>
<Divider style={ styles.bottomMargin20 }/>
<InputError
nativeID= { 'password' }
placeholder={ 'login.password' }
value={ this.state.password }
onChangeText={ this.handlePassChange }
Expand Down
8 changes: 7 additions & 1 deletion src/js/screens/QrCodeScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ThemeProvider } from 'react-native-elements';
import SecondaryHeader from '../components/SecondaryHeader';
import { colors } from '../utils/colors';
import { handleQuickActionsNavigation } from '../config/QuickActionsNavigation';
import TestFairy from 'react-native-testfairy';

export default class QrCodeScanner extends Component {
componentDidMount() {
Expand All @@ -20,7 +21,12 @@ export default class QrCodeScanner extends Component {
const newUrl = `${ validWww ? 'https://' : '' }${ url }`;
Linking
.openURL(newUrl)
.catch(err => Alert.alert('An error occurred', err));
.catch(err => {
Alert.alert('An error occurred', err);

// Log important exceptions to have access to their stacktraces inside your session
TestFairy.logException(err);
});
} else {
Alert.alert(`'${ url }' is not a valid url`);
}
Expand Down
4 changes: 4 additions & 0 deletions src/js/shopping-cart.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import TestFairy from 'react-native-testfairy';
import SyncStorage from 'sync-storage';
import { InventoryData } from './data/inventory-data';

Expand Down Expand Up @@ -81,6 +82,9 @@ export class ShoppingCart {
ShoppingCart.LISTENERS.forEach((curListener) => {
curListener.forceUpdate();
});

// Update attributes with latest cart items, see them on JIRA when a feedback is reported
TestFairy.setAttribute('cart', JSON.stringify(newContents));
}

static resetCart() {
Expand Down