app/wrapper_test.go

v1.5.2
skunky-art/app/wrapper_test.go history · blame · raw

117 lines · 3715 bytes

  1package app
  2
  3import (
  4	"encoding/json"
  5	"errors"
  6	"net/http/httptest"
  7	"net/url"
  8	"strings"
  9	"testing"
 10
 11	"github.com/krazywarez/devianter"
 12)
 13
 14// withAvatarCache turns the media cache on over a temporary directory and
 15// swaps in a counting avatar fetcher for the test's duration.
 16func withAvatarCache(t *testing.T, enabled bool, fetch func(string, rune) (string, error)) *int {
 17	t.Helper()
 18	cache, orig := CFG.Cache, fetchAvatar
 19	CFG.Cache.Enabled = enabled
 20	CFG.Cache.MemCache = false
 21	CFG.Cache.Path = t.TempDir()
 22	calls := 0
 23	fetchAvatar = func(name string, r rune) (string, error) {
 24		calls++
 25		return fetch(name, r)
 26	}
 27	t.Cleanup(func() { CFG.Cache, fetchAvatar = cache, orig })
 28	return &calls
 29}
 30
 31func emojitar(name string) *httptest.ResponseRecorder {
 32	rec := httptest.NewRecorder()
 33	skunkyart{Writer: rec, Host: "http://localhost", Type: 'a'}.Emojitar(name)
 34	return rec
 35}
 36
 37func TestEmojitarServesFromCacheAfterFirstFetch(t *testing.T) {
 38	calls := withAvatarCache(t, true, func(string, rune) (string, error) { return "png", nil })
 39
 40	first := emojitar("Alice")
 41	second := emojitar("alice") // case-insensitive, as DeviantArt's paths are
 42
 43	if *calls != 1 {
 44		t.Errorf("avatar fetched %d times, want 1", *calls)
 45	}
 46	if first.Body.String() != "png" || second.Body.String() != "png" {
 47		t.Errorf("bodies %q and %q, want both png", first.Body.String(), second.Body.String())
 48	}
 49}
 50
 51func TestEmojitarDoesNotCacheAMiss(t *testing.T) {
 52	calls := withAvatarCache(t, true, func(string, rune) (string, error) { return "", errors.New("user not exists") })
 53
 54	first := emojitar("nobody")
 55	emojitar("nobody")
 56
 57	if first.Code != 404 {
 58		t.Errorf("status %d, want 404", first.Code)
 59	}
 60	if *calls != 2 {
 61		t.Errorf("avatar fetched %d times, want 2: a miss must not be cached", *calls)
 62	}
 63}
 64
 65func TestEmojitarFetchesEveryTimeWithCacheOff(t *testing.T) {
 66	calls := withAvatarCache(t, false, func(string, rune) (string, error) { return "png", nil })
 67
 68	emojitar("alice")
 69	emojitar("alice")
 70
 71	if *calls != 2 {
 72		t.Errorf("avatar fetched %d times, want 2 with the cache off", *calls)
 73	}
 74}
 75
 76// TestUserAboutRendersProfileDetails is the regression test for the branch
 77// upstream had disabled with `else if false`: a person's about tab must show
 78// their interests, social links and how long they have been registered. The
 79// profile is decoded from JSON shaped like DeviantArt's, since the module
 80// slice's element type embeds an unexported struct and cannot be built by
 81// name from here.
 82func TestUserAboutRendersProfileDetails(t *testing.T) {
 83	const profile = `{
 84	  "owner": {"isGroup": false, "username": "alice"},
 85	  "gruser": {"gruserId": 42, "page": {"modules": [
 86	    {"name": "about", "moduleData": {"about": {
 87	      "deviantFor": 86400,
 88	      "interests": [{"label": "Favourite animal", "value": "skunk"}],
 89	      "socialLinks": [{"value": "https://social.example/alice"}]
 90	    }}}
 91	  ]}}
 92	}`
 93	orig := fetchProfile
 94	fetchProfile = func(string) (devianter.GRuser, devianter.Error, error) {
 95		var p devianter.GRuser
 96		if err := json.Unmarshal([]byte(profile), &p); err != nil {
 97			t.Fatal(err)
 98		}
 99		return p, devianter.Error{}, nil
100	}
101	t.Cleanup(func() { fetchProfile = orig })
102
103	loadTemplates()
104	rec := httptest.NewRecorder()
105	s := skunkyart{Writer: rec, Host: "http://localhost", BasePath: "/", Type: 'a', Query: "alice", Args: url.Values{}, _pth: "/group_user"}
106	s.GRUser()
107
108	body := rec.Body.String()
109	for _, want := range []string{"Favourite animal: <b>skunk</b>", `href="https://social.example/alice"`, "Registration date"} {
110		if !strings.Contains(body, want) {
111			t.Errorf("about page lacks %q:\n%s", want, body)
112		}
113	}
114	if strings.Contains(body, "0001-01-01") {
115		t.Error("registration date is the zero time")
116	}
117}