diff --git a/backend/src/main/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandler.kt b/backend/src/main/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandler.kt index 50aa551..f7148e5 100644 --- a/backend/src/main/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandler.kt +++ b/backend/src/main/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandler.kt @@ -2,6 +2,7 @@ package nl.stevenbontenbal.chorister.event import nl.stevenbontenbal.chorister.model.entities.SetlistEntry import nl.stevenbontenbal.chorister.repository.SetlistEntryRepository +import org.springframework.data.rest.core.annotation.HandleAfterDelete import org.springframework.data.rest.core.annotation.HandleBeforeCreate import org.springframework.data.rest.core.annotation.RepositoryEventHandler import org.springframework.stereotype.Component @@ -11,11 +12,19 @@ import org.springframework.stereotype.Component class SetlistEntryEventHandler( private val setlistEntryRepository: SetlistEntryRepository ) { - @HandleBeforeCreate fun handleSetlistEntryCreate(setlistEntry: SetlistEntry) { val setlist = setlistEntry.setlist val no = setlist.entries.size + 1 setlistEntry.number = no } + + @HandleAfterDelete + fun handleSetlistEntryDelete(oldSetlistEntry: SetlistEntry) { + oldSetlistEntry.setlist.id?.let { + val laterEntries = setlistEntryRepository.findBySetlistIdAndNumberGreaterThan(it, oldSetlistEntry.number) + laterEntries.forEach { current -> current.number -- } + setlistEntryRepository.saveAll(laterEntries) + } + } } \ No newline at end of file diff --git a/backend/src/main/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepository.kt b/backend/src/main/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepository.kt index 9dc7bf2..5fd366f 100644 --- a/backend/src/main/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepository.kt +++ b/backend/src/main/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepository.kt @@ -4,8 +4,12 @@ import nl.stevenbontenbal.chorister.model.entities.SetlistEntry import nl.stevenbontenbal.chorister.model.entities.SetlistEntryId import org.springframework.data.repository.CrudRepository import org.springframework.data.rest.core.annotation.RepositoryRestResource +import org.springframework.data.rest.core.annotation.RestResource @RepositoryRestResource interface SetlistEntryRepository: CrudRepository { fun findBySetlistId(setlistId: Long): Iterable + + @RestResource(exported = false) + fun findBySetlistIdAndNumberGreaterThan(id: Long, number: Int): Iterable } \ No newline at end of file diff --git a/backend/src/test/kotlin/nl/stevenbontenbal/chorister/TestDataExtensions.kt b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/TestDataExtensions.kt index 5358dc4..2443b85 100644 --- a/backend/src/test/kotlin/nl/stevenbontenbal/chorister/TestDataExtensions.kt +++ b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/TestDataExtensions.kt @@ -4,6 +4,7 @@ import nl.stevenbontenbal.chorister.model.entities.* import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager import java.time.LocalDate import java.util.* +import kotlin.collections.List fun Song.Companion.create(choir: Choir): Song { return Song( @@ -19,14 +20,19 @@ fun Song.Companion.create(choir: Choir): Song { ) } -fun Setlist.Companion.create(choir: Choir): Setlist { +fun Setlist.Companion.create(choir: Choir, id: Long? = null): Setlist { return Setlist( + id = id, choir = choir, name = "Christmas Morning", date = LocalDate.of(2022, 12, 25), ) } +fun Setlist.Companion.create(choir: Choir, entityManager: TestEntityManager): Setlist { + return Setlist.create(choir).persist(entityManager) +} + fun Category.Companion.create(choir: Choir, categoryType: CategoryType): Category { return Category( name = "Christmas", @@ -60,14 +66,18 @@ fun Invite.Companion.create(choir: Choir): Invite { ) } -fun SetlistEntry.Companion.create(setlist: Setlist, song: Song): SetlistEntry { +fun SetlistEntry.Companion.create(setlist: Setlist, song: Song, number: Int = 1): SetlistEntry { return SetlistEntry( setlist = setlist, song = song, - number = 1 + number = number ) } +fun SetlistEntry.Companion.create(setlist: Setlist, songs: List): List { + return songs.mapIndexed { index, song -> SetlistEntry.create(setlist, song, index + 1) } +} + fun T.persist(entityManager: TestEntityManager): T { entityManager.persist(this) return this diff --git a/backend/src/test/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandlerTests.kt b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandlerTests.kt new file mode 100644 index 0000000..1df926c --- /dev/null +++ b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/event/SetlistEntryEventHandlerTests.kt @@ -0,0 +1,79 @@ +package nl.stevenbontenbal.chorister.event + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import nl.stevenbontenbal.chorister.configuration.ChoristerConfiguration +import nl.stevenbontenbal.chorister.create +import nl.stevenbontenbal.chorister.model.entities.Choir +import nl.stevenbontenbal.chorister.model.entities.Setlist +import nl.stevenbontenbal.chorister.model.entities.SetlistEntry +import nl.stevenbontenbal.chorister.model.entities.Song +import nl.stevenbontenbal.chorister.repository.SetlistEntryRepository +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.runner.RunWith +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.junit4.SpringRunner + +@RunWith(SpringRunner::class) +@ContextConfiguration(classes = [ChoristerConfiguration::class]) +class SetlistEntryEventHandlerTests { + @Test + fun `when setlist empty then first entry is 1`() { + // Arrange + val choir = Choir.create() + val setlist = Setlist.create(choir, 1) + val song1 = Song.create(choir) + val entry = SetlistEntry.create(setlist, song1) + val repository: SetlistEntryRepository = mockk(relaxed = true) + val target = SetlistEntryEventHandler(repository) + + // Act + target.handleSetlistEntryCreate(entry) + + // Assert + Assertions.assertThat(entry.number).isEqualTo(1) + } + + @Test + fun `when setlist contains 2 then next entry is 3`() { + // Arrange + val choir = Choir.create() + val setlist = Setlist.create(choir, 1) + val song1 = Song.create(choir) + val song2 = Song.create(choir) + val song3 = Song.create(choir) + val entries = SetlistEntry.create(setlist, listOf(song1, song2, song3)) + setlist.entries.addAll(entries.take(2)) + val repository: SetlistEntryRepository = mockk(relaxed = true) + val target = SetlistEntryEventHandler(repository) + + // Act + target.handleSetlistEntryDelete(entries[2]) + + // Assert + Assertions.assertThat(entries[2].number).isEqualTo(3) + } + + @Test + fun `when entry deleted then following entries are reordered`() { + // Arrange + val choir = Choir.create() + val setlist = Setlist.create(choir, 1) + val song1 = Song.create(choir) + val song2 = Song.create(choir) + val song3 = Song.create(choir) + val entries = SetlistEntry.create(setlist, listOf(song1, song2, song3)) + val repository: SetlistEntryRepository = mockk(relaxed = true) + every { repository.findBySetlistIdAndNumberGreaterThan(setlist.id!!, 1) }.returns(listOf(entries[1], entries[2])) + val target = SetlistEntryEventHandler(repository) + + // Act + target.handleSetlistEntryDelete(entries[0]) + + // Assert + verify(exactly = 1) { repository.saveAll(listOf(entries[1], entries[2])) } + Assertions.assertThat(entries[1].number).isEqualTo(1) + } +} \ No newline at end of file diff --git a/backend/src/test/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepositoryTests.kt b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepositoryTests.kt index c09b466..52131e6 100644 --- a/backend/src/test/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepositoryTests.kt +++ b/backend/src/test/kotlin/nl/stevenbontenbal/chorister/repository/SetlistEntryRepositoryTests.kt @@ -21,12 +21,12 @@ class SetlistEntryRepositoryTests @Autowired constructor( fun `When findBySetlistId then return all setlist's entries`() { // Arrange val choir = Choir.create().persist(entityManager) - val setlist = Setlist.create(choir).persist(entityManager) + val setlist = Setlist.create(choir, entityManager) val song1 = Song.create(choir).persist(entityManager) val song2 = Song.create(choir).persist(entityManager) - val song3 = Song.create(choir).persist(entityManager) - val entry1 = SetlistEntry.create(setlist, song1).persist(entityManager) - val entry2 = SetlistEntry.create(setlist, song2).persist(entityManager) + Song.create(choir).persist(entityManager) + SetlistEntry.create(setlist, song1).persist(entityManager) + SetlistEntry.create(setlist, song2).persist(entityManager) // Act val setlists = setlistEntryRepository.findBySetlistId(setlistId = setlist.id!!) // Assert