revert 0e534c8, rewriting plugin tests to use actual pugins (#11713)

Revert https://mattermost.atlassian.net/browse/MM-14559. The tests were refactored, but all the hooks were be run as:

    _, ret := hooks.MessageWillBePosted(nil, nil)

and the plugins were panicking, but then nothing was actually failing because this hook doesn't support returning a "proper" error. Good news is that the old tests are still passing, so nothing has regressed in the toolkit, but thinking we should revisit this holistically instead of trying to fix in place.
Этот коммит содержится в:
Jesse Hallam
2019-07-29 10:07:00 -03:00
коммит произвёл GitHub
родитель e067272e16
Коммит 4beb1226c8
18 изменённых файлов: 538 добавлений и 972 удалений

Просмотреть файл

@@ -76,7 +76,7 @@ TESTFLAGS ?= -short
TESTFLAGSEE ?= -short
# Packages lists
TE_PACKAGES=$(shell go list ./...|grep -v plugin_tests)
TE_PACKAGES=$(shell go list ./...)
# Plugins Packages
PLUGIN_PACKAGES=mattermost-plugin-zoom-v1.0.7

Просмотреть файл

@@ -6,24 +6,20 @@ package app
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"image"
"image/color"
"image/png"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"
"text/template"
"time"
"github.com/mattermost/mattermost-server/utils/fileutils"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/services/mailservice"
"github.com/mattermost/mattermost-server/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -279,6 +275,25 @@ func TestPluginAPIGetUsersInTeam(t *testing.T) {
}
}
func TestPluginAPIUpdateUserStatus(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
statuses := []string{model.STATUS_ONLINE, model.STATUS_AWAY, model.STATUS_DND, model.STATUS_OFFLINE}
for _, s := range statuses {
status, err := api.UpdateUserStatus(th.BasicUser.Id, s)
require.Nil(t, err)
require.NotNil(t, status)
assert.Equal(t, s, status.Status)
}
status, err := api.UpdateUserStatus(th.BasicUser.Id, "notrealstatus")
assert.NotNil(t, err)
assert.Nil(t, status)
}
func TestPluginAPIGetFile(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -393,12 +408,45 @@ func TestPluginAPILoadPluginConfiguration(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.PluginSettings.Plugins["testloadpluginconfig"] = pluginJson
})
setupPluginApiTest(t,
`
package main
testFolder, found := fileutils.FindDir("tests")
require.True(t, found, "Cannot find tests folder")
fullPath := path.Join(testFolder, "plugin_tests", "manual.test_load_configuration_plugin", "main.go")
import (
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/model"
"fmt"
)
err := pluginAPIHookTest(t, th, fullPath, "testloadpluginconfig", nil, `{"id": "testloadpluginconfig", "backend": {"executable": "backend.exe"}, "settings_schema": {
type configuration struct {
MyStringSetting string
MyIntSetting int
MyBoolSetting bool
}
type MyPlugin struct {
plugin.MattermostPlugin
configuration configuration
}
func (p *MyPlugin) OnConfigurationChange() error {
if err := p.API.LoadPluginConfiguration(&p.configuration); err != nil {
return err
}
return nil
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
return nil, fmt.Sprintf("%v%v%v", p.configuration.MyStringSetting, p.configuration.MyIntSetting, p.configuration.MyBoolSetting)
}
func main() {
plugin.ClientMain(&MyPlugin{})
}
`,
`{"id": "testloadpluginconfig", "backend": {"executable": "backend.exe"}, "settings_schema": {
"settings": [
{
"key": "MyStringSetting",
@@ -413,9 +461,11 @@ func TestPluginAPILoadPluginConfiguration(t *testing.T) {
"type": "bool"
}
]
}}`)
}}`, "testloadpluginconfig", th.App)
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testloadpluginconfig")
assert.NoError(t, err)
_, ret := hooks.MessageWillBePosted(nil, nil)
assert.Equal(t, "str32true", ret)
}
func TestPluginAPILoadPluginConfigurationDefaults(t *testing.T) {
@@ -429,12 +479,45 @@ func TestPluginAPILoadPluginConfigurationDefaults(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.PluginSettings.Plugins["testloadpluginconfig"] = pluginJson
})
setupPluginApiTest(t,
`
package main
testFolder, found := fileutils.FindDir("tests")
require.True(t, found, "Cannot find tests folder")
fullPath := path.Join(testFolder, "plugin_tests", "manual.test_load_configuration_defaults_plugin", "main.go")
import (
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/model"
"fmt"
)
err := pluginAPIHookTest(t, th, fullPath, "testloadpluginconfig", nil, `{
type configuration struct {
MyStringSetting string
MyIntSetting int
MyBoolSetting bool
}
type MyPlugin struct {
plugin.MattermostPlugin
configuration configuration
}
func (p *MyPlugin) OnConfigurationChange() error {
if err := p.API.LoadPluginConfiguration(&p.configuration); err != nil {
return err
}
return nil
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
return nil, fmt.Sprintf("%v%v%v", p.configuration.MyStringSetting, p.configuration.MyIntSetting, p.configuration.MyBoolSetting)
}
func main() {
plugin.ClientMain(&MyPlugin{})
}
`,
`{"id": "testloadpluginconfig", "backend": {"executable": "backend.exe"}, "settings_schema": {
"settings": [
{
"key": "MyStringSetting",
@@ -452,10 +535,98 @@ func TestPluginAPILoadPluginConfigurationDefaults(t *testing.T) {
"default": true
}
]
}`)
}}`, "testloadpluginconfig", th.App)
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testloadpluginconfig")
assert.NoError(t, err)
_, ret := hooks.MessageWillBePosted(nil, nil)
assert.Equal(t, "override35true", ret)
}
func TestPluginAPIGetBundlePath(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
setupPluginApiTest(t,
`
package main
import (
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/model"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
bundlePath, err := p.API.GetBundlePath()
if err != nil {
return nil, err.Error() + "failed get bundle path"
}
return nil, bundlePath
}
func main() {
plugin.ClientMain(&MyPlugin{})
}
`, `{"id": "testplugin", "backend": {"executable": "backend.exe"}}`, "testplugin", th.App)
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testplugin")
require.Nil(t, err)
require.NotNil(t, hooks)
bundlePath, err := filepath.Abs(filepath.Join(*th.App.Config().PluginSettings.Directory, "testplugin"))
require.Nil(t, err)
_, errString := hooks.MessageWillBePosted(nil, nil)
assert.Equal(t, bundlePath, errString)
}
func TestPluginAPIGetProfileImage(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
// check existing user first
data, err := api.GetProfileImage(th.BasicUser.Id)
require.Nil(t, err)
require.NotEmpty(t, data)
// then unknown user
data, err = api.GetProfileImage(model.NewId())
require.NotNil(t, err)
require.Nil(t, data)
}
func TestPluginAPISetProfileImage(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
// Create an 128 x 128 image
img := image.NewRGBA(image.Rect(0, 0, 128, 128))
// Draw a red dot at (2, 3)
img.Set(2, 3, color.RGBA{255, 0, 0, 255})
buf := new(bytes.Buffer)
err := png.Encode(buf, img)
require.Nil(t, err)
dataBytes := buf.Bytes()
// Set the user profile image
err = api.SetProfileImage(th.BasicUser.Id, dataBytes)
require.Nil(t, err)
// Get the user profile image to check
imageProfile, err := api.GetProfileImage(th.BasicUser.Id)
require.Nil(t, err)
require.NotEmpty(t, imageProfile)
colorful := color.NRGBA{255, 0, 0, 255}
byteReader := bytes.NewReader(imageProfile)
img2, _, err2 := image.Decode(byteReader)
require.Nil(t, err2)
require.Equal(t, img2.At(2, 3), colorful)
}
func TestPluginAPIGetPlugins(t *testing.T) {
@@ -577,6 +748,88 @@ func TestPluginAPISetTeamIcon(t *testing.T) {
require.Equal(t, img2.At(2, 3), colorful)
}
func TestPluginAPISearchChannels(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
t.Run("all fine", func(t *testing.T) {
channels, err := api.SearchChannels(th.BasicTeam.Id, th.BasicChannel.Name)
assert.Nil(t, err)
assert.Len(t, channels, 1)
})
t.Run("invalid team id", func(t *testing.T) {
channels, err := api.SearchChannels("invalidid", th.BasicChannel.Name)
assert.Nil(t, err)
assert.Empty(t, channels)
})
}
func TestPluginAPISearchPostsInTeam(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
testCases := []struct {
description string
teamId string
params []*model.SearchParams
expectedPostsLen int
}{
{
"nil params",
th.BasicTeam.Id,
nil,
0,
},
{
"empty params",
th.BasicTeam.Id,
[]*model.SearchParams{},
0,
},
{
"doesn't match any posts",
th.BasicTeam.Id,
model.ParseSearchParams("bad message", 0),
0,
},
{
"matched posts",
th.BasicTeam.Id,
model.ParseSearchParams(th.BasicPost.Message, 0),
1,
},
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
posts, err := api.SearchPostsInTeam(testCase.teamId, testCase.params)
assert.Nil(t, err)
assert.Equal(t, testCase.expectedPostsLen, len(posts))
})
}
}
func TestPluginAPIGetChannelsForTeamForUser(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
t.Run("all fine", func(t *testing.T) {
channels, err := api.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, false)
assert.Nil(t, err)
assert.Len(t, channels, 3)
})
t.Run("invalid team id", func(t *testing.T) {
channels, err := api.GetChannelsForTeamForUser("invalidid", th.BasicUser.Id, false)
assert.NotNil(t, err)
assert.Empty(t, channels)
})
}
func TestPluginAPIRemoveTeamIcon(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -600,64 +853,278 @@ func TestPluginAPIRemoveTeamIcon(t *testing.T) {
require.Nil(t, err)
}
func pluginAPIHookTest(t *testing.T, th *TestHelper, fileName string, id string, params map[string]interface{}, settingsSchema string) error {
tpl := template.Must(template.ParseFiles(fileName))
builder := &strings.Builder{}
if err := tpl.Execute(builder, params); err != nil {
panic(err)
}
code := builder.String()
schema := `{"settings": [ ] }`
if settingsSchema != "" {
schema = settingsSchema
}
setupPluginApiTest(t, code,
fmt.Sprintf(`{"id": "%v", "backend": {"executable": "backend.exe"}, "settings_schema": %v}`, id, schema),
id, th.App)
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin(id)
assert.NoError(t, err)
require.NotNil(t, hooks)
_, ret := hooks.MessageWillBePosted(nil, nil)
if ret != "" {
return errors.New(ret)
}
return nil
func TestPluginAPIUpdateUserActive(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
err := api.UpdateUserActive(th.BasicUser.Id, true)
require.Nil(t, err)
user, err := api.GetUser(th.BasicUser.Id)
require.Nil(t, err)
require.Equal(t, int64(0), user.DeleteAt)
err = api.UpdateUserActive(th.BasicUser.Id, false)
require.Nil(t, err)
user, err = api.GetUser(th.BasicUser.Id)
require.Nil(t, err)
require.NotNil(t, user)
require.NotEqual(t, int64(0), user.DeleteAt)
err = api.UpdateUserActive(th.BasicUser.Id, true)
require.Nil(t, err)
err = api.UpdateUserActive(th.BasicUser.Id, true)
require.Nil(t, err)
user, err = api.GetUser(th.BasicUser.Id)
require.Nil(t, err)
require.Equal(t, int64(0), user.DeleteAt)
}
// This is a meta-test function. It does the following:
// 1. Scans "tests/plugin_tests" folder
// 2. For each folder - compiles the main.go inside and executes it, validating it's result
// 3. If folder starts with "manual." it is skipped ("manual." tests executed in other part of this file)
// 4. Before compiling the main.go file is passed through templating and the following values are available in the template: BasicUser, BasicUser2, BasicChannel, BasicTeam, BasicPost
func TestPluginAPIGetDirectChannel(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
func TestBasicAPIPlugins(t *testing.T) {
testFolder, found := fileutils.FindDir("tests")
require.True(t, found, "Cannot read find test folder")
fullPath := path.Join(testFolder, "plugin_tests")
dirs, err := ioutil.ReadDir(fullPath)
require.NoError(t, err, "Cannot read test folder %v", fullPath)
for _, dir := range dirs {
d := dir.Name()
if dir.IsDir() && !strings.HasPrefix(d, "manual.") {
t.Run(d, func(t *testing.T) {
mainPath := path.Join(fullPath, d, "main.go")
_, err := os.Stat(mainPath)
assert.NoError(t, err, "Cannot find plugin main file at %v", mainPath)
th := Setup(t).InitBasic()
defer th.TearDown()
params := map[string]interface{}{
"BasicUser": th.BasicUser,
"BasicUser2": th.BasicUser2,
"BasicChannel": th.BasicChannel,
"BasicTeam": th.BasicTeam,
"BasicPost": th.BasicPost,
}
dm1, err := api.GetDirectChannel(th.BasicUser.Id, th.BasicUser2.Id)
require.Nil(t, err)
require.NotEmpty(t, dm1)
err = pluginAPIHookTest(t, th, mainPath, dir.Name(), params, "")
assert.NoError(t, err)
})
dm2, err := api.GetDirectChannel(th.BasicUser.Id, th.BasicUser.Id)
require.Nil(t, err)
require.NotEmpty(t, dm2)
dm3, err := api.GetDirectChannel(th.BasicUser.Id, model.NewId())
require.NotNil(t, err)
require.Empty(t, dm3)
}
func TestPluginAPISendMail(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
to := th.BasicUser.Email
subject := "testing plugin api sending email"
body := "this is a test."
err := api.SendMail(to, subject, body)
require.Nil(t, err)
// Check if we received the email
var resultsMailbox mailservice.JSONMessageHeaderInbucket
errMail := mailservice.RetryInbucket(5, func() error {
var err error
resultsMailbox, err = mailservice.GetMailBox(to)
return err
})
require.Nil(t, errMail)
require.NotZero(t, len(resultsMailbox))
require.True(t, strings.ContainsAny(resultsMailbox[len(resultsMailbox)-1].To[0], to))
resultsEmail, err1 := mailservice.GetMessageFromMailbox(to, resultsMailbox[len(resultsMailbox)-1].ID)
require.Nil(t, err1)
require.Equal(t, resultsEmail.Subject, subject)
require.Equal(t, resultsEmail.Body.Text, body)
}
func TestPluginAPI_SearchTeams(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
t.Run("all fine", func(t *testing.T) {
teams, err := api.SearchTeams(th.BasicTeam.Name)
assert.Nil(t, err)
assert.Len(t, teams, 1)
teams, err = api.SearchTeams(th.BasicTeam.DisplayName)
assert.Nil(t, err)
assert.Len(t, teams, 1)
teams, err = api.SearchTeams(th.BasicTeam.Name[:3])
assert.Nil(t, err)
assert.Len(t, teams, 1)
})
t.Run("invalid team name", func(t *testing.T) {
teams, err := api.SearchTeams("not found")
assert.Nil(t, err)
assert.Empty(t, teams)
})
}
func TestPluginBots(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
setupPluginApiTest(t,
`
package main
import (
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/model"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
createdBot, err := p.API.CreateBot(&model.Bot{
Username: "bot",
Description: "a plugin bot",
})
if err != nil {
return nil, err.Error() + "failed to create bot"
}
fetchedBot, err := p.API.GetBot(createdBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.Description != "a plugin bot" {
return nil, "GetBot did not return the expected bot Description"
}
if fetchedBot.OwnerId != "testpluginbots" {
return nil, "GetBot did not return the expected bot OwnerId"
}
updatedDescription := createdBot.Description + ", updated"
patchedBot, err := p.API.PatchBot(createdBot.UserId, &model.BotPatch{
Description: &updatedDescription,
})
if err != nil {
return nil, err.Error() + "failed to patch bot"
}
fetchedBot, err = p.API.GetBot(patchedBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.UserId != patchedBot.UserId {
return nil, "GetBot did not return the expected bot"
}
if fetchedBot.Description != "a plugin bot, updated" {
return nil, "GetBot did not return the updated bot Description"
}
fetchedBots, err := p.API.GetBots(&model.BotGetOptions{
Page: 0,
PerPage: 1,
OwnerId: "",
IncludeDeleted: false,
})
if err != nil {
return nil, err.Error() + "failed to get bots"
}
if len(fetchedBots) != 1 {
return nil, "GetBots did not return a single bot"
}
if fetchedBot.UserId != fetchedBots[0].UserId {
return nil, "GetBots did not return the expected bot"
}
_, err = p.API.UpdateBotActive(fetchedBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to disable bot"
}
fetchedBot, err = p.API.GetBot(patchedBot.UserId, false)
if err == nil {
return nil, "expected not to find disabled bot"
}
_, err = p.API.UpdateBotActive(fetchedBot.UserId, true)
if err != nil {
return nil, err.Error() + "failed to disable bot"
}
fetchedBot, err = p.API.GetBot(patchedBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot after enabling"
}
if fetchedBot.UserId != patchedBot.UserId {
return nil, "GetBot did not return the expected bot after enabling"
}
err = p.API.PermanentDeleteBot(patchedBot.UserId)
if err != nil {
return nil, err.Error() + "failed to delete bot"
}
_, err = p.API.GetBot(patchedBot.UserId, false)
if err == nil {
return nil, err.Error() + "found bot after permanently deleting"
}
createdBotWithOverriddenCreator, err := p.API.CreateBot(&model.Bot{
Username: "bot",
Description: "a plugin bot",
OwnerId: "abc123",
})
if err != nil {
return nil, err.Error() + "failed to create bot with overridden creator"
}
fetchedBot, err = p.API.GetBot(createdBotWithOverriddenCreator.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.Description != "a plugin bot" {
return nil, "GetBot did not return the expected bot Description"
}
if fetchedBot.OwnerId != "abc123" {
return nil, "GetBot did not return the expected bot OwnerId"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}
`,
`{"id": "testpluginbots", "backend": {"executable": "backend.exe"}}`,
"testpluginbots",
th.App,
)
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testpluginbots")
assert.NoError(t, err)
_, errString := hooks.MessageWillBePosted(nil, nil)
assert.Empty(t, errString)
}
func TestPluginAPI_GetTeamMembersForUser(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
userId := th.BasicUser.Id
teamMembers, err := api.GetTeamMembersForUser(userId, 0, 10)
assert.Nil(t, err)
assert.Equal(t, len(teamMembers), 1)
assert.Equal(t, teamMembers[0].TeamId, th.BasicTeam.Id)
assert.Equal(t, teamMembers[0].UserId, th.BasicUser.Id)
}
func TestPluginAPI_GetChannelMembersForUser(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
api := th.SetupPluginAPI()
userId := th.BasicUser.Id
teamId := th.BasicTeam.Id
channelMembers, err := api.GetChannelMembersForUser(teamId, userId, 0, 10)
assert.Nil(t, err)
assert.Equal(t, len(channelMembers), 3)
assert.Equal(t, channelMembers[0].UserId, th.BasicUser.Id)
}
func TestPluginAPIKVCompareAndSet(t *testing.T) {

Просмотреть файл

@@ -1,46 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type configuration struct {
MyStringSetting string
MyIntSetting int
MyBoolSetting bool
}
type MyPlugin struct {
plugin.MattermostPlugin
configuration configuration
}
func (p *MyPlugin) OnConfigurationChange() error {
if err := p.API.LoadPluginConfiguration(&p.configuration); err != nil {
return err
}
return nil
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
if p.configuration.MyStringSetting != "override" {
return nil, "MyStringSetting has invalid value"
}
if p.configuration.MyIntSetting != 35 {
return nil, "MyIntSetting has invalid value"
}
if p.configuration.MyBoolSetting != true {
return nil, "MyBoolSetting has invalid value"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,48 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type configuration struct {
MyStringSetting string
MyIntSetting int
MyBoolSetting bool
}
type MyPlugin struct {
plugin.MattermostPlugin
configuration configuration
}
func (p *MyPlugin) OnConfigurationChange() error {
if err := p.API.LoadPluginConfiguration(&p.configuration); err != nil {
return err
}
return nil
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
if p.configuration.MyStringSetting != "str" {
return nil, "MyStringSetting has invalid value"
}
if p.configuration.MyIntSetting != 32 {
return nil, fmt.Sprintf("MyIntSetting has invalid value %v != %v", p.configuration.MyIntSetting, 32)
}
if p.configuration.MyBoolSetting != true {
return nil, "MyBoolSetting has invalid value"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,117 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
createdBot, err := p.API.CreateBot(&model.Bot{
Username: "bot",
Description: "a plugin bot",
})
if err != nil {
return nil, err.Error() + "failed to create bot"
}
fetchedBot, err := p.API.GetBot(createdBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.Description != "a plugin bot" {
return nil, "GetBot did not return the expected bot Description"
}
if fetchedBot.OwnerId != "test_bots_plugin" {
return nil, "GetBot did not return the expected bot OwnerId"
}
updatedDescription := createdBot.Description + ", updated"
patchedBot, err := p.API.PatchBot(createdBot.UserId, &model.BotPatch{
Description: &updatedDescription,
})
if err != nil {
return nil, err.Error() + "failed to patch bot"
}
fetchedBot, err = p.API.GetBot(patchedBot.UserId, false)
if err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.UserId != patchedBot.UserId {
return nil, "GetBot did not return the expected bot"
}
if fetchedBot.Description != "a plugin bot, updated" {
return nil, "GetBot did not return the updated bot Description"
}
fetchedBots, err := p.API.GetBots(&model.BotGetOptions{
Page: 0,
PerPage: 1,
OwnerId: "",
IncludeDeleted: false,
})
if err != nil {
return nil, err.Error() + "failed to get bots"
}
if len(fetchedBots) != 1 {
return nil, "GetBots did not return a single bot"
}
if fetchedBot.UserId != fetchedBots[0].UserId {
return nil, "GetBots did not return the expected bot"
}
if _, err = p.API.UpdateBotActive(fetchedBot.UserId, false); err != nil {
return nil, err.Error() + "failed to disable bot"
}
if fetchedBot, err = p.API.GetBot(patchedBot.UserId, false); err == nil {
return nil, "expected not to find disabled bot"
}
if _, err = p.API.UpdateBotActive(fetchedBot.UserId, true); err != nil {
return nil, err.Error() + "failed to disable bot"
}
if fetchedBot, err = p.API.GetBot(patchedBot.UserId, false); err != nil {
return nil, err.Error() + "failed to get bot after enabling"
}
if fetchedBot.UserId != patchedBot.UserId {
return nil, "GetBot did not return the expected bot after enabling"
}
if err = p.API.PermanentDeleteBot(patchedBot.UserId); err != nil {
return nil, err.Error() + "failed to delete bot"
}
if _, err = p.API.GetBot(patchedBot.UserId, false); err == nil {
return nil, err.Error() + "found bot after permanently deleting"
}
createdBotWithOverriddenCreator, err := p.API.CreateBot(&model.Bot{
Username: "bot",
Description: "a plugin bot",
OwnerId: "abc123",
})
if err != nil {
return nil, err.Error() + "failed to create bot with overridden creator"
}
if fetchedBot, err = p.API.GetBot(createdBotWithOverriddenCreator.UserId, false); err != nil {
return nil, err.Error() + "failed to get bot"
}
if fetchedBot.Description != "a plugin bot" {
return nil, "GetBot did not return the expected bot Description"
}
if fetchedBot.OwnerId != "abc123" {
return nil, "GetBot did not return the expected bot OwnerId"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,31 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"path/filepath"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
bundlePath, err := p.API.GetBundlePath()
if err != nil {
return nil, err.Error() + "failed get bundle path"
} else if bundlePathFromConfig, _ := filepath.Abs(filepath.Join(*p.API.GetConfig().PluginSettings.Directory, "test_get_bundle_path_plugin")); bundlePathFromConfig != bundlePath {
return nil, fmt.Sprintf("Invalid bundle path returned: %v vs %v", bundlePathFromConfig, bundlePath)
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,36 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
channels, err := p.API.GetChannelsForTeamForUser("{{.BasicTeam.Id}}", "{{.BasicUser.Id}}", false)
if err != nil {
return nil, err.Error()
}
if len(channels) != 3 {
return nil, "Returned invalid number of channels"
}
channels, err = p.API.GetChannelsForTeamForUser("invalidid", "{{.BasicUser.Id}}", false)
if err == nil {
return nil, "Expected to get an error while retrieving channels for invalid id"
}
if len(channels) != 0 {
return nil, "Returned invalid number of channels"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,73 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"reflect"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func isEmpty(object interface{}) bool {
// get nil case out of the way
if object == nil {
return true
}
objValue := reflect.ValueOf(object)
switch objValue.Kind() {
// collection types are empty when they have no element
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
}
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
dm1, err := p.API.GetDirectChannel("{{.BasicUser.Id}}", "{{.BasicUser2.Id}}")
if err != nil {
return nil, err.Error()
}
if isEmpty(dm1) {
return nil, "dm1 is empty"
}
dm2, err := p.API.GetDirectChannel("{{.BasicUser.Id}}", "{{.BasicUser.Id}}")
if err != nil {
return nil, err.Error()
}
if isEmpty(dm2) {
return nil, "dm2 is empty"
}
dm3, err := p.API.GetDirectChannel("{{.BasicUser.Id}}", model.NewId())
if err == nil {
return nil, "Expected to get error while fetching incorrect channel"
}
if !isEmpty(dm3) {
return nil, "dm3 is NOT empty"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,65 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"reflect"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func isEmpty(object interface{}) bool {
// get nil case out of the way
if object == nil {
return true
}
objValue := reflect.ValueOf(object)
switch objValue.Kind() {
// collection types are empty when they have no element
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
}
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
// check existing user first
data, err := p.API.GetProfileImage("{{.BasicUser.Id}}")
if err != nil {
return nil, err.Error()
}
if isEmpty(data) {
return nil, "GetProfileImage return empty"
}
// then unknown user
data, err = p.API.GetProfileImage(model.NewId())
if err == nil || data != nil {
return nil, "GetProfileImage should've returned an error"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,31 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
channelMembers, err := p.API.GetChannelMembersForUser("{{.BasicTeam.Id}}", "{{.BasicUser.Id}}", 0, 10)
if err != nil {
return nil, err.Error() + "failed to get channel members"
} else if len(channelMembers) != 3 {
return nil, "Invalid number of channel members"
} else if channelMembers[0].UserId != "{{.BasicUser.Id}}" {
return nil, "Invalid user id returned"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,29 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
teamMembers, err := p.API.GetTeamMembersForUser("{{.BasicUser.Id}}", 0, 10)
if err != nil {
return nil, err.Error() + "failed to get team members"
} else if len(teamMembers) != 1 {
return nil, "Invalid number of team members"
} else if teamMembers[0].UserId != "{{.BasicUser.Id}}" || teamMembers[0].TeamId != "{{.BasicTeam.Id}}" {
return nil, "Invalid user or team id returned"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,38 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
channels, err := p.API.SearchChannels("{{.BasicTeam.Id}}", "{{.BasicChannel.Name}}")
if err != nil {
return nil, err.Error()
}
if len(channels) != 1 {
return nil, "Returned invalid number of channels"
}
channels, err = p.API.SearchChannels("invalidid", "{{.BasicChannel.Name}}")
if err != nil {
return nil, err.Error()
}
if len(channels) != 0 {
return nil, "Returned invalid number of channels"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,65 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
testCases := []struct {
description string
teamId string
params []*model.SearchParams
expectedPostsLen int
}{
{
"nil params",
"{{.BasicTeam.Id}}",
nil,
0,
},
{
"empty params",
"{{.BasicTeam.Id}}",
[]*model.SearchParams{},
0,
},
{
"doesn't match any posts",
"{{.BasicTeam.Id}}",
model.ParseSearchParams("bad message", 0),
0,
},
{
"matched posts",
"{{.BasicTeam.Id}}",
model.ParseSearchParams("{{.BasicPost.Message}}", 0),
1,
},
}
for _, testCase := range testCases {
posts, err := p.API.SearchPostsInTeam(testCase.teamId, testCase.params)
if err != nil {
return nil, fmt.Sprintf("%v: %v", testCase.description, err.Error())
}
if testCase.expectedPostsLen != len(posts) {
return nil, fmt.Sprintf("%v: invalid number of posts: %v != %v", testCase.description, testCase.expectedPostsLen, len(posts))
}
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,56 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
teams, err := p.API.SearchTeams("{{.BasicTeam.Name}}")
if err != nil {
return nil, "search failed: " + err.Message
}
if len(teams) != 1 {
return nil, fmt.Sprintf("search failed, wrong number of teams: %v", len(teams))
}
teams, err = p.API.SearchTeams("{{.BasicTeam.DisplayName}}")
if err != nil {
return nil, "search failed: " + err.Message
}
if len(teams) != 1 {
return nil, fmt.Sprintf("search failed, wrong number of teams: %v", len(teams))
}
teams, err = p.API.SearchTeams("{{.BasicTeam.Name}}"[:3])
if err != nil {
return nil, "search failed: " + err.Message
}
if len(teams) != 1 {
return nil, fmt.Sprintf("search failed, wrong number of teams: %v", len(teams))
}
teams, err = p.API.SearchTeams("not found")
if err != nil {
return nil, "search failed: " + err.Message
}
if len(teams) != 0 {
return nil, fmt.Sprintf("search failed, wrong number of teams: %v", len(teams))
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,59 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"strings"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/services/mailservice"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
to := "{{.BasicUser.Email}}"
subject := "testing plugin api sending email"
body := "this is a test."
if err := p.API.SendMail(to, subject, body); err != nil {
return nil, err.Error()
}
// Check if we received the email
var resultsMailbox mailservice.JSONMessageHeaderInbucket
if errMail := mailservice.RetryInbucket(5, func() error {
var err error
resultsMailbox, err = mailservice.GetMailBox(to)
return err
}); errMail != nil {
return nil, errMail.Error()
}
if len(resultsMailbox) == 0 {
return nil, fmt.Sprintf("No mailbox results. Should be %v", len(resultsMailbox))
}
if !strings.ContainsAny(resultsMailbox[len(resultsMailbox)-1].To[0], to) {
return nil, "Result doesn't contain recipient"
}
resultsEmail, err1 := mailservice.GetMessageFromMailbox(to, resultsMailbox[len(resultsMailbox)-1].ID)
if err1 != nil {
return nil, err1.Error()
}
if resultsEmail.Subject != subject {
return nil, fmt.Sprintf("subject differs: %v vs %s", resultsEmail.Subject, subject)
}
if resultsEmail.Body.Text != body {
return nil, fmt.Sprintf("body differs: %v vs %s", resultsEmail.Body.Text, body)
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,90 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"bytes"
"fmt"
"image"
"image/color"
"image/png"
"reflect"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func isEmpty(object interface{}) bool {
// get nil case out of the way
if object == nil {
return true
}
objValue := reflect.ValueOf(object)
switch objValue.Kind() {
// collection types are empty when they have no element
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
}
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
// Create an 128 x 128 image
img := image.NewRGBA(image.Rect(0, 0, 128, 128))
// Draw a red dot at (2, 3)
img.Set(2, 3, color.RGBA{255, 0, 0, 255})
buf := new(bytes.Buffer)
if err := png.Encode(buf, img); err != nil {
return nil, err.Error()
}
dataBytes := buf.Bytes()
// Set the user profile image
if err := p.API.SetProfileImage("{{.BasicUser.Id}}", dataBytes); err != nil {
return nil, err.Error()
}
// Get the user profile image to check
imageProfile, err := p.API.GetProfileImage("{{.BasicUser.Id}}")
if err != nil {
return nil, err.Error()
}
if isEmpty(imageProfile) {
return nil, "profile image is empty"
}
colorful := color.NRGBA{255, 0, 0, 255}
byteReader := bytes.NewReader(imageProfile)
img2, _, err2 := image.Decode(byteReader)
if err2 != nil {
return nil, err.Error()
}
if img2.At(2, 3) != colorful {
return nil, fmt.Sprintf("color mismatch %v != %v", img2.At(2, 3), colorful)
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,68 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
uid := "{{.BasicUser.Id}}"
if err := p.API.UpdateUserActive(uid, true); err != nil {
return nil, err.Error()
}
user, err := p.API.GetUser(uid)
if err != nil {
return nil, err.Error()
}
if int64(0) != user.DeleteAt {
return nil, "DeleteAt value is not 0"
}
if err = p.API.UpdateUserActive(uid, false); err != nil {
return nil, err.Error()
}
user, err = p.API.GetUser(uid)
if err != nil {
return nil, err.Error()
}
if user == nil {
return nil, "GetUser returned nil"
}
if int64(0) == user.DeleteAt {
return nil, "DeleteAt value is 0"
}
if err = p.API.UpdateUserActive(uid, true); err != nil {
return nil, err.Error()
}
if err = p.API.UpdateUserActive(uid, true); err != nil {
return nil, err.Error()
}
user, err = p.API.GetUser(uid)
if err != nil {
return nil, err.Error()
}
if int64(0) != user.DeleteAt {
return nil, "DeleteAt value is not 0"
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}

Просмотреть файл

@@ -1,49 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
type MyPlugin struct {
plugin.MattermostPlugin
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
uid := "{{.BasicUser.Id}}"
statuses := []string{model.STATUS_ONLINE, model.STATUS_AWAY, model.STATUS_DND, model.STATUS_OFFLINE}
for _, s := range statuses {
status, err := p.API.UpdateUserStatus(uid, s)
if err != nil {
return nil, err.Error()
}
if status == nil {
return nil, "Status was expected, got nil"
}
if s != status.Status {
return nil, fmt.Sprintf("Invalid status returned: %v != %v", s, status.Status)
}
}
status, err := p.API.UpdateUserStatus(uid, "notrealstatus")
if err == nil {
return nil, "Expected to get an error while updating invalid user status"
}
if status != nil {
return nil, "Status was expected to be nil, got: " + status.Status
}
return nil, ""
}
func main() {
plugin.ClientMain(&MyPlugin{})
}