@@ -2,8 +2,21 @@ import * as mockedtimetodisplaynative from './tracing/mockedtimetodisplaynative'
22jest . mock ( '../src/js/tracing/timetodisplaynative' , ( ) => mockedtimetodisplaynative ) ;
33
44import { defaultStackParser } from '@sentry/browser' ;
5- import type { Envelope , Event , Outcome , Transport , TransportMakeRequestResponse } from '@sentry/core' ;
6- import { rejectedSyncPromise , SentryError } from '@sentry/core' ;
5+ import type {
6+ Envelope ,
7+ Event ,
8+ Outcome ,
9+ SessionAggregates ,
10+ Transport ,
11+ TransportMakeRequestResponse ,
12+ } from '@sentry/core' ;
13+ import {
14+ addAutoIpAddressToSession ,
15+ addAutoIpAddressToUser ,
16+ makeSession ,
17+ rejectedSyncPromise ,
18+ SentryError ,
19+ } from '@sentry/core' ;
720import * as RN from 'react-native' ;
821
922import { ReactNativeClient } from '../src/js/client' ;
@@ -625,6 +638,206 @@ describe('Tests ReactNativeClient', () => {
625638 client . recordDroppedEvent ( 'before_send' , 'error' ) ;
626639 }
627640 } ) ;
641+
642+ describe ( 'ipAddress' , ( ) => {
643+ let mockTransportSend : jest . Mock ;
644+ let client : ReactNativeClient ;
645+
646+ beforeEach ( ( ) => {
647+ mockTransportSend = jest . fn ( ( ) => Promise . resolve ( ) ) ;
648+ client = new ReactNativeClient ( {
649+ ...DEFAULT_OPTIONS ,
650+ dsn : EXAMPLE_DSN ,
651+ transport : ( ) => ( {
652+ send : mockTransportSend ,
653+ flush : jest . fn ( ) ,
654+ } ) ,
655+ sendDefaultPii : true ,
656+ } ) ;
657+ } ) ;
658+
659+ test ( 'preserves ip_address null' , ( ) => {
660+ client . captureEvent ( {
661+ user : {
662+ ip_address : null ,
663+ } ,
664+ } ) ;
665+
666+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ) . toEqual (
667+ expect . objectContaining ( { ip_address : null } ) ,
668+ ) ;
669+ } ) ;
670+
671+ test ( 'preserves ip_address value if set' , ( ) => {
672+ client . captureEvent ( {
673+ user : {
674+ ip_address : '203.45.167.89' ,
675+ } ,
676+ } ) ;
677+
678+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ) . toEqual (
679+ expect . objectContaining ( { ip_address : '203.45.167.89' } ) ,
680+ ) ;
681+ } ) ;
682+
683+ test ( 'adds ip_address {{auto}} to user if set to undefined' , ( ) => {
684+ client . captureEvent ( {
685+ user : {
686+ ip_address : undefined ,
687+ } ,
688+ } ) ;
689+
690+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ) . toEqual (
691+ expect . objectContaining ( { ip_address : '{{auto}}' } ) ,
692+ ) ;
693+ } ) ;
694+
695+ test ( 'adds ip_address {{auto}} to user if not set' , ( ) => {
696+ client . captureEvent ( {
697+ user : { } ,
698+ } ) ;
699+
700+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ) . toEqual (
701+ expect . objectContaining ( { ip_address : '{{auto}}' } ) ,
702+ ) ;
703+ } ) ;
704+
705+ test ( 'adds ip_address {{auto}} to undefined user' , ( ) => {
706+ client . captureEvent ( { } ) ;
707+
708+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ) . toEqual (
709+ expect . objectContaining ( { ip_address : '{{auto}}' } ) ,
710+ ) ;
711+ } ) ;
712+
713+ test ( 'does not add ip_address {{auto}} to undefined user if sendDefaultPii is false' , ( ) => {
714+ const { client, onSpy } = createClientWithSpy ( {
715+ transport : ( ) => ( {
716+ send : mockTransportSend ,
717+ flush : jest . fn ( ) ,
718+ } ) ,
719+ sendDefaultPii : false ,
720+ } ) ;
721+
722+ client . captureEvent ( { } ) ;
723+
724+ expect ( onSpy ) . not . toHaveBeenCalledWith ( 'postprocessEvent' , addAutoIpAddressToUser ) ;
725+ expect (
726+ mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . user ?. ip_address ,
727+ ) . toBeUndefined ( ) ;
728+ } ) ;
729+
730+ test ( 'uses ip address hooks if sendDefaultPii is true' , ( ) => {
731+ const { onSpy } = createClientWithSpy ( {
732+ sendDefaultPii : true ,
733+ } ) ;
734+
735+ expect ( onSpy ) . toHaveBeenCalledWith ( 'postprocessEvent' , addAutoIpAddressToUser ) ;
736+ expect ( onSpy ) . toHaveBeenCalledWith ( 'beforeSendSession' , addAutoIpAddressToSession ) ;
737+ } ) ;
738+
739+ test ( 'does not add ip_address {{auto}} to session if sendDefaultPii is false' , ( ) => {
740+ const { client, onSpy } = createClientWithSpy ( {
741+ release : 'test' , // required for sessions to be sent
742+ transport : ( ) => ( {
743+ send : mockTransportSend ,
744+ flush : jest . fn ( ) ,
745+ } ) ,
746+ sendDefaultPii : false ,
747+ } ) ;
748+
749+ const session = makeSession ( ) ;
750+ session . ipAddress = undefined ;
751+ client . captureSession ( session ) ;
752+
753+ expect ( onSpy ) . not . toHaveBeenCalledWith ( 'beforeSendSession' , addAutoIpAddressToSession ) ;
754+ expect (
755+ mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . attrs . ip_address ,
756+ ) . toBeUndefined ( ) ;
757+ } ) ;
758+
759+ test ( 'does not add ip_address {{auto}} to session aggregate if sendDefaultPii is false' , ( ) => {
760+ const { client, onSpy } = createClientWithSpy ( {
761+ release : 'test' , // required for sessions to be sent
762+ transport : ( ) => ( {
763+ send : mockTransportSend ,
764+ flush : jest . fn ( ) ,
765+ } ) ,
766+ sendDefaultPii : false ,
767+ } ) ;
768+
769+ const session : SessionAggregates = {
770+ aggregates : [ ] ,
771+ } ;
772+ client . sendSession ( session ) ;
773+
774+ expect ( onSpy ) . not . toHaveBeenCalledWith ( 'beforeSendSession' , addAutoIpAddressToSession ) ;
775+ expect (
776+ mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . attrs . ip_address ,
777+ ) . toBeUndefined ( ) ;
778+ } ) ;
779+
780+ test ( 'does not overwrite session aggregate ip_address if already set' , ( ) => {
781+ const { client } = createClientWithSpy ( {
782+ release : 'test' , // required for sessions to be sent
783+ transport : ( ) => ( {
784+ send : mockTransportSend ,
785+ flush : jest . fn ( ) ,
786+ } ) ,
787+ sendDefaultPii : true ,
788+ } ) ;
789+
790+ const session : SessionAggregates = {
791+ aggregates : [ ] ,
792+ attrs : {
793+ ip_address : '123.45.67.89' ,
794+ } ,
795+ } ;
796+ client . sendSession ( session ) ;
797+
798+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . attrs . ip_address ) . toBe (
799+ '123.45.67.89' ,
800+ ) ;
801+ } ) ;
802+
803+ test ( 'does add ip_address {{auto}} to session if sendDefaultPii is true' , ( ) => {
804+ const { client } = createClientWithSpy ( {
805+ release : 'test' , // required for sessions to be sent
806+ transport : ( ) => ( {
807+ send : mockTransportSend ,
808+ flush : jest . fn ( ) ,
809+ } ) ,
810+ sendDefaultPii : true ,
811+ } ) ;
812+
813+ const session = makeSession ( ) ;
814+ session . ipAddress = undefined ;
815+ client . captureSession ( session ) ;
816+
817+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . attrs . ip_address ) . toBe (
818+ '{{auto}}' ,
819+ ) ;
820+ } ) ;
821+
822+ test ( 'does not overwrite session ip_address if already set' , ( ) => {
823+ const { client } = createClientWithSpy ( {
824+ release : 'test' , // required for sessions to be sent
825+ transport : ( ) => ( {
826+ send : mockTransportSend ,
827+ flush : jest . fn ( ) ,
828+ } ) ,
829+ sendDefaultPii : true ,
830+ } ) ;
831+
832+ const session = makeSession ( ) ;
833+ session . ipAddress = '123.45.67.89' ;
834+ client . captureSession ( session ) ;
835+
836+ expect ( mockTransportSend . mock . calls [ 0 ] [ firstArg ] [ envelopeItems ] [ 0 ] [ envelopeItemPayload ] . attrs . ip_address ) . toBe (
837+ '123.45.67.89' ,
838+ ) ;
839+ } ) ;
840+ } ) ;
628841} ) ;
629842
630843function mockedOptions ( options : Partial < ReactNativeClientOptions > ) : ReactNativeClientOptions {
@@ -638,3 +851,23 @@ function mockedOptions(options: Partial<ReactNativeClientOptions>): ReactNativeC
638851 ...options ,
639852 } ;
640853}
854+
855+ function createClientWithSpy ( options : Partial < ReactNativeClientOptions > ) {
856+ const onSpy = jest . fn ( ) ;
857+ class SpyClient extends ReactNativeClient {
858+ public on ( hook : string , callback : unknown ) : ( ) => void {
859+ onSpy ( hook , callback ) ;
860+ // @ts -expect-error - the public interface doesn't allow string and unknown
861+ return super . on ( hook , callback ) ;
862+ }
863+ }
864+
865+ return {
866+ client : new SpyClient ( {
867+ ...DEFAULT_OPTIONS ,
868+ dsn : EXAMPLE_DSN ,
869+ ...options ,
870+ } ) ,
871+ onSpy,
872+ } ;
873+ }
0 commit comments