Skip to content

Commit

Permalink
Bugfix: Fix post insertion for live created posts (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
julian-wls authored Nov 29, 2024
1 parent 4a8671b commit 022853a
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ internal class MetisStorageServiceImpl(
serverId: String,
clientSidePostId: String,
serverSidePostId: Long?,
conversationId: Long = this.conversationId,
postingType: BasePostingEntity.PostingType
): MetisPostContextEntity =
MetisPostContextEntity(
Expand Down Expand Up @@ -471,11 +472,13 @@ internal class MetisStorageServiceImpl(
metisDao.insertOrUpdateUser(postingAuthor)

val standalonePostId = sp.id
val conversationId = sp.conversation?.id
val postMetisContext =
metisContext.toPostMetisContext(
serverId = host,
clientSidePostId = clientSidePostId,
serverSidePostId = standalonePostId,
conversationId = conversationId?: metisContext.conversationId,
postingType = BasePostingEntity.PostingType.STANDALONE
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.storage.impl

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.testing.asSnapshot
import androidx.test.platform.app.InstrumentationRegistry
import de.tum.informatics.www1.artemis.native_app.core.model.account.User
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.AnswerPost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.StandalonePost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.UserRole
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.OneToOneChat
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.AnswerPostPojo
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
import de.tum.informatics.www1.artemis.native_app.feature.metistest.MetisDatabaseProviderMock
import kotlinx.datetime.Clock

abstract class MetisStorageBaseTest {

private val databaseProviderMock = MetisDatabaseProviderMock(InstrumentationRegistry.getInstrumentation().context)
internal val sut = MetisStorageServiceImpl(databaseProviderMock)

internal val host = "host"

private val author = User(id = 20, name = "AuthorName")
private val parentClientPostId = "parent-client-id-0"
internal val answerClientPostId = "answer-client-id-0"

private val course: MetisContext.Course = MetisContext.Course(courseId = 1)
internal val conversation = OneToOneChat(id = 2)
internal val metisContext = MetisContext.Conversation(course.courseId, conversation.id)

internal val conversationTwo = OneToOneChat(id = 3)
internal val metisContextTwo = MetisContext.Conversation(course.courseId, conversationTwo.id)

internal val localAnswerPojo = AnswerPostPojo(
parentPostId = parentClientPostId,
postId = answerClientPostId,
resolvesPost = false,
basePostingCache = AnswerPostPojo.BasePostingCache(
serverPostId = 0,
authorId = author.id,
creationDate = Clock.System.now(),
updatedDate = null,
content = "Answer post content 0",
authorRole = UserRole.USER,
authorName = author.name!!
),
reactions = emptyList(),
serverPostIdCache = AnswerPostPojo.ServerPostIdCache(
serverPostId = null // Only local answer post, no server id
)
)

internal val basePostPojo = PostPojo(
clientPostId = parentClientPostId,
serverPostId = 0,
content = "Base post content",
resolved = false,
updatedDate = null,
creationDate = Clock.System.now(),
authorId = author.id,
title = null,
authorName = author.name!!,
authorRole = UserRole.USER,
courseWideContext = null,
tags = emptyList(),
answers = emptyList(),
reactions = emptyList()
)

internal val basePost = StandalonePost(basePostPojo, conversation)
internal val basePostTwo = StandalonePost(basePostPojo, conversationTwo)
internal val localAnswer = AnswerPost(localAnswerPojo, basePost)

internal suspend fun getStoredPosts(metisContext: MetisContext) = sut.getStoredPosts(
serverId = host,
metisContext = metisContext
).loadAsList()

internal suspend fun <T : Any> PagingSource<Int, T>.loadAsList(): List<T> {
return Pager(PagingConfig(pageSize = 10), pagingSourceFactory = { this }).flow.asSnapshot {
scrollTo(50)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.storage.impl

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.testing.asSnapshot
import androidx.test.platform.app.InstrumentationRegistry

import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
import de.tum.informatics.www1.artemis.native_app.core.model.account.User
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.AnswerPost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.StandalonePost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.UserRole
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.OneToOneChat
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.AnswerPostPojo
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
import de.tum.informatics.www1.artemis.native_app.feature.metistest.MetisDatabaseProviderMock
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Clock
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.experimental.categories.Category
Expand All @@ -25,59 +13,7 @@ import org.robolectric.RobolectricTestRunner

@Category(UnitTest::class)
@RunWith(RobolectricTestRunner::class)
class MetisStorageServiceImplUpgradeLocalAnswerPostTest {

private val databaseProviderMock = MetisDatabaseProviderMock(InstrumentationRegistry.getInstrumentation().context)
private val sut = MetisStorageServiceImpl(databaseProviderMock)

private val host = "host"

private val author = User(id = 20, name = "AuthorName")
private val parentClientPostId = "parent-client-id-0"
private val answerClientPostId = "answer-client-id-0"

private val course: MetisContext.Course = MetisContext.Course(courseId = 1)
private val conversation = OneToOneChat(id = 2)
private val metisContext = MetisContext.Conversation(course.courseId, conversation.id)

private val localAnswerPojo = AnswerPostPojo(
parentPostId = parentClientPostId,
postId = answerClientPostId,
resolvesPost = false,
basePostingCache = AnswerPostPojo.BasePostingCache(
serverPostId = 0,
authorId = author.id,
creationDate = Clock.System.now(),
updatedDate = null,
content = "Answer post content 0",
authorRole = UserRole.USER,
authorName = author.name!!
),
reactions = emptyList(),
serverPostIdCache = AnswerPostPojo.ServerPostIdCache(
serverPostId = null // Only local answer post, no server id
)
)

private val basePostPojo = PostPojo(
clientPostId = parentClientPostId,
serverPostId = 0,
content = "Base post content",
resolved = false,
updatedDate = null,
creationDate = Clock.System.now(),
authorId = author.id,
title = null,
authorName = author.name!!,
authorRole = UserRole.USER,
courseWideContext = null,
tags = emptyList(),
answers = emptyList(),
reactions = emptyList()
)

private val basePost = StandalonePost(basePostPojo, conversation)
private val localAnswer = AnswerPost(localAnswerPojo, basePost)
class MetisStorageServiceImplUpgradeLocalAnswerPostTest : MetisStorageBaseTest() {

private lateinit var basePostUpdated: StandalonePost
private lateinit var answerUpdated: AnswerPost
Expand Down Expand Up @@ -182,26 +118,15 @@ class MetisStorageServiceImplUpgradeLocalAnswerPostTest {
}

private suspend fun assertStoredContentIsTheSame() {
val posts = getStoredPosts()
val posts = getStoredPosts(metisContext)
assertEquals(1, posts.size)
assertEquals(basePostPojo.content, posts.first().content)
assertEquals(1, posts.first().answers.size)
assertEquals(localAnswerPojo.content, posts.first().answers.first().content)
}

private suspend fun assertUpgradeSuccessful() {
val posts = getStoredPosts()
val posts = getStoredPosts(metisContext)
assertEquals(answerUpdated.serverPostId, posts.first().answers.first().serverPostId)
}

private suspend fun getStoredPosts() = sut.getStoredPosts(
serverId = host,
metisContext = metisContext
).loadAsList()

private suspend fun <T : Any> PagingSource<Int, T>.loadAsList(): List<T> {
return Pager(PagingConfig(pageSize = 10), pagingSourceFactory = { this }).flow.asSnapshot {
scrollTo(50)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.storage.impl

import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.StandalonePost
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.experimental.categories.Category
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import kotlin.test.assertEquals

@Category(UnitTest::class)
@RunWith(RobolectricTestRunner::class)
class MetisStorageServiceTestLiveCreation : MetisStorageBaseTest() {

@Test
fun testInsertLiveCreatedPostWithExistingPost() = runTest {
// GIVEN: A base post already exists
sut.insertOrUpdatePosts(
host = host,
metisContext = metisContext,
posts = listOf(basePost),
)

// WHEN: Inserting a live-created post with the same id into the same conversation
sut.insertLiveCreatedPost(
host = host,
metisContext = metisContext,
post = basePost
)

// THEN: No post should be inserted and the existing posts should not be modified
val posts = getStoredPosts(metisContext)
val standalonePost = StandalonePost(posts.first(), conversation)
assertEquals(1, posts.size)
assertEquals(basePost.content, standalonePost.content)
assertEquals(basePost.id, standalonePost.id)
assertEquals(basePost.conversation, standalonePost.conversation)
}

@Test
fun testInsertLiveCreatedPost() = runTest {
// GIVEN: An empty conversation

// WHEN: Inserting a live-created post into a different conversation than the current
sut.insertLiveCreatedPost(
host = host,
metisContext = metisContext,
post = basePostTwo
)

// THEN: The post should be inserted and matched to the correct conversation
val posts = getStoredPosts(metisContextTwo)
assertEquals(1, posts.size)
assertEquals(basePostTwo.content, posts.first().content)

val createdPost = posts[0]

val createdStandalonePost = StandalonePost(createdPost, conversationTwo)
assertEquals(basePostTwo.conversation?.id, createdStandalonePost.conversation?.id)
}
}

0 comments on commit 022853a

Please sign in to comment.