@@ -138,11 +138,13 @@ const mockEventService: jest.Mocked<Partial<EventService>> = {
138138 postDirectBusMessage : jest . fn ( ) ,
139139} ;
140140
141- const mockMemberPrisma : Partial < MemberPrismaService > = {
141+ const memberUpdateMock = jest . fn ( ) ;
142+ const mockMemberPrisma : any = {
142143 // Only the parts used by UserService need to be mocked
143144 member : {
144145 create : jest . fn ( ) ,
145- } as any ,
146+ update : memberUpdateMock ,
147+ } ,
146148} ;
147149
148150const mockConfigService = {
@@ -1562,6 +1564,8 @@ describe('UserService', () => {
15621564 beforeEach ( ( ) => {
15631565 jest . clearAllMocks ( ) ;
15641566
1567+ memberUpdateMock . mockResolvedValue ( undefined ) ;
1568+
15651569 // Mock checkEmailAvailabilityForUser
15661570 mockCheckEmail = jest
15671571 . spyOn ( service , 'checkEmailAvailabilityForUser' )
@@ -1652,6 +1656,10 @@ describe('UserService', () => {
16521656 { userId : 1 , handle : 'testuser' } ,
16531657 ) ;
16541658 expect ( result ) . toEqual ( mockUser ) ;
1659+ expect ( memberUpdateMock ) . toHaveBeenCalledWith ( {
1660+ where : { userId } ,
1661+ data : { email : newEmail . toLowerCase ( ) } ,
1662+ } ) ;
16551663 } ) ;
16561664
16571665 it ( 'should throw BadRequestException for invalid user ID format' , async ( ) => {
@@ -1863,6 +1871,48 @@ describe('UserService', () => {
18631871 ) ;
18641872 } ) ;
18651873
1874+ it ( 'should log an error if members.member update fails but continue' , async ( ) => {
1875+ const txMock = {
1876+ user : {
1877+ findUnique : jest . fn ( ) . mockResolvedValue ( mockUser ) ,
1878+ update : jest . fn ( ) . mockResolvedValue ( mockUser ) ,
1879+ } ,
1880+ email : {
1881+ findFirst : jest
1882+ . fn ( )
1883+ . mockResolvedValueOnce ( mockCurrentEmailRecord )
1884+ . mockResolvedValueOnce ( null ) ,
1885+ update : jest . fn ( ) . mockResolvedValue ( mockUpdatedEmailRecord ) ,
1886+ } ,
1887+ } ;
1888+ mockPrismaOltp . $transaction . mockImplementation (
1889+ < T > ( callback ) : Promise < T > => {
1890+ const result = callback ( txMock ) ;
1891+ return result instanceof Promise ? result : Promise . resolve ( result ) ;
1892+ } ,
1893+ ) ;
1894+
1895+ memberUpdateMock . mockRejectedValueOnce (
1896+ new Error ( 'Member update failed' ) ,
1897+ ) ;
1898+
1899+ const result = await service . updatePrimaryEmail (
1900+ userIdString ,
1901+ newEmail ,
1902+ mockAuthUser ,
1903+ ) ;
1904+
1905+ expect ( result ) . toEqual ( mockUser ) ;
1906+ expect ( memberUpdateMock ) . toHaveBeenCalledWith ( {
1907+ where : { userId } ,
1908+ data : { email : newEmail . toLowerCase ( ) } ,
1909+ } ) ;
1910+ expect ( loggerErrorSpy ) . toHaveBeenCalledWith (
1911+ expect . stringContaining ( 'Failed to update members.member email' ) ,
1912+ expect . any ( String ) ,
1913+ ) ;
1914+ } ) ;
1915+
18661916 it ( 'should handle case when updated email record is not found after transaction' , async ( ) => {
18671917 // Set up transaction mock
18681918 const txMock = {
@@ -1965,6 +2015,7 @@ describe('UserService', () => {
19652015 const userIdString = '1' ;
19662016 const oldStatus = 'U' ;
19672017 const newStatus = 'A' ; // Unverified to Active
2018+ const statusComment = 'Unit test comment' ;
19682019 const mockExistingUser = createMockUserModel ( {
19692020 user_id : new Decimal ( userId ) ,
19702021 status : oldStatus ,
@@ -1992,6 +2043,7 @@ describe('UserService', () => {
19922043 userIdString ,
19932044 newStatus ,
19942045 mockUser ,
2046+ statusComment ,
19952047 ) ;
19962048
19972049 expect ( prismaOltp . user . update ) . toHaveBeenCalledWith ( {
@@ -2023,7 +2075,7 @@ describe('UserService', () => {
20232075 prismaOltp . user . findUnique . mockResolvedValue ( fromActiveUser ) ;
20242076 prismaOltp . user . update . mockResolvedValue ( toInactiveUser ) ;
20252077
2026- await service . updateStatus ( userIdString , 'I' , mockUser ) ;
2078+ await service . updateStatus ( userIdString , 'I' , mockUser , statusComment ) ;
20272079 expect ( mockEventService . postEnvelopedNotification ) . toHaveBeenCalledWith (
20282080 'event.user.deactivated' ,
20292081 service . toCamelCase ( toInactiveUser ) ,
@@ -2037,17 +2089,17 @@ describe('UserService', () => {
20372089
20382090 it ( 'should throw BadRequest for invalid user ID or status code' , async ( ) => {
20392091 await expect (
2040- service . updateStatus ( 'abc' , newStatus , mockUser ) ,
2092+ service . updateStatus ( 'abc' , newStatus , mockUser , statusComment ) ,
20412093 ) . rejects . toThrow ( BadRequestException ) ;
20422094 await expect (
2043- service . updateStatus ( userIdString , 'X' , mockUser ) ,
2095+ service . updateStatus ( userIdString , 'X' , mockUser , statusComment ) ,
20442096 ) . rejects . toThrow ( BadRequestException ) ;
20452097 } ) ;
20462098
20472099 it ( 'should throw NotFoundException if user not found' , async ( ) => {
20482100 prismaOltp . user . findUnique . mockResolvedValue ( null ) ;
20492101 await expect (
2050- service . updateStatus ( userIdString , newStatus , mockUser ) ,
2102+ service . updateStatus ( userIdString , newStatus , mockUser , statusComment ) ,
20512103 ) . rejects . toThrow ( NotFoundException ) ;
20522104 } ) ;
20532105
@@ -2056,6 +2108,7 @@ describe('UserService', () => {
20562108 userIdString ,
20572109 oldStatus ,
20582110 mockUser ,
2111+ statusComment ,
20592112 ) ;
20602113 expect ( prismaOltp . user . update ) . not . toHaveBeenCalled ( ) ;
20612114 expect ( result ) . toEqual ( mockExistingUser ) ;
0 commit comments