Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
540 lines
19 KiB
Go
540 lines
19 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package app
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
)
|
|
|
|
func createMembershipSystemPost(t *testing.T, th *TestHelper, channel *model.Channel) *model.Post {
|
|
t.Helper()
|
|
|
|
post := &model.Post{
|
|
UserId: th.BasicUser.Id,
|
|
ChannelId: channel.Id,
|
|
Message: "user joined the channel",
|
|
Type: model.PostTypeJoinChannel,
|
|
Props: model.StringInterface{
|
|
"username": th.BasicUser.Username,
|
|
},
|
|
}
|
|
|
|
created, _, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
|
|
require.Nil(t, appErr)
|
|
require.NotNil(t, created)
|
|
|
|
return created
|
|
}
|
|
|
|
func setChannelDisableJoinLeaveMessages(t *testing.T, th *TestHelper, channel *model.Channel, disabled bool) *model.Channel {
|
|
t.Helper()
|
|
|
|
patch := &model.ChannelPatch{
|
|
DisableJoinLeaveMessages: &disabled,
|
|
}
|
|
|
|
updated, appErr := th.App.PatchChannel(th.Context, channel, patch, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
return updated
|
|
}
|
|
|
|
func TestDisableJoinLeaveMessagesReadSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost := th.CreatePost(t, channel)
|
|
|
|
t.Run("excludes membership posts from channel list when enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
postList, appErr := th.App.GetPostsPage(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
Page: 0,
|
|
PerPage: 60,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
|
|
_, foundMembership := postList.Posts[membershipPost.Id]
|
|
require.False(t, foundMembership)
|
|
require.Contains(t, postList.Posts, normalPost.Id)
|
|
})
|
|
|
|
t.Run("two-way door restores visibility when disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
postList, appErr := th.App.GetPostsPage(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
Page: 0,
|
|
PerPage: 60,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.Contains(t, postList.Posts, membershipPost.Id)
|
|
})
|
|
|
|
t.Run("get single post returns not found when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
_, appErr := th.App.GetSinglePost(th.Context, membershipPost.Id, false)
|
|
require.NotNil(t, appErr)
|
|
require.Equal(t, "app.post.get.app_error", appErr.Id)
|
|
})
|
|
|
|
t.Run("membership posts remain in database when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
stored, err := th.App.Srv().Store().Post().GetSingle(th.Context, membershipPost.Id, false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, model.PostTypeJoinChannel, stored.Type)
|
|
})
|
|
}
|
|
|
|
func TestGetPostsSinceSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost := th.CreatePost(t, channel)
|
|
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
// Use Time: 0 to avoid the localcachelayer short-circuit, which compares
|
|
// the cached last-post-time against options.Time and would return empty if
|
|
// the cache pre-dates posts created during the test.
|
|
postList, appErr := th.App.GetPostsSince(th.Context, model.GetPostsSinceOptions{
|
|
ChannelId: channel.Id,
|
|
Time: 0,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, postList.Posts, membershipPost.Id)
|
|
require.Contains(t, postList.Posts, normalPost.Id)
|
|
}
|
|
|
|
func TestFlaggedPostsSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
|
|
preference := model.Preference{
|
|
UserId: th.BasicUser.Id,
|
|
Category: model.PreferenceCategoryFlaggedPost,
|
|
Name: membershipPost.Id,
|
|
Value: "true",
|
|
}
|
|
err := th.App.Srv().Store().Preference().Save(model.Preferences{preference})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("excluded from flagged posts when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
flagged, appErr := th.App.GetFlaggedPosts(th.Context, th.BasicUser.Id, 0, 10)
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, flagged.Order, membershipPost.Id)
|
|
})
|
|
|
|
t.Run("visible in flagged posts when re-enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
flagged, appErr := th.App.GetFlaggedPosts(th.Context, th.BasicUser.Id, 0, 10)
|
|
require.Nil(t, appErr)
|
|
require.Contains(t, flagged.Order, membershipPost.Id)
|
|
})
|
|
}
|
|
|
|
func TestMembershipSystemPostNotificationSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
normalPost := th.CreatePost(t, channel)
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
|
|
t.Run("suppresses membership post notifications when disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
ch, appErr := th.App.GetChannel(th.Context, channel.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
require.True(t, th.App.shouldSuppressMembershipSystemPost(th.Context, ch, membershipPost))
|
|
require.False(t, th.App.shouldSuppressMembershipSystemPost(th.Context, ch, normalPost))
|
|
})
|
|
|
|
t.Run("does not suppress when enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
ch, appErr := th.App.GetChannel(th.Context, channel.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
require.False(t, th.App.shouldSuppressMembershipSystemPost(th.Context, ch, membershipPost))
|
|
})
|
|
|
|
t.Run("does not suppress add-type posts even when disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
ch, appErr := th.App.GetChannel(th.Context, channel.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
addPost := &model.Post{
|
|
UserId: th.BasicUser.Id,
|
|
ChannelId: channel.Id,
|
|
Type: model.PostTypeAddToChannel,
|
|
Props: model.StringInterface{
|
|
model.PostPropsAddedUserId: th.BasicUser2.Id,
|
|
"username": th.BasicUser2.Username,
|
|
},
|
|
}
|
|
require.False(t, th.App.shouldSuppressMembershipSystemPost(th.Context, ch, addPost),
|
|
"add-type posts must not be suppressed so the added user still receives notifications")
|
|
})
|
|
}
|
|
|
|
func TestFilterSuppressedMembershipPostsFromSlice(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost := th.CreatePost(t, channel)
|
|
|
|
t.Run("regular posts are returned intact when suppression is disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
filtered, appErr := th.App.filterSuppressedMembershipPostsFromSlice(th.Context, []*model.Post{normalPost})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, filtered, 1, "regular posts must not be dropped")
|
|
require.Equal(t, normalPost.Id, filtered[0].Id)
|
|
})
|
|
|
|
t.Run("regular posts are returned intact when suppression is enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
filtered, appErr := th.App.filterSuppressedMembershipPostsFromSlice(th.Context, []*model.Post{normalPost})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, filtered, 1, "regular posts must not be dropped even when suppression is on")
|
|
require.Equal(t, normalPost.Id, filtered[0].Id)
|
|
})
|
|
|
|
t.Run("membership posts are removed when suppression is enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
filtered, appErr := th.App.filterSuppressedMembershipPostsFromSlice(th.Context, []*model.Post{membershipPost, normalPost})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, filtered, 1)
|
|
require.Equal(t, normalPost.Id, filtered[0].Id)
|
|
})
|
|
|
|
t.Run("membership posts are kept when suppression is disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
filtered, appErr := th.App.filterSuppressedMembershipPostsFromSlice(th.Context, []*model.Post{membershipPost, normalPost})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, filtered, 2)
|
|
})
|
|
}
|
|
|
|
func TestGetPostsByIdsSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost := th.CreatePost(t, channel)
|
|
|
|
t.Run("returns regular posts when suppression is enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
posts, _, appErr := th.App.GetPostsByIds([]string{normalPost.Id})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, posts, 1, "regular posts must survive GetPostsByIds when suppression is on")
|
|
require.Equal(t, normalPost.Id, posts[0].Id)
|
|
})
|
|
|
|
t.Run("returns regular posts when suppression is disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
posts, _, appErr := th.App.GetPostsByIds([]string{normalPost.Id})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, posts, 1)
|
|
require.Equal(t, normalPost.Id, posts[0].Id)
|
|
})
|
|
|
|
t.Run("suppresses membership post from GetPostsByIds when enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
posts, _, appErr := th.App.GetPostsByIds([]string{membershipPost.Id})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, posts, 0, "membership post must be suppressed")
|
|
})
|
|
|
|
t.Run("returns membership post from GetPostsByIds when suppression is disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
posts, _, appErr := th.App.GetPostsByIds([]string{membershipPost.Id})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, posts, 1)
|
|
require.Equal(t, membershipPost.Id, posts[0].Id)
|
|
})
|
|
|
|
t.Run("partial suppression: returns only regular post when both IDs requested with suppression enabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
posts, _, appErr := th.App.GetPostsByIds([]string{membershipPost.Id, normalPost.Id})
|
|
require.Nil(t, appErr)
|
|
require.Len(t, posts, 1, "only the regular post should survive")
|
|
require.Equal(t, normalPost.Id, posts[0].Id)
|
|
})
|
|
}
|
|
|
|
func TestGetPostThreadSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
rootPost := createMembershipSystemPost(t, th, channel)
|
|
replyPost := th.CreatePost(t, channel)
|
|
|
|
t.Run("membership root post excluded from thread when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
list, appErr := th.App.GetPostThread(th.Context, rootPost.Id, model.GetPostsOptions{}, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, list.Posts, rootPost.Id)
|
|
})
|
|
|
|
t.Run("regular post thread visible when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
list, appErr := th.App.GetPostThread(th.Context, replyPost.Id, model.GetPostsOptions{}, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
require.Contains(t, list.Posts, replyPost.Id)
|
|
})
|
|
|
|
t.Run("membership post visible in thread when suppression disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
list, appErr := th.App.GetPostThread(th.Context, rootPost.Id, model.GetPostsOptions{}, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
require.Contains(t, list.Posts, rootPost.Id)
|
|
})
|
|
}
|
|
|
|
func TestGetPostsBeforeAfterSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
normalPost1 := th.CreatePost(t, channel)
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost2 := th.CreatePost(t, channel)
|
|
|
|
t.Run("GetPostsBeforePost excludes membership posts when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
postList, appErr := th.App.GetPostsBeforePost(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
PostId: normalPost2.Id,
|
|
Page: 0,
|
|
PerPage: 10,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, postList.Posts, membershipPost.Id)
|
|
require.Contains(t, postList.Posts, normalPost1.Id)
|
|
})
|
|
|
|
t.Run("GetPostsAfterPost excludes membership posts when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
postList, appErr := th.App.GetPostsAfterPost(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
PostId: normalPost1.Id,
|
|
Page: 0,
|
|
PerPage: 10,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, postList.Posts, membershipPost.Id)
|
|
require.Contains(t, postList.Posts, normalPost2.Id)
|
|
})
|
|
}
|
|
|
|
// TestPaginationCursorExcludesMembershipPosts covers the "Load more messages"
|
|
// bug where NextPostId/PrevPostId, computed via AddCursorIdsForPostList after
|
|
// the fetch, pointed at a membership post the read paths had already excluded
|
|
// from the response - most visibly when the excluded post was the newest or
|
|
// oldest post in the channel and burn-on-read's visibility-aware cursor lookup
|
|
// (which takes over from the plain lookups) had no membership-post exclusion
|
|
// of its own.
|
|
func TestPaginationCursorExcludesMembershipPosts(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
t.Run("newest post in channel is a membership post", func(t *testing.T) {
|
|
channel := th.CreateChannel(t, th.BasicTeam)
|
|
normal1 := th.CreatePost(t, channel)
|
|
normal2 := th.CreatePost(t, channel)
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
postList, appErr := th.App.GetPostsPage(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
Page: 0,
|
|
PerPage: 60,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, postList.Posts, membershipPost.Id)
|
|
require.Contains(t, postList.Posts, normal1.Id)
|
|
require.Contains(t, postList.Posts, normal2.Id)
|
|
|
|
th.App.AddCursorIdsForPostList(postList, th.BasicUser.Id, "", "", 0, 0, 60, false)
|
|
require.Empty(t, postList.NextPostId, "NextPostId must not reference the suppressed membership post")
|
|
})
|
|
|
|
t.Run("newest post in channel is a membership post, burn-on-read enabled", func(t *testing.T) {
|
|
enableBoRFeature(th)
|
|
defer th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableBurnOnRead = new(false) })
|
|
|
|
channel := th.CreateChannel(t, th.BasicTeam)
|
|
normal1 := th.CreatePost(t, channel)
|
|
normal2 := th.CreatePost(t, channel)
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
postList, appErr := th.App.GetPostsPage(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
Page: 0,
|
|
PerPage: 60,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.NotContains(t, postList.Posts, membershipPost.Id)
|
|
require.Contains(t, postList.Posts, normal1.Id)
|
|
require.Contains(t, postList.Posts, normal2.Id)
|
|
|
|
th.App.AddCursorIdsForPostList(postList, th.BasicUser.Id, "", "", 0, 0, 60, false)
|
|
require.Empty(t, postList.NextPostId, "NextPostId must not reference the suppressed membership post even with burn-on-read enabled")
|
|
})
|
|
|
|
t.Run("run of membership posts between two blocks of real content is paged past in one round trip", func(t *testing.T) {
|
|
enableBoRFeature(th)
|
|
defer th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableBurnOnRead = new(false) })
|
|
|
|
channel := th.CreateChannel(t, th.BasicTeam)
|
|
older := th.CreatePost(t, channel)
|
|
for range 5 {
|
|
createMembershipSystemPost(t, th, channel)
|
|
}
|
|
newer := th.CreatePost(t, channel)
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
// perPage (3) is smaller than the run of membership posts (5), so a
|
|
// naive offset-then-filter approach would return an empty page here.
|
|
postList, appErr := th.App.GetPostsAfterPost(th.Context, model.GetPostsOptions{
|
|
ChannelId: channel.Id,
|
|
PostId: older.Id,
|
|
Page: 0,
|
|
PerPage: 3,
|
|
UserId: th.BasicUser.Id,
|
|
})
|
|
require.Nil(t, appErr)
|
|
require.Contains(t, postList.Posts, newer.Id)
|
|
|
|
th.App.AddCursorIdsForPostList(postList, th.BasicUser.Id, older.Id, "", 0, 0, 3, false)
|
|
require.Empty(t, postList.NextPostId, "no more posts exist after newer")
|
|
})
|
|
}
|
|
|
|
func TestGetPermalinkPostSuppression(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
channel := th.BasicChannel
|
|
membershipPost := createMembershipSystemPost(t, th, channel)
|
|
normalPost := th.CreatePost(t, channel)
|
|
|
|
t.Run("membership post permalink returns not found when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
_, appErr := th.App.GetPermalinkPost(th.Context, membershipPost.Id, th.BasicUser.Id)
|
|
require.NotNil(t, appErr)
|
|
require.Equal(t, "api.post_get_post_by_id.get.app_error", appErr.Id)
|
|
})
|
|
|
|
t.Run("regular post permalink visible when suppressed", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, true)
|
|
|
|
perma, appErr := th.App.GetPermalinkPost(th.Context, normalPost.Id, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotNil(t, perma)
|
|
})
|
|
|
|
t.Run("membership post permalink visible when suppression disabled", func(t *testing.T) {
|
|
setChannelDisableJoinLeaveMessages(t, th, channel, false)
|
|
|
|
perma, appErr := th.App.GetPermalinkPost(th.Context, membershipPost.Id, th.BasicUser.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotNil(t, perma)
|
|
})
|
|
}
|
|
|
|
func TestRemovePostIDFromOrder(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.Equal(t, []string{"b", "c"}, removePostIDFromOrder([]string{"a", "b", "c"}, "a"))
|
|
require.Equal(t, []string{"a", "c"}, removePostIDFromOrder([]string{"a", "b", "c"}, "b"))
|
|
require.Equal(t, []string{"a", "b"}, removePostIDFromOrder([]string{"a", "b", "c"}, "c"))
|
|
require.Equal(t, []string{"a", "b", "c"}, removePostIDFromOrder([]string{"a", "b", "c"}, "x"))
|
|
require.Empty(t, removePostIDFromOrder([]string{}, "a"))
|
|
require.Empty(t, removePostIDFromOrder(nil, "a"))
|
|
}
|
|
|
|
func TestShouldChannelExcludeMembershipSystemPostsModel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
disabled := &model.Channel{
|
|
Type: model.ChannelTypeOpen,
|
|
DisableJoinLeaveMessages: true,
|
|
}
|
|
require.True(t, model.ShouldChannelExcludeMembershipSystemPosts(disabled))
|
|
|
|
enabled := &model.Channel{
|
|
Type: model.ChannelTypeOpen,
|
|
DisableJoinLeaveMessages: false,
|
|
}
|
|
require.False(t, model.ShouldChannelExcludeMembershipSystemPosts(enabled))
|
|
|
|
sharedDisabled := &model.Channel{
|
|
Type: model.ChannelTypeOpen,
|
|
DisableJoinLeaveMessages: true,
|
|
Shared: model.NewPointer(true),
|
|
}
|
|
require.True(t, model.ShouldChannelExcludeMembershipSystemPosts(sharedDisabled))
|
|
|
|
sharedEnabled := &model.Channel{
|
|
Type: model.ChannelTypeOpen,
|
|
DisableJoinLeaveMessages: false,
|
|
Shared: model.NewPointer(true),
|
|
}
|
|
require.False(t, model.ShouldChannelExcludeMembershipSystemPosts(sharedEnabled))
|
|
|
|
direct := &model.Channel{
|
|
Type: model.ChannelTypeDirect,
|
|
DisableJoinLeaveMessages: true,
|
|
}
|
|
require.False(t, model.ShouldChannelExcludeMembershipSystemPosts(direct))
|
|
}
|