diff --git a/src/main/java/uk/gov/companieshouse/accounts/association/configuration/AsyncEmailConfig.java b/src/main/java/uk/gov/companieshouse/accounts/association/configuration/AsyncEmailConfig.java deleted file mode 100644 index 6f8626a..0000000 --- a/src/main/java/uk/gov/companieshouse/accounts/association/configuration/AsyncEmailConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package uk.gov.companieshouse.accounts.association.configuration; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableAsync; - -@Configuration -@EnableAsync -@ComponentScan(basePackages = "uk.gov.companieshouse.email_producer") -public class AsyncEmailConfig { - - -} diff --git a/src/main/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociations.java b/src/main/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociations.java index bedebe4..0fffeaf 100644 --- a/src/main/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociations.java +++ b/src/main/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociations.java @@ -5,6 +5,8 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import uk.gov.companieshouse.accounts.association.exceptions.BadRequestRuntimeException; import uk.gov.companieshouse.accounts.association.exceptions.NotFoundRuntimeException; import uk.gov.companieshouse.accounts.association.models.AssociationDao; @@ -18,17 +20,14 @@ import uk.gov.companieshouse.api.accounts.associations.api.UserCompanyAssociationsInterface; import uk.gov.companieshouse.api.accounts.associations.model.*; import uk.gov.companieshouse.api.accounts.associations.model.Association.ApprovalRouteEnum; -import uk.gov.companieshouse.api.accounts.user.model.User; import uk.gov.companieshouse.api.company.CompanyDetails; import uk.gov.companieshouse.logging.Logger; import uk.gov.companieshouse.logging.LoggerFactory; import java.time.LocalDateTime; -import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.function.Supplier; import static uk.gov.companieshouse.accounts.association.utils.RequestContextUtil.getXRequestId; import static uk.gov.companieshouse.api.accounts.associations.model.Association.StatusEnum.AWAITING_APPROVAL; @@ -97,8 +96,12 @@ public ResponseEntity addAssociation(final String xRequestId, } LOG.debugContext( xRequestId, String.format( "Attempting to create requests for users associated with company %s", companyNumber ), null ); - final var associatedUsers = associationsService.fetchAssociatedUsers( companyNumber ); - emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( xRequestId, companyDetails, displayName, associatedUsers ); + + Mono.just( companyNumber ) + .map( associationsService::fetchAssociatedUsers ) + .flatMapMany( Flux::fromIterable ) + .flatMap( emailService.sendAuthCodeConfirmationEmailToAssociatedUser( xRequestId, companyDetails, displayName ) ) + .subscribe(); return new ResponseEntity<>(new ResponseBodyPost().associationId(association.getId()), HttpStatus.CREATED); } @@ -223,7 +226,10 @@ public ResponseEntity inviteUser(final String xRequestId, fina final var inviterDisplayName = Optional.ofNullable( inviterUserDetails.getDisplayName() ).orElse( inviterUserDetails.getEmail() ); LOG.debugContext( xRequestId, String.format( "Attempting to create requests for users associated with company %s", companyNumber ), null ); - final var associatedUsers = associationsService.fetchAssociatedUsers( companyNumber ); + final var cachedAssociatedUsers = Mono.just( companyNumber ) + .map( associationsService::fetchAssociatedUsers ) + .flatMapMany( Flux::fromIterable ) + .cache(); final var inviteeUserDetails = usersService.searchUserDetails( List.of( inviteeEmail ) ); @@ -242,8 +248,8 @@ public ResponseEntity inviteUser(final String xRequestId, fina LOG.debugContext( xRequestId, String.format( "Attempting to create new invitation. Association's id: %s", association.getId() ), null ); final var invitationAssociation = associationsService.sendNewInvitation(ericIdentity, association); LOG.infoContext( xRequestId, String.format( "Created new invitation. Association's id: %s", invitationAssociation.getId() ), null ); - emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, invitationAssociation.getApprovalExpiryAt().toString(), inviteeEmail ); - emailService.sendInvitationEmailToAssociatedUsers( xRequestId, companyDetails, inviterDisplayName,inviteeEmail, associatedUsers ); + emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, invitationAssociation.getApprovalExpiryAt().toString(), inviteeEmail ).subscribe(); + cachedAssociatedUsers.flatMap( emailService.sendInvitationEmailToAssociatedUser( xRequestId, companyDetails, inviterDisplayName, inviteeEmail ) ).subscribe(); return new ResponseEntity<>( new ResponseBodyPost().associationId( invitationAssociation.getId() ), HttpStatus.CREATED ); } @@ -259,8 +265,8 @@ public ResponseEntity inviteUser(final String xRequestId, fina LOG.debugContext( xRequestId, String.format( "Attempting to create new invitation. Association's for user %s and company", inviteeUserId, companyNumber ), null ); association = associationsService.createAssociation(companyNumber,inviteeUserId,null,ApprovalRouteEnum.INVITATION,ericIdentity); LOG.infoContext( xRequestId, String.format( "Created new invitation. Association's id: %s", association.getId() ), null ); - emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ); - emailService.sendInvitationEmailToAssociatedUsers( xRequestId, companyDetails, inviterDisplayName,inviteeDisplayName, associatedUsers ); + emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ).subscribe(); + cachedAssociatedUsers.flatMap( emailService.sendInvitationEmailToAssociatedUser( xRequestId, companyDetails, inviterDisplayName, inviteeDisplayName ) ).subscribe(); return new ResponseEntity<>( new ResponseBodyPost().associationId( association.getId() ), HttpStatus.CREATED ); } else if(associationWithUserID.get().getStatus().equals("confirmed")) { LOG.errorContext( xRequestId, new Exception( String.format( "%s already has a confirmed association at company %s", inviteeEmail, companyNumber ) ), null ); @@ -269,17 +275,16 @@ public ResponseEntity inviteUser(final String xRequestId, fina LOG.debugContext( xRequestId, String.format( "Attempting to create new invitation. Association's id: %s", associationWithUserID.get().getId() ), null ); association = associationsService.sendNewInvitation(ericIdentity, associationWithUserID.get()); LOG.infoContext( xRequestId, String.format( "Created new invitation. Association's id: %s", association.getId() ), null ); - emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ); - emailService.sendInvitationEmailToAssociatedUsers( xRequestId, companyDetails, inviterDisplayName,inviteeDisplayName, associatedUsers ); + emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ).subscribe(); + cachedAssociatedUsers.flatMap( emailService.sendInvitationEmailToAssociatedUser( xRequestId, companyDetails, inviterDisplayName, inviteeDisplayName ) ).subscribe(); return new ResponseEntity<>( new ResponseBodyPost().associationId( association.getId() ), HttpStatus.CREATED ); } //if association with email not found, user not found LOG.debugContext( xRequestId, String.format( "Attempting to create new invitation for user %s and company %s", inviteeEmail, companyNumber ), null ); association = associationsService.createAssociation(companyNumber, null ,inviteeEmail,ApprovalRouteEnum.INVITATION,ericIdentity); LOG.infoContext( xRequestId, String.format( "Created new invitation. Association's id: %s", association.getId() ), null ); - emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ); - emailService.sendInvitationEmailToAssociatedUsers( xRequestId, companyDetails, inviterDisplayName,inviteeEmail, associatedUsers ); - + emailService.sendInviteEmail( xRequestId, companyDetails, inviterDisplayName, association.getApprovalExpiryAt().toString(), inviteeEmail ).subscribe(); + cachedAssociatedUsers.flatMap( emailService.sendInvitationEmailToAssociatedUser( xRequestId, companyDetails, inviterDisplayName, inviteeEmail ) ).subscribe(); return new ResponseEntity<>( new ResponseBodyPost().associationId( association.getId() ), HttpStatus.CREATED ); } @@ -369,40 +374,41 @@ public ResponseEntity updateAssociationStatusForId( final String xRequestI return new ResponseEntity<>( HttpStatus.OK ); } - private void sendEmailNotificationForStatusUpdate(String xRequestId, String requestingUserDisplayValue, String targetUserDisplayValue, boolean requestingAndTargetUserMatches, RequestBodyPut.StatusEnum newStatus, String oldStatus, AssociationDao associationDao) { - final String companyNumber = associationDao.getCompanyNumber(); - final List invitations = associationDao.getInvitations(); - - final var companyDetails = companyService.fetchCompanyProfile(companyNumber); - LOG.debugContext( xRequestId, String.format( "Attempting to create requests for users associated with company %s", companyNumber ), null ); - final var requestsToFetchAssociatedUsers = associationsService.fetchAssociatedUsers(companyNumber); - - final var authorisedUserRemoved = oldStatus.equals(CONFIRMED.getValue()) && newStatus.equals(REMOVED); - final var userAcceptedInvitation = requestingAndTargetUserMatches && oldStatus.equals(AWAITING_APPROVAL.getValue()) && newStatus.equals(CONFIRMED); - final var userCancelledInvitation = !requestingAndTargetUserMatches && oldStatus.equals(AWAITING_APPROVAL.getValue()) && newStatus.equals(REMOVED); - final var userRejectedInvitation = requestingAndTargetUserMatches && oldStatus.equals(AWAITING_APPROVAL.getValue()) && newStatus.equals(REMOVED); - - if (userRejectedInvitation) { - emailService.sendInvitationRejectedEmailToAssociatedUsers(xRequestId, companyDetails, requestingUserDisplayValue, requestsToFetchAssociatedUsers); - } else if (authorisedUserRemoved) { - emailService.sendAuthorisationRemovedEmailToRemovedUser(xRequestId, companyDetails, requestingUserDisplayValue, associationDao.getUserId()); - emailService.sendAuthorisationRemovedEmailToAssociatedUsers(xRequestId, companyDetails, requestingUserDisplayValue, targetUserDisplayValue, requestsToFetchAssociatedUsers); - } else if (userAcceptedInvitation) { - final var invitedByDisplayName = invitations.stream() - .max(Comparator.comparing(InvitationDao::getInvitedAt)) - .map(InvitationDao::getInvitedBy) - .map(usersService::fetchUserDetails) - .map(user -> Optional.ofNullable(user.getDisplayName()).orElse(user.getEmail())) - .orElseThrow(() -> new NullPointerException("Inviter does not exist.")); - - emailService.sendInvitationAcceptedEmailToAssociatedUsers(xRequestId, companyDetails, invitedByDisplayName, requestingUserDisplayValue, requestsToFetchAssociatedUsers); - } else if (userCancelledInvitation) { - final Supplier requestToGetCancelledUserEmail = Objects.isNull( associationDao.getUserEmail() ) ? () -> usersService.fetchUserDetails( associationDao.getUserId() ) : () -> new User().email( associationDao.getUserEmail() ); - emailService.sendInviteCancelledEmail(xRequestId, companyDetails, requestingUserDisplayValue, requestToGetCancelledUserEmail ); - emailService.sendInvitationCancelledEmailToAssociatedUsers(xRequestId, companyDetails, requestingUserDisplayValue, targetUserDisplayValue, requestsToFetchAssociatedUsers); + private void sendEmailNotificationForStatusUpdate( final String xRequestId, final String requestingUserDisplayValue, final String targetUserDisplayValue, final boolean requestingAndTargetUserMatches, final RequestBodyPut.StatusEnum newStatus, final String oldStatus, final AssociationDao associationDao ) { + final var cachedCompanyName = Mono.just( associationDao.getCompanyNumber() ) + .map( companyService::fetchCompanyProfile ) + .map( CompanyDetails::getCompanyName ) + .cache(); + + final var cachedAssociatedUsers = + Mono.just( associationDao.getCompanyNumber() ) + .map( associationsService::fetchAssociatedUsers ) + .flatMapMany( Flux::fromIterable ) + .cache(); + + final var cachedInvitedByDisplayName = Mono.just( associationDao ) + .map( AssociationDao::getInvitations ) + .flatMapMany( Flux::fromIterable ) + .reduce( (firstInvitation, secondInvitation) -> firstInvitation.getInvitedAt().isAfter( secondInvitation.getInvitedAt() ) ? firstInvitation : secondInvitation ) + .map( InvitationDao::getInvitedBy ) + .map( usersService::fetchUserDetails ) + .map( user -> Optional.ofNullable( user.getDisplayName() ).orElse( user.getEmail() ) ) + .cache(); + + var emails = Flux.empty(); + if ( requestingAndTargetUserMatches && oldStatus.equals( AWAITING_APPROVAL.getValue() ) && newStatus.equals( REMOVED ) ) { + emails = emails.concatWith( cachedAssociatedUsers.flatMap( emailService.sendInvitationRejectedEmailToAssociatedUser( xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, requestingUserDisplayValue ) ) ); + } else if ( oldStatus.equals( CONFIRMED.getValue() ) && newStatus.equals( REMOVED ) ) { + emails = emails.concatWith( emailService.sendAuthorisationRemovedEmailToRemovedUser( xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, requestingUserDisplayValue, associationDao.getUserId() ) ); + emails = emails.concatWith( cachedAssociatedUsers.flatMap( emailService.sendAuthorisationRemovedEmailToAssociatedUser( xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, requestingUserDisplayValue, targetUserDisplayValue ) ) ); + } else if ( requestingAndTargetUserMatches && oldStatus.equals( AWAITING_APPROVAL.getValue() ) && newStatus.equals( CONFIRMED ) ) { + emails = emails.concatWith( cachedAssociatedUsers.flatMap( emailService.sendInvitationAcceptedEmailToAssociatedUser( xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, cachedInvitedByDisplayName, requestingUserDisplayValue ) ) ); + } else if ( !requestingAndTargetUserMatches && oldStatus.equals( AWAITING_APPROVAL.getValue() ) && newStatus.equals( REMOVED ) ) { + emails = emails.concatWith( emailService.sendInviteCancelledEmail(xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, requestingUserDisplayValue, associationDao ) ); + emails = emails.concatWith( cachedAssociatedUsers.flatMap( emailService.sendInvitationCancelledEmailToAssociatedUser( xRequestId, associationDao.getCompanyNumber(), cachedCompanyName, requestingUserDisplayValue, targetUserDisplayValue ) ) ); } + emails.subscribe(); } - } diff --git a/src/main/java/uk/gov/companieshouse/accounts/association/service/EmailService.java b/src/main/java/uk/gov/companieshouse/accounts/association/service/EmailService.java index 80b4925..c49b1cb 100644 --- a/src/main/java/uk/gov/companieshouse/accounts/association/service/EmailService.java +++ b/src/main/java/uk/gov/companieshouse/accounts/association/service/EmailService.java @@ -1,101 +1,55 @@ package uk.gov.companieshouse.accounts.association.service; +import java.util.Objects; +import java.util.function.Function; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; +import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; +import uk.gov.companieshouse.accounts.association.models.AssociationDao; import uk.gov.companieshouse.accounts.association.models.email.EmailNotification; import uk.gov.companieshouse.accounts.association.models.email.builders.*; import uk.gov.companieshouse.accounts.association.utils.MessageType; -import uk.gov.companieshouse.accounts.association.utils.StaticPropertyUtil; import uk.gov.companieshouse.api.accounts.user.model.User; import uk.gov.companieshouse.api.company.CompanyDetails; import uk.gov.companieshouse.email_producer.EmailProducer; +import uk.gov.companieshouse.email_producer.model.EmailData; import uk.gov.companieshouse.logging.Logger; import uk.gov.companieshouse.logging.LoggerFactory; -import java.util.List; -import java.util.function.Supplier; - +import static uk.gov.companieshouse.accounts.association.utils.MessageType.AUTHORISATION_REMOVED_MESSAGE_TYPE; import static uk.gov.companieshouse.accounts.association.utils.MessageType.AUTH_CODE_CONFIRMATION_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_ACCEPTED_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_CANCELLED_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_REJECTED_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITE_CANCELLED_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITE_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.YOUR_AUTHORISATION_REMOVED_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.StaticPropertyUtil.APPLICATION_NAMESPACE; @Service +@ComponentScan( basePackages = "uk.gov.companieshouse.email_producer" ) public class EmailService { @Value( "${invitation.url}" ) private String invitationLink; - protected static final Logger LOG = LoggerFactory.getLogger(StaticPropertyUtil.APPLICATION_NAMESPACE); + protected static final Logger LOG = LoggerFactory.getLogger( APPLICATION_NAMESPACE ); private final UsersService usersService; private final EmailProducer emailProducer; - @Autowired public EmailService( final UsersService usersService, final EmailProducer emailProducer ) { this.usersService = usersService; this.emailProducer = emailProducer; } - @Async - public void sendAuthCodeConfirmationEmailToAssociatedUsers( final String xRequestId, final CompanyDetails companyDetails, final String displayName, final List userIds ) { - userIds.forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new AuthCodeConfirmationEmailBuilder() - .setRecipientEmail( user.getEmail() ) - .setDisplayName( displayName ) - .setCompanyName( companyDetails.getCompanyName() ) - .build(); - - final var logMessageSupplier = new EmailNotification(AUTH_CODE_CONFIRMATION_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber()); - try { - emailProducer.sendEmail( emailData, AUTH_CODE_CONFIRMATION_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, logMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( logMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); - } - - @Async - public void sendAuthorisationRemovedEmailToAssociatedUsers( final String xRequestId, final CompanyDetails companyDetails, final String removedByDisplayName, final String removedUserDisplayName, final List userIds ) { - userIds.forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new AuthorisationRemovedEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setRemovedByDisplayName( removedByDisplayName ) - .setRemovedUserDisplayName( removedUserDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - final var logMessageSupplier = new EmailNotification( MessageType.AUTHORISATION_REMOVED_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, logMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( logMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); - } - - @Async - public void sendAuthorisationRemovedEmailToRemovedUser(final String xRequestId, final CompanyDetails companyDetails, final String removedByDisplayName, final String userId ) { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new YourAuthorisationRemovedEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setRemovedByDisplayName( removedByDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - - final var logMessageSupplier = new EmailNotification( MessageType.YOUR_AUTHORISATION_REMOVED_MESSAGE_TYPE, removedByDisplayName, user.getEmail(), companyDetails.getCompanyNumber() ); + private void sendEmail( final String xRequestId, final MessageType messageType, final EmailData emailData, final EmailNotification logMessageSupplier ){ try { - emailProducer.sendEmail( emailData, MessageType.YOUR_AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ); + emailProducer.sendEmail( emailData, messageType.getValue() ); LOG.infoContext( xRequestId, logMessageSupplier.toMessage(), null ); } catch ( Exception exception ){ LOG.errorContext( xRequestId, new Exception( logMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); @@ -103,137 +57,138 @@ public void sendAuthorisationRemovedEmailToRemovedUser(final String xRequestId, } } - @Async - public void sendInvitationCancelledEmailToAssociatedUsers( final String xRequestId, final CompanyDetails companyDetails, final String cancelledByDisplayName, final String cancelledUserDisplayName, final List userIds ) { - userIds.forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new InvitationCancelledEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setCancelledByDisplayName( cancelledByDisplayName ) - .setCancelledUserDisplayName( cancelledUserDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITATION_CANCELLED_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITATION_CANCELLED_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, loggingMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); + public Function> sendAuthCodeConfirmationEmailToAssociatedUser( final String xRequestId, final CompanyDetails companyDetails, final String displayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new AuthCodeConfirmationEmailBuilder() + .setRecipientEmail( user.getEmail() ) + .setDisplayName( displayName ) + .setCompanyName( companyDetails.getCompanyName() ) + .build() ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( AUTH_CODE_CONFIRMATION_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyDetails.getCompanyNumber() ); + sendEmail( xRequestId, AUTH_CODE_CONFIRMATION_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } - @Async - public void sendInvitationEmailToAssociatedUsers(final String xRequestId, final CompanyDetails companyDetails, final String inviterDisplayName, final String inviteeDisplayName, final List userIds ) { - userIds.forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new InvitationEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setInviteeDisplayName( inviteeDisplayName ) - .setInviterDisplayName( inviterDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITATION_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITATION_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, loggingMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); + public Function> sendAuthorisationRemovedEmailToAssociatedUser( final String xRequestId, final String companyNumber, final Mono companyName, final String removedByDisplayName, final String removedUserDisplayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new AuthorisationRemovedEmailBuilder() + .setRemovedByDisplayName( removedByDisplayName ) + .setRemovedUserDisplayName( removedUserDisplayName ) + .setRecipientEmail( user.getEmail() ) ) + .zipWith( companyName, AuthorisationRemovedEmailBuilder::setCompanyName ) + .map( AuthorisationRemovedEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( AUTHORISATION_REMOVED_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, AUTHORISATION_REMOVED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } - @Async - public void sendInvitationAcceptedEmailToAssociatedUsers(final String xRequestId, final CompanyDetails companyDetails, final String inviterDisplayName, final String inviteeDisplayName, final List userIds ) { - userIds .forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new InvitationAcceptedEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setInviteeDisplayName( inviteeDisplayName ) - .setInviterDisplayName( inviterDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITATION_ACCEPTED_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITATION_ACCEPTED_MESSAGE_TYPE.getValue() ); - LOG.infoContext(xRequestId, loggingMessageSupplier.toMessage(), null); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); + public Mono sendAuthorisationRemovedEmailToRemovedUser( final String xRequestId, final String companyNumber, final Mono companyName, final String removedByDisplayName, final String userId ) { + return Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new YourAuthorisationRemovedEmailBuilder() + .setRemovedByDisplayName( removedByDisplayName ) + .setRecipientEmail( user.getEmail() ) ) + .zipWith( companyName, YourAuthorisationRemovedEmailBuilder::setCompanyName ) + .map( YourAuthorisationRemovedEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( YOUR_AUTHORISATION_REMOVED_MESSAGE_TYPE, removedByDisplayName, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, YOUR_AUTHORISATION_REMOVED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } - @Async - public void sendInvitationRejectedEmailToAssociatedUsers(final String xRequestId, final CompanyDetails companyDetails, final String inviteeDisplayName, final List userIds ) { - userIds.forEach( userId -> { - final var user = usersService.fetchUserDetails( userId ); - - final var emailData = new InvitationRejectedEmailBuilder() - .setCompanyName( companyDetails.getCompanyName() ) - .setInviteeDisplayName( inviteeDisplayName ) - .setRecipientEmail( user.getEmail() ) - .build(); - - - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITATION_REJECTED_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, user.getEmail(), companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITATION_REJECTED_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, loggingMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } - }); + public Function> sendInvitationCancelledEmailToAssociatedUser( final String xRequestId, final String companyNumber, final Mono companyName, final String cancelledByDisplayName, final String cancelledUserDisplayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new InvitationCancelledEmailBuilder() + .setCancelledByDisplayName( cancelledByDisplayName ) + .setCancelledUserDisplayName( cancelledUserDisplayName ) + .setRecipientEmail( user.getEmail() ) ) + .zipWith( companyName, InvitationCancelledEmailBuilder::setCompanyName ) + .map( InvitationCancelledEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITATION_CANCELLED_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, INVITATION_CANCELLED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } - @Async - public void sendInviteEmail( final String xRequestId, final CompanyDetails companyDetails, final String inviterDisplayName, final String invitationExpiryTimestamp, final String inviteeEmail ){ - final var emailData = new InviteEmailBuilder() - .setRecipientEmail( inviteeEmail ) - .setInviterDisplayName( inviterDisplayName ) - .setCompanyName( companyDetails.getCompanyName() ) - .setInvitationExpiryTimestamp( invitationExpiryTimestamp ) - .setInvitationLink( invitationLink ) - .build(); - - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITE_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, inviteeEmail, companyDetails.getCompanyNumber() ).setInvitationExpiryTimestamp( invitationExpiryTimestamp ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITE_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, loggingMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } + public Function> sendInvitationEmailToAssociatedUser( final String xRequestId, final CompanyDetails companyDetails, final String inviterDisplayName, final String inviteeDisplayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new InvitationEmailBuilder() + .setCompanyName( companyDetails.getCompanyName() ) + .setInviteeDisplayName( inviteeDisplayName ) + .setInviterDisplayName( inviterDisplayName ) + .setRecipientEmail( user.getEmail() ) + .build() ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITATION_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyDetails.getCompanyNumber() ); + sendEmail( xRequestId, INVITATION_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } - @Async - public void sendInviteCancelledEmail( final String xRequestId, final CompanyDetails companyDetails, final String cancelledByDisplayName, final Supplier inviteeUserSupplier ){ - final var inviteeEmail = inviteeUserSupplier.get().getEmail(); + public Function> sendInvitationAcceptedEmailToAssociatedUser( final String xRequestId, final String companyNumber, final Mono companyName, final Mono invitedByDisplayName, final String inviteeDisplayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new InvitationAcceptedEmailBuilder() + .setInviteeDisplayName( inviteeDisplayName ) + .setRecipientEmail( user.getEmail() ) ) + .zipWith( invitedByDisplayName, InvitationAcceptedEmailBuilder::setInviterDisplayName ) + .zipWith( companyName, InvitationAcceptedEmailBuilder::setCompanyName ) + .map( InvitationAcceptedEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITATION_ACCEPTED_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, INVITATION_ACCEPTED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); + } - final var emailData = new InviteCancelledEmailBuilder() - .setRecipientEmail( inviteeEmail ) - .setCompanyName( companyDetails.getCompanyName() ) - .setCancelledBy( cancelledByDisplayName ) - .build(); + public Function> sendInvitationRejectedEmailToAssociatedUser( final String xRequestId, final String companyNumber, final Mono companyName, final String inviteeDisplayName ) { + return userId -> Mono.just( userId ) + .map( usersService::fetchUserDetails ) + .map( user -> new InvitationRejectedEmailBuilder() + .setInviteeDisplayName( inviteeDisplayName ) + .setRecipientEmail( user.getEmail() ) ) + .zipWith( companyName, InvitationRejectedEmailBuilder::setCompanyName ) + .map( InvitationRejectedEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITATION_REJECTED_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, INVITATION_REJECTED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); + } - final var loggingMessageSupplier = new EmailNotification( MessageType.INVITE_CANCELLED_MESSAGE_TYPE, StaticPropertyUtil.APPLICATION_NAMESPACE, inviteeEmail, companyDetails.getCompanyNumber() ); - try { - emailProducer.sendEmail( emailData, MessageType.INVITE_CANCELLED_MESSAGE_TYPE.getValue() ); - LOG.infoContext( xRequestId, loggingMessageSupplier.toMessage(), null ); - } catch ( Exception exception ){ - LOG.errorContext( xRequestId, new Exception( loggingMessageSupplier.toMessageSendingFailureLoggingMessage() ), null ); - throw exception; - } + public Mono sendInviteEmail( final String xRequestId, final CompanyDetails companyDetails, final String inviterDisplayName, final String invitationExpiryTimestamp, final String inviteeEmail ){ + return Mono.just( new InviteEmailBuilder() + .setRecipientEmail( inviteeEmail ) + .setInviterDisplayName( inviterDisplayName ) + .setCompanyName( companyDetails.getCompanyName() ) + .setInvitationExpiryTimestamp( invitationExpiryTimestamp ) + .setInvitationLink( invitationLink ) + .build() ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITE_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyDetails.getCompanyNumber() ).setInvitationExpiryTimestamp( invitationExpiryTimestamp ); + sendEmail( xRequestId, INVITE_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); + } + + public Mono sendInviteCancelledEmail( final String xRequestId, final String companyNumber, final Mono companyName, final String cancelledByDisplayName, final AssociationDao associationDao ){ + return Mono.just( associationDao ) + .filter( dao -> Objects.nonNull( dao.getUserId() ) ) + .map( AssociationDao::getUserId ) + .map( usersService::fetchUserDetails ) + .map( User::getEmail ) + .switchIfEmpty( Mono.just( associationDao.getUserEmail() ) ) + .map( inviteeEmail -> new InviteCancelledEmailBuilder() + .setRecipientEmail( inviteeEmail ) + .setCancelledBy( cancelledByDisplayName ) ) + .zipWith( companyName, InviteCancelledEmailBuilder::setCompanyName ) + .map( InviteCancelledEmailBuilder::build ) + .doOnNext( emailData -> { + final var logMessageSupplier = new EmailNotification( INVITE_CANCELLED_MESSAGE_TYPE, APPLICATION_NAMESPACE, emailData.getTo(), companyNumber ); + sendEmail( xRequestId, INVITE_CANCELLED_MESSAGE_TYPE, emailData, logMessageSupplier ); } ) + .then(); } } diff --git a/src/test/java/uk/gov/companieshouse/accounts/association/common/TestDataManager.java b/src/test/java/uk/gov/companieshouse/accounts/association/common/TestDataManager.java index 418b023..81dd7f4 100644 --- a/src/test/java/uk/gov/companieshouse/accounts/association/common/TestDataManager.java +++ b/src/test/java/uk/gov/companieshouse/accounts/association/common/TestDataManager.java @@ -764,7 +764,7 @@ private void instantiateAssociationDaoSuppliers(){ final var association = new AssociationDao(); association.setCompanyNumber("111111"); association.setUserEmail( "light.yagami@death.note" ); - association.setStatus(StatusEnum.CONFIRMED.getValue()); + association.setStatus(StatusEnum.AWAITING_APPROVAL.getValue()); association.setId("34"); association.setApprovedAt( now.plusDays(61) ); association.setRemovedAt( now.plusDays(62) ); diff --git a/src/test/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociationsTest.java b/src/test/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociationsTest.java index ed4adbb..125964d 100644 --- a/src/test/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociationsTest.java +++ b/src/test/java/uk/gov/companieshouse/accounts/association/controller/UserCompanyAssociationsTest.java @@ -1,6 +1,7 @@ package uk.gov.companieshouse.accounts.association.controller; import java.util.Map; +import java.util.function.Function; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; @@ -15,6 +16,7 @@ import org.springframework.data.mongodb.core.query.Update; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import reactor.core.publisher.Mono; import uk.gov.companieshouse.accounts.association.common.ComparisonUtils; import uk.gov.companieshouse.accounts.association.common.Mockers; import uk.gov.companieshouse.accounts.association.common.TestDataManager; @@ -74,6 +76,8 @@ class UserCompanyAssociationsTest { private final LocalDateTime now = LocalDateTime.now(); + final Function> sendEmailMock = userId -> Mono.empty(); + private static final TestDataManager testDataManager = TestDataManager.getInstance(); private static Mockers mockers; @@ -567,10 +571,13 @@ void addAssociationWithNonexistentCompanyNumberReturnsNotFound() throws Exceptio @Test void addAssociationCreatesNewAssociationCorrectlyAndReturnsAssociationIdWithCreatedHttpStatus() throws Exception { final var associationDao = testDataManager.fetchAssociationDaos( "1" ).getFirst(); + final var company = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "111" ); + mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); Mockito.doReturn(associationDao).when(associationsService).createAssociation("111111", "111", null, ApprovalRouteEnum.AUTH_CODE, null); Mockito.doReturn(new PageImpl(new ArrayList<>())).when(associationsService).fetchAssociationsDaoForUserStatusAndCompany(any(),any(), any(),any(),anyString()); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), eq( company ), eq( "Batman" ) ); final var response = mockMvc.perform(post("/associations") .header("X-Request-Id", "theId123") @@ -609,6 +616,7 @@ void addAssociationWithUserThatHasNoDisplayNameSetsDisplayNameToEmailAddress() t Mockito.doReturn(associationDao).when(associationsService).createAssociation("333333", "666", null, ApprovalRouteEnum.AUTH_CODE, null); Mockito.doReturn(new PageImpl(new ArrayList<>())).when(associationsService).fetchAssociationsDaoForUserStatusAndCompany(any(),any(), any(),any(),anyString()); Mockito.doReturn( List.of( "666" ) ).when( associationsService ).fetchAssociatedUsers( "333333" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), eq( company ), eq( "homer.simpson@springfield.com" ) ); mockMvc.perform(post( "/associations" ) .header("X-Request-Id", "theId123") @@ -619,7 +627,7 @@ void addAssociationWithUserThatHasNoDisplayNameSetsDisplayNameToEmailAddress() t .content( "{\"company_number\":\"333333\"}" ) ) .andExpect( status().isCreated() ); - Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUsers( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "homer.simpson@springfield.com" ), argThat( list -> list.size() == 1 ) ); + Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "homer.simpson@springfield.com" ) ); } @Test @@ -633,6 +641,7 @@ void existingAssociationWithStatusAwaitingApprovalWhenPostedShouldUpdateAssociat mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); Mockito.doReturn(page).when(associationsService).fetchAssociationsDaoForUserStatusAndCompany(user, List.of(AWAITING_APPROVAL.getValue(), CONFIRMED.getValue(), REMOVED.getValue()),0,15,"111111"); Mockito.doReturn(associationDao).when(associationsService).upsertAssociation(any(AssociationDao.class)); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), eq( company ), eq( "homer.simpson@springfield.com" ) ); mockMvc.perform(post("/associations") .header("Eric-identity", "666") @@ -643,7 +652,7 @@ void existingAssociationWithStatusAwaitingApprovalWhenPostedShouldUpdateAssociat .content("{\"company_number\":\"111111\"}")) .andExpect(status().isCreated()); - Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUsers( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "homer.simpson@springfield.com" ), argThat(List::isEmpty) ); + Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "homer.simpson@springfield.com" ) ); } @Test @@ -657,6 +666,7 @@ void existingAssociationWithStatusRemovedWhenPostedShouldUpdateAssociationWithSt mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); Mockito.doReturn(page).when(associationsService).fetchAssociationsDaoForUserStatusAndCompany(user, List.of(AWAITING_APPROVAL.getValue(), CONFIRMED.getValue(), REMOVED.getValue()),0,15,"111111"); Mockito.doReturn(associationDao).when(associationsService).upsertAssociation(any(AssociationDao.class)); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), eq( company ), eq( "ross@friends.com" ) ); mockMvc.perform(post("/associations") .header("Eric-identity", "5555") @@ -667,7 +677,7 @@ void existingAssociationWithStatusRemovedWhenPostedShouldUpdateAssociationWithSt .content("{\"company_number\":\"111111\"}")) .andExpect(status().isCreated()); - Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUsers( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "ross@friends.com" ), argThat(List::isEmpty) ); + Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "ross@friends.com" ) ); } @Test @@ -680,6 +690,7 @@ void addAssociationWithUserThatHasDisplayNameUsesDisplayName() throws Exception Mockito.doReturn(new PageImpl(new ArrayList<>())).when(associationsService).fetchAssociationsDaoForUserStatusAndCompany(any(),any(), any(),any(),anyString()); Mockito.doReturn( List.of( "000" ) ).when( associationsService ).fetchAssociatedUsers( "333333" ); Mockito.doReturn(associationDao).when(associationsService).createAssociation("333333", "9999", null, ApprovalRouteEnum.AUTH_CODE, null); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), eq( company ), eq( "Scrooge McDuck" ) ); mockMvc.perform(post( "/associations" ) .header("X-Request-Id", "theId123") @@ -690,7 +701,7 @@ void addAssociationWithUserThatHasDisplayNameUsesDisplayName() throws Exception .content( "{\"company_number\":\"333333\"}" ) ) .andExpect( status().isCreated() ); - Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUsers( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "Scrooge McDuck" ), argThat( list -> list.size() == 1 ) ); + Mockito.verify( emailService ).sendAuthCodeConfirmationEmailToAssociatedUser( eq( "theId123" ), argThat( comparisonUtils.compare( company, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq( "Scrooge McDuck" ) ); } @Test @@ -772,8 +783,11 @@ void updateAssociationStatusForIdWithRemovedUpdatesAssociationStatus() throws Ex mockers.mockUsersServiceFetchUserDetails( "000" ); mockers.mockUsersServiceFetchUserDetails( "9999" ); + mockers.mockCompanyServiceFetchCompanyProfile( "333333" ); Mockito.doReturn( Optional.of( association ) ).when( associationsService ).findAssociationDaoById( "35" ); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendAuthorisationRemovedEmailToRemovedUser( eq( "theId123" ), eq( "333333" ), any( Mono.class ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthorisationRemovedEmailToAssociatedUser( eq( "theId123" ), eq( "333333" ), any( Mono.class ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(patch("/associations/35") .header("X-Request-Id", "theId123") @@ -849,6 +863,7 @@ void updateAssociationStatusForIdWithNullUserIdAndExistingUserAndRemovedUpdatesA mockers.mockUsersServiceFetchUserDetails( "000" ); Mockito.doReturn( Optional.of( association ) ).when( associationsService ).findAssociationDaoById( "34" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationRejectedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "light.yagami@death.note" ) ); mockMvc.perform(patch("/associations/34") .header("X-Request-Id", "theId123") @@ -869,6 +884,7 @@ void updateAssociationStatusForIdWithNullUserIdAndNonexistentUserAndRemovedUpdat mockers.mockUsersServiceSearchUserDetailsEmptyList( "light.yagami@death.note" ); mockers.mockUsersServiceFetchUserDetails( "000" ); Mockito.doReturn( Optional.of( association ) ).when( associationsService ).findAssociationDaoById( "34" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationRejectedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "light.yagami@death.note" ) ); mockMvc.perform(patch("/associations/34") .header("X-Request-Id", "theId123") @@ -885,13 +901,14 @@ void updateAssociationStatusForIdWithNullUserIdAndNonexistentUserAndRemovedUpdat @Test void updateAssociationStatusForIdNotificationsWhereTargetUserIdExistsSendsNotification() throws Exception { final var association = testDataManager.fetchAssociationDaos( "35" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "333333" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "9999", "000" ); mockers.mockCompanyServiceFetchCompanyProfile( "333333" ); Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("35"); Mockito.doReturn( List.of( "9999" ) ).when( associationsService ).fetchAssociatedUsers( "333333" ); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendAuthorisationRemovedEmailToRemovedUser( eq( "theId123" ), eq( "333333" ), any( Mono.class ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthorisationRemovedEmailToAssociatedUser( eq( "theId123" ), eq( "333333" ), any( Mono.class ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform( patch( "/associations/35" ) .header("X-Request-Id", "theId123") @@ -902,19 +919,20 @@ void updateAssociationStatusForIdNotificationsWhereTargetUserIdExistsSendsNotifi .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ), any() ); + Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUser( eq( "theId123" ), eq( "333333" ), any( Mono.class ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); } @Test void updateAssociationStatusForIdNotificationsWhereTargetUserIdDoesNotExistSendsNotification() throws Exception { final var association = testDataManager.fetchAssociationDaos( "34" ).getFirst(); - final var company = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "111", "000" ); mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("34"); Mockito.doReturn( List.of( "111" ) ).when( associationsService ).fetchAssociatedUsers( "111111" ); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteCancelledEmail( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( association ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( "light.yagami@death.note" ) ); mockMvc.perform( patch( "/associations/34" ) .header("X-Request-Id", "theId123") @@ -925,13 +943,12 @@ void updateAssociationStatusForIdNotificationsWhereTargetUserIdDoesNotExistSends .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUsers( eq( "theId123" ), eq( company ), eq( "Batman" ), eq( "light.yagami@death.note" ), any() ); + Mockito.verify( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( "light.yagami@death.note" ) ); } @Test void updateAssociationStatusForIdNotificationsWhereUserCannotBeFoundSendsNotification() throws Exception { final var association = testDataManager.fetchAssociationDaos( "34" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceSearchUserDetailsEmptyList( "light.yagami@death.note" ); mockers.mockUsersServiceFetchUserDetails( "111" ); @@ -939,6 +956,8 @@ void updateAssociationStatusForIdNotificationsWhereUserCannotBeFoundSendsNotific Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("34"); Mockito.doReturn( List.of("000" ) ).when( associationsService ).fetchAssociatedUsers( "111111" ); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteCancelledEmail( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( association ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( "light.yagami@death.note" ) ); mockMvc.perform( patch( "/associations/34" ) .header("X-Request-Id", "theId123") @@ -949,13 +968,12 @@ void updateAssociationStatusForIdNotificationsWhereUserCannotBeFoundSendsNotific .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "Batman" ), eq( "light.yagami@death.note" ), any() ); + Mockito.verify( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Batman" ), eq( "light.yagami@death.note" ) ); } @Test void updateAssociationStatusForIdNotificationsUsesDisplayNamesWhenAvailable() throws Exception { final var association = testDataManager.fetchAssociationDaos( "4" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); @@ -963,6 +981,8 @@ void updateAssociationStatusForIdNotificationsUsesDisplayNamesWhenAvailable() th Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("4"); Mockito.doReturn( List.of( "333" ) ).when( associationsService ).fetchAssociatedUsers( "111111" ); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendAuthorisationRemovedEmailToRemovedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Harleen Quinzel" ), eq( "Boy Wonder" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendAuthorisationRemovedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Harleen Quinzel" ), eq( "Boy Wonder" ) ); mockMvc.perform( patch( "/associations/4" ) .header("X-Request-Id", "theId123") @@ -973,8 +993,8 @@ void updateAssociationStatusForIdNotificationsUsesDisplayNamesWhenAvailable() th .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendAuthorisationRemovedEmailToRemovedUser( eq( "theId123" ), eq( companyDetails ), eq( "Harleen Quinzel" ), any() ); - Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "Harleen Quinzel" ), eq("Boy Wonder"), any() ); + Mockito.verify( emailService ).sendAuthorisationRemovedEmailToRemovedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Harleen Quinzel" ), eq( "444" ) ); + Mockito.verify( emailService ).sendAuthorisationRemovedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), eq( "Harleen Quinzel" ), eq("Boy Wonder") ); } @Test @@ -987,6 +1007,7 @@ void updateAssociationStatusForIdUserAcceptedInvitationNotificationsSendsNotific mockers.mockCompanyServiceFetchCompanyProfile( "111111" ); Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("6"); Mockito.doReturn( List.of( "222", "444" ) ).when( associationsService ).fetchAssociatedUsers( "111111" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationAcceptedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), any( Mono.class ), eq( "homer.simpson@springfield.com" ) ); mockMvc.perform( patch( "/associations/6" ) .header("X-Request-Id", "theId123") @@ -997,7 +1018,7 @@ void updateAssociationStatusForIdUserAcceptedInvitationNotificationsSendsNotific .content( "{\"status\":\"confirmed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendInvitationAcceptedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "the.joker@gotham.city" ), eq( "homer.simpson@springfield.com" ), any() ); + Mockito.verify( emailService ).sendInvitationAcceptedEmailToAssociatedUser( eq( "theId123" ), eq( "111111" ), any( Mono.class ), any( Mono.class ), eq( "homer.simpson@springfield.com" ) ); } @Test @@ -1043,13 +1064,13 @@ void confirmUserStatusRequestForExistingAssociationWithoutOneLoginUserAndDiffere @Test void updateAssociationStatusForIdUserAcceptedInvitationNotificationsUsesDisplayNamesWhenAvailable() throws Exception { final var association = testDataManager.fetchAssociationDaos( "38" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "x222222" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "9999", "444" ); mockers.mockUsersServiceSearchUserDetailsEmptyList( "scrooge.mcduck@disney.land" ); mockers.mockCompanyServiceFetchCompanyProfile( "x222222" ); Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("38"); Mockito.doReturn( List.of( "111", "222", "444" ) ).when( associationsService ).fetchAssociatedUsers( "x222222" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationAcceptedEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), any( Mono.class ), eq( "Scrooge McDuck" ) ); mockMvc.perform( patch( "/associations/38" ) .header("X-Request-Id", "theId123") @@ -1060,13 +1081,12 @@ void updateAssociationStatusForIdUserAcceptedInvitationNotificationsUsesDisplayN .content( "{\"status\":\"confirmed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendInvitationAcceptedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "Boy Wonder" ), eq( "Scrooge McDuck" ), any() ); + Mockito.verify( emailService ).sendInvitationAcceptedEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), any(), eq( "Scrooge McDuck" ) ); } @Test void updateAssociationStatusForIdUserCancelledInvitationNotificationsSendsNotification() throws Exception { final var association = testDataManager.fetchAssociationDaos( "38" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "x222222" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "9999", "222" ); mockers.mockUsersServiceSearchUserDetailsEmptyList( "scrooge.mcduck@disney.land" ); @@ -1074,6 +1094,8 @@ void updateAssociationStatusForIdUserCancelledInvitationNotificationsSendsNotifi Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("38"); Mockito.doReturn( List.of( "111", "222", "444" ) ).when( associationsService ).fetchAssociatedUsers( "x222222" ); Mockito.doReturn( true ).when( associationsService ).confirmedAssociationExists( "x222222", "222" ); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteCancelledEmail( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), eq( "the.joker@gotham.city" ), eq( association ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), eq( "the.joker@gotham.city" ), eq( "Scrooge McDuck" ) ); mockMvc.perform( patch( "/associations/38" ) .header("X-Request-Id", "theId123") @@ -1084,13 +1106,12 @@ void updateAssociationStatusForIdUserCancelledInvitationNotificationsSendsNotifi .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendInvitationCancelledEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "the.joker@gotham.city" ), eq( "Scrooge McDuck" ), any() ); + Mockito.verify( emailService ).sendInvitationCancelledEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), eq( "the.joker@gotham.city" ), eq( "Scrooge McDuck" ) ); } @Test void updateAssociationStatusForIdUserRejectedInvitationNotificationsSendsNotification() throws Exception { final var association = testDataManager.fetchAssociationDaos( "38" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "x222222" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "9999" ); mockers.mockUsersServiceSearchUserDetailsEmptyList( "scrooge.mcduck@disney.land" ); @@ -1098,6 +1119,8 @@ void updateAssociationStatusForIdUserRejectedInvitationNotificationsSendsNotific Mockito.doReturn(Optional.of(association)).when(associationsService).findAssociationDaoById("38"); Mockito.doReturn( List.of( "111", "222", "444" ) ).when( associationsService ).fetchAssociatedUsers( "x222222" ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationRejectedEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), eq( "Scrooge McDuck" ) ); + mockMvc.perform( patch( "/associations/38" ) .header("X-Request-Id", "theId123") .header("Eric-identity", "9999") @@ -1107,7 +1130,7 @@ void updateAssociationStatusForIdUserRejectedInvitationNotificationsSendsNotific .content( "{\"status\":\"removed\"}" ) ) .andExpect( status().isOk() ); - Mockito.verify( emailService ).sendInvitationRejectedEmailToAssociatedUsers( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any() ); + Mockito.verify( emailService ).sendInvitationRejectedEmailToAssociatedUser( eq( "theId123" ), eq( "x222222" ), any( Mono.class ), eq( "Scrooge McDuck" ) ); } @Test @@ -1235,6 +1258,8 @@ void inviteUserWhereAssociationBetweenInviteeEmailAndCompanyNumberExistsAndInvit Mockito.doReturn(Optional.of(associationDao)).when(associationsService).fetchAssociationForCompanyNumberAndUserEmail("444444", "light.yagami@death.note"); Mockito.doReturn(associationDao).when(associationsService).sendNewInvitation(eq("9999"), any()); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteEmail( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any( String.class ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(post("/associations/invitations") .header("X-Request-Id", "theId123") @@ -1247,7 +1272,7 @@ void inviteUserWhereAssociationBetweenInviteeEmailAndCompanyNumberExistsAndInvit Mockito.verify(associationsService).sendNewInvitation(eq("9999"), argThat( comparisonUtils.compare( associationDaoForComparison, List.of( "id", "companyNumber", "createdAt", "approvedAt", "removedAt", "approvalRoute", "approvalExpiryAt", "invitations", "etag", "version" ), List.of( "userId", "userEmail" ), Map.of() ) )); Mockito.verify( emailService ).sendInviteEmail( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), anyString(), eq( "light.yagami@death.note" ) ); - Mockito.verify( emailService ).sendInvitationEmailToAssociatedUsers( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note"), argThat( List::isEmpty ) ); + Mockito.verify( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note") ); } @Test @@ -1262,6 +1287,8 @@ void inviteUserWhereAssociationBetweenInviteeEmailAndCompanyNumberExistsAndInvit Mockito.doReturn(Optional.of(associationDao)).when(associationsService).fetchAssociationForCompanyNumberAndUserEmail("444444", "light.yagami@death.note"); Mockito.doReturn(associationDao).when(associationsService).sendNewInvitation(eq("9999"), any()); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteEmail( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any( String.class ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(post("/associations/invitations") .header("X-Request-Id", "theId123") @@ -1274,7 +1301,7 @@ void inviteUserWhereAssociationBetweenInviteeEmailAndCompanyNumberExistsAndInvit Mockito.verify(associationsService).sendNewInvitation(eq("9999"), argThat(comparisonUtils.compare( associationDaoForComparison, List.of( "id", "companyNumber", "createdAt", "approvedAt", "removedAt", "approvalRoute", "approvalExpiryAt", "invitations", "etag", "version", "userId", "userEmail" ), List.of(), Map.of() ))); Mockito.verify( emailService ).sendInviteEmail( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), anyString(), eq( "light.yagami@death.note" ) ); - Mockito.verify( emailService ).sendInvitationEmailToAssociatedUsers( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note"), argThat( List::isEmpty ) ); + Mockito.verify( emailService ).sendInvitationEmailToAssociatedUser( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note") ); } @Test @@ -1290,6 +1317,8 @@ void inviteUserWhereInviteeUserIsFoundAndAssociationBetweenInviteeUserIdAndCompa Mockito.doReturn(Optional.of(targetUserAssociation)).when(associationsService).fetchAssociationForCompanyNumberAndUserId("444444", "000"); Mockito.doReturn(requestingUserAssociation).when(associationsService).sendNewInvitation(eq("9999"), any()); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteEmail( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any( String.class ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(post("/associations/invitations") .header("X-Request-Id", "theId123") @@ -1302,7 +1331,7 @@ void inviteUserWhereInviteeUserIsFoundAndAssociationBetweenInviteeUserIdAndCompa Mockito.verify(associationsService).sendNewInvitation(eq("9999"), any() ); Mockito.verify( emailService ).sendInviteEmail( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), anyString(), eq( "light.yagami@death.note" ) ); - Mockito.verify( emailService ).sendInvitationEmailToAssociatedUsers( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note"), argThat( List::isEmpty ) ); + Mockito.verify( emailService ).sendInvitationEmailToAssociatedUser( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note") ); } @Test @@ -1317,6 +1346,8 @@ void inviteUserWhereInviteeUserIsFoundAndAssociationBetweenInviteeUserIdAndCompa Mockito.doReturn(Optional.empty()).when(associationsService).fetchAssociationForCompanyNumberAndUserId("444444", "000"); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); Mockito.doReturn( association).when( associationsService ).createAssociation( "444444", "000", null, ApprovalRouteEnum.INVITATION, "9999" ); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteEmail( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any( String.class ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(post("/associations/invitations") .header("X-Request-Id", "theId123") @@ -1328,7 +1359,7 @@ void inviteUserWhereInviteeUserIsFoundAndAssociationBetweenInviteeUserIdAndCompa .andExpect(status().isCreated()); Mockito.verify( emailService ).sendInviteEmail( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), anyString(), eq( "light.yagami@death.note" ) ); - Mockito.verify( emailService ).sendInvitationEmailToAssociatedUsers( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note"), argThat( List::isEmpty ) ); + Mockito.verify( emailService ).sendInvitationEmailToAssociatedUser( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note") ); } @Test @@ -1343,6 +1374,8 @@ void inviteUserWhereAssociationBetweenInviteeUserEmailAndCompanyNumberDoesNotExi Mockito.doReturn(Optional.empty()).when(associationsService).fetchAssociationForCompanyNumberAndUserId("444444", "000"); Mockito.when(associationsService.confirmedAssociationExists(Mockito.any(), Mockito.any())).thenReturn(true); Mockito.doReturn( newAssociation).when( associationsService ).createAssociation( "444444", null, "light.yagami@death.note", ApprovalRouteEnum.INVITATION, "9999" ); + Mockito.doReturn( Mono.empty() ).when( emailService ).sendInviteEmail( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), any( String.class ), eq( "light.yagami@death.note" ) ); + Mockito.doReturn( sendEmailMock ).when( emailService ).sendInvitationEmailToAssociatedUser( eq( "theId123" ), eq( companyDetails ), eq( "Scrooge McDuck" ), eq( "light.yagami@death.note" ) ); mockMvc.perform(post("/associations/invitations") .header("X-Request-Id", "theId123") @@ -1354,7 +1387,7 @@ void inviteUserWhereAssociationBetweenInviteeUserEmailAndCompanyNumberDoesNotExi .andExpect(status().isCreated()); Mockito.verify( emailService ).sendInviteEmail( eq( "theId123" ), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), anyString(), eq( "light.yagami@death.note" ) ); - Mockito.verify( emailService ).sendInvitationEmailToAssociatedUsers( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note"), argThat( List::isEmpty ) ); + Mockito.verify( emailService ).sendInvitationEmailToAssociatedUser( eq("theId123"), argThat( comparisonUtils.compare( companyDetails, List.of( "companyNumber", "companyName" ), List.of(), Map.of() ) ), eq("Scrooge McDuck"), eq("light.yagami@death.note") ); } @Test diff --git a/src/test/java/uk/gov/companieshouse/accounts/association/integration/UserCompanyAssociationsTest.java b/src/test/java/uk/gov/companieshouse/accounts/association/integration/UserCompanyAssociationsTest.java index affab55..25e5ff6 100644 --- a/src/test/java/uk/gov/companieshouse/accounts/association/integration/UserCompanyAssociationsTest.java +++ b/src/test/java/uk/gov/companieshouse/accounts/association/integration/UserCompanyAssociationsTest.java @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.reactive.function.client.WebClient; import uk.gov.companieshouse.accounts.association.common.ComparisonUtils; import uk.gov.companieshouse.accounts.association.common.Mockers; import uk.gov.companieshouse.accounts.association.common.TestDataManager; @@ -58,10 +57,10 @@ import static uk.gov.companieshouse.accounts.association.common.ParsingUtils.localDateTimeToNormalisedString; import static uk.gov.companieshouse.accounts.association.common.ParsingUtils.parseResponseTo; import static uk.gov.companieshouse.accounts.association.common.ParsingUtils.reduceTimestampResolution; -import static uk.gov.companieshouse.accounts.association.utils.MessageType.AUTHORISATION_REMOVED_MESSAGE_TYPE; import static uk.gov.companieshouse.accounts.association.utils.MessageType.AUTH_CODE_CONFIRMATION_MESSAGE_TYPE; import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_ACCEPTED_MESSAGE_TYPE; import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITATION_MESSAGE_TYPE; +import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITE_CANCELLED_MESSAGE_TYPE; import static uk.gov.companieshouse.accounts.association.utils.MessageType.INVITE_MESSAGE_TYPE; @AutoConfigureMockMvc @@ -875,7 +874,7 @@ void updateAssociationStatusForIdNotificationsWhereTargetUserIdDoesNotExistSends latch.await( 10, TimeUnit.SECONDS ); - Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.authorisationRemovedEmailMatcher( "Batman", "light.yagami@death.note", "Wayne Enterprises", "bruce.wayne@gotham.city" ) ), eq( AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ) ); + Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.inviteCancelledEmailMatcher( "light.yagami@death.note", "Wayne Enterprises", "Batman" ) ), eq( INVITE_CANCELLED_MESSAGE_TYPE.getValue() ) ); } @Test @@ -899,7 +898,7 @@ void updateAssociationStatusForIdNotificationsWhereUserCannotBeFoundSendsNotific .andExpect( status().isOk() ); latch.await( 10, TimeUnit.SECONDS ); - Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.authorisationRemovedEmailMatcher( "Batman", "light.yagami@death.note", "Wayne Enterprises", "bruce.wayne@gotham.city" ) ), eq( AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ) ); + Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.inviteCancelledEmailMatcher( "light.yagami@death.note", "Wayne Enterprises", "Batman" ) ), eq( INVITE_CANCELLED_MESSAGE_TYPE.getValue() ) ); } @Test diff --git a/src/test/java/uk/gov/companieshouse/accounts/association/service/EmailServiceTest.java b/src/test/java/uk/gov/companieshouse/accounts/association/service/EmailServiceTest.java index ae2f15a..cb870be 100644 --- a/src/test/java/uk/gov/companieshouse/accounts/association/service/EmailServiceTest.java +++ b/src/test/java/uk/gov/companieshouse/accounts/association/service/EmailServiceTest.java @@ -9,16 +9,13 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; import org.springframework.test.util.ReflectionTestUtils; +import reactor.core.publisher.Mono; import uk.gov.companieshouse.accounts.association.common.ComparisonUtils; import uk.gov.companieshouse.accounts.association.common.Mockers; import uk.gov.companieshouse.accounts.association.common.TestDataManager; import uk.gov.companieshouse.accounts.association.models.email.builders.InvitationAcceptedEmailBuilder; -import uk.gov.companieshouse.accounts.association.repositories.AssociationsRepository; import uk.gov.companieshouse.accounts.association.utils.MessageType; -import uk.gov.companieshouse.api.accounts.user.model.User; import uk.gov.companieshouse.api.company.CompanyDetails; import uk.gov.companieshouse.email_producer.EmailProducer; import uk.gov.companieshouse.email_producer.EmailSendingException; @@ -35,9 +32,6 @@ class EmailServiceTest { @Mock private EmailProducer emailProducer; - @Mock - private AssociationsRepository associationsRepository; - @Mock private UsersService usersService; @@ -64,105 +58,74 @@ void sendAuthCodeConfirmationEmailToAssociatedUsersWithNullCompanyDetailsOrNullC final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", null, "Harleen Quinzel", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Harleen Quinzel", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", companyDetails, null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", null, "Harleen Quinzel" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", emptyCompanyDetails, "Harleen Quinzel" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", companyDetails, null ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel" ).apply( null ).block() ); } @Test void sendAuthCodeConfirmationEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", List.of("333") ); + emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.authCodeConfirmationEmailMatcher( "harley.quinn@gotham.city", "Wayne Enterprises", "Harleen Quinzel" ) ), eq( MessageType.AUTH_CODE_CONFIRMATION_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendAuthCodeConfirmationEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", companyDetails, "Krishna Patel", List.of() ); - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.authCodeConfirmationEmailMatcher( "kpatel@companieshouse.gov.uk", "Wayne Enterprises", "Krishna Patel" ) ), eq( AUTH_CODE_CONFIRMATION_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendAuthCodeConfirmationEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( AUTH_CODE_CONFIRMATION_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendAuthCodeConfirmationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel" ).apply( "333" ).block() ); } @Test void sendAuthorisationRemovedEmailToAssociatedUsersWithNullCompanyDetailsOrNullCompanyNameOrNullDisplayNamesOrNullRequestsThrowsNullPointerException(){ - final var emptyCompanyDetails = new CompanyDetails(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", null, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, null, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", null,"Harleen Quinzel", "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), null, "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", null ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", "Batman" ).apply( null ).block() ); } @Test void sendAuthorisationRemovedEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ); + emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", "Batman" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.authorisationRemovedEmailMatcher( "Harleen Quinzel", "Batman", "Wayne Enterprises", "harley.quinn@gotham.city" ) ), eq( AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendAuthorisationRemovedEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, "Krishna Patel", "Batman", List.of() ); - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.authorisationRemovedEmailMatcher( "Krishna Patel", "Batman", "Wayne Enterprises", "kpatel@companieshouse.gov.uk" ) ), eq( AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendAuthorisationRemovedEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( AUTHORISATION_REMOVED_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendAuthorisationRemovedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", "Batman").apply( "333" ).block() ); } @Test void sendInvitationCancelledEmailToAssociatedUsersWithNullCompanyDetailsOrNullCompanyNameOrNullDisplayNamesOrNullRequestsThrowsNullPointerException(){ - final var emptyCompanyDetails = new CompanyDetails(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", null, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, null, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", null, "Harleen Quinzel", "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), null, "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", null ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", "Batman" ).apply( null ).block() ); } @Test void sendInvitationCancelledEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ); + emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Harleen Quinzel", "Batman" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.invitationCancelledEmailMatcher( "harley.quinn@gotham.city", "Harleen Quinzel", "Batman", "Wayne Enterprises" ) ), eq( INVITATION_CANCELLED_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendInvitationCancelledEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, "Krishna Patel", "Batman", List.of() ); - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.invitationCancelledEmailMatcher( "kpatel@companieshouse.gov.uk", "Krishna Patel", "Batman", "Wayne Enterprises" ) ), eq( INVITATION_CANCELLED_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendInvitationCancelledEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( INVITATION_CANCELLED_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationCancelledEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises"), "Harleen Quinzel", "Batman" ).apply( "333" ).block() ); } @Test @@ -171,47 +134,37 @@ void sendInvitationEmailToAssociatedUsersNullCompanyDetailsOrNullCompanyNameOrNu final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", null, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, null, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", null, "Harleen Quinzel", "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", emptyCompanyDetails, "Harleen Quinzel", "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", companyDetails, null, "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel", null ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel", "Batman" ).apply( null ).block() ); } @Test void sendInvitationEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ); + emailService.sendInvitationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel", "Batman" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.invitationAndInviteEmailDataMatcher( "harley.quinn@gotham.city", "Harleen Quinzel", "bruce.wayne@gotham.city", "Batman", "Wayne Enterprises", COMPANY_INVITATIONS_URL ) ), eq( INVITATION_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendInvitationEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, "Krishna Patel", "Batman", List.of() ); - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.invitationAndInviteEmailDataMatcher( "kpatel@companieshouse.gov.uk", "Krishna Patel", "bruce.wayne@gotham.city", "Batman", "Wayne Enterprises", COMPANY_INVITATIONS_URL ) ), eq( INVITATION_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendInvitationEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( INVITATION_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Elon Musk", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationEmailToAssociatedUser( "theId12345", companyDetails, "Harleen Quinzel", "Elon Musk" ).apply( "333" ).block() ); } @Test void sendInvitationAcceptedEmailToAssociatedUsersWithNullCompanyDetailsOrNullCompanyNameOrNullDisplayNamesOrNullRequestsThrowsNullPointerException(){ - final var emptyCompanyDetails = new CompanyDetails(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", null, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, null, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", null, Mono.just( "Harleen Quinzel" ), "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), null, "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), Mono.just("Harleen Quinzel" ), null ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), Mono.just("Harleen Quinzel" ), "Batman" ).apply( null ).block() ); } @Test @@ -220,68 +173,40 @@ void sendInvitationAcceptedEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ .setInviterDisplayName( "Harleen Quinzel" ) .setInviteeDisplayName( "Batman" ) .setCompanyName( "Wayne Enterprises" ); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ); + emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), Mono.just( "Harleen Quinzel" ), "Batman" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.invitationAcceptedEmailDataMatcher( List.of( "harley.quinn@gotham.city" ), expectedBaseEmail ) ), eq( INVITATION_ACCEPTED_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendInvitationAcceptedEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var expectedBaseEmail = new InvitationAcceptedEmailBuilder() - .setInviterDisplayName( "Harleen Quinzel" ) - .setInviteeDisplayName( "Batman" ) - .setCompanyName( "Wayne Enterprises" ); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - - emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of() ); - - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.invitationAcceptedEmailDataMatcher( List.of( "harley.quinn@gotham.city" ), expectedBaseEmail ) ), eq( INVITATION_ACCEPTED_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendInvitationAcceptedEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( INVITATION_ACCEPTED_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUsers( "theId12345", companyDetails, "Harleen Quinzel", "Batman", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationAcceptedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), Mono.just( "Harleen Quinzel" ), "Batman" ).apply( "333" ).block() ); } @Test void sendInvitationRejectedEmailToAssociatedUsersWithNullCompanyDetailsOrNullCompanyNameOrNullDisplayNameOrNullRequestsThrowsNullPointerException(){ - final var emptyCompanyDetails = new CompanyDetails(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", null, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", emptyCompanyDetails, "Batman", List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", companyDetails, null, List.of("333") ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", companyDetails, "Batman", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUser( "theId12345", "111111", null, "Batman" ).apply( "333" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), null ).apply( "333" ).block() ); } @Test void sendInvitationRejectedEmailToAssociatedUsersThrowsEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); - emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", companyDetails, "Batman", List.of("333") ); + emailService.sendInvitationRejectedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Batman" ).apply( "333" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.invitationRejectedEmailMatcher( "harley.quinn@gotham.city", "Batman", "Wayne Enterprises" ) ), eq( INVITATION_REJECTED_MESSAGE_TYPE.getValue() ) ); } - @Test - void sendInvitationRejectedEmailToAssociatedUsersDoesNotThrowEmailOnKafkaQueue(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", companyDetails, "Batman", List.of() ); - Mockito.verify( emailProducer, Mockito.never() ).sendEmail( argThat( comparisonUtils.invitationRejectedEmailMatcher( "kpatel@companieshouse.gov.uk", "Batman", "Wayne Enterprises" ) ), eq( INVITATION_REJECTED_MESSAGE_TYPE.getValue() ) ); - } - @Test void sendInvitationRejectedEmailToAssociatedUsersWithUnexpectedIssueThrowsEmailSendingException(){ - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockUsersServiceFetchUserDetails( "333" ); mockers.mockEmailSendingFailure( INVITATION_REJECTED_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUsers( "theId12345", companyDetails, "Batman", List.of("333") ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInvitationRejectedEmailToAssociatedUser( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Batman" ).apply( "333" ).block() ); } @Test @@ -289,17 +214,17 @@ void sendInviteEmailWithNullCompanyDetailsOrNullCompanyNameOrNullInviterDisplayN final var emptyCompanyDetails = new CompanyDetails(); final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", null, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", emptyCompanyDetails, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, null, "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", null, "kpatel@companieshouse.gov.uk" ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", "1992-05-01T10:30:00.000000", null ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", null, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", emptyCompanyDetails, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, null, "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", null, "kpatel@companieshouse.gov.uk" ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", "1992-05-01T10:30:00.000000", null ).block() ); } @Test void sendInviteEmailThrowsEmailOnKafkaQueue(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ); + emailService.sendInviteEmail( "theId12345", companyDetails, "Batman", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ).block(); Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.invitationAndInviteEmailDataMatcher( "bruce.wayne@gotham.city", "Batman", "kpatel@companieshouse.gov.uk", "Krishna Patel", "Wayne Enterprises", COMPANY_INVITATIONS_URL ) ), eq( INVITE_MESSAGE_TYPE.getValue() ) ); } @@ -307,28 +232,24 @@ void sendInviteEmailThrowsEmailOnKafkaQueue(){ void sendInviteEmailWithUnexpectedIssueThrowsEmailSendingException(){ final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); mockers.mockEmailSendingFailure( INVITE_MESSAGE_TYPE.getValue() ); - Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Krishna Patel", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ) ); + Assertions.assertThrows( EmailSendingException.class, () -> emailService.sendInviteEmail( "theId12345", companyDetails, "Krishna Patel", "1992-05-01T10:30:00.000000", "kpatel@companieshouse.gov.uk" ).block() ); } @Test void sendInviteCancelledEmailWithoutCompanyDetailsOrCompanyNameOrCancelledByDisplayNameOrInviteeUserSupplierOrEmailThrowsNullPointerException(){ - final var emptyCompanyDetails = new CompanyDetails(); - final var userDetails = testDataManager.fetchUserDtos( "111" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); + final var association = testDataManager.fetchAssociationDaos( "34" ).getFirst(); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", null, "Batman", () -> userDetails ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", emptyCompanyDetails, "Batman", () -> userDetails ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", companyDetails, null, () -> userDetails ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", companyDetails, "Batman", null ) ); - Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", companyDetails, "Batman", () -> new User() ) ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", "111111", null, "Batman", association ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), null, association ).block() ); + Assertions.assertThrows( NullPointerException.class, () -> emailService.sendInviteCancelledEmail( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Batman", null ).block() ); } @Test void sendInviteCancelledEmailSendsEmail(){ - final var userDetails = testDataManager.fetchUserDtos( "111" ).getFirst(); - final var companyDetails = testDataManager.fetchCompanyDetailsDtos( "111111" ).getFirst(); - emailService.sendInviteCancelledEmail( "theId12345", companyDetails, "Batman", () -> userDetails ); - Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.inviteCancelledEmailMatcher( "bruce.wayne@gotham.city", "Wayne Enterprises", "Batman" ) ), eq( INVITE_CANCELLED_MESSAGE_TYPE.getValue() ) ); + final var association = testDataManager.fetchAssociationDaos( "34" ).getFirst(); + + emailService.sendInviteCancelledEmail( "theId12345", "111111", Mono.just( "Wayne Enterprises" ), "Batman", association ).block(); + Mockito.verify( emailProducer ).sendEmail( argThat( comparisonUtils.inviteCancelledEmailMatcher( "light.yagami@death.note", "Wayne Enterprises", "Batman" ) ), eq( INVITE_CANCELLED_MESSAGE_TYPE.getValue() ) ); } }