diff --git a/packages/contact-center/ui-logging/src/withMetrics.tsx b/packages/contact-center/ui-logging/src/withMetrics.tsx index 77354d3dd..41da8814f 100644 --- a/packages/contact-center/ui-logging/src/withMetrics.tsx +++ b/packages/contact-center/ui-logging/src/withMetrics.tsx @@ -1,9 +1,11 @@ import React, {useEffect, useRef} from 'react'; import {havePropsChanged, logMetrics} from './metricsLogger'; -export default function withMetrics

(Component: any, widgetName: string) { +export default function withMetrics

(Component: any, widgetName: string, propsToWatch?: string[]) { return React.memo( (props: P) => { + const prevWatchedPropsRef = useRef | null>(null); + useEffect(() => { logMetrics({ widgetName, @@ -20,7 +22,25 @@ export default function withMetrics

(Component: any, widgetName }; }, []); - // TODO: https://jira-eng-sjc12.cisco.com/jira/browse/CAI-6890 PROPS_UPDATED event + useEffect(() => { + if (!propsToWatch || propsToWatch.length === 0) return; + + const currentWatchedProps: Record = {}; + for (const key of propsToWatch) { + currentWatchedProps[key] = (props as Record)[key]; + } + + if (prevWatchedPropsRef.current !== null && havePropsChanged(prevWatchedPropsRef.current, currentWatchedProps)) { + logMetrics({ + widgetName, + event: 'PROPS_UPDATED', + props: currentWatchedProps, + timestamp: Date.now(), + }); + } + + prevWatchedPropsRef.current = currentWatchedProps; + }); return ; }, diff --git a/packages/contact-center/ui-logging/tests/withMetrics.test.tsx b/packages/contact-center/ui-logging/tests/withMetrics.test.tsx index 23ec71691..d86aa91f9 100644 --- a/packages/contact-center/ui-logging/tests/withMetrics.test.tsx +++ b/packages/contact-center/ui-logging/tests/withMetrics.test.tsx @@ -102,4 +102,89 @@ describe('withMetrics HOC', () => { rerender(); expect(renderSpy).toHaveBeenCalledTimes(2); }); + + describe('PROPS_UPDATED event', () => { + it('should log PROPS_UPDATED when watched props change', () => { + const mockTime = 1234567890; + jest.setSystemTime(mockTime); + + const WrappedWithWatch = withMetrics(TestComponent, 'TestWidget', ['name']); + + const {rerender} = render(); + logMetricsSpy.mockClear(); + + rerender(); + + expect(logMetricsSpy).toHaveBeenCalledWith({ + widgetName: 'TestWidget', + event: 'PROPS_UPDATED', + props: {name: 'updated'}, + timestamp: mockTime, + }); + }); + + it('should not log PROPS_UPDATED when only unwatched props change', () => { + const mockTime = 1234567890; + jest.setSystemTime(mockTime); + + const WrappedWithWatch = withMetrics(TestComponent, 'TestWidget', ['name']); + + const {rerender} = render(); + logMetricsSpy.mockClear(); + + rerender(); + + expect(logMetricsSpy).not.toHaveBeenCalledWith( + expect.objectContaining({event: 'PROPS_UPDATED'}) + ); + }); + + it('should not log PROPS_UPDATED when no propsToWatch is provided', () => { + const mockTime = 1234567890; + jest.setSystemTime(mockTime); + + const WrappedNoWatch = withMetrics(TestComponent, 'TestWidget'); + + const {rerender} = render(); + logMetricsSpy.mockClear(); + + rerender(); + + expect(logMetricsSpy).not.toHaveBeenCalledWith( + expect.objectContaining({event: 'PROPS_UPDATED'}) + ); + }); + + it('should not log PROPS_UPDATED on initial render', () => { + const mockTime = 1234567890; + jest.setSystemTime(mockTime); + + const WrappedWithWatch = withMetrics(TestComponent, 'TestWidget', ['name']); + + render(); + + expect(logMetricsSpy).not.toHaveBeenCalledWith( + expect.objectContaining({event: 'PROPS_UPDATED'}) + ); + }); + + it('should only include watched props in the log payload', () => { + const mockTime = 1234567890; + jest.setSystemTime(mockTime); + + const WrappedWithWatch = withMetrics(TestComponent, 'TestWidget', ['name']); + + const {rerender} = render(); + logMetricsSpy.mockClear(); + + rerender(); + + const propsUpdatedCall = logMetricsSpy.mock.calls.find( + (call) => call[0].event === 'PROPS_UPDATED' + ); + expect(propsUpdatedCall).toBeDefined(); + expect(propsUpdatedCall[0].props).toEqual({name: 'updated'}); + expect(propsUpdatedCall[0].props).not.toHaveProperty('otherProp'); + }); + }); });