focalboard/server/services/store/storetests/subscriptions.go
Miguel de la Cruz 08c0b7a2fd
Refactor error usage from the store level up and add API helpers (#3792)
* Refactor error usage from the store level up and add API helpers

* Complete API tests

* Fix merge errorResponse calls

* Remove ensure helpers to allow for custom messages on permission errors

* Fix bad import and call

* Remove bad user check on auth that was added as part of the main merge

* Fix empty list test

* Replace deprecated proxy calls to ioutil.ReadAll with io.ReadAll

* Add information to the NotFound errors

* Add context to all remaining errors and address review comments

* Fix linter

* Adapt the new card API endpoints to the error refactor

* Remove almost all customErrorResponse calls

* Add request entity too large to errorResponse and remove customErrorResponse

* Fix linter
2022-09-13 12:18:40 +02:00

325 lines
10 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package storetests
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/store"
)
//nolint:dupl
func StoreTestSubscriptionsStore(t *testing.T, setup func(t *testing.T) (store.Store, func())) {
t.Run("CreateSubscription", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testCreateSubscription(t, store)
})
t.Run("DeleteSubscription", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testDeleteSubscription(t, store)
})
t.Run("UndeleteSubscription", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testUndeleteSubscription(t, store)
})
t.Run("GetSubscription", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testGetSubscription(t, store)
})
t.Run("GetSubscriptions", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testGetSubscriptions(t, store)
})
t.Run("GetSubscribersForBlock", func(t *testing.T) {
store, tearDown := setup(t)
defer tearDown()
testGetSubscribersForBlock(t, store)
})
}
func testCreateSubscription(t *testing.T, store store.Store) {
t.Run("create subscriptions", func(t *testing.T) {
users := createTestUsers(t, store, 10)
blocks := createTestBlocks(t, store, users[0].ID, 50)
for i, user := range users {
for j := 0; j < i; j++ {
sub := &model.Subscription{
BlockType: blocks[j].Type,
BlockID: blocks[j].ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subNew, err := store.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
assert.NotZero(t, subNew.NotifiedAt)
assert.NotZero(t, subNew.CreateAt)
assert.Zero(t, subNew.DeleteAt)
}
}
// ensure each user has the right number of subscriptions
for i, user := range users {
subs, err := store.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Len(t, subs, i)
}
})
t.Run("duplicate subscription", func(t *testing.T) {
admin := createTestUsers(t, store, 1)[0]
user := createTestUsers(t, store, 1)[0]
block := createTestBlocks(t, store, admin.ID, 1)[0]
sub := &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subNew, err := store.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
sub = &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subDup, err := store.CreateSubscription(sub)
require.NoError(t, err, "create duplicate subscription should not error")
assert.Equal(t, subNew.BlockID, subDup.BlockID)
assert.Equal(t, subNew.SubscriberID, subDup.SubscriberID)
})
t.Run("invalid subscription", func(t *testing.T) {
admin := createTestUsers(t, store, 1)[0]
user := createTestUsers(t, store, 1)[0]
block := createTestBlocks(t, store, admin.ID, 1)[0]
sub := &model.Subscription{}
_, err := store.CreateSubscription(sub)
assert.ErrorAs(t, err, &model.ErrInvalidSubscription{}, "invalid subscription should error")
sub.BlockType = block.Type
_, err = store.CreateSubscription(sub)
assert.ErrorAs(t, err, &model.ErrInvalidSubscription{}, "invalid subscription should error")
sub.BlockID = block.ID
_, err = store.CreateSubscription(sub)
assert.ErrorAs(t, err, &model.ErrInvalidSubscription{}, "invalid subscription should error")
sub.SubscriberType = "user"
_, err = store.CreateSubscription(sub)
assert.ErrorAs(t, err, &model.ErrInvalidSubscription{}, "invalid subscription should error")
sub.SubscriberID = user.ID
subNew, err := store.CreateSubscription(sub)
assert.NoError(t, err, "valid subscription should not error")
assert.NoError(t, subNew.IsValid(), "created subscription should be valid")
})
}
func testDeleteSubscription(t *testing.T, s store.Store) {
t.Run("delete subscription", func(t *testing.T) {
user := createTestUsers(t, s, 1)[0]
block := createTestBlocks(t, s, user.ID, 1)[0]
sub := &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subNew, err := s.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
// check the subscription exists
subs, err := s.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Len(t, subs, 1)
assert.Equal(t, subNew.BlockID, subs[0].BlockID)
assert.Equal(t, subNew.SubscriberID, subs[0].SubscriberID)
err = s.DeleteSubscription(block.ID, user.ID)
require.NoError(t, err, "delete subscription should not error")
// check the subscription was deleted
subs, err = s.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Empty(t, subs)
})
t.Run("delete non-existent subscription", func(t *testing.T) {
err := s.DeleteSubscription("bogus", "bogus")
require.Error(t, err, "delete non-existent subscription should error")
require.True(t, model.IsErrNotFound(err), "Should be ErrNotFound compatible error")
})
}
func testUndeleteSubscription(t *testing.T, s store.Store) {
t.Run("undelete subscription", func(t *testing.T) {
user := createTestUsers(t, s, 1)[0]
block := createTestBlocks(t, s, user.ID, 1)[0]
sub := &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subNew, err := s.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
// check the subscription exists
subs, err := s.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Len(t, subs, 1)
assert.Equal(t, subNew.BlockID, subs[0].BlockID)
assert.Equal(t, subNew.SubscriberID, subs[0].SubscriberID)
err = s.DeleteSubscription(block.ID, user.ID)
require.NoError(t, err, "delete subscription should not error")
// check the subscription was deleted
subs, err = s.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Empty(t, subs)
// re-create the subscription
subUndeleted, err := s.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
// check the undeleted subscription exists
subs, err = s.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Len(t, subs, 1)
assert.Equal(t, subUndeleted.BlockID, subs[0].BlockID)
assert.Equal(t, subUndeleted.SubscriberID, subs[0].SubscriberID)
})
}
func testGetSubscription(t *testing.T, s store.Store) {
t.Run("get subscription", func(t *testing.T) {
user := createTestUsers(t, s, 1)[0]
block := createTestBlocks(t, s, user.ID, 1)[0]
sub := &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
subNew, err := s.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
// make sure subscription can be fetched
sub, err = s.GetSubscription(block.ID, user.ID)
require.NoError(t, err, "get subscription should not error")
assert.Equal(t, subNew, sub)
})
t.Run("get non-existent subscription", func(t *testing.T) {
sub, err := s.GetSubscription("bogus", "bogus")
require.Error(t, err, "get non-existent subscription should error")
require.True(t, model.IsErrNotFound(err), "Should be ErrNotFound compatible error")
require.Nil(t, sub, "get subscription should return nil")
})
}
func testGetSubscriptions(t *testing.T, store store.Store) {
t.Run("get subscriptions", func(t *testing.T) {
author := createTestUsers(t, store, 1)[0]
user := createTestUsers(t, store, 1)[0]
blocks := createTestBlocks(t, store, author.ID, 50)
for _, block := range blocks {
sub := &model.Subscription{
BlockType: block.Type,
BlockID: block.ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
_, err := store.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
}
// ensure user has the right number of subscriptions
subs, err := store.GetSubscriptions(user.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Len(t, subs, len(blocks))
// ensure author has no subscriptions
subs, err = store.GetSubscriptions(author.ID)
require.NoError(t, err, "get subscriptions should not error")
assert.Empty(t, subs)
})
t.Run("get subscriptions for invalid user", func(t *testing.T) {
subs, err := store.GetSubscriptions("bogus")
require.NoError(t, err, "get subscriptions should not error")
assert.Empty(t, subs)
})
}
func testGetSubscribersForBlock(t *testing.T, store store.Store) {
t.Run("get subscribers for block", func(t *testing.T) {
users := createTestUsers(t, store, 50)
blocks := createTestBlocks(t, store, users[0].ID, 2)
for _, user := range users {
sub := &model.Subscription{
BlockType: blocks[1].Type,
BlockID: blocks[1].ID,
SubscriberType: "user",
SubscriberID: user.ID,
}
_, err := store.CreateSubscription(sub)
require.NoError(t, err, "create subscription should not error")
}
// make sure block[1] has the right number of users subscribed
subs, err := store.GetSubscribersForBlock(blocks[1].ID)
require.NoError(t, err, "get subscribers for block should not error")
assert.Len(t, subs, 50)
count, err := store.GetSubscribersCountForBlock(blocks[1].ID)
require.NoError(t, err, "get subscribers for block should not error")
assert.Equal(t, 50, count)
// make sure block[0] has zero users subscribed
subs, err = store.GetSubscribersForBlock(blocks[0].ID)
require.NoError(t, err, "get subscribers for block should not error")
assert.Empty(t, subs)
count, err = store.GetSubscribersCountForBlock(blocks[0].ID)
require.NoError(t, err, "get subscribers for block should not error")
assert.Zero(t, count)
})
t.Run("get subscribers for invalid block", func(t *testing.T) {
subs, err := store.GetSubscribersForBlock("bogus")
require.NoError(t, err, "get subscribers for block should not error")
assert.Empty(t, subs)
})
}