ABC-90 Add POST /emoji/search and GET /emoji/autocomplete API endpoints (#8125)
* Add POST /emoji/search and GET /emoji/autocomplete API endpoints * Add constant to be clearer
Этот коммит содержится в:
коммит произвёл
Christopher Speller
родитель
599991ea73
Коммит
4f4a765e7d
@@ -184,7 +184,7 @@ func Init(a *app.App, root *mux.Router, full bool) *API {
|
|||||||
api.BaseRoutes.DataRetention = api.BaseRoutes.ApiRoot.PathPrefix("/data_retention").Subrouter()
|
api.BaseRoutes.DataRetention = api.BaseRoutes.ApiRoot.PathPrefix("/data_retention").Subrouter()
|
||||||
|
|
||||||
api.BaseRoutes.Emojis = api.BaseRoutes.ApiRoot.PathPrefix("/emoji").Subrouter()
|
api.BaseRoutes.Emojis = api.BaseRoutes.ApiRoot.PathPrefix("/emoji").Subrouter()
|
||||||
api.BaseRoutes.Emoji = api.BaseRoutes.Emojis.PathPrefix("/{emoji_id:[A-Za-z0-9]+}").Subrouter()
|
api.BaseRoutes.Emoji = api.BaseRoutes.ApiRoot.PathPrefix("/emoji/{emoji_id:[A-Za-z0-9]+}").Subrouter()
|
||||||
|
|
||||||
api.BaseRoutes.ReactionByNameForPostForUser = api.BaseRoutes.PostForUser.PathPrefix("/reactions/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}").Subrouter()
|
api.BaseRoutes.ReactionByNameForPostForUser = api.BaseRoutes.PostForUser.PathPrefix("/reactions/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}").Subrouter()
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,15 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EMOJI_MAX_AUTOCOMPLETE_ITEMS = 100
|
||||||
|
)
|
||||||
|
|
||||||
func (api *API) InitEmoji() {
|
func (api *API) InitEmoji() {
|
||||||
api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(createEmoji)).Methods("POST")
|
api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(createEmoji)).Methods("POST")
|
||||||
api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(getEmojiList)).Methods("GET")
|
api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(getEmojiList)).Methods("GET")
|
||||||
|
api.BaseRoutes.Emojis.Handle("/search", api.ApiSessionRequired(searchEmojis)).Methods("POST")
|
||||||
|
api.BaseRoutes.Emojis.Handle("/autocomplete", api.ApiSessionRequired(autocompleteEmojis)).Methods("GET")
|
||||||
api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(deleteEmoji)).Methods("DELETE")
|
api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(deleteEmoji)).Methods("DELETE")
|
||||||
api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(getEmoji)).Methods("GET")
|
api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(getEmoji)).Methods("GET")
|
||||||
api.BaseRoutes.Emoji.Handle("/image", api.ApiSessionRequiredTrustRequester(getEmojiImage)).Methods("GET")
|
api.BaseRoutes.Emoji.Handle("/image", api.ApiSessionRequiredTrustRequester(getEmojiImage)).Methods("GET")
|
||||||
@@ -162,3 +168,41 @@ func getEmojiImage(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("Cache-Control", "max-age=2592000, public")
|
w.Header().Set("Cache-Control", "max-age=2592000, public")
|
||||||
w.Write(image)
|
w.Write(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func searchEmojis(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
emojiSearch := model.EmojiSearchFromJson(r.Body)
|
||||||
|
if emojiSearch == nil {
|
||||||
|
c.SetInvalidParam("term")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if emojiSearch.Term == "" {
|
||||||
|
c.SetInvalidParam("term")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
emojis, err := c.App.SearchEmoji(emojiSearch.Term, emojiSearch.PrefixOnly, PER_PAGE_MAXIMUM)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
w.Write([]byte(model.EmojiListToJson(emojis)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func autocompleteEmojis(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
name := r.URL.Query().Get("name")
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
c.SetInvalidUrlParam("name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
emojis, err := c.App.SearchEmoji(name, true, EMOJI_MAX_AUTOCOMPLETE_ITEMS)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
w.Write([]byte(model.EmojiListToJson(emojis)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
"github.com/mattermost/mattermost-server/utils"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateEmoji(t *testing.T) {
|
func TestCreateEmoji(t *testing.T) {
|
||||||
@@ -432,3 +434,135 @@ func TestGetEmojiImage(t *testing.T) {
|
|||||||
_, resp = Client.GetEmojiImage("")
|
_, resp = Client.GetEmojiImage("")
|
||||||
CheckBadRequestStatus(t, resp)
|
CheckBadRequestStatus(t, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSearchEmoji(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
Client := th.Client
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
|
||||||
|
|
||||||
|
searchTerm1 := model.NewId()
|
||||||
|
searchTerm2 := model.NewId()
|
||||||
|
|
||||||
|
emojis := []*model.Emoji{
|
||||||
|
{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
Name: searchTerm1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
Name: "blargh_" + searchTerm2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, emoji := range emojis {
|
||||||
|
emoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
emojis[idx] = emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
search := &model.EmojiSearch{Term: searchTerm1}
|
||||||
|
remojis, resp := Client.SearchEmoji(search)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, e := range remojis {
|
||||||
|
if e.Name == emojis[0].Name {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, found)
|
||||||
|
|
||||||
|
search.Term = searchTerm2
|
||||||
|
search.PrefixOnly = true
|
||||||
|
remojis, resp = Client.SearchEmoji(search)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
found = false
|
||||||
|
for _, e := range remojis {
|
||||||
|
if e.Name == emojis[1].Name {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, found)
|
||||||
|
|
||||||
|
search.PrefixOnly = false
|
||||||
|
remojis, resp = Client.SearchEmoji(search)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
found = false
|
||||||
|
for _, e := range remojis {
|
||||||
|
if e.Name == emojis[1].Name {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, found)
|
||||||
|
|
||||||
|
search.Term = ""
|
||||||
|
_, resp = Client.SearchEmoji(search)
|
||||||
|
CheckBadRequestStatus(t, resp)
|
||||||
|
|
||||||
|
Client.Logout()
|
||||||
|
_, resp = Client.SearchEmoji(search)
|
||||||
|
CheckUnauthorizedStatus(t, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAutocompleteEmoji(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
Client := th.Client
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
|
||||||
|
|
||||||
|
searchTerm1 := model.NewId()
|
||||||
|
|
||||||
|
emojis := []*model.Emoji{
|
||||||
|
{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
Name: searchTerm1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CreatorId: th.BasicUser.Id,
|
||||||
|
Name: "blargh_" + searchTerm1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, emoji := range emojis {
|
||||||
|
emoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
emojis[idx] = emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
remojis, resp := Client.AutocompleteEmoji(searchTerm1, "")
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
found1 := false
|
||||||
|
found2 := false
|
||||||
|
for _, e := range remojis {
|
||||||
|
if e.Name == emojis[0].Name {
|
||||||
|
found1 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Name == emojis[1].Name {
|
||||||
|
found2 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, found1)
|
||||||
|
assert.False(t, found2)
|
||||||
|
|
||||||
|
_, resp = Client.AutocompleteEmoji("", "")
|
||||||
|
CheckBadRequestStatus(t, resp)
|
||||||
|
|
||||||
|
Client.Logout()
|
||||||
|
_, resp = Client.AutocompleteEmoji(searchTerm1, "")
|
||||||
|
CheckUnauthorizedStatus(t, resp)
|
||||||
|
}
|
||||||
|
|||||||
16
app/emoji.go
16
app/emoji.go
@@ -134,11 +134,11 @@ func (a *App) DeleteEmoji(emoji *model.Emoji) *model.AppError {
|
|||||||
|
|
||||||
func (a *App) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) {
|
func (a *App) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) {
|
||||||
if !*a.Config().ServiceSettings.EnableCustomEmoji {
|
if !*a.Config().ServiceSettings.EnableCustomEmoji {
|
||||||
return nil, model.NewAppError("deleteEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
|
return nil, model.NewAppError("GetEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*a.Config().FileSettings.DriverName) == 0 {
|
if len(*a.Config().FileSettings.DriverName) == 0 {
|
||||||
return nil, model.NewAppError("deleteImage", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented)
|
return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result := <-a.Srv.Store.Emoji().Get(emojiId, false); result.Err != nil {
|
if result := <-a.Srv.Store.Emoji().Get(emojiId, false); result.Err != nil {
|
||||||
@@ -169,6 +169,18 @@ func (a *App) GetEmojiImage(emojiId string) (imageByte []byte, imageType string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) SearchEmoji(name string, prefixOnly bool, limit int) ([]*model.Emoji, *model.AppError) {
|
||||||
|
if !*a.Config().ServiceSettings.EnableCustomEmoji {
|
||||||
|
return nil, model.NewAppError("SearchEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := <-a.Srv.Store.Emoji().Search(name, prefixOnly, limit); result.Err != nil {
|
||||||
|
return nil, result.Err
|
||||||
|
} else {
|
||||||
|
return result.Data.([]*model.Emoji), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func resizeEmojiGif(gifImg *gif.GIF) *gif.GIF {
|
func resizeEmojiGif(gifImg *gif.GIF) *gif.GIF {
|
||||||
// Create a new RGBA image to hold the incremental frames.
|
// Create a new RGBA image to hold the incremental frames.
|
||||||
firstFrame := gifImg.Image[0].Bounds()
|
firstFrame := gifImg.Image[0].Bounds()
|
||||||
|
|||||||
@@ -3070,6 +3070,27 @@ func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchEmoji returns a list of emoji matching some search criteria.
|
||||||
|
func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response) {
|
||||||
|
if r, err := c.DoApiPost(c.GetEmojisRoute()+"/search", search.ToJson()); err != nil {
|
||||||
|
return nil, BuildErrorResponse(r, err)
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return EmojiListFromJson(r.Body), BuildResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutocompleteEmoji returns a list of emoji starting with or matching name.
|
||||||
|
func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Response) {
|
||||||
|
query := fmt.Sprintf("?name=%v", name)
|
||||||
|
if r, err := c.DoApiGet(c.GetEmojisRoute()+"/autocomplete"+query, ""); err != nil {
|
||||||
|
return nil, BuildErrorResponse(r, err)
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return EmojiListFromJson(r.Body), BuildResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reaction Section
|
// Reaction Section
|
||||||
|
|
||||||
// SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned.
|
// SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned.
|
||||||
|
|||||||
34
model/emoji_search.go
Обычный файл
34
model/emoji_search.go
Обычный файл
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmojiSearch struct {
|
||||||
|
Term string `json:"term"`
|
||||||
|
PrefixOnly bool `json:"prefix_only"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *EmojiSearch) ToJson() string {
|
||||||
|
b, err := json.Marshal(es)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmojiSearchFromJson(data io.Reader) *EmojiSearch {
|
||||||
|
decoder := json.NewDecoder(data)
|
||||||
|
var es EmojiSearch
|
||||||
|
err := decoder.Decode(&es)
|
||||||
|
if err == nil {
|
||||||
|
return &es
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
19
model/emoji_search_test.go
Обычный файл
19
model/emoji_search_test.go
Обычный файл
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEmojiSearchJson(t *testing.T) {
|
||||||
|
emojiSearch := EmojiSearch{Term: NewId()}
|
||||||
|
json := emojiSearch.ToJson()
|
||||||
|
remojiSearch := EmojiSearchFromJson(strings.NewReader(json))
|
||||||
|
|
||||||
|
if emojiSearch.Term != remojiSearch.Term {
|
||||||
|
t.Fatal("Terms do not match")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,6 +46,7 @@ func (es SqlEmojiStore) CreateIndexesIfNotExists() {
|
|||||||
es.CreateIndexIfNotExists("idx_emoji_update_at", "Emoji", "UpdateAt")
|
es.CreateIndexIfNotExists("idx_emoji_update_at", "Emoji", "UpdateAt")
|
||||||
es.CreateIndexIfNotExists("idx_emoji_create_at", "Emoji", "CreateAt")
|
es.CreateIndexIfNotExists("idx_emoji_create_at", "Emoji", "CreateAt")
|
||||||
es.CreateIndexIfNotExists("idx_emoji_delete_at", "Emoji", "DeleteAt")
|
es.CreateIndexIfNotExists("idx_emoji_delete_at", "Emoji", "DeleteAt")
|
||||||
|
es.CreateIndexIfNotExists("idx_emoji_name", "Emoji", "Name")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) Save(emoji *model.Emoji) store.StoreChannel {
|
func (es SqlEmojiStore) Save(emoji *model.Emoji) store.StoreChannel {
|
||||||
@@ -162,3 +163,31 @@ func (es SqlEmojiStore) Delete(id string, time int64) store.StoreChannel {
|
|||||||
emojiCache.Remove(id)
|
emojiCache.Remove(id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (es SqlEmojiStore) Search(name string, prefixOnly bool, limit int) store.StoreChannel {
|
||||||
|
return store.Do(func(result *store.StoreResult) {
|
||||||
|
var emojis []*model.Emoji
|
||||||
|
|
||||||
|
term := ""
|
||||||
|
if !prefixOnly {
|
||||||
|
term = "%"
|
||||||
|
}
|
||||||
|
|
||||||
|
term += name + "%"
|
||||||
|
|
||||||
|
if _, err := es.GetReplica().Select(&emojis,
|
||||||
|
`SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
Emoji
|
||||||
|
WHERE
|
||||||
|
Name LIKE :Name
|
||||||
|
AND DeleteAt = 0
|
||||||
|
ORDER BY Name
|
||||||
|
LIMIT :Limit`, map[string]interface{}{"Name": term, "Limit": limit}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlEmojiStore.Search", "store.sql_emoji.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError)
|
||||||
|
} else {
|
||||||
|
result.Data = emojis
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -393,6 +393,7 @@ type EmojiStore interface {
|
|||||||
GetByName(name string) StoreChannel
|
GetByName(name string) StoreChannel
|
||||||
GetList(offset, limit int, sort string) StoreChannel
|
GetList(offset, limit int, sort string) StoreChannel
|
||||||
Delete(id string, time int64) StoreChannel
|
Delete(id string, time int64) StoreChannel
|
||||||
|
Search(name string, prefixOnly bool, limit int) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
type StatusStore interface {
|
type StatusStore interface {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func TestEmojiStore(t *testing.T, ss store.Store) {
|
|||||||
t.Run("EmojiGet", func(t *testing.T) { testEmojiGet(t, ss) })
|
t.Run("EmojiGet", func(t *testing.T) { testEmojiGet(t, ss) })
|
||||||
t.Run("EmojiGetByName", func(t *testing.T) { testEmojiGetByName(t, ss) })
|
t.Run("EmojiGetByName", func(t *testing.T) { testEmojiGetByName(t, ss) })
|
||||||
t.Run("EmojiGetList", func(t *testing.T) { testEmojiGetList(t, ss) })
|
t.Run("EmojiGetList", func(t *testing.T) { testEmojiGetList(t, ss) })
|
||||||
|
t.Run("EmojiSearch", func(t *testing.T) { testEmojiSearch(t, ss) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEmojiSaveDelete(t *testing.T, ss store.Store) {
|
func testEmojiSaveDelete(t *testing.T, ss store.Store) {
|
||||||
@@ -191,3 +192,70 @@ func testEmojiGetList(t *testing.T, ss store.Store) {
|
|||||||
assert.Equal(t, emojis[2].Name, remojis[1].Name)
|
assert.Equal(t, emojis[2].Name, remojis[1].Name)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testEmojiSearch(t *testing.T, ss store.Store) {
|
||||||
|
emojis := []model.Emoji{
|
||||||
|
{
|
||||||
|
CreatorId: model.NewId(),
|
||||||
|
Name: "blargh_" + model.NewId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CreatorId: model.NewId(),
|
||||||
|
Name: model.NewId() + "_blargh",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CreatorId: model.NewId(),
|
||||||
|
Name: model.NewId() + "_blargh_" + model.NewId(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CreatorId: model.NewId(),
|
||||||
|
Name: model.NewId(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, emoji := range emojis {
|
||||||
|
emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
for _, emoji := range emojis {
|
||||||
|
store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix()))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
shouldFind := []bool{true, false, false, false}
|
||||||
|
|
||||||
|
if result := <-ss.Emoji().Search("blargh", true, 100); result.Err != nil {
|
||||||
|
t.Fatal(result.Err)
|
||||||
|
} else {
|
||||||
|
for i, emoji := range emojis {
|
||||||
|
found := false
|
||||||
|
|
||||||
|
for _, savedEmoji := range result.Data.([]*model.Emoji) {
|
||||||
|
if emoji.Id == savedEmoji.Id {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldFind = []bool{true, true, true, false}
|
||||||
|
if result := <-ss.Emoji().Search("blargh", false, 100); result.Err != nil {
|
||||||
|
t.Fatal(result.Err)
|
||||||
|
} else {
|
||||||
|
for i, emoji := range emojis {
|
||||||
|
found := false
|
||||||
|
|
||||||
|
for _, savedEmoji := range result.Data.([]*model.Emoji) {
|
||||||
|
if emoji.Id == savedEmoji.Id {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,3 +92,19 @@ func (_m *EmojiStore) Save(emoji *model.Emoji) store.StoreChannel {
|
|||||||
|
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search provides a mock function with given fields: name, prefixOnly, limit
|
||||||
|
func (_m *EmojiStore) Search(name string, prefixOnly bool, limit int) store.StoreChannel {
|
||||||
|
ret := _m.Called(name, prefixOnly, limit)
|
||||||
|
|
||||||
|
var r0 store.StoreChannel
|
||||||
|
if rf, ok := ret.Get(0).(func(string, bool, int) store.StoreChannel); ok {
|
||||||
|
r0 = rf(name, prefixOnly, limit)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(store.StoreChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user