Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,54 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-check</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/openapi/**</exclude>
<exclude>**/generated/**</exclude>
<exclude>**/SiteBackendApplication*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/be/sgl/backend/entity/setting/SettingId.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ enum class SettingId {
REPRESENTATIVE_TITLE,
REPRESENTATIVE_USERNAME,
REPRESENTATIVE_SIGNATURE,
CALENDAR_NAME
CALENDAR_NAME,
ORGANIZATION_NAME
}
99 changes: 99 additions & 0 deletions src/test/kotlin/be/sgl/backend/alert/AlertLoggerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package be.sgl.backend.alert

import be.sgl.backend.service.MailService
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
import org.springframework.test.util.ReflectionTestUtils

class AlertLoggerTest {

@Mock
private lateinit var mailService: MailService

@Mock
private lateinit var mailBuilder: MailService.MailBuilder

@InjectMocks
private lateinit var alertLogger: AlertLogger

@BeforeEach
fun setup() {
MockitoAnnotations.openMocks(this)
ReflectionTestUtils.setField(alertLogger, "enabled", true)
ReflectionTestUtils.setField(alertLogger, "mailRecipient", "admin@example.com")
ReflectionTestUtils.setField(alertLogger, "environment", "test")
ReflectionTestUtils.setField(alertLogger, "host", "https://test.example.com")
}

@Test
fun `alert with lambda should send email when enabled`() {
`when`(mailService.builder()).thenReturn(mailBuilder)
`when`(mailBuilder.to(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.subject(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.body(anyString())).thenReturn(mailBuilder)

alertLogger.alert(AlertCode.NEW_USER_EXISTS_NO_MEMBERSHIP) { "Test alert message" }

verify(mailService).builder()
verify(mailBuilder).to("admin@example.com")
verify(mailBuilder).subject("https://test.example.com - test: NEW_USER_EXISTS_NO_MEMBERSHIP")
verify(mailBuilder).body("Test alert message")
verify(mailBuilder).send()
}

@Test
fun `alert with string should send email when enabled`() {
`when`(mailService.builder()).thenReturn(mailBuilder)
`when`(mailBuilder.to(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.subject(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.body(anyString())).thenReturn(mailBuilder)

alertLogger.alert(AlertCode.NEW_USER_EXISTS_PAID_MEMBERSHIP, "Test alert message")

verify(mailService).builder()
verify(mailBuilder).to("admin@example.com")
verify(mailBuilder).subject("https://test.example.com - test: NEW_USER_EXISTS_PAID_MEMBERSHIP")
verify(mailBuilder).body("Test alert message")
verify(mailBuilder).send()
}

@Test
fun `alert should not send email when disabled`() {
ReflectionTestUtils.setField(alertLogger, "enabled", false)

alertLogger.alert(AlertCode.NEW_USER_EXISTS_NO_MEMBERSHIP, "Test alert message")

verify(mailService, never()).builder()
}

@Test
fun `alert should use correct mail recipient`() {
ReflectionTestUtils.setField(alertLogger, "mailRecipient", "custom@example.com")
`when`(mailService.builder()).thenReturn(mailBuilder)
`when`(mailBuilder.to(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.subject(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.body(anyString())).thenReturn(mailBuilder)

alertLogger.alert(AlertCode.NEW_USER_EXISTS_NO_MEMBERSHIP, "Test alert")

verify(mailBuilder).to("custom@example.com")
}

@Test
fun `alert should format subject with host environment and code`() {
ReflectionTestUtils.setField(alertLogger, "host", "https://prod.example.com")
ReflectionTestUtils.setField(alertLogger, "environment", "production")
`when`(mailService.builder()).thenReturn(mailBuilder)
`when`(mailBuilder.to(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.subject(anyString())).thenReturn(mailBuilder)
`when`(mailBuilder.body(anyString())).thenReturn(mailBuilder)

alertLogger.alert(AlertCode.NEW_USER_EXISTS_PAID_MEMBERSHIP, "Test")

verify(mailBuilder).subject("https://prod.example.com - production: NEW_USER_EXISTS_PAID_MEMBERSHIP")
}
}
166 changes: 166 additions & 0 deletions src/test/kotlin/be/sgl/backend/config/CustomUserDetailsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package be.sgl.backend.config

import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.oauth2.jwt.Jwt

class CustomUserDetailsTest {

@Test
fun `CustomUserDetails should extract username from JWT`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertEquals("john.doe", userDetails.username)
}

@Test
fun `CustomUserDetails should extract firstName from JWT`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertEquals("John", userDetails.firstName)
}

@Test
fun `CustomUserDetails should extract lastName from JWT`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertEquals("Doe", userDetails.lastName)
}

@Test
fun `CustomUserDetails should extract email from JWT`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertEquals("john.doe@example.com", userDetails.email)
}

@Test
fun `CustomUserDetails should extract externalId from JWT`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertEquals("ext-12345", userDetails.externalId)
}

@Test
fun `CustomUserDetails should extract authorities from JWT roles`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(listOf("ROLE_USER", "ROLE_ADMIN"))

val userDetails = CustomUserDetails(jwt)

val authorities = userDetails.authorities
assertEquals(2, authorities.size)
assertTrue(authorities.contains(SimpleGrantedAuthority("ROLE_USER")))
assertTrue(authorities.contains(SimpleGrantedAuthority("ROLE_ADMIN")))
}

@Test
fun `CustomUserDetails should have empty authorities when roles claim is null`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

val authorities = userDetails.authorities
assertTrue(authorities.isEmpty())
}

@Test
fun `CustomUserDetails should have empty authorities when roles claim is empty list`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(emptyList())

val userDetails = CustomUserDetails(jwt)

val authorities = userDetails.authorities
assertTrue(authorities.isEmpty())
}

@Test
fun `CustomUserDetails getPassword should return null`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertNull(userDetails.password)
}

@Test
fun `CustomUserDetails should implement UserDetails interface`() {
val jwt = mock(Jwt::class.java)
`when`(jwt.getClaim<String>("preferred_username")).thenReturn("john.doe")
`when`(jwt.getClaim<String>("given_name")).thenReturn("John")
`when`(jwt.getClaim<String>("family_name")).thenReturn("Doe")
`when`(jwt.getClaim<String>("email")).thenReturn("john.doe@example.com")
`when`(jwt.getClaim<String>("sub")).thenReturn("ext-12345")
`when`(jwt.getClaimAsStringList("roles")).thenReturn(null)

val userDetails = CustomUserDetails(jwt)

assertTrue(userDetails is org.springframework.security.core.userdetails.UserDetails)
}
}
Loading