Skip to content
This repository was archived by the owner on Feb 4, 2025. It is now read-only.
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package org.wordpress.android.fluxc.page

import com.nhaarman.mockitokotlin2.mock
import com.yarolegovich.wellsql.WellSql
import kotlinx.coroutines.Dispatchers
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.wordpress.android.fluxc.SingleStoreWellSqlConfigForTests
import org.wordpress.android.fluxc.model.PostModel
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.post.PostStatus
import org.wordpress.android.fluxc.persistence.PostSqlUtils
import org.wordpress.android.fluxc.store.PageStore
import org.wordpress.android.fluxc.test
import java.util.UUID
import kotlin.random.Random

@RunWith(RobolectricTestRunner::class)
class PageStoreLocalChangesTest {
private val postSqlUtils = PostSqlUtils()
private val pageStore = PageStore(
postStore = mock(),
dispatcher = mock(),
coroutineContext = Dispatchers.Default,
postSqlUtils = postSqlUtils
)

@Before
fun setUp() {
val appContext = RuntimeEnvironment.application.applicationContext
val modelsToTest = listOf(PostModel::class.java)
val config = SingleStoreWellSqlConfigForTests(appContext, modelsToTest, "")
WellSql.init(config)
config.reset()
}

@After
fun tearDown() {
WellSql.closeDb()
}

@Test
fun `getLocalDraftPages returns local draft pages only`() = test {
// Arrange
val site = SiteModel().apply { id = 3_000 }

val baseTitle = "Voluptatem harum repellendus"
val expectedPages = List(3) {
createLocalDraft(localSiteId = site.id, baseTitle = baseTitle, isPage = true)
}

val unexpectedPosts = listOf(
// local draft post
createLocalDraft(localSiteId = site.id, isPage = false),
// other site page
createLocalDraft(localSiteId = 4_000, isPage = true),
// uploaded page
PostModel().apply {
title = "Title"
localSiteId = site.id
setIsLocalDraft(false)
}
)

expectedPages.plus(unexpectedPosts).forEach { postSqlUtils.insertPostForResult(it) }

// Act
val localDraftPages = pageStore.getLocalDraftPages(site)

// Assert
assertThat(localDraftPages).hasSize(3)
assertThat(localDraftPages).allMatch { it.title.startsWith(baseTitle) }
assertThat(localDraftPages.map { it.id }).isEqualTo(expectedPages.map { it.id })
}

@Test
fun `getPagesWithLocalChanges returns local draft and locally changed pages only`() = test {
// Arrange
val site = SiteModel().apply { id = 3_000 }

val baseTitle = "Voluptatem harum repellendus"
val expectedPages = mutableListOf<PostModel>().apply {
addAll(List(3) {
createLocalDraft(localSiteId = site.id, baseTitle = baseTitle, isPage = true)
})

addAll(List(5) {
createUploadedPost(localSiteId = site.id, baseTitle = baseTitle, isPage = true).apply {
setIsLocallyChanged(true)
}
})

add(createUploadedPost(localSiteId = site.id, baseTitle = baseTitle, isPage = true).apply {
status = PostStatus.PUBLISHED.toString()
setIsLocallyChanged(true)
})
}.toList()

val unexpectedPosts = listOf(
// local draft post
createLocalDraft(localSiteId = site.id, isPage = false),
// other site page
createLocalDraft(localSiteId = 4_000, isPage = true),
// uploaded post
createUploadedPost(localSiteId = site.id, isPage = false),
// uploaded post with changes
createUploadedPost(localSiteId = site.id, isPage = false).apply { setIsLocallyChanged(true) },
// uploaded page with no changes
createUploadedPost(localSiteId = site.id, isPage = true),
// published page with no changes
createUploadedPost(localSiteId = site.id, isPage = true).apply {
status = PostStatus.PUBLISHED.toString()
}
)

expectedPages.plus(unexpectedPosts).forEach { postSqlUtils.insertPostForResult(it) }

// Act
val locallyChangedPages = pageStore.getPagesWithLocalChanges(site)

// Assert
assertThat(locallyChangedPages).hasSize(expectedPages.size)
assertThat(locallyChangedPages).allMatch { it.title.startsWith(baseTitle) }
assertThat(locallyChangedPages.map { it.id }).isEqualTo(expectedPages.map { it.id })
}

private fun createLocalDraft(localSiteId: Int, baseTitle: String = "Title", isPage: Boolean) = PostModel().apply {
this.localSiteId = localSiteId
title = "$baseTitle:${UUID.randomUUID()}"
setIsPage(isPage)
setIsLocalDraft(true)
status = PostStatus.DRAFT.toString()
}

private fun createUploadedPost(localSiteId: Int, baseTitle: String = "Title", isPage: Boolean) = PostModel().apply {
this.localSiteId = localSiteId
remotePostId = Random.nextLong()
title = "$baseTitle:${UUID.randomUUID()}"
setIsPage(isPage)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId;
import org.wordpress.android.fluxc.model.PostModel;
import org.wordpress.android.fluxc.model.SiteModel;
import org.wordpress.android.fluxc.model.post.PostStatus;
import org.wordpress.android.fluxc.model.revisions.Diff;
import org.wordpress.android.fluxc.model.revisions.DiffOperations;
import org.wordpress.android.fluxc.model.revisions.LocalDiffModel;
Expand All @@ -31,6 +32,7 @@
import org.wordpress.android.util.DateTimeUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
Expand All @@ -39,6 +41,7 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

Expand Down Expand Up @@ -471,6 +474,73 @@ public void testGetLocalDraftPostsMethodOnlyReturnsLocalDrafts() {
}
}

@Test
public void testGetPostsWithLocalChangesReturnsLocalDraftsAndChangedPostsOnly() {
// Arrange
final SiteModel site = new SiteModel();
site.setId(PostTestUtils.DEFAULT_LOCAL_SITE_ID);

// Objects that should be included
final ArrayList<Integer> expectedPostIds = new ArrayList<>();
final String baseTitle = "Rerum";
for (int i = 0; i < 3; i++) {
final String compoundTitle = baseTitle.concat(":").concat(UUID.randomUUID().toString());
final PostModel post = PostTestUtils.generateSampleLocalDraftPost(compoundTitle);
mPostSqlUtils.insertPostForResult(post);
expectedPostIds.add(post.getId());
}
for (int i = 0; i < 5; i++) {
final String compoundTitle = baseTitle.concat(":").concat(UUID.randomUUID().toString());
final PostModel post = PostTestUtils.generateSampleLocallyChangedPost(compoundTitle);
mPostSqlUtils.insertPostForResult(post);
expectedPostIds.add(post.getId());
}

final PostModel modifiedUploadPost = PostTestUtils.generateSampleUploadedPost();
modifiedUploadPost.setTitle(baseTitle.concat("-c_up_post"));
modifiedUploadPost.setIsLocallyChanged(true);
mPostSqlUtils.insertPostForResult(modifiedUploadPost);
expectedPostIds.add(modifiedUploadPost.getId());

final PostModel modifiedPublishedPost = PostTestUtils.generateSampleUploadedPost();
modifiedPublishedPost.setTitle(baseTitle.concat("-mpp"));
modifiedPublishedPost.setIsLocallyChanged(true);
modifiedPublishedPost.setStatus(PostStatus.PUBLISHED.toString());
mPostSqlUtils.insertPostForResult(modifiedPublishedPost);
expectedPostIds.add(modifiedPublishedPost.getId());

// Objects that should not be included
final PostModel localDraftPage = PostTestUtils.generateSampleLocalDraftPost();
localDraftPage.setIsPage(true);
mPostSqlUtils.insertPostForResult(localDraftPage);

final PostModel unchangedUploadedPost = PostTestUtils.generateSampleUploadedPost();
mPostSqlUtils.insertPostForResult(unchangedUploadedPost);

final PostModel unchangedPublishedPost = PostTestUtils.generateSampleUploadedPost();
modifiedPublishedPost.setStatus(PostStatus.PUBLISHED.toString());
mPostSqlUtils.insertPostForResult(unchangedPublishedPost);

final List<Integer> unexpectedPostIds = Arrays.asList(
localDraftPage.getId(),
unchangedUploadedPost.getId(),
unchangedPublishedPost.getId());

// Act
final List<PostModel> locallyChangedPosts = mPostStore.getPostsWithLocalChanges(site);

// Assert
assertEquals(expectedPostIds.size(), locallyChangedPosts.size());
for (PostModel locallyChangedPost : locallyChangedPosts) {
assertThat(locallyChangedPost.getId()).isNotIn(unexpectedPostIds);
assertThat(locallyChangedPost.getId()).isIn(expectedPostIds);

assertTrue(locallyChangedPost.isLocalDraft() || locallyChangedPost.isLocallyChanged());
assertThat(locallyChangedPost.getTitle()).startsWith(baseTitle);
}
}


/**
* Tests that getPostsByLocalOrRemotePostIds works correctly in various situations.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ static PostModel generateSampleLocalDraftPost(@NonNull String title) {
return example;
}

public static PostModel generateSampleLocallyChangedPost() {
static PostModel generateSampleLocallyChangedPost() {
return generateSampleLocallyChangedPost("A test post");
}

static PostModel generateSampleLocallyChangedPost(@NonNull String title) {
PostModel example = new PostModel();
example.setLocalSiteId(DEFAULT_LOCAL_SITE_ID);
example.setRemotePostId(7);
example.setTitle("A test post");
example.setTitle(title);
example.setContent("Bunch of content here");
example.setIsLocallyChanged(true);
return example;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ public List<PostModel> getLocalDrafts(@NonNull Integer localSiteId, boolean isPa
.getAsModel();
}

public List<PostModel> getPostsWithLocalChanges(@NonNull Integer localSiteId, boolean isPage) {
return WellSql.select(PostModel.class)
.where()
.equals(PostModelTable.IS_PAGE, isPage)
.equals(PostModelTable.LOCAL_SITE_ID, localSiteId)
.beginGroup()
.equals(PostModelTable.IS_LOCAL_DRAFT, true).or().equals(PostModelTable.IS_LOCALLY_CHANGED, true)
.endGroup()
.endWhere()
.getAsModel();
}

public List<PostModel> getPostsByRemoteIds(@Nullable List<Long> remoteIds, int localSiteId) {
if (remoteIds != null && remoteIds.size() > 0) {
return WellSql.select(PostModel.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class PageStore @Inject constructor(
}

/**
* Get pages that have not been uploaded to the server yet.
* Get local draft pages that have not been uploaded to the server yet.
*
* This returns [PostModel] instead of [PageModel] to accommodate the `UploadService` in WPAndroid which relies
* heavily on [PostModel]. When `UploadService` gets refactored, we should change this back to using [PageModel].
Expand All @@ -193,6 +193,16 @@ class PageStore @Inject constructor(
return@withContext postSqlUtils.getLocalDrafts(site.id, true)
}

/**
* Get pages that have not been uploaded to the server yet.
*
* This returns [PostModel] instead of [PageModel] to accommodate the `UploadService` in WPAndroid which relies
* heavily on [PostModel]. When `UploadService` gets refactored, we should change this back to using [PageModel].
*/
suspend fun getPagesWithLocalChanges(site: SiteModel): List<PostModel> = withContext(coroutineContext) {
return@withContext postSqlUtils.getPostsWithLocalChanges(site.id, true)
}

private fun fetchPages(site: SiteModel, loadMore: Boolean) {
val payload = FetchPostsPayload(site, loadMore, PAGE_TYPES)
dispatcher.dispatch(PostActionBuilder.newFetchPagesAction(payload))
Expand Down
Loading