-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HAI-1526 Add functions to send hanke and application invitation emails
Add templates for hanke and application invitation emails. Add functionality to send these invitations in EmailSenderService. Note: It is possible for inviter name to be unknown. In these cases the emails use only the inviter email ([email protected] kutsui sinut..). Using the new email sending features will be implemented on a different upcoming pr.
- Loading branch information
Showing
8 changed files
with
394 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,10 +10,13 @@ import assertk.assertions.startsWith | |
import com.icegreen.greenmail.configuration.GreenMailConfiguration | ||
import com.icegreen.greenmail.junit5.GreenMailExtension | ||
import com.icegreen.greenmail.util.ServerSetupTest | ||
import fi.hel.haitaton.hanke.ContactType | ||
import fi.hel.haitaton.hanke.DatabaseTest | ||
import fi.hel.haitaton.hanke.application.ApplicationType | ||
import fi.hel.haitaton.hanke.firstReceivedMessage | ||
import jakarta.mail.internet.MimeMessage | ||
import jakarta.mail.internet.MimeMultipart | ||
import org.junit.jupiter.api.Nested | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.api.extension.RegisterExtension | ||
import org.springframework.beans.factory.annotation.Autowired | ||
|
@@ -23,6 +26,7 @@ import org.testcontainers.junit.jupiter.Testcontainers | |
|
||
private const val TEST_EMAIL = "[email protected]" | ||
private const val APPLICATION_IDENTIFIER = "JS2300001" | ||
private const val DEFAULT_INVITER_NAME = "Kalle Kutsuja" | ||
|
||
@Testcontainers | ||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | ||
|
@@ -39,54 +43,208 @@ class EmailSenderServiceITest : DatabaseTest() { | |
|
||
@Autowired lateinit var emailSenderService: EmailSenderService | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with correct recipient`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail(TEST_EMAIL, 13L, APPLICATION_IDENTIFIER) | ||
@Nested | ||
inner class JohtoSelvitysComplete { | ||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with correct recipient`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail( | ||
TEST_EMAIL, | ||
13L, | ||
APPLICATION_IDENTIFIER | ||
) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.allRecipients).hasSize(1) | ||
assertThat(email.allRecipients[0].toString()).isEqualTo(TEST_EMAIL) | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with sender from properties`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail( | ||
TEST_EMAIL, | ||
13L, | ||
APPLICATION_IDENTIFIER | ||
) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.from).hasSize(1) | ||
assertThat(email.from[0].toString()).isEqualTo("[email protected]") | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with correct subject`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail( | ||
TEST_EMAIL, | ||
13L, | ||
APPLICATION_IDENTIFIER | ||
) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.subject) | ||
.isEqualTo( | ||
"Johtoselvitys JS2300001 / Ledningsutredning JS2300001 / Cable report JS2300001" | ||
) | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with parametrized hybrid body`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail( | ||
TEST_EMAIL, | ||
13L, | ||
APPLICATION_IDENTIFIER | ||
) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.allRecipients).hasSize(1) | ||
assertThat(email.allRecipients[0].toString()).isEqualTo(TEST_EMAIL) | ||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).all { | ||
contains(APPLICATION_IDENTIFIER) | ||
contains("http://localhost:3001/fi/hakemus/13") | ||
contains("http://localhost:3001/sv/ansokan/13") | ||
contains("http://localhost:3001/en/application/13") | ||
} | ||
// Compress all whitespace into single spaces so that they don't interfere with | ||
// matching. | ||
val squashedHtmlBody = htmlBody.replace("\\s+".toRegex(), " ") | ||
assertThat(squashedHtmlBody).all { | ||
contains(APPLICATION_IDENTIFIER) | ||
contains("""<a href="http://localhost:3001/fi/hakemus/13">""") | ||
contains("""<a href="http://localhost:3001/sv/ansokan/13">""") | ||
contains("""<a href="http://localhost:3001/en/application/13">""") | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with sender from properties`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail(TEST_EMAIL, 13L, APPLICATION_IDENTIFIER) | ||
@Nested | ||
inner class HankeInvitation { | ||
|
||
@Test | ||
fun `sendHankeInvitationEmail sends email with correct recipient`() { | ||
emailSenderService.sendHankeInvitationEmail(TEST_EMAIL, hankeInvitationData()) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.allRecipients).hasSize(1) | ||
assertThat(email.allRecipients[0].toString()).isEqualTo(TEST_EMAIL) | ||
} | ||
|
||
@Test | ||
fun `sendHankeInvitationEmail sends email with sender from properties`() { | ||
emailSenderService.sendHankeInvitationEmail(TEST_EMAIL, hankeInvitationData()) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.from).hasSize(1) | ||
assertThat(email.from[0].toString()).isEqualTo("[email protected]") | ||
} | ||
|
||
@Test | ||
fun `sendHankeInvitationEmail sends email with correct subject`() { | ||
emailSenderService.sendHankeInvitationEmail(TEST_EMAIL, hankeInvitationData()) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.subject).isEqualTo("Sinut on lisätty hankkeelle HAI24-1") | ||
} | ||
|
||
@Test | ||
fun `sendHankeInvitationEmail sends email with parametrized hybrid body`() { | ||
val data = hankeInvitationData() | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.from).hasSize(1) | ||
assertThat(email.from[0].toString()).isEqualTo("[email protected]") | ||
emailSenderService.sendHankeInvitationEmail(TEST_EMAIL, data) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).all { | ||
startsWith("${data.inviterName} (${data.inviterEmail}) lisäsi sinut") | ||
contains("hankkeelle ${data.hankeNimi} (${data.hankeTunnus}).") | ||
contains("http://localhost:3001/${data.invitationToken}") | ||
} | ||
assertThat(htmlBody).all { | ||
contains("<p>${data.inviterName} (${data.inviterEmail}) lisäsi sinut") | ||
contains("hankkeelle <b>${data.hankeNimi} (${data.hankeTunnus})</b>.") | ||
contains("""<a href="http://localhost:3001/${data.invitationToken}">""") | ||
} | ||
} | ||
|
||
@Test | ||
fun `sendHankeInvitationEmail handles input without inviter name`() { | ||
val data = hankeInvitationData(inviterName = null) | ||
|
||
emailSenderService.sendHankeInvitationEmail(TEST_EMAIL, data) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).startsWith("Asioija ${data.inviterEmail} lisäsi sinut") | ||
assertThat(htmlBody).contains("<p>Asioija ${data.inviterEmail} lisäsi sinut") | ||
} | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with correct subject`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail(TEST_EMAIL, 13L, APPLICATION_IDENTIFIER) | ||
@Nested | ||
inner class ApplicationInvitation { | ||
@Test | ||
fun `sendApplicationInvitationEmail sends email with correct recipient`() { | ||
emailSenderService.sendApplicationInvitationEmail( | ||
TEST_EMAIL, | ||
applicationInvitationData() | ||
) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.allRecipients).hasSize(1) | ||
assertThat(email.allRecipients[0].toString()).isEqualTo(TEST_EMAIL) | ||
} | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.subject) | ||
.isEqualTo( | ||
"Johtoselvitys JS2300001 / Ledningsutredning JS2300001 / Cable report JS2300001" | ||
@Test | ||
fun `sendApplicationInvitationEmail sends email with sender from properties`() { | ||
emailSenderService.sendApplicationInvitationEmail( | ||
TEST_EMAIL, | ||
applicationInvitationData() | ||
) | ||
} | ||
|
||
@Test | ||
fun `sendJohtoselvitysCompleteEmail sends email with parametrized hybrid body`() { | ||
emailSenderService.sendJohtoselvitysCompleteEmail(TEST_EMAIL, 13L, APPLICATION_IDENTIFIER) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).all { | ||
contains(APPLICATION_IDENTIFIER) | ||
contains("http://localhost:3001/fi/hakemus/13") | ||
contains("http://localhost:3001/sv/ansokan/13") | ||
contains("http://localhost:3001/en/application/13") | ||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.from).hasSize(1) | ||
assertThat(email.from[0].toString()).isEqualTo("[email protected]") | ||
} | ||
// Compress all whitespace into single spaces so that they don't interfere with matching. | ||
val squashedHtmlBody = htmlBody.replace("\\s+".toRegex(), " ") | ||
assertThat(squashedHtmlBody).all { | ||
contains(APPLICATION_IDENTIFIER) | ||
contains("""<a href="http://localhost:3001/fi/hakemus/13">""") | ||
contains("""<a href="http://localhost:3001/sv/ansokan/13">""") | ||
contains("""<a href="http://localhost:3001/en/application/13">""") | ||
|
||
@Test | ||
fun `sendApplicationInvitationEmail sends email with correct subject`() { | ||
val data = applicationInvitationData() | ||
emailSenderService.sendApplicationInvitationEmail(TEST_EMAIL, data) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
assertThat(email.subject) | ||
.isEqualTo("Sinut on lisätty hakemukselle ${data.applicationIdentifier}") | ||
} | ||
|
||
@Test | ||
fun `sendApplicationInvitationEmail sends email with parametrized hybrid body`() { | ||
val data = applicationInvitationData() | ||
|
||
emailSenderService.sendApplicationInvitationEmail(TEST_EMAIL, data) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).all { | ||
startsWith("${data.inviterName} (${data.inviterEmail}) on") | ||
contains("tehnyt johtoselvityshakemuksen (${data.applicationIdentifier})") | ||
contains("hankkeella ${data.hankeTunnus}") | ||
contains("rooliin ${data.roleType.text()}.") | ||
contains("Tarkastele hakemusta Haitattomassa: http://localhost:3001") | ||
} | ||
assertThat(htmlBody).all { | ||
contains("${data.inviterName} (${data.inviterEmail})") | ||
contains("johtoselvityshakemuksen (${data.applicationIdentifier})") | ||
contains("rooliin ${data.roleType.text()}") | ||
contains("""Tarkastele hakemusta Haitattomassa: <a href="http://localhost:3001">""") | ||
} | ||
} | ||
|
||
@Test | ||
fun `sendApplicationInvitationEmail handles input without inviter name`() { | ||
val data = applicationInvitationData(inviterName = null) | ||
|
||
emailSenderService.sendApplicationInvitationEmail(TEST_EMAIL, data) | ||
|
||
val email = greenMail.firstReceivedMessage() | ||
val (textBody, htmlBody) = getBodiesFromHybridEmail(email) | ||
assertThat(textBody).startsWith("Asioija ${data.inviterEmail} on tehnyt") | ||
assertThat(htmlBody).contains("<p>Asioija ${data.inviterEmail} on tehnyt") | ||
} | ||
} | ||
|
||
|
@@ -116,4 +274,25 @@ class EmailSenderServiceITest : DatabaseTest() { | |
.map { i -> mp3.getBodyPart(i).content.toString() } | ||
return Pair(bodies[0], bodies[1]) | ||
} | ||
|
||
private fun hankeInvitationData(inviterName: String? = DEFAULT_INVITER_NAME) = | ||
HankeInvitationData( | ||
inviterName = inviterName, | ||
inviterEmail = "[email protected]", | ||
hankeTunnus = "HAI24-1", | ||
hankeNimi = "Mannerheimintien liikenneuudistus", | ||
invitationToken = "MgtzRbcPsvoKQamnaSxCnmW7", | ||
) | ||
|
||
private fun applicationInvitationData(inviterName: String? = DEFAULT_INVITER_NAME) = | ||
ApplicationInvitationData( | ||
inviterName = inviterName, | ||
inviterEmail = "[email protected]", | ||
applicationType = ApplicationType.CABLE_REPORT, | ||
applicationIdentifier = APPLICATION_IDENTIFIER, | ||
hankeTunnus = "HAI24-1", | ||
roleType = ContactType.RAKENNUTTAJA, | ||
) | ||
|
||
private fun ContactType.text() = toString().lowercase() | ||
} |
Oops, something went wrong.