summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2018-01-23 11:04:44 -0500
committerChristopher Speller <crspeller@gmail.com>2018-01-23 08:04:44 -0800
commit4f4a765e7d0bbfdfecc0c52ae4be35f8d3b737ca (patch)
tree063aa55db9299f09d4176b201db658f1d7acced5 /store
parent599991ea731953f772824ce3ed1e591246aa004f (diff)
downloadchat-4f4a765e7d0bbfdfecc0c52ae4be35f8d3b737ca.tar.gz
chat-4f4a765e7d0bbfdfecc0c52ae4be35f8d3b737ca.tar.bz2
chat-4f4a765e7d0bbfdfecc0c52ae4be35f8d3b737ca.zip
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
Diffstat (limited to 'store')
-rw-r--r--store/sqlstore/emoji_store.go29
-rw-r--r--store/store.go1
-rw-r--r--store/storetest/emoji_store.go68
-rw-r--r--store/storetest/mocks/EmojiStore.go16
4 files changed, 114 insertions, 0 deletions
diff --git a/store/sqlstore/emoji_store.go b/store/sqlstore/emoji_store.go
index 734190dbb..afd87b83d 100644
--- a/store/sqlstore/emoji_store.go
+++ b/store/sqlstore/emoji_store.go
@@ -46,6 +46,7 @@ func (es SqlEmojiStore) CreateIndexesIfNotExists() {
es.CreateIndexIfNotExists("idx_emoji_update_at", "Emoji", "UpdateAt")
es.CreateIndexIfNotExists("idx_emoji_create_at", "Emoji", "CreateAt")
es.CreateIndexIfNotExists("idx_emoji_delete_at", "Emoji", "DeleteAt")
+ es.CreateIndexIfNotExists("idx_emoji_name", "Emoji", "Name")
}
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)
})
}
+
+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
+ }
+ })
+}
diff --git a/store/store.go b/store/store.go
index 8cb5093ea..2742c0889 100644
--- a/store/store.go
+++ b/store/store.go
@@ -393,6 +393,7 @@ type EmojiStore interface {
GetByName(name string) StoreChannel
GetList(offset, limit int, sort string) StoreChannel
Delete(id string, time int64) StoreChannel
+ Search(name string, prefixOnly bool, limit int) StoreChannel
}
type StatusStore interface {
diff --git a/store/storetest/emoji_store.go b/store/storetest/emoji_store.go
index a862440e5..9e4dbaa6e 100644
--- a/store/storetest/emoji_store.go
+++ b/store/storetest/emoji_store.go
@@ -18,6 +18,7 @@ func TestEmojiStore(t *testing.T, ss store.Store) {
t.Run("EmojiGet", func(t *testing.T) { testEmojiGet(t, ss) })
t.Run("EmojiGetByName", func(t *testing.T) { testEmojiGetByName(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) {
@@ -191,3 +192,70 @@ func testEmojiGetList(t *testing.T, ss store.Store) {
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)
+ }
+ }
+}
diff --git a/store/storetest/mocks/EmojiStore.go b/store/storetest/mocks/EmojiStore.go
index d1bfe7f00..9871c98aa 100644
--- a/store/storetest/mocks/EmojiStore.go
+++ b/store/storetest/mocks/EmojiStore.go
@@ -92,3 +92,19 @@ func (_m *EmojiStore) Save(emoji *model.Emoji) store.StoreChannel {
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
+}