grafana/pkg/api/avatar/avatar_test.go
Michael Mandrus f9d86557cf
Dashboard: Mix initials and custom gravatars in recent viewers list (#47212)
* Use Wiring to initialize Avatar Cache Server

Create AvatarCacheServer Provider function and pass it in as an
argument to HTTPServer. Also convert CacheServer to a singleton
so that we keep all cached Avatar info in one place for easier access

* Refactor avatar cache server and add 'isCustom' check

Avatar cache server needs to perform two similar fetches
back-to-back; break up functions to allow for easy reuse.
Then add handling to see if a user has a custom avatar.

* Add additional accessors so that /recents api can easily use the cache

* Minor mods to avatar server to facilitiate unit testing

* add unit tests for avatar fetching

* add error handling in case we somehow fetch gravatars while they are disabled

* linting: read error return value in unit test

* Use http package status codes

Co-authored-by: Ezequiel Victorero <evictorero@gmail.com>

* Use http package status codes

Co-authored-by: Ezequiel Victorero <evictorero@gmail.com>

* Use http package status codes

Co-authored-by: Ezequiel Victorero <evictorero@gmail.com>

* Incorporate suggestions from PR
-avoid mutating arguments
-change error handler function to private and make name more descriptive

Co-authored-by: Ezequiel Victorero <evictorero@gmail.com>
2022-04-05 22:56:17 -04:00

121 lines
3.5 KiB
Go

package avatar
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
const DEFAULT_NONSENSE_HASH string = "9e107d9d372bb6826bd81d3542a419d6"
const CUSTOM_NONSENSE_HASH string = "d2a9116d4a63304733ca0f3471e57d16"
var NONSENSE_BODY []byte = []byte("Bogus API response")
func TestAvatar_AvatarRetrieval(t *testing.T) {
avc := ProvideAvatarCacheServer(setting.NewCfg())
callCounter := 0
mockServer := setupMockGravatarServer(&callCounter, false)
t.Cleanup(func() {
avc.cache.Flush()
mockServer.Close()
})
av := avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
// verify there was a call to get the image and a call to the 404 fallback
require.Equal(t, callCounter, 2)
require.Equal(t, av.data.Bytes(), NONSENSE_BODY)
avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
//since the avatar is cached, there should not have been anymore REST calls
require.Equal(t, callCounter, 2)
}
func TestAvatar_CheckCustom(t *testing.T) {
avc := ProvideAvatarCacheServer(setting.NewCfg())
callCounter := 0
mockServer := setupMockGravatarServer(&callCounter, false)
t.Cleanup(func() {
avc.cache.Flush()
mockServer.Close()
})
av := avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
// verify this avatar is not marked custom
require.False(t, av.isCustom)
av2 := avc.getAvatarForHash(CUSTOM_NONSENSE_HASH, mockServer.URL+"/avatar/")
// verify this avatar is marked custom
require.True(t, av2.isCustom)
}
func TestAvatar_FallbackCase(t *testing.T) {
avc := ProvideAvatarCacheServer(setting.NewCfg())
callCounter := 0
mockServer := setupMockGravatarServer(&callCounter, true)
t.Cleanup(func() {
avc.cache.Flush()
mockServer.Close()
})
av := avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
// the client should not have gotten a valid response back from the first call
// there should only be one REST call, and the avatar url should be the default
require.Equal(t, callCounter, 1)
require.False(t, av.isCustom)
require.True(t, av.notFound)
require.Equal(t, av, avc.notFound)
}
func TestAvatar_ExpirationHandler(t *testing.T) {
avc := ProvideAvatarCacheServer(setting.NewCfg())
callCounter := 0
mockServer := setupMockGravatarServer(&callCounter, false)
t.Cleanup(func() {
avc.cache.Flush()
mockServer.Close()
})
av := avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
// verify there was a call to get the image and a call to the 404 fallback
require.Equal(t, callCounter, 2)
require.Equal(t, av.data.Bytes(), NONSENSE_BODY)
// manually expire the avatar in the cache
av.timestamp = av.timestamp.Add(-time.Minute * 15)
avc.getAvatarForHash(DEFAULT_NONSENSE_HASH, mockServer.URL+"/avatar/")
//since the avatar is expired, there should be two more REST calls
require.Equal(t, callCounter, 4)
}
func setupMockGravatarServer(counter *int, simulateError bool) *httptest.Server {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
(*counter)++
splitUri := strings.Split(r.RequestURI, "?")
urlHash := splitUri[0][len("/avatar/"):]
params := splitUri[1]
if params == "d=404" {
if urlHash == DEFAULT_NONSENSE_HASH {
w.WriteHeader(404)
} else {
_, _ = w.Write(NONSENSE_BODY)
}
} else {
if simulateError {
w.WriteHeader(500)
} else {
_, _ = w.Write(NONSENSE_BODY)
}
}
}))
return server
}