diff --git a/packages/core/src/DdSdkReactNative.tsx b/packages/core/src/DdSdkReactNative.tsx index aae1422e6..b74605ddb 100644 --- a/packages/core/src/DdSdkReactNative.tsx +++ b/packages/core/src/DdSdkReactNative.tsx @@ -530,7 +530,7 @@ export class DdSdkReactNative { DdBabelInteractionTracking.config = { trackInteractions, useAccessibilityLabel: - configuration.rumConfiguration?.useAccessibilityLabel || + configuration.rumConfiguration?.useAccessibilityLabel ?? RUM_DEFAULTS.useAccessibilityLabel }; diff --git a/packages/core/src/__tests__/DdSdkReactNative.test.tsx b/packages/core/src/__tests__/DdSdkReactNative.test.tsx index a8d975dc7..1b35fc49e 100644 --- a/packages/core/src/__tests__/DdSdkReactNative.test.tsx +++ b/packages/core/src/__tests__/DdSdkReactNative.test.tsx @@ -18,6 +18,7 @@ import { ProxyConfiguration, ProxyType, SdkVerbosity } from '../config/types'; import { DdLogs } from '../logs/DdLogs'; import { DdRum } from '../rum/DdRum'; import { DdRumErrorTracking } from '../rum/instrumentation/DdRumErrorTracking'; +import { DdBabelInteractionTracking } from '../rum/instrumentation/interactionTracking/DdBabelInteractionTracking'; import { DdRumUserInteractionTracking } from '../rum/instrumentation/interactionTracking/DdRumUserInteractionTracking'; import { DdRumResourceTracking } from '../rum/instrumentation/resourceTracking/DdRumResourceTracking'; import { PropagatorType, RumActionType } from '../rum/types'; @@ -653,6 +654,50 @@ describe('DdSdkReactNative', () => { }); describe('feature enablement', () => { + describe('Babel interaction tracking', () => { + const originalConfig = DdBabelInteractionTracking.config; + const originalPluginFlag = + globalThis.__DD_RN_BABEL_PLUGIN_ENABLED__; + + beforeEach(() => { + globalThis.__DD_RN_BABEL_PLUGIN_ENABLED__ = true; + NativeModules.DdSdk.initialize.mockResolvedValue(null); + }); + + afterEach(() => { + globalThis.__DD_RN_BABEL_PLUGIN_ENABLED__ = originalPluginFlag; + DdBabelInteractionTracking.config = originalConfig; + }); + + it.each([ + { useAccessibilityLabel: false, expected: false }, + { useAccessibilityLabel: true, expected: true }, + { useAccessibilityLabel: undefined, expected: true } + ])( + 'respects useAccessibilityLabel=$useAccessibilityLabel during initialization', + async ({ useAccessibilityLabel, expected }) => { + const configuration = new CoreConfiguration('2', 'env'); + configuration.rumConfiguration = new RumConfiguration( + '1', + true, + false, + false, + { useAccessibilityLabel } + ); + + await DdSdkReactNative.initialize(configuration); + + expect(DdBabelInteractionTracking.config).toEqual({ + trackInteractions: true, + useAccessibilityLabel: expected + }); + expect( + DdRumUserInteractionTracking.startTracking + ).not.toHaveBeenCalled(); + } + ); + }); + it('enables user interaction feature when initialize { user interaction config enabled }', async () => { // GIVEN const fakeAppId = '1'; diff --git a/packages/core/src/rum/instrumentation/interactionTracking/__tests__/DdBabelInteractionTracking.test.ts b/packages/core/src/rum/instrumentation/interactionTracking/__tests__/DdBabelInteractionTracking.test.ts index 003d4da27..c74b86ba5 100644 --- a/packages/core/src/rum/instrumentation/interactionTracking/__tests__/DdBabelInteractionTracking.test.ts +++ b/packages/core/src/rum/instrumentation/interactionTracking/__tests__/DdBabelInteractionTracking.test.ts @@ -69,7 +69,10 @@ describe('DdBabelInteractionTracking.wrapRumAction', () => { it('should forward the first handler argument as actionContext to DdRum.addAction', () => { const mockAddAction = jest.fn().mockResolvedValue(undefined); - DdBabelInteractionTracking.config = { trackInteractions: true }; + DdBabelInteractionTracking.config = { + trackInteractions: true, + useAccessibilityLabel: true + }; DdBabelInteractionTracking.attachRumInstance({ addAction: mockAddAction } as any); @@ -94,4 +97,104 @@ describe('DdBabelInteractionTracking.wrapRumAction', () => { event ); }); + + describe('action naming precedence', () => { + const mockAddAction = jest.fn().mockResolvedValue(undefined); + const originalConfig = DdBabelInteractionTracking.config; + + beforeEach(() => { + mockAddAction.mockClear(); + DdBabelInteractionTracking.attachRumInstance({ + addAction: mockAddAction + } as any); + }); + + afterEach(() => { + DdBabelInteractionTracking.config = originalConfig; + }); + + describe.each([true, false])( + 'useAccessibilityLabel=%s', + useAccessibilityLabel => { + it.each([ + { + source: + 'dd-action-name over custom attribute, accessibility label and content', + attributes: { + 'dd-action-name': ['Explicit'], + customName: ['Custom'], + accessibilityLabel: ['Accessible'] + }, + content: ['Content'], + expected: 'Pressable ("Explicit")' + }, + { + source: + 'custom attribute over accessibility label and content', + attributes: { + customName: ['Custom'], + accessibilityLabel: ['Accessible'] + }, + content: ['Content'], + expected: 'Pressable ("Custom")' + }, + { + source: + 'accessibility label or content according to configuration', + attributes: { accessibilityLabel: ['Accessible'] }, + content: ['Content'], + expected: useAccessibilityLabel + ? 'Pressable ("Accessible")' + : 'Pressable ("Content")' + }, + { + source: + 'accessibility label or component name when there is no content', + attributes: { accessibilityLabel: ['Edit'] }, + content: [], + expected: useAccessibilityLabel + ? 'Pressable ("Edit")' + : 'Pressable' + }, + { + source: 'content when there are no naming attributes', + attributes: {}, + content: ['Content'], + expected: 'Pressable ("Content")' + }, + { + source: + 'component name when there are no naming attributes or content', + attributes: {}, + content: [], + expected: 'Pressable' + } + ])('uses $source', ({ attributes, content, expected }) => { + DdBabelInteractionTracking.config = { + trackInteractions: true, + useAccessibilityLabel + }; + const wrapped = DdBabelInteractionTracking.wrapRumAction( + jest.fn(), + RumActionType.TAP, + { + options: { + useContent: true, + useNamePrefix: true + }, + handlerArgs: [], + componentName: 'Pressable', + getContent: () => content, + ...attributes + } as any + ); + + wrapped(); + + expect(mockAddAction).toHaveBeenCalledTimes(1); + expect(mockAddAction.mock.calls[0][1]).toBe(expected); + }); + } + ); + }); });