59 lines
1.7 KiB
Go
59 lines
1.7 KiB
Go
package httputil
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/gob"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type quote struct{ Author, Text string }
|
|
|
|
// With no transport installed we are not on the client, so the fetch must not
|
|
// happen and the callback must not fire — that is what leaves an SSR'd page in
|
|
// its loading state (spinner/skeleton) rather than rendering a fetch error the
|
|
// server had no way to avoid.
|
|
func TestFetchWithoutTransportDoesNotCallBack(t *testing.T) {
|
|
defer SetClientTransport(nil)
|
|
SetClientTransport(nil)
|
|
|
|
called := make(chan error, 1)
|
|
FetchGob("/api/quotes", func(_ []quote, err error) { called <- err })
|
|
FetchJSON("/api/quotes", func(_ []quote, err error) { called <- err })
|
|
|
|
select {
|
|
case err := <-called:
|
|
t.Fatalf("callback ran with no transport installed (err=%v); SSR would render an error instead of the loading state", err)
|
|
case <-time.After(50 * time.Millisecond):
|
|
}
|
|
}
|
|
|
|
// The client path is unchanged: with a transport installed the body is fetched
|
|
// and decoded into the same Go type the server encoded.
|
|
func TestFetchGobWithTransport(t *testing.T) {
|
|
defer SetClientTransport(nil)
|
|
want := []quote{{Author: "Rob Pike", Text: "When in doubt, use brute force."}}
|
|
var buf bytes.Buffer
|
|
if err := gob.NewEncoder(&buf).Encode(want); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
SetClientTransport(func(string) ([]byte, error) { return buf.Bytes(), nil })
|
|
|
|
got := make(chan []quote, 1)
|
|
FetchGob("/api/quotes", func(qs []quote, err error) {
|
|
if err != nil {
|
|
t.Errorf("FetchGob: %v", err)
|
|
}
|
|
got <- qs
|
|
})
|
|
|
|
select {
|
|
case qs := <-got:
|
|
if len(qs) != 1 || qs[0] != want[0] {
|
|
t.Fatalf("decoded %v, want %v", qs, want)
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("FetchGob callback never ran")
|
|
}
|
|
}
|