@@ -67,6 +67,7 @@ import {
6767 Reference ,
6868 type NotificationAwardContext ,
6969 type NotificationOpportunityMatchContext ,
70+ type NotificationWarmIntroContext ,
7071} from '../../src/notifications' ;
7172import { postsFixture } from '../fixture/post' ;
7273import { sourcesFixture } from '../fixture/source' ;
@@ -96,6 +97,8 @@ import { BriefPost } from '../../src/entity/posts/BriefPost';
9697import { CampaignUpdateEvent } from '../../src/common/campaign/common' ;
9798import { Opportunity } from '../../src/entity/opportunities/Opportunity' ;
9899import { OpportunityMatch } from '../../src/entity/OpportunityMatch' ;
100+ import { OpportunityUserRecruiter } from '../../src/entity/opportunities/user' ;
101+ import { OpportunityUserType } from '../../src/entity/opportunities/types' ;
99102import {
100103 opportunitiesFixture ,
101104 opportunityMatchesFixture ,
@@ -2749,3 +2752,74 @@ describe('poll result notifications', () => {
27492752 expect ( args . transactional_message_id ) . toEqual ( '84' ) ;
27502753 } ) ;
27512754} ) ;
2755+
2756+ describe ( 'warm_intro notification' , ( ) => {
2757+ it ( 'should send email to both candidate and recruiter' , async ( ) => {
2758+ await saveFixtures ( con , Organization , organizationsFixture ) ;
2759+ await saveFixtures ( con , Opportunity , opportunitiesFixture ) ;
2760+ await saveFixtures ( con , OpportunityMatch , opportunityMatchesFixture ) ;
2761+
2762+ // Create a recruiter user
2763+ const recruiter = await con . getRepository ( User ) . save ( {
2764+ id : 'recruiter123' ,
2765+ name : 'John Recruiter' ,
2766+ email : 'recruiter@test.com' ,
2767+ username : 'recruiter' ,
2768+ } ) ;
2769+
2770+ // Link recruiter to opportunity
2771+ await con . getRepository ( OpportunityUserRecruiter ) . save ( {
2772+ opportunityId : opportunitiesFixture [ 0 ] . id ,
2773+ userId : recruiter . id ,
2774+ type : OpportunityUserType . Recruiter ,
2775+ } ) ;
2776+
2777+ // Update opportunity match with warmIntro
2778+ await con . getRepository ( OpportunityMatch ) . update (
2779+ {
2780+ opportunityId : opportunitiesFixture [ 0 ] . id ,
2781+ userId : '1' ,
2782+ } ,
2783+ {
2784+ applicationRank : {
2785+ warmIntro : '<p>Great match based on your experience!</p>' ,
2786+ } ,
2787+ } ,
2788+ ) ;
2789+
2790+ const ctx : NotificationWarmIntroContext = {
2791+ userIds : [ '1' ] ,
2792+ opportunityId : opportunitiesFixture [ 0 ] . id ,
2793+ description : 'Great match based on your experience!' ,
2794+ recruiter,
2795+ organization : organizationsFixture [ 0 ] ,
2796+ } ;
2797+
2798+ const notificationId = await saveNotificationV2Fixture (
2799+ con ,
2800+ NotificationType . WarmIntro ,
2801+ ctx ,
2802+ ) ;
2803+
2804+ await expectSuccessfulBackground ( worker , {
2805+ notification : {
2806+ id : notificationId ,
2807+ userId : '1' ,
2808+ } ,
2809+ } ) ;
2810+
2811+ expect ( sendEmail ) . toHaveBeenCalledTimes ( 1 ) ;
2812+ const args = jest . mocked ( sendEmail ) . mock
2813+ . calls [ 0 ] [ 0 ] as SendEmailRequestWithTemplate ;
2814+
2815+ expect ( args . message_data ) . toEqual ( {
2816+ title : `It's a match!` ,
2817+ copy : '<p>Great match based on your experience!</p>' ,
2818+ cc : 'recruiter@test.com' ,
2819+ } ) ;
2820+
2821+ // Verify both emails are in the 'to' field
2822+ expect ( args . to ) . toEqual ( 'ido@daily.dev,recruiter@test.com' ) ;
2823+ expect ( args . transactional_message_id ) . toEqual ( '85' ) ;
2824+ } ) ;
2825+ } ) ;
0 commit comments