feat(API): media library
This commit is contained in:
1 parent
95ae043d3e
commit
0d99544579
65 files changed
+3992
-1530
No files matched your search
@@ -0,0 +1,160 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"RenewCMS/api"
|
||||
validator "RenewCMS/api/pkg/validator"
|
||||
domainArticle "RenewCMS/internal/domain/article"
|
||||
domainImage "RenewCMS/internal/domain/image"
|
||||
"RenewCMS/internal/domain/user"
|
||||
"RenewCMS/internal/infrastructure/config"
|
||||
"RenewCMS/internal/infrastructure/useCases"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
mediaVerifiedUserId uint32 = 1
|
||||
mediaSecondUserId uint32 = 2
|
||||
mediaUnverifiedUserId uint32 = 3
|
||||
mediaStaleUserId uint32 = 4
|
||||
)
|
||||
|
||||
type mediaEnv struct {
|
||||
articles *mockArticleRepo
|
||||
images *mockImageRepo
|
||||
users *mockUserRepo
|
||||
token *jwtauth.JWTAuth
|
||||
router http.Handler
|
||||
}
|
||||
|
||||
func newMediaEnv(t *testing.T) *mediaEnv {
|
||||
t.Helper()
|
||||
validator.InitValidator()
|
||||
|
||||
env := &mediaEnv{
|
||||
articles: newMockArticleRepo(),
|
||||
images: newMockImageRepo(),
|
||||
users: newMockUserRepo(),
|
||||
token: jwtauth.New("HS256", []byte("test-secret"), nil),
|
||||
}
|
||||
env.users.users[mediaVerifiedUserId] = user.User{ID: 1, Username: "ines", DisplayName: "Inès Duarte", IsVerified: true}
|
||||
env.users.users[mediaSecondUserId] = user.User{ID: 2, Username: "marta", IsVerified: true}
|
||||
env.users.users[mediaUnverifiedUserId] = user.User{ID: 3, Username: "pending", IsVerified: false}
|
||||
env.users.users[mediaStaleUserId] = user.User{ID: 4, Username: "stale", IsVerified: true, TokenVersion: 1}
|
||||
|
||||
container := &api.UseCases{
|
||||
Token: env.token,
|
||||
CreateArticleUseCase: useCases.NewCreateArticleUseCase(env.articles),
|
||||
GetArticleUseCase: useCases.NewGetArticleUseCase(env.articles),
|
||||
ListArticlesUseCase: useCases.NewListArticlesUseCase(env.articles),
|
||||
UpdateArticleUseCase: useCases.NewUpdateArticleUseCase(env.articles),
|
||||
DeleteArticleUseCase: useCases.NewDeleteArticleUseCase(env.articles),
|
||||
GetUserUseCase: useCases.NewGetUserUseCase(env.users),
|
||||
CreateImageUseCase: useCases.NewCreateImageUseCase(env.images),
|
||||
ListMediaUseCase: useCases.NewListMediaUseCase(env.images, env.articles, env.users),
|
||||
RenameMediaUseCase: useCases.NewRenameMediaUseCase(env.images),
|
||||
DeleteMediaUseCase: useCases.NewDeleteMediaUseCase(env.images),
|
||||
MergeMediaUseCase: useCases.NewMergeMediaUseCase(env.images, env.articles),
|
||||
GetMediaUsageUseCase: useCases.NewGetMediaUsageUseCase(env.images, env.articles),
|
||||
}
|
||||
router := chi.NewRouter()
|
||||
router.Mount("/v1", api.InitBackendRoutes(container, config.Settings{}))
|
||||
env.router = router
|
||||
return env
|
||||
}
|
||||
|
||||
func (e *mediaEnv) cookie(t *testing.T, userId uint32, tokenVersion uint32) *http.Cookie {
|
||||
t.Helper()
|
||||
_, tokenString, err := e.token.Encode(map[string]any{"user_id": userId, "token_version": tokenVersion})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to encode jwt: %v", err)
|
||||
}
|
||||
return &http.Cookie{Name: "jwt", Value: tokenString}
|
||||
}
|
||||
|
||||
func (e *mediaEnv) serve(t *testing.T, req *http.Request, userId uint32) *httptest.ResponseRecorder {
|
||||
t.Helper()
|
||||
if userId != 0 {
|
||||
req.AddCookie(e.cookie(t, userId, 0))
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
e.router.ServeHTTP(rec, req)
|
||||
return rec
|
||||
}
|
||||
|
||||
func (e *mediaEnv) send(t *testing.T, method string, path string, body string, userId uint32) *httptest.ResponseRecorder {
|
||||
t.Helper()
|
||||
req := httptest.NewRequest(method, path, strings.NewReader(body))
|
||||
if body != "" {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
return e.serve(t, req, userId)
|
||||
}
|
||||
|
||||
func (e *mediaEnv) seedImage(id uint32, filename string, size int64, contentType string, width int, height int, hash string, uploadedBy uint32) {
|
||||
extension := map[string]string{"image/jpeg": ".jpeg", "image/svg+xml": ".svg", "image/png": ".png"}[contentType]
|
||||
e.images.images[id] = domainImage.Image{
|
||||
ID: id,
|
||||
Path: "/static/uploadedImages/img-" + strconv.Itoa(int(id)) + "-" + extension,
|
||||
Filename: filename,
|
||||
Size: size,
|
||||
ContentType: contentType,
|
||||
Width: width,
|
||||
Height: height,
|
||||
SHA256: hash,
|
||||
UploadedByID: uploadedBy,
|
||||
CreatedAt: mockImageEpoch.Add(time.Duration(id) * time.Minute),
|
||||
}
|
||||
if id > e.images.nextID {
|
||||
e.images.nextID = id
|
||||
}
|
||||
}
|
||||
|
||||
func (e *mediaEnv) urlOf(id uint32) string {
|
||||
return e.images.images[id].Path
|
||||
}
|
||||
|
||||
func (e *mediaEnv) seedArticle(id uint32, title string, online bool, body string) {
|
||||
e.articles.articles[id] = domainArticle.Article{ID: id, Title: title, IsOnline: online, Body: body}
|
||||
if id > e.articles.nextID {
|
||||
e.articles.nextID = id
|
||||
}
|
||||
}
|
||||
|
||||
func (e *mediaEnv) bodies() map[uint32]string {
|
||||
result := map[uint32]string{}
|
||||
for id, a := range e.articles.articles {
|
||||
result[id] = a.Body
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *mediaEnv) imageIds() []uint32 {
|
||||
ids := make([]uint32, 0)
|
||||
for _, img := range e.images.sortedImages() {
|
||||
ids = append(ids, img.ID)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func decodeObject(t *testing.T, body string) map[string]any {
|
||||
t.Helper()
|
||||
var decoded map[string]any
|
||||
if err := json.Unmarshal([]byte(body), &decoded); err != nil {
|
||||
t.Fatalf("failed to decode %q: %v", body, err)
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
func numberOf(value any) uint32 {
|
||||
number, _ := value.(float64)
|
||||
return uint32(number)
|
||||
}
|
||||
Reference in new issue
Block a user