Add more persistance tests
This commit is contained in:
parent
a37254452b
commit
78b84dc62a
@ -3,6 +3,7 @@ import be.simplenotes.Libs
|
|||||||
plugins {
|
plugins {
|
||||||
id("be.simplenotes.base")
|
id("be.simplenotes.base")
|
||||||
kotlin("kapt")
|
kotlin("kapt")
|
||||||
|
`java-test-fixtures`
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -22,4 +23,15 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(Libs.junit)
|
testImplementation(Libs.junit)
|
||||||
testImplementation(Libs.assertJ)
|
testImplementation(Libs.assertJ)
|
||||||
|
testImplementation(Libs.logbackClassic)
|
||||||
|
testImplementation("org.testcontainers:mariadb:1.15.0-rc2")
|
||||||
|
|
||||||
|
testFixturesImplementation(project(":simplenotes-types"))
|
||||||
|
testFixturesImplementation(project(":simplenotes-config"))
|
||||||
|
testFixturesImplementation("com.github.javafaker:javafaker:1.0.2")
|
||||||
|
testFixturesImplementation("org.testcontainers:mariadb:1.15.0-rc2")
|
||||||
|
testFixturesImplementation(Libs.koinCore)
|
||||||
|
testFixturesImplementation(Libs.flywayCore)
|
||||||
|
testFixturesImplementation(Libs.junit)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package be.simplenotes.persistance
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.parallel.ResourceLock
|
||||||
|
|
||||||
|
@ResourceLock("h2")
|
||||||
|
class H2DbHealthCheckImplTest : DbTest() {
|
||||||
|
private val healthCheck = koin.get<DbHealthCheck>()
|
||||||
|
override fun dataSourceConfig() = h2dataSourceConfig()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun healthCheck() {
|
||||||
|
assertThat(healthCheck.isOk()).isTrue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResourceLock("mariadb")
|
||||||
|
class MariaDbHealthCheckImplTest : DbTest() {
|
||||||
|
private val healthCheck = koin.get<DbHealthCheck>()
|
||||||
|
lateinit var mariaDB: KMariadbContainer
|
||||||
|
|
||||||
|
override fun dataSourceConfig(): DataSourceConfig {
|
||||||
|
mariaDB = KMariadbContainer()
|
||||||
|
mariaDB.start()
|
||||||
|
return mariadbDataSourceConfig(mariaDB.jdbcUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun healthCheck() {
|
||||||
|
assertThat(healthCheck.isOk()).isTrue
|
||||||
|
mariaDB.stop()
|
||||||
|
assertThat(healthCheck.isOk()).isFalse
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,13 +1,12 @@
|
|||||||
package be.simplenotes.persistance.notes
|
package be.simplenotes.persistance.notes
|
||||||
|
|
||||||
import be.simplenotes.config.DataSourceConfig
|
import be.simplenotes.persistance.DbTest
|
||||||
import be.simplenotes.persistance.DbMigrations
|
|
||||||
import be.simplenotes.persistance.converters.NoteConverter
|
import be.simplenotes.persistance.converters.NoteConverter
|
||||||
import be.simplenotes.persistance.migrationModule
|
|
||||||
import be.simplenotes.persistance.persistanceModule
|
|
||||||
import be.simplenotes.persistance.repositories.NoteRepository
|
import be.simplenotes.persistance.repositories.NoteRepository
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
import be.simplenotes.types.*
|
import be.simplenotes.persistance.users.createFakeUser
|
||||||
|
import be.simplenotes.types.ExportedNote
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
import me.liuwj.ktorm.database.Database
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.dsl.eq
|
import me.liuwj.ktorm.dsl.eq
|
||||||
import me.liuwj.ktorm.entity.filter
|
import me.liuwj.ktorm.entity.filter
|
||||||
@ -16,42 +15,12 @@ import me.liuwj.ktorm.entity.mapColumns
|
|||||||
import me.liuwj.ktorm.entity.toList
|
import me.liuwj.ktorm.entity.toList
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.flywaydb.core.Flyway
|
|
||||||
import org.junit.jupiter.api.*
|
import org.junit.jupiter.api.*
|
||||||
import org.junit.jupiter.api.parallel.ResourceLock
|
|
||||||
import org.koin.dsl.koinApplication
|
|
||||||
import org.koin.dsl.module
|
|
||||||
import org.mapstruct.factory.Mappers
|
import org.mapstruct.factory.Mappers
|
||||||
import java.sql.SQLIntegrityConstraintViolationException
|
import java.sql.SQLIntegrityConstraintViolationException
|
||||||
import java.util.*
|
|
||||||
import javax.sql.DataSource
|
|
||||||
|
|
||||||
@ResourceLock("h2")
|
internal abstract class BaseNoteRepositoryImplTest : DbTest() {
|
||||||
internal class NoteRepositoryImplTest {
|
|
||||||
private val testModule = module {
|
|
||||||
single { dataSourceConfig() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val koinApp = koinApplication {
|
|
||||||
modules(persistanceModule, migrationModule, testModule)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dataSourceConfig() = DataSourceConfig(
|
|
||||||
jdbcUrl = "jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;",
|
|
||||||
driverClassName = "org.h2.Driver",
|
|
||||||
username = "h2",
|
|
||||||
password = "",
|
|
||||||
maximumPoolSize = 2,
|
|
||||||
connectionTimeout = 3000
|
|
||||||
)
|
|
||||||
|
|
||||||
private val koin = koinApp.koin
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
fun afterAll() = koinApp.close()
|
|
||||||
|
|
||||||
private val migration = koin.get<DbMigrations>()
|
|
||||||
private val dataSource = koin.get<DataSource>()
|
|
||||||
private val noteRepo = koin.get<NoteRepository>()
|
private val noteRepo = koin.get<NoteRepository>()
|
||||||
private val userRepo = koin.get<UserRepository>()
|
private val userRepo = koin.get<UserRepository>()
|
||||||
private val db = koin.get<Database>()
|
private val db = koin.get<Database>()
|
||||||
@ -60,35 +29,18 @@ internal class NoteRepositoryImplTest {
|
|||||||
private lateinit var user2: PersistedUser
|
private lateinit var user2: PersistedUser
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun beforeEach() {
|
fun insertUsers() {
|
||||||
Flyway.configure()
|
user1 = userRepo.createFakeUser()!!
|
||||||
.dataSource(dataSource)
|
user2 = userRepo.createFakeUser()!!
|
||||||
.load()
|
|
||||||
.clean()
|
|
||||||
|
|
||||||
migration.migrate()
|
|
||||||
|
|
||||||
user1 = userRepo.create(User("1", "1"))!!
|
|
||||||
user2 = userRepo.create(User("2", "2"))!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNote(
|
|
||||||
userId: Int,
|
|
||||||
title: String,
|
|
||||||
tags: List<String> = emptyList(),
|
|
||||||
md: String = "md",
|
|
||||||
html: String = "html",
|
|
||||||
): PersistedNote = noteRepo.create(userId, Note(NoteMetadata(title, tags), md, html))
|
|
||||||
|
|
||||||
private fun PersistedNote.toPersistedMeta() = PersistedNoteMetadata(meta.title, meta.tags, updatedAt, uuid)
|
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("create()")
|
@DisplayName("create()")
|
||||||
inner class Create {
|
inner class Create {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `create note for non existing user`() {
|
fun `create note for non existing user`() {
|
||||||
val note = Note(NoteMetadata("title", emptyList()), "md", "html")
|
val note = fakeNote()
|
||||||
|
|
||||||
assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
noteRepo.create(1000, note)
|
noteRepo.create(1000, note)
|
||||||
@ -97,7 +49,7 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `create note for existing user`() {
|
fun `create note for existing user`() {
|
||||||
val note = Note(NoteMetadata("title", emptyList()), "md", "html")
|
val note = fakeNote()
|
||||||
|
|
||||||
assertThat(noteRepo.create(user1.id, note))
|
assertThat(noteRepo.create(user1.id, note))
|
||||||
.isEqualToIgnoringGivenFields(note, "uuid", "updatedAt", "public")
|
.isEqualToIgnoringGivenFields(note, "uuid", "updatedAt", "public")
|
||||||
@ -116,15 +68,8 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `find all notes`() {
|
fun `find all notes`() {
|
||||||
val notes1 = listOf(
|
val notes1 = noteRepo.insertFakeNotes(user1, count = 3)
|
||||||
createNote(user1.id, "1", listOf("a", "b")),
|
val notes2 = listOf(noteRepo.insertFakeNote(user2))
|
||||||
createNote(user1.id, "2"),
|
|
||||||
createNote(user1.id, "3", listOf("c"))
|
|
||||||
)
|
|
||||||
|
|
||||||
val notes2 = listOf(
|
|
||||||
createNote(user2.id, "4")
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(noteRepo.findAll(user1.id))
|
assertThat(noteRepo.findAll(user1.id))
|
||||||
.hasSize(3)
|
.hasSize(3)
|
||||||
@ -143,13 +88,15 @@ internal class NoteRepositoryImplTest {
|
|||||||
assertThat(noteRepo.findAll(1000)).isEmpty()
|
assertThat(noteRepo.findAll(1000)).isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: datetime -> timestamp migration
|
||||||
|
@Disabled("Not working with mariadb, inserts are too fast so the updated_at is the same")
|
||||||
@Test
|
@Test
|
||||||
fun pagination() {
|
fun pagination() {
|
||||||
(50 downTo 1).forEach {
|
(50 downTo 1).forEach { i ->
|
||||||
createNote(user1.id, "$it")
|
noteRepo.insertFakeNote(user1, "$i")
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(noteRepo.findAll(user1.id, limit = 20, offset = 0))
|
assertThat(noteRepo.findAll(user1.id, limit = 20, offset = 0).onEach { println(it) })
|
||||||
.hasSize(20)
|
.hasSize(20)
|
||||||
.allMatch { it.title.toInt() in 1..20 }
|
.allMatch { it.title.toInt() in 1..20 }
|
||||||
|
|
||||||
@ -164,12 +111,13 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `find all notes with tag`() {
|
fun `find all notes with tag`() {
|
||||||
createNote(user1.id, "1", listOf("a", "b"))
|
with(noteRepo) {
|
||||||
createNote(user1.id, "2")
|
insertFakeNote(user1, "1", listOf("a", "b"))
|
||||||
createNote(user1.id, "3", listOf("c"))
|
insertFakeNote(user1, "2", tags = emptyList())
|
||||||
createNote(user1.id, "4", listOf("c"))
|
insertFakeNote(user1, "3", listOf("c"))
|
||||||
createNote(user2.id, "5", listOf("c"))
|
insertFakeNote(user1, "4", listOf("c"))
|
||||||
|
insertFakeNote(user2, "5", listOf("c"))
|
||||||
|
}
|
||||||
assertThat(noteRepo.findAll(user1.id, tag = "a"))
|
assertThat(noteRepo.findAll(user1.id, tag = "a"))
|
||||||
.hasSize(1)
|
.hasSize(1)
|
||||||
.first()
|
.first()
|
||||||
@ -189,34 +137,31 @@ internal class NoteRepositoryImplTest {
|
|||||||
@Test
|
@Test
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun `find an existing note`() {
|
fun `find an existing note`() {
|
||||||
createNote(user1.id, "1", listOf("a", "b"))
|
val fakeNote = noteRepo.insertFakeNote(user1)
|
||||||
|
|
||||||
val converter = Mappers.getMapper(NoteConverter::class.java)
|
val converter = Mappers.getMapper(NoteConverter::class.java)
|
||||||
|
|
||||||
val note = db.notes.find { it.title eq "1" }!!
|
val note = db.notes.find { it.title eq fakeNote.meta.title }!!
|
||||||
.let { entity ->
|
.let { entity ->
|
||||||
val tags = db.tags.filter { it.noteUuid eq entity.uuid }.mapColumns { it.name } as List<String>
|
val tags = db.tags.filter { it.noteUuid eq entity.uuid }.mapColumns { it.name } as List<String>
|
||||||
converter.toPersistedNote(entity, tags)
|
converter.toPersistedNote(entity, tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertThat(noteRepo.find(user1.id, note.uuid))
|
assertThat(noteRepo.find(user1.id, note.uuid)).isEqualTo(note)
|
||||||
.isEqualTo(note)
|
assertThat(noteRepo.exists(user1.id, note.uuid)).isTrue
|
||||||
|
|
||||||
assertThat(noteRepo.exists(user1.id, note.uuid))
|
|
||||||
.isTrue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `find an existing note from the wrong user`() {
|
fun `find an existing note from the wrong user`() {
|
||||||
val note = createNote(user1.id, "1", listOf("a", "b"))
|
val note = noteRepo.insertFakeNote(user1)
|
||||||
assertThat(noteRepo.find(user2.id, note.uuid)).isNull()
|
assertThat(noteRepo.find(user2.id, note.uuid)).isNull()
|
||||||
assertThat(noteRepo.exists(user2.id, note.uuid)).isFalse
|
assertThat(noteRepo.exists(user2.id, note.uuid)).isFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `find a non existing note`() {
|
fun `find a non existing note`() {
|
||||||
createNote(user1.id, "1", listOf("a", "b"))
|
noteRepo.insertFakeNote(user1)
|
||||||
val uuid = UUID.randomUUID()
|
val uuid = fakeUuid()
|
||||||
assertThat(noteRepo.find(user1.id, uuid)).isNull()
|
assertThat(noteRepo.find(user1.id, uuid)).isNull()
|
||||||
assertThat(noteRepo.exists(user2.id, uuid)).isFalse
|
assertThat(noteRepo.exists(user2.id, uuid)).isFalse
|
||||||
}
|
}
|
||||||
@ -228,16 +173,14 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `delete an existing note for a user should succeed and then fail`() {
|
fun `delete an existing note for a user should succeed and then fail`() {
|
||||||
val note = createNote(user1.id, "1", listOf("a", "b"))
|
val note = noteRepo.insertFakeNote(user1)
|
||||||
assertThat(noteRepo.delete(user1.id, note.uuid))
|
assertThat(noteRepo.delete(user1.id, note.uuid)).isTrue
|
||||||
.isTrue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `delete an existing note for the wrong user`() {
|
fun `delete an existing note for the wrong user`() {
|
||||||
val note = createNote(user1.id, "1", listOf("a", "b"))
|
val note = noteRepo.insertFakeNote(user1)
|
||||||
assertThat(noteRepo.delete(1000, note.uuid))
|
assertThat(noteRepo.delete(1000, note.uuid)).isFalse
|
||||||
.isFalse
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,15 +190,8 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getTags() {
|
fun getTags() {
|
||||||
val notes1 = listOf(
|
val notes1 = noteRepo.insertFakeNotes(user1, count = 3)
|
||||||
createNote(user1.id, "1", listOf("a", "b")),
|
val notes2 = noteRepo.insertFakeNotes(user2, count = 1)
|
||||||
createNote(user1.id, "2"),
|
|
||||||
createNote(user1.id, "3", listOf("c", "a"))
|
|
||||||
)
|
|
||||||
|
|
||||||
val notes2 = listOf(
|
|
||||||
createNote(user2.id, "4", listOf("a"))
|
|
||||||
)
|
|
||||||
|
|
||||||
val user1Tags = notes1.flatMap { it.meta.tags }.toSet()
|
val user1Tags = notes1.flatMap { it.meta.tags }.toSet()
|
||||||
assertThat(noteRepo.getTags(user1.id))
|
assertThat(noteRepo.getTags(user1.id))
|
||||||
@ -276,16 +212,18 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getTags() {
|
fun getTags() {
|
||||||
val note1 = createNote(user1.id, "1", listOf("a", "b"))
|
val note1 = noteRepo.insertFakeNote(user1)
|
||||||
val newNote1 = Note(meta = note1.meta, markdown = "new", "new")
|
val newNote1 = fakeNote()
|
||||||
assertThat(noteRepo.update(user1.id, note1.uuid, newNote1))
|
|
||||||
.isNotNull
|
assertThat(noteRepo.update(user1.id, note1.uuid, newNote1)).isNotNull
|
||||||
|
|
||||||
assertThat(noteRepo.find(user1.id, note1.uuid))
|
assertThat(noteRepo.find(user1.id, note1.uuid))
|
||||||
.isEqualToComparingOnlyGivenFields(newNote1, "meta", "markdown", "html")
|
.isEqualToComparingOnlyGivenFields(newNote1, "meta", "markdown", "html")
|
||||||
|
|
||||||
val note2 = createNote(user1.id, "2")
|
val note2 = noteRepo.insertFakeNote(user1)
|
||||||
val newNote2 = Note(meta = note1.meta.copy(tags = listOf("a")), markdown = "new", "new")
|
val newNote2 = fakeNote().let {
|
||||||
|
it.copy(meta = it.meta.copy(tags = tagGenerator().take(3).toList()))
|
||||||
|
}
|
||||||
assertThat(noteRepo.update(user1.id, note2.uuid, newNote2))
|
assertThat(noteRepo.update(user1.id, note2.uuid, newNote2))
|
||||||
.isNotNull
|
.isNotNull
|
||||||
|
|
||||||
@ -299,7 +237,7 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `trashed noted should be restored`() {
|
fun `trashed noted should be restored`() {
|
||||||
val note1 = createNote(user1.id, "1", listOf("a", "b"))
|
val note1 = noteRepo.insertFakeNote(user1, "1", listOf("a", "b"))
|
||||||
|
|
||||||
assertThat(noteRepo.delete(user1.id, note1.uuid, permanent = false))
|
assertThat(noteRepo.delete(user1.id, note1.uuid, permanent = false))
|
||||||
.isTrue
|
.isTrue
|
||||||
@ -321,11 +259,69 @@ internal class NoteRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `permanent delete`() {
|
fun `permanent delete`() {
|
||||||
val note1 = createNote(user1.id, "1", listOf("a", "b"))
|
val note = noteRepo.insertFakeNote(user1)
|
||||||
assertThat(noteRepo.delete(user1.id, note1.uuid, permanent = true))
|
assertThat(noteRepo.delete(user1.id, note.uuid, permanent = true)).isTrue
|
||||||
.isTrue
|
assertThat(noteRepo.restore(user1.id, note.uuid)).isFalse
|
||||||
|
|
||||||
assertThat(noteRepo.restore(user1.id, note1.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.meta.title,
|
||||||
|
tags = n.meta.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))
|
||||||
|
.isEqualToIgnoringGivenFields(n.copy(public = true), "updatedAt")
|
||||||
|
|
||||||
|
noteRepo.makePrivate(user1.id, n.uuid)
|
||||||
|
assertThat(noteRepo.findPublic(n.uuid)).isNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package be.simplenotes.persistance.notes
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
|
import be.simplenotes.persistance.KMariadbContainer
|
||||||
|
import be.simplenotes.persistance.h2dataSourceConfig
|
||||||
|
import be.simplenotes.persistance.mariadbDataSourceConfig
|
||||||
|
import org.junit.jupiter.api.AfterAll
|
||||||
|
import org.junit.jupiter.api.parallel.ResourceLock
|
||||||
|
|
||||||
|
@ResourceLock("h2")
|
||||||
|
internal class H2NoteRepositoryImplTests : BaseNoteRepositoryImplTest() {
|
||||||
|
override fun dataSourceConfig() = h2dataSourceConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResourceLock("mariadb")
|
||||||
|
internal class MariaDbNoteRepositoryImplTests : BaseNoteRepositoryImplTest() {
|
||||||
|
lateinit var mariaDB: KMariadbContainer
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
fun stopMariaDB() {
|
||||||
|
mariaDB.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dataSourceConfig(): DataSourceConfig {
|
||||||
|
mariaDB = KMariadbContainer()
|
||||||
|
mariaDB.start()
|
||||||
|
return mariadbDataSourceConfig(mariaDB.jdbcUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,73 +1,27 @@
|
|||||||
package be.simplenotes.persistance.users
|
package be.simplenotes.persistance.users
|
||||||
|
|
||||||
import be.simplenotes.config.DataSourceConfig
|
import be.simplenotes.persistance.DbTest
|
||||||
import be.simplenotes.persistance.DbMigrations
|
|
||||||
import be.simplenotes.persistance.migrationModule
|
|
||||||
import be.simplenotes.persistance.persistanceModule
|
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
import be.simplenotes.types.User
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.database.*
|
import me.liuwj.ktorm.dsl.eq
|
||||||
import me.liuwj.ktorm.dsl.*
|
import me.liuwj.ktorm.entity.find
|
||||||
import me.liuwj.ktorm.entity.*
|
import me.liuwj.ktorm.entity.toList
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.flywaydb.core.Flyway
|
|
||||||
import org.junit.jupiter.api.AfterAll
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
|
||||||
import org.junit.jupiter.api.Nested
|
import org.junit.jupiter.api.Nested
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.parallel.ResourceLock
|
|
||||||
import org.koin.dsl.koinApplication
|
|
||||||
import org.koin.dsl.module
|
|
||||||
import javax.sql.DataSource
|
|
||||||
|
|
||||||
@ResourceLock("h2")
|
internal abstract class BaseUserRepositoryImplTest : DbTest() {
|
||||||
internal class UserRepositoryImplTest {
|
|
||||||
|
|
||||||
// region setup
|
|
||||||
private val testModule = module {
|
|
||||||
single { dataSourceConfig() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val koinApp = koinApplication {
|
|
||||||
modules(persistanceModule, migrationModule, testModule)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dataSourceConfig() = DataSourceConfig(
|
|
||||||
jdbcUrl = "jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;",
|
|
||||||
driverClassName = "org.h2.Driver",
|
|
||||||
username = "h2",
|
|
||||||
password = "",
|
|
||||||
maximumPoolSize = 2,
|
|
||||||
connectionTimeout = 3000
|
|
||||||
)
|
|
||||||
|
|
||||||
private val koin = koinApp.koin
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
fun afterAll() = koinApp.close()
|
|
||||||
|
|
||||||
private val migration = koin.get<DbMigrations>()
|
|
||||||
private val dataSource = koin.get<DataSource>()
|
|
||||||
private val userRepo = koin.get<UserRepository>()
|
private val userRepo = koin.get<UserRepository>()
|
||||||
private val db = koin.get<Database>()
|
private val db = koin.get<Database>()
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
fun beforeEach() {
|
|
||||||
Flyway.configure()
|
|
||||||
.dataSource(dataSource)
|
|
||||||
.load()
|
|
||||||
.clean()
|
|
||||||
migration.migrate()
|
|
||||||
}
|
|
||||||
// endregion setup
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `insert user`() {
|
fun `insert user`() {
|
||||||
val user = User("username", "test")
|
val user = fakeUser()
|
||||||
assertThat(userRepo.create(user))
|
assertThat(userRepo.create(user))
|
||||||
.isNotNull
|
.isNotNull
|
||||||
.hasFieldOrPropertyWithValue("username", user.username)
|
.extracting("username", "password")
|
||||||
.hasFieldOrPropertyWithValue("password", user.password)
|
.contains(user.username, user.password)
|
||||||
|
|
||||||
assertThat(db.users.find { it.username eq user.username }).isNotNull
|
assertThat(db.users.find { it.username eq user.username }).isNotNull
|
||||||
assertThat(db.users.toList()).hasSize(1)
|
assertThat(db.users.toList()).hasSize(1)
|
||||||
@ -79,7 +33,7 @@ internal class UserRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `query existing user`() {
|
fun `query existing user`() {
|
||||||
val user = User("username", "test")
|
val user = fakeUser()
|
||||||
userRepo.create(user)
|
userRepo.create(user)
|
||||||
|
|
||||||
val foundUserMaybe = userRepo.find(user.username)
|
val foundUserMaybe = userRepo.find(user.username)
|
||||||
@ -105,7 +59,7 @@ internal class UserRepositoryImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `delete existing user`() {
|
fun `delete existing user`() {
|
||||||
val user = User("username", "test")
|
val user = fakeUser()
|
||||||
userRepo.create(user)
|
userRepo.create(user)
|
||||||
|
|
||||||
val foundUser = userRepo.find(user.username)!!
|
val foundUser = userRepo.find(user.username)!!
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package be.simplenotes.persistance.users
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
|
import be.simplenotes.persistance.KMariadbContainer
|
||||||
|
import be.simplenotes.persistance.h2dataSourceConfig
|
||||||
|
import be.simplenotes.persistance.mariadbDataSourceConfig
|
||||||
|
import org.junit.jupiter.api.AfterAll
|
||||||
|
import org.junit.jupiter.api.parallel.ResourceLock
|
||||||
|
|
||||||
|
@ResourceLock("h2")
|
||||||
|
internal class UserRepositoryImplTest : BaseUserRepositoryImplTest() {
|
||||||
|
override fun dataSourceConfig() = h2dataSourceConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResourceLock("mariadb")
|
||||||
|
internal class MariaDbUserRepositoryImplTest : BaseUserRepositoryImplTest() {
|
||||||
|
lateinit var mariaDB: KMariadbContainer
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
fun stopMariaDB() {
|
||||||
|
mariaDB.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dataSourceConfig(): DataSourceConfig {
|
||||||
|
mariaDB = KMariadbContainer()
|
||||||
|
mariaDB.start()
|
||||||
|
return mariadbDataSourceConfig(mariaDB.jdbcUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
simplenotes-persistance/src/test/resources/logback.xml
Normal file
15
simplenotes-persistance/src/test/resources/logback.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<withJansi>true</withJansi>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%cyan(%d{YYYY-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{36}) - %msg%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
<logger name="me.liuwj.ktorm.database" level="DEBUG"/>
|
||||||
|
<logger name="com.zaxxer.hikari" level="INFO"/>
|
||||||
|
<logger name="org.flywaydb.core" level="DEBUG"/>
|
||||||
|
</configuration>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package be.simplenotes.persistance
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
|
import org.testcontainers.containers.MariaDBContainer
|
||||||
|
|
||||||
|
class KMariadbContainer : MariaDBContainer<KMariadbContainer>("mariadb:10.5.5")
|
||||||
|
|
||||||
|
fun h2dataSourceConfig() = DataSourceConfig(
|
||||||
|
jdbcUrl = "jdbc:h2:mem:regular;DB_CLOSE_DELAY=-1;",
|
||||||
|
driverClassName = "org.h2.Driver",
|
||||||
|
username = "h2",
|
||||||
|
password = "",
|
||||||
|
maximumPoolSize = 2,
|
||||||
|
connectionTimeout = 3000
|
||||||
|
)
|
||||||
|
|
||||||
|
fun mariadbDataSourceConfig(jdbcUrl: String) = DataSourceConfig(
|
||||||
|
jdbcUrl = jdbcUrl,
|
||||||
|
driverClassName = "org.mariadb.jdbc.Driver",
|
||||||
|
username = "test",
|
||||||
|
password = "test",
|
||||||
|
maximumPoolSize = 2,
|
||||||
|
connectionTimeout = 3000
|
||||||
|
)
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package be.simplenotes.persistance
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
|
import org.flywaydb.core.Flyway.*
|
||||||
|
import org.junit.jupiter.api.AfterAll
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.koin.dsl.koinApplication
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import javax.sql.DataSource
|
||||||
|
|
||||||
|
abstract class DbTest {
|
||||||
|
|
||||||
|
abstract fun dataSourceConfig(): DataSourceConfig
|
||||||
|
|
||||||
|
private val testModule = module {
|
||||||
|
single { dataSourceConfig() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val koinApp = koinApplication {
|
||||||
|
modules(persistanceModule, migrationModule, testModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
val koin = koinApp.koin
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
fun afterAll() = koinApp.close()
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun beforeEach() {
|
||||||
|
val migration = koin.get<DbMigrations>()
|
||||||
|
val dataSource = koin.get<DataSource>()
|
||||||
|
configure()
|
||||||
|
.dataSource(dataSource)
|
||||||
|
.load()
|
||||||
|
.clean()
|
||||||
|
|
||||||
|
migration.migrate()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package be.simplenotes.persistance.notes
|
||||||
|
|
||||||
|
import be.simplenotes.persistance.repositories.NoteRepository
|
||||||
|
import be.simplenotes.types.*
|
||||||
|
import com.github.javafaker.Faker
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
private val faker = Faker()
|
||||||
|
|
||||||
|
fun fakeUuid() = UUID.randomUUID()!!
|
||||||
|
fun fakeTitle() = faker.lorem().characters(3, 50)!!
|
||||||
|
fun tagGenerator() = generateSequence { faker.lorem().word() }
|
||||||
|
fun fakeTags() = tagGenerator().take(faker.random().nextInt(0, 3)).toList()
|
||||||
|
fun fakeContent() = faker.lorem().paragraph(faker.random().nextInt(0, 3))!!
|
||||||
|
fun fakeNote() = Note(NoteMetadata(fakeTitle(), fakeTags()), fakeContent(), fakeContent())
|
||||||
|
|
||||||
|
fun PersistedNote.toPersistedMeta() =
|
||||||
|
PersistedNoteMetadata(meta.title, meta.tags, updatedAt, uuid)
|
||||||
|
|
||||||
|
fun NoteRepository.insertFakeNote(
|
||||||
|
userId: Int,
|
||||||
|
title: String,
|
||||||
|
tags: List<String> = emptyList(),
|
||||||
|
md: String = "md",
|
||||||
|
html: String = "html",
|
||||||
|
): PersistedNote = create(userId, Note(NoteMetadata(title, tags), md, html))
|
||||||
|
|
||||||
|
fun NoteRepository.insertFakeNote(
|
||||||
|
user: PersistedUser,
|
||||||
|
title: String = fakeTitle(),
|
||||||
|
tags: List<String> = fakeTags(),
|
||||||
|
md: String = fakeContent(),
|
||||||
|
html: String = fakeContent(),
|
||||||
|
): PersistedNote = insertFakeNote(user.id, title, tags, md, html)
|
||||||
|
|
||||||
|
fun NoteRepository.insertFakeNotes(user: PersistedUser, count: Int): List<PersistedNote> =
|
||||||
|
generateSequence { insertFakeNote(user) }.take(count).toList()
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package be.simplenotes.persistance.users
|
||||||
|
|
||||||
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
|
import be.simplenotes.types.User
|
||||||
|
import com.github.javafaker.Faker
|
||||||
|
|
||||||
|
private val faker = Faker()
|
||||||
|
|
||||||
|
fun fakeUser() = User(faker.name().username(), faker.internet().password())
|
||||||
|
|
||||||
|
fun UserRepository.createFakeUser(): PersistedUser? {
|
||||||
|
return create(fakeUser())
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user