Skip to content
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
34 changes: 32 additions & 2 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,41 @@ import { Route } from "@react-navigation/native";
import { NestedNavigator } from './screens/NestedNavigator/NestedNavigator';
import { getDatadogConfig, onDatadogInitialization } from './ddUtils';
import { TrackingConsent } from '@datadog/mobile-react-native';
import { NavigationTrackingOptions, ParamsTrackingPredicate, ViewTrackingPredicate } from '@datadog/mobile-react-navigation/src/rum/instrumentation/DdRumReactNavigationTracking';

const Tab = createBottomTabNavigator();

const viewPredicate: ViewNamePredicate = function customViewNamePredicate(route: Route<string, any | undefined>, trackedName: string) {
// === Navigation Tracking custom predicates
const viewNamePredicate: ViewNamePredicate = function customViewNamePredicate(route: Route<string, any | undefined>, trackedName: string) {
return "Custom RN " + trackedName;
}

const viewTrackingPredicate: ViewTrackingPredicate = function customViewTrackingPredicate(route: Route<string, any | undefined>) {
if (route.name === "AlertModal") {
return false;
}

return true;
}

const paramsTrackingPredicate: ParamsTrackingPredicate = function customParamsTrackingPredicate(route: Route<string, any | undefined>) {
const filteredParams: any = {};
if (route.params?.creditCardNumber) {
filteredParams["creditCardNumber"] = "XXXX XXXX XXXX XXXX";
}

if (route.params?.username) {
filteredParams["username"] = route.params.username;
}

return filteredParams;
}

const navigationTrackingOptions: NavigationTrackingOptions = {
viewNamePredicate,
viewTrackingPredicate,
paramsTrackingPredicate,
}
// === Datadog Provider Configuration schemes ===

// 1.- Direct configuration
Expand All @@ -39,7 +67,9 @@ export default function App() {
return (
<DatadogProvider configuration={configuration} onInitialization={onDatadogInitialization}>
<NavigationContainer ref={navigationRef} onReady={() => {
DdRumReactNavigationTracking.startTrackingViews(navigationRef.current, viewPredicate)
DdRumReactNavigationTracking.startTrackingViews(
navigationRef.current,
navigationTrackingOptions)
}}>
<Tab.Navigator screenOptions={{
tabBarLabelStyle: style.tabLabelStyle,
Expand Down
48 changes: 39 additions & 9 deletions example/src/WixApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,43 @@ import {
} from '@datadog/mobile-react-native-navigation';

import styles from './screens/styles';
import { DdTrace } from '@datadog/mobile-react-native';
import TraceScreen from './screens/TraceScreen';
import { NavigationTrackingOptions, ParamsTrackingPredicate, ViewTrackingPredicate } from '@datadog/mobile-react-native-navigation/src/rum/instrumentation/DdRumReactNativeNavigationTracking';

const viewPredicate: ViewNamePredicate = (
_event: ComponentDidAppearEvent,
trackedName: string
) => {
return 'Custom RNN ' + trackedName;
};
// === Navigation Tracking custom predicates
const viewNamePredicate: ViewNamePredicate = function customViewNamePredicate(_event: ComponentDidAppearEvent, trackedName: string) {
return "Custom RN " + trackedName;
}

const viewTrackingPredicate: ViewTrackingPredicate = function customViewTrackingPredicate(event: ComponentDidAppearEvent) {
if (event.name === "AlertModal") {
return false;
}

return true;
}

const paramsTrackingPredicate: ParamsTrackingPredicate = function customParamsTrackingPredicate(event: ComponentDidAppearEvent) {
const filteredParams: any = {};
if (event.passProps?.creditCardNumber) {
filteredParams["creditCardNumber"] = "XXXX XXXX XXXX XXXX";
}

if (event.passProps?.username) {
filteredParams["username"] = event.passProps.username;
}

return filteredParams;
}

const navigationTrackingOptions: NavigationTrackingOptions = {
viewNamePredicate,
viewTrackingPredicate,
paramsTrackingPredicate,
}

function startReactNativeNavigation() {
DdRumReactNativeNavigationTracking.startTracking(viewPredicate);
DdRumReactNativeNavigationTracking.startTracking(navigationTrackingOptions);
registerScreens();
Navigation.events().registerAppLaunchedListener(async () => {
Navigation.setRoot({
Expand Down Expand Up @@ -80,7 +105,12 @@ const HomeScreen = props => {
title="About"
onPress={() => {
Navigation.push(props.componentId, {
component: { name: 'About' }
component: { name: 'About',
passProps: {
username: "test",
creditCardNumber: "4242 4242 4242 4242"
}
}
});
}}
/>
Expand Down
4 changes: 2 additions & 2 deletions example/src/screens/NestedNavigator/ScreenWithLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import {useNavigation} from '@react-navigation/native'
export const ScreenWithLinks = (props: {links: { routeName: string}[]}) => {
const {navigate} = useNavigation()
return (<>
{props.links.map(link => <Button title={`go to ${link.routeName}`} onPress={() => navigate(link.routeName)} key={link.routeName} />)}
{props.links.map(link => <Button title={`go to ${link.routeName}`} onPress={() => navigate(link.routeName, {username: "test", creditCardNumber: "4242 4242 4242 4242"})} key={link.routeName} />)}
</>)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import { Navigation } from 'react-native-navigation';
import { AppState, Button } from 'react-native';
import React from 'react';

import type { ViewNamePredicate } from '../../../rum/instrumentation/DdRumReactNativeNavigationTracking';
import type {
ParamsTrackingPredicate,
ViewNamePredicate,
ViewTrackingPredicate
} from '../../../rum/instrumentation/DdRumReactNativeNavigationTracking';
import { DdRumReactNativeNavigationTracking } from '../../../rum/instrumentation/DdRumReactNativeNavigationTracking';

import { AppStateMockLegacy } from './__utils__/AppStateMockLegacy';
Expand Down Expand Up @@ -104,7 +108,7 @@ it('M send a RUM ViewEvent W startTracking() for the first view', async () => {
);
});

it('M send a RUM ViewEvent W startTracking() componentDidAppear { custom viewPredicate }', async () => {
it('M send a RUM ViewEvent W startTracking() componentDidAppear { custom viewNamePredicate }', async () => {
// GIVEN

// eslint-disable-next-line func-names
Expand All @@ -117,7 +121,9 @@ it('M send a RUM ViewEvent W startTracking() componentDidAppear { custom viewPre
}
return _trackedName;
};
DdRumReactNativeNavigationTracking.startTracking(predicate);
DdRumReactNativeNavigationTracking.startTracking({
viewNamePredicate: predicate
});

// WHEN
const { findByText } = render(
Expand All @@ -135,7 +141,7 @@ it('M send a RUM ViewEvent W startTracking() componentDidAppear { custom viewPre
);
});

it('M not send a RUM ViewEvent W startTracking() componentDidAppear { viewPredicate returns null }', async () => {
it('M not send a RUM ViewEvent W startTracking() componentDidAppear { viewNamePredicate returns null }', async () => {
// GIVEN
let viewDropped = false;

Expand All @@ -150,7 +156,9 @@ it('M not send a RUM ViewEvent W startTracking() componentDidAppear { viewPredic
}
return _trackedName;
};
DdRumReactNativeNavigationTracking.startTracking(predicate);
DdRumReactNativeNavigationTracking.startTracking({
viewNamePredicate: predicate
});

// WHEN
const { findByText } = render(
Expand All @@ -165,6 +173,101 @@ it('M not send a RUM ViewEvent W startTracking() componentDidAppear { viewPredic
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'Home');
});

it('M send a RUM ViewEvent W startTracking() componentDidAppear { viewTrackingPredicate always returns true }', async () => {
// GIVEN
// eslint-disable-next-line func-names
let hasRunPredicate = false;
const predicate: ViewTrackingPredicate = function (
_event: ComponentDidAppearEvent
) {
hasRunPredicate = true;
return true;
};
DdRumReactNativeNavigationTracking.startTracking({
viewTrackingPredicate: predicate
});

// WHEN
const { findByText } = render(
<ApplicationMock entryPoint={() => startPlayground()} />
);
const button = await findByText('Go to About');
await fireEvent(button, 'press');
await waitFor(() => hasRunPredicate);

// THEN
expect(DdRum.startView).toHaveBeenCalledTimes(2);
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'Home');
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'About');
});

it('M send a RUM ViewEvent W startTracking() componentDidAppear { viewTrackingPredicate skips tracking About screen }', async () => {
// GIVEN
// eslint-disable-next-line func-names
let hasRunPredicate = false;
const predicate: ViewTrackingPredicate = function (
_event: ComponentDidAppearEvent
) {
hasRunPredicate = true;
return _event.componentName !== 'About';
};
DdRumReactNativeNavigationTracking.startTracking({
viewTrackingPredicate: predicate
});

// WHEN
const { findByText } = render(
<ApplicationMock entryPoint={() => startPlayground()} />
);
const button = await findByText('Go to About');
await fireEvent(button, 'press');
await waitFor(() => hasRunPredicate);

// THEN
expect(DdRum.startView).toHaveBeenCalledTimes(1);
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'Home');
expect(DdRum.startView).not.toHaveBeenCalledWith(
expect.any(String),
'About'
);
});

it('M send a RUM ViewEvent W startTracking() componentDidAppear { paramsTrackingPredicate adds custom parameters }', async () => {
// GIVEN
// eslint-disable-next-line func-names
let hasRunPredicate = false;
const testPassProps = {
param1: true,
param2: 'abc'
};
const predicate: ParamsTrackingPredicate = function (
_event: ComponentDidAppearEvent
) {
hasRunPredicate = true;
return testPassProps;
};
DdRumReactNativeNavigationTracking.startTracking({
paramsTrackingPredicate: predicate
});

// WHEN
const { findByText } = render(
<ApplicationMock entryPoint={() => startPlayground()} />
);
const button = await findByText('Go to About');
await fireEvent(button, 'press');
await waitFor(() => hasRunPredicate);

// THEN
expect(DdRum.startView).toHaveBeenCalledTimes(2);
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'Home', {
passProps: testPassProps
});
expect(DdRum.startView).toHaveBeenCalledWith(expect.any(String), 'About', {
passProps: testPassProps
});
});

describe.each([
['react-native 0.63-0.64', AppStateMockLegacy],
['react-native 0.65+', AppStateMock]
Expand Down
14 changes: 12 additions & 2 deletions packages/react-native-navigation/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@
* Copyright 2016-Present Datadog, Inc.
*/

import type { ViewNamePredicate } from './rum/instrumentation/DdRumReactNativeNavigationTracking';
import type {
ViewNamePredicate,
ViewTrackingPredicate,
ParamsTrackingPredicate,
NavigationTrackingOptions
} from './rum/instrumentation/DdRumReactNativeNavigationTracking';
import { DdRumReactNativeNavigationTracking } from './rum/instrumentation/DdRumReactNativeNavigationTracking';

export { DdRumReactNativeNavigationTracking };

export type { ViewNamePredicate };
export type {
ViewNamePredicate,
ViewTrackingPredicate,
ParamsTrackingPredicate,
NavigationTrackingOptions
};

export * from 'react-native-navigation';
Loading