SimpleNotes/persistence/test/NoteRepositoryImplTest.kt

328 lines
10 KiB
Kotlin

package be.simplenotes.persistence
import be.simplenotes.persistence.notes.*
import be.simplenotes.persistence.repositories.NoteRepository
import be.simplenotes.persistence.repositories.UserRepository
import be.simplenotes.persistence.users.createFakeUser
import be.simplenotes.types.ExportedNote
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedUser
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.ktorm.database.Database
import org.ktorm.dsl.eq
import org.ktorm.entity.filter
import org.ktorm.entity.find
import org.ktorm.entity.mapColumns
import org.ktorm.entity.toList
import java.sql.SQLIntegrityConstraintViolationException
internal class NoteRepositoryImplTest : DbTest() {
private lateinit var noteRepo: NoteRepository
private lateinit var userRepo: UserRepository
private lateinit var db: Database
private lateinit var user1: PersistedUser
private lateinit var user2: PersistedUser
@BeforeEach
fun insertUsers() {
noteRepo = beanContext.getBean()
userRepo = beanContext.getBean()
db = beanContext.getBean()
user1 = userRepo.createFakeUser()!!
user2 = userRepo.createFakeUser()!!
}
@Nested
@DisplayName("create()")
inner class Create {
@Test
fun `create note for non existing user`() {
val note = fakeNote()
assertThatThrownBy {
noteRepo.create(1000, note)
}.isInstanceOf(SQLIntegrityConstraintViolationException::class.java)
}
@Test
fun `create note for existing user`() {
val note = fakeNote()
assertThat(noteRepo.create(user1.id, note))
.hasNoNullFieldsOrProperties()
.usingRecursiveComparison()
.ignoringFields("uuid", "updatedAt", "public")
.isEqualTo(note)
assertThat(db.notes.toList())
.hasSize(1)
.first()
.usingRecursiveComparison()
.ignoringFields("uuid", "updatedAt", "public")
.isEqualTo(note)
}
}
@Nested
@DisplayName("findAll()")
inner class FindAll {
@Test
fun `find all notes`() {
val notes1 = noteRepo.insertFakeNotes(user1, count = 3)
val notes2 = listOf(noteRepo.insertFakeNote(user2))
assertThat(noteRepo.findAll(user1.id))
.hasSize(3)
.usingElementComparatorIgnoringFields("updatedAt")
.containsExactlyInAnyOrderElementsOf(
notes1.map { it.toPersistedMeta() },
)
assertThat(noteRepo.findAll(user2.id))
.hasSize(1)
.usingElementComparatorIgnoringFields("updatedAt")
.containsExactlyInAnyOrderElementsOf(
notes2.map { it.toPersistedMeta() },
)
assertThat(noteRepo.findAll(1000)).isEmpty()
}
@Test
fun `find all notes with tag`() {
with(noteRepo) {
insertFakeNote(user1, "1", listOf("a", "b"))
insertFakeNote(user1, "2", tags = emptyList())
insertFakeNote(user1, "3", listOf("c"))
insertFakeNote(user1, "4", listOf("c"))
insertFakeNote(user2, "5", listOf("c"))
}
assertThat(noteRepo.findAll(user1.id, tag = "a"))
.hasSize(1)
.first()
.hasFieldOrPropertyWithValue("title", "1")
assertThat(noteRepo.findAll(user1.id, tag = "c"))
.hasSize(2)
assertThat(noteRepo.findAll(user2.id, tag = "c"))
.hasSize(1)
}
}
@Nested
@DisplayName("find() | exists()")
inner class FindExists {
@Test
@Suppress("UNCHECKED_CAST")
fun `find an existing note`() {
val fakeNote = noteRepo.insertFakeNote(user1)
val note = db.notes.find { Notes.title eq fakeNote.title }!!
.let { entity ->
val tags = db.tags.filter {
be.simplenotes.persistence.Tags.noteUuid eq entity.uuid
}.mapColumns { be.simplenotes.persistence.Tags.name } as List<String>
PersistedNote(
uuid = entity.uuid,
title = entity.title,
tags = tags,
markdown = entity.markdown,
html = entity.html,
updatedAt = entity.updatedAt,
public = entity.public,
)
}
assertThat(noteRepo.find(user1.id, note.uuid)).isEqualTo(note)
assertThat(noteRepo.exists(user1.id, note.uuid)).isTrue
}
@Test
fun `find an existing note from the wrong user`() {
val note = noteRepo.insertFakeNote(user1)
assertThat(noteRepo.find(user2.id, note.uuid)).isNull()
assertThat(noteRepo.exists(user2.id, note.uuid)).isFalse
}
@Test
fun `find a non existing note`() {
noteRepo.insertFakeNote(user1)
val uuid = fakeUuid()
assertThat(noteRepo.find(user1.id, uuid)).isNull()
assertThat(noteRepo.exists(user2.id, uuid)).isFalse
}
}
@Nested
@DisplayName("delete()")
inner class Delete {
@Test
fun `delete an existing note for a user should succeed and then fail`() {
val note = noteRepo.insertFakeNote(user1)
assertThat(noteRepo.delete(user1.id, note.uuid)).isTrue
}
@Test
fun `delete an existing note for the wrong user`() {
val note = noteRepo.insertFakeNote(user1)
assertThat(noteRepo.delete(1000, note.uuid)).isFalse
}
}
@Nested
@DisplayName("getTags()")
inner class Tags {
@Test
fun getTags() {
val notes1 = noteRepo.insertFakeNotes(user1, count = 3)
val notes2 = noteRepo.insertFakeNotes(user2, count = 1)
val user1Tags = notes1.flatMap { it.tags }.toSet()
assertThat(noteRepo.getTags(user1.id))
.containsExactlyInAnyOrderElementsOf(user1Tags)
val user2Tags = notes2.flatMap { it.tags }.toSet()
assertThat(noteRepo.getTags(user2.id))
.containsExactlyInAnyOrderElementsOf(user2Tags)
assertThat(noteRepo.getTags(1000))
.isEmpty()
}
}
@Nested
@DisplayName("update()")
inner class Update {
@Test
fun getTags() {
val note1 = noteRepo.insertFakeNote(user1)
val newNote1 = fakeNote()
assertThat(noteRepo.update(user1.id, note1.uuid, newNote1)).isNotNull
assertThat(noteRepo.find(user1.id, note1.uuid))
.usingRecursiveComparison()
.ignoringFields("updatedAt", "uuid", "public")
.isEqualTo(newNote1)
val note2 = noteRepo.insertFakeNote(user1)
val newNote2 = fakeNote().copy(tags = tagGenerator().take(3).toList())
assertThat(noteRepo.update(user1.id, note2.uuid, newNote2))
.isNotNull
assertThat(noteRepo.find(user1.id, note2.uuid))
.usingRecursiveComparison()
.ignoringFields("updatedAt", "uuid", "public")
.isEqualTo(newNote2)
}
}
@Nested
inner class Trash {
@Test
fun `trashed noted should be restored`() {
val note1 = noteRepo.insertFakeNote(user1, "1", listOf("a", "b"))
assertThat(noteRepo.delete(user1.id, note1.uuid, permanent = false))
.isTrue
val isDeleted = db.notes
.find { Notes.uuid eq note1.uuid }
?.deleted
assertThat(isDeleted).`as`("Check that Notes.deleted is true").isTrue
assertThat(noteRepo.restore(user1.id, note1.uuid)).isTrue
val isDeleted2 = db.notes
.find { Notes.uuid eq note1.uuid }
?.deleted
assertThat(isDeleted2).`as`("Check that Notes.deleted is false after restore()").isFalse
}
@Test
fun `permanent delete`() {
val note = noteRepo.insertFakeNote(user1)
assertThat(noteRepo.delete(user1.id, note.uuid, permanent = true)).isTrue
assertThat(noteRepo.restore(user1.id, note.uuid)).isFalse
}
}
@Test
fun count() {
assertThat(noteRepo.count(user1.id)).isEqualTo(0)
noteRepo.insertFakeNotes(user1, count = 10)
assertThat(noteRepo.count(user1.id)).isEqualTo(10)
}
@Test
fun countWithTag() {
noteRepo.insertFakeNote(user1, tags = listOf("a", "b"))
noteRepo.insertFakeNote(user1, tags = emptyList())
noteRepo.insertFakeNote(user1, tags = listOf("a"))
noteRepo.insertFakeNote(user1, tags = emptyList())
assertThat(noteRepo.count(user1.id, tag = "a")).isEqualTo(2)
}
@Test
fun export() {
val notes = noteRepo.insertFakeNotes(user1, count = 4)
noteRepo.delete(user1.id, notes.first().uuid, permanent = false)
val export = noteRepo.export(user1.id)
val expected = notes.mapIndexed { i, n ->
ExportedNote(
title = n.title,
tags = n.tags,
markdown = n.markdown,
html = n.html,
updatedAt = n.updatedAt,
trash = i == 0,
)
}
assertThat(export)
.usingElementComparatorIgnoringFields("updatedAt")
.containsExactlyInAnyOrderElementsOf(expected)
}
@Test
fun findAllDetails() {
val notes = noteRepo.insertFakeNotes(user1, count = 10)
val res = noteRepo.findAllDetails(user1.id)
assertThat(res)
.usingElementComparatorIgnoringFields("updatedAt")
.containsExactlyInAnyOrderElementsOf(notes)
}
@Test
fun access() {
val n = noteRepo.insertFakeNote(user1)
noteRepo.makePublic(user1.id, n.uuid)
assertThat(noteRepo.findPublic(n.uuid))
.usingRecursiveComparison()
.ignoringFields("updatedAt")
.isEqualTo(n.copy(public = true))
noteRepo.makePrivate(user1.id, n.uuid)
assertThat(noteRepo.findPublic(n.uuid)).isNull()
}
}