@@ -57,7 +57,7 @@ const leadQueryResponse = {
5757 ] ,
5858} ;
5959
60- const ownerQueryResponse = {
60+ const _ownerQueryResponse = {
6161 records : [
6262 {
6363 Id : "owner001" ,
@@ -88,14 +88,19 @@ vi.mock("./graphql/SalesforceGraphQLClient", () => ({
8888
8989describe ( "SalesforceCRMService" , ( ) => {
9090 let service : SalesforceCRMService ;
91- let mockConnection : { query : any ; sobject : any } ;
91+ let mockConnection : {
92+ query : ReturnType < typeof vi . fn > ;
93+ sobject : ReturnType < typeof vi . fn > ;
94+ search : ReturnType < typeof vi . fn > ;
95+ } ;
9296
9397 setupAndTeardown ( ) ;
9498
9599 beforeEach ( ( ) => {
96100 mockConnection = {
97101 query : vi . fn ( ) ,
98102 sobject : vi . fn ( ) ,
103+ search : vi . fn ( ) ,
99104 } ;
100105
101106 const mockCredential : CredentialPayload = {
@@ -334,7 +339,7 @@ describe("SalesforceCRMService", () => {
334339
335340 expect ( querySpy ) . toHaveBeenNthCalledWith (
336341 1 ,
337- "SELECT Id, Email, OwnerId, AccountId, Account.Owner.Email, Account.Website FROM Contact WHERE Email = 'test@example.com' AND AccountId != null"
342+ "SELECT Id, Email, OwnerId, AccountId, Account.OwnerId, Account. Owner.Email, Account.Website FROM Contact WHERE Email = 'test@example.com' AND AccountId != null"
338343 ) ;
339344 } ) ;
340345 } ) ;
@@ -424,7 +429,7 @@ describe("SalesforceCRMService", () => {
424429
425430 expect ( querySpy ) . toHaveBeenNthCalledWith (
426431 1 ,
427- "SELECT Id, Email, OwnerId, AccountId, Account.Owner.Email, Account.Website FROM Contact WHERE Email = 'test@example.com' AND AccountId != null"
432+ "SELECT Id, Email, OwnerId, AccountId, Account.OwnerId, Account. Owner.Email, Account.Website FROM Contact WHERE Email = 'test@example.com' AND AccountId != null"
428433 ) ;
429434 } ) ;
430435 } ) ;
@@ -522,6 +527,224 @@ describe("SalesforceCRMService", () => {
522527 } ) ;
523528 } ) ;
524529
530+ describe ( "getContactOrLeadFromEmail via getContacts" , ( ) => {
531+ describe ( "with roundRobinSkipFallbackToLeadOwner enabled" , ( ) => {
532+ it ( "should return contact when contact is found" , async ( ) => {
533+ mockAppOptions ( {
534+ createEventOn : SalesforceRecordEnum . CONTACT ,
535+ roundRobinSkipCheckRecordOn : SalesforceRecordEnum . CONTACT ,
536+ roundRobinSkipFallbackToLeadOwner : true ,
537+ } ) ;
538+
539+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
540+ searchSpy . mockResolvedValueOnce ( {
541+ searchRecords : [
542+ {
543+ Id : "contact001" ,
544+ Email : "test@example.com" ,
545+ OwnerId : "owner001" ,
546+ attributes : { type : "Contact" } ,
547+ Owner : { Email : "owner@example.com" } ,
548+ } ,
549+ ] ,
550+ } ) ;
551+
552+ const result = await service . getContacts ( {
553+ emails : "test@example.com" ,
554+ forRoundRobinSkip : true ,
555+ } ) ;
556+
557+ expect ( result ) . toEqual ( [
558+ {
559+ id : "contact001" ,
560+ email : "test@example.com" ,
561+ ownerId : "owner001" ,
562+ ownerEmail : "owner@example.com" ,
563+ recordType : "Contact" ,
564+ } ,
565+ ] ) ;
566+
567+ expect ( searchSpy ) . toHaveBeenCalledWith (
568+ "FIND {test@example.com} IN EMAIL FIELDS RETURNING Lead(Id, Email, OwnerId, Owner.Email), Contact(Id, Email, OwnerId, Owner.Email)"
569+ ) ;
570+ } ) ;
571+
572+ it ( "should return lead when no contact exists but lead is found" , async ( ) => {
573+ mockAppOptions ( {
574+ createEventOn : SalesforceRecordEnum . CONTACT ,
575+ roundRobinSkipCheckRecordOn : SalesforceRecordEnum . CONTACT ,
576+ roundRobinSkipFallbackToLeadOwner : true ,
577+ } ) ;
578+
579+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
580+ searchSpy . mockResolvedValueOnce ( {
581+ searchRecords : [
582+ {
583+ Id : "lead001" ,
584+ Email : "test@example.com" ,
585+ OwnerId : "owner001" ,
586+ attributes : { type : "Lead" } ,
587+ Owner : { Email : "owner@example.com" } ,
588+ } ,
589+ ] ,
590+ } ) ;
591+
592+ const result = await service . getContacts ( {
593+ emails : "test@example.com" ,
594+ forRoundRobinSkip : true ,
595+ } ) ;
596+
597+ expect ( result ) . toEqual ( [
598+ {
599+ id : "lead001" ,
600+ email : "test@example.com" ,
601+ ownerId : "owner001" ,
602+ ownerEmail : "owner@example.com" ,
603+ recordType : "Lead" ,
604+ } ,
605+ ] ) ;
606+
607+ expect ( searchSpy ) . toHaveBeenCalled ( ) ;
608+ } ) ;
609+
610+ it ( "should prefer contact over lead when both exist" , async ( ) => {
611+ mockAppOptions ( {
612+ createEventOn : SalesforceRecordEnum . CONTACT ,
613+ roundRobinSkipCheckRecordOn : SalesforceRecordEnum . CONTACT ,
614+ roundRobinSkipFallbackToLeadOwner : true ,
615+ } ) ;
616+
617+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
618+ searchSpy . mockResolvedValueOnce ( {
619+ searchRecords : [
620+ {
621+ Id : "lead001" ,
622+ Email : "test@example.com" ,
623+ OwnerId : "owner002" ,
624+ attributes : { type : "Lead" } ,
625+ Owner : { Email : "lead-owner@example.com" } ,
626+ } ,
627+ {
628+ Id : "contact001" ,
629+ Email : "test@example.com" ,
630+ OwnerId : "owner001" ,
631+ attributes : { type : "Contact" } ,
632+ Owner : { Email : "contact-owner@example.com" } ,
633+ } ,
634+ ] ,
635+ } ) ;
636+
637+ const result = await service . getContacts ( {
638+ emails : "test@example.com" ,
639+ forRoundRobinSkip : true ,
640+ } ) ;
641+
642+ expect ( result ) . toEqual ( [
643+ {
644+ id : "contact001" ,
645+ email : "test@example.com" ,
646+ ownerId : "owner001" ,
647+ ownerEmail : "contact-owner@example.com" ,
648+ recordType : "Contact" ,
649+ } ,
650+ ] ) ;
651+
652+ expect ( searchSpy ) . toHaveBeenCalled ( ) ;
653+ } ) ;
654+
655+ it ( "should return empty array when no records found" , async ( ) => {
656+ mockAppOptions ( {
657+ createEventOn : SalesforceRecordEnum . CONTACT ,
658+ roundRobinSkipCheckRecordOn : SalesforceRecordEnum . CONTACT ,
659+ roundRobinSkipFallbackToLeadOwner : true ,
660+ } ) ;
661+
662+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
663+ searchSpy . mockResolvedValueOnce ( {
664+ searchRecords : [ ] ,
665+ } ) ;
666+
667+ const result = await service . getContacts ( {
668+ emails : "test@example.com" ,
669+ forRoundRobinSkip : true ,
670+ } ) ;
671+
672+ expect ( result ) . toEqual ( [ ] ) ;
673+ expect ( searchSpy ) . toHaveBeenCalled ( ) ;
674+ } ) ;
675+ } ) ;
676+
677+ describe ( "with createEventOnLeadCheckForContact enabled" , ( ) => {
678+ it ( "should find and return contact when it exists" , async ( ) => {
679+ mockAppOptions ( {
680+ createEventOn : SalesforceRecordEnum . LEAD ,
681+ createEventOnLeadCheckForContact : true ,
682+ } ) ;
683+
684+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
685+ searchSpy . mockResolvedValueOnce ( {
686+ searchRecords : [
687+ {
688+ Id : "contact001" ,
689+ Email : "test@example.com" ,
690+ OwnerId : "owner001" ,
691+ attributes : { type : "Contact" } ,
692+ Owner : { Email : "owner@example.com" } ,
693+ } ,
694+ ] ,
695+ } ) ;
696+
697+ const result = await service . getContacts ( {
698+ emails : "test@example.com" ,
699+ } ) ;
700+
701+ expect ( result ) . toEqual ( [
702+ {
703+ id : "contact001" ,
704+ email : "test@example.com" ,
705+ recordType : "Contact" ,
706+ } ,
707+ ] ) ;
708+
709+ expect ( searchSpy ) . toHaveBeenCalled ( ) ;
710+ } ) ;
711+
712+ it ( "should fallback to lead when contact not found" , async ( ) => {
713+ mockAppOptions ( {
714+ createEventOn : SalesforceRecordEnum . LEAD ,
715+ createEventOnLeadCheckForContact : true ,
716+ } ) ;
717+
718+ const searchSpy = vi . spyOn ( mockConnection , "search" ) ;
719+ searchSpy . mockResolvedValueOnce ( {
720+ searchRecords : [
721+ {
722+ Id : "lead001" ,
723+ Email : "test@example.com" ,
724+ OwnerId : "owner001" ,
725+ attributes : { type : "Lead" } ,
726+ Owner : { Email : "owner@example.com" } ,
727+ } ,
728+ ] ,
729+ } ) ;
730+
731+ const result = await service . getContacts ( {
732+ emails : "test@example.com" ,
733+ } ) ;
734+
735+ expect ( result ) . toEqual ( [
736+ {
737+ id : "lead001" ,
738+ email : "test@example.com" ,
739+ recordType : "Lead" ,
740+ } ,
741+ ] ) ;
742+
743+ expect ( searchSpy ) . toHaveBeenCalled ( ) ;
744+ } ) ;
745+ } ) ;
746+ } ) ;
747+
525748 describe ( "createContacts" , ( ) => {
526749 describe ( "createEventOn lead" , ( ) => {
527750 describe ( "createNewContactUnderAccount enabled" , ( ) => {
0 commit comments