Files
cmroubao/backend-api/internal/platform/shunyunbao/image_test.go
T

191 lines
4.4 KiB
Go

package shunyunbao
import (
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"cmroubao/backend-api/internal/domain"
)
func TestSessionManagerFetchProductImageUsesFixedAuthenticatedEndpoint(
t *testing.T,
) {
var requestPath, rawQuery, accept string
manager, closeServer := imageSessionManager(
t,
func(writer http.ResponseWriter, request *http.Request) {
requestPath = request.URL.Path
rawQuery = request.URL.RawQuery
accept = request.Header.Get("Accept")
if cookie, err := request.Cookie("authenticated"); err != nil ||
cookie.Value != "yes" {
t.Fatalf("image cookie = %v, %v", cookie, err)
}
writer.Header().Set("Content-Type", "image/png")
writer.Header().Set("Content-Length", "4")
_, _ = writer.Write([]byte("png!"))
},
)
defer closeServer()
image, err := manager.FetchProductImage(context.Background(), "190")
if err != nil {
t.Fatalf("FetchProductImage() error = %v", err)
}
defer image.Content.Close()
content, err := io.ReadAll(image.Content)
if err != nil {
t.Fatalf("read image: %v", err)
}
if requestPath != ProductImagePath || rawQuery != "id=190" ||
image.MediaType != "image/png" || string(content) != "png!" ||
!strings.Contains(accept, "image/jpeg") {
t.Fatalf(
"image request/result = %q / %q / %q / %q / %q",
requestPath,
rawQuery,
accept,
image.MediaType,
content,
)
}
}
func TestSessionManagerFetchProductImageClassifiesFailures(t *testing.T) {
manager, closeServer := imageSessionManager(
t,
func(writer http.ResponseWriter, request *http.Request) {
switch request.URL.Query().Get("id") {
case "190":
writer.WriteHeader(http.StatusNotFound)
case "191":
writer.Header().Set("Content-Type", "application/json")
_, _ = writer.Write([]byte(`{"status":false}`))
case "192":
writer.Header().Set("Location", ProductImagePath+"?id=190")
writer.WriteHeader(http.StatusFound)
case "193":
writer.Header().Set(
"Content-Type",
"image/jpeg",
)
writer.Header().Set(
"Content-Length",
"20971521",
)
default:
writer.WriteHeader(http.StatusUnauthorized)
}
},
)
defer closeServer()
tests := []struct {
ref string
want error
}{
{"190", domain.ErrFreightImageNotFound},
{"191", domain.ErrFreightImageInvalid},
{"192", domain.ErrFreightSourceUnavailable},
{"193", domain.ErrFreightImageInvalid},
{"194", domain.ErrFreightSourceSessionNeeded},
}
for _, test := range tests {
image, err := manager.FetchProductImage(
context.Background(),
test.ref,
)
if image.Content != nil {
image.Content.Close()
}
if !errors.Is(err, test.want) {
t.Fatalf("FetchProductImage(%q) error = %v", test.ref, err)
}
}
if _, err := manager.FetchProductImage(
context.Background(),
"195",
); !errors.Is(err, domain.ErrFreightSourceSessionNeeded) {
t.Fatalf("request after unauthorized error = %v", err)
}
}
func TestSessionManagerFetchProductImageRejectsUntrustedReferences(
t *testing.T,
) {
manager := testSessionManager(t, "http://127.0.0.1:1", "user", "password")
for _, value := range []string{
"",
"0",
"0190",
"-1",
"1.5",
"https://invalid.example/image",
} {
if _, err := manager.FetchProductImage(
context.Background(),
value,
); !errors.Is(err, domain.ErrFreightImageInvalid) {
t.Fatalf("FetchProductImage(%q) error = %v", value, err)
}
}
}
func imageSessionManager(
t *testing.T,
imageHandler http.HandlerFunc,
) (*SessionManager, func()) {
t.Helper()
server := httptest.NewServer(http.HandlerFunc(func(
writer http.ResponseWriter,
request *http.Request,
) {
switch request.URL.Path {
case CaptchaPath:
http.SetCookie(
writer,
&http.Cookie{Name: "captcha", Value: "ready", Path: "/"},
)
writer.Header().Set("Content-Type", "image/png")
_, _ = writer.Write([]byte("captcha"))
case LoginPath:
http.SetCookie(
writer,
&http.Cookie{
Name: "authenticated",
Value: "yes",
Path: "/",
},
)
_, _ = writer.Write(
[]byte(
`{"status":true,"data":{"user":{"id":1,"username":"test-user"}}}`,
),
)
case UserPath:
_, _ = writer.Write(
[]byte(
`{"status":true,"data":{"id":1,"username":"test-user"}}`,
),
)
case ProductImagePath:
imageHandler(writer, request)
default:
writer.WriteHeader(http.StatusNotFound)
}
}))
manager := testSessionManager(
t,
server.URL,
"test-user",
"test-password",
)
loginForSource(t, manager)
return manager, server.Close
}