Files
upstream-mattermost/server/channels/app/post_membership_messages_test.go
upstream-mirror 240db4e2a7
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
snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:29:55 +05:00

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))
}