Merge branch 'master' into develop

This commit is contained in:
Gani Georgiev 2025-04-20 13:41:44 +03:00
commit 52dcb4192c
1 changed files with 155 additions and 72 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"image"
"image/jpeg"
"image/png"
"io"
"mime/multipart"
@ -14,6 +15,7 @@ import (
"strings"
"testing"
"github.com/gabriel-vasile/mimetype"
"github.com/pocketbase/pocketbase/tools/filesystem"
)
@ -627,7 +629,9 @@ func TestFileSystemList(t *testing.T) {
"",
[]string{
"image.png",
"image.jpg",
"image.svg",
"image.webp",
"image_! noext",
"style.css",
"main.js",
@ -650,25 +654,30 @@ func TestFileSystemList(t *testing.T) {
}
for _, s := range scenarios {
objs, err := fsys.List(s.prefix)
if err != nil {
t.Fatalf("[%s] %v", s.prefix, err)
}
if len(s.expected) != len(objs) {
t.Fatalf("[%s] Expected %d files, got \n%v", s.prefix, len(s.expected), objs)
}
ObjsLoop:
for _, obj := range objs {
for _, name := range s.expected {
if name == obj.Key {
continue ObjsLoop
}
t.Run("prefix_"+s.prefix, func(t *testing.T) {
objs, err := fsys.List(s.prefix)
if err != nil {
t.Fatal(err)
}
t.Fatalf("[%s] Unexpected file %q", s.prefix, obj.Key)
}
if len(s.expected) != len(objs) {
t.Fatalf("Expected %d files, got \n%v", len(s.expected), objs)
}
for _, obj := range objs {
var exists bool
for _, name := range s.expected {
if name == obj.Key {
exists = true
break
}
}
if !exists {
t.Fatalf("Unexpected file %q", obj.Key)
}
}
})
}
}
@ -746,39 +755,67 @@ func TestFileSystemCreateThumb(t *testing.T) {
defer fsys.Close()
scenarios := []struct {
file string
thumb string
cropCenter bool
expectError bool
file string
thumb string
size string
expectedMimeType string
}{
// missing
{"missing.txt", "thumb_test_missing", true, true},
{"missing.txt", "thumb_test_missing", "100x100", ""},
// non-image existing file
{"test/sub1.txt", "thumb_test_sub1", true, true},
// existing image file - crop center
{"image.png", "thumb_file_center", true, false},
// existing image file - crop top
{"image.png", "thumb_file_top", false, false},
{"test/sub1.txt", "thumb_test_sub1", "100x100", ""},
// existing image file with existing thumb path = should fail
{"image.png", "test", true, true},
{"image.png", "test", "100x100", ""},
// existing image file with invalid thumb size
{"image.png", "thumb0", "invalid", ""},
// existing image file with 0xH thumb size
{"image.png", "thumb_0xH", "0x100", "image/png"},
// existing image file with Wx0 thumb size
{"image.png", "thumb_Wx0", "100x0", "image/png"},
// existing image file with WxH thumb size
{"image.png", "thumb_WxH", "100x100", "image/png"},
// existing image file with WxHt thumb size
{"image.png", "thumb_WxHt", "100x100t", "image/png"},
// existing image file with WxHb thumb size
{"image.png", "thumb_WxHb", "100x100b", "image/png"},
// existing image file with WxHf thumb size
{"image.png", "thumb_WxHf", "100x100f", "image/png"},
// jpg
{"image.jpg", "thumb.jpg", "100x100", "image/jpeg"},
// webp (should produce png)
{"image.webp", "thumb.webp", "100x100", "image/png"},
}
for i, scenario := range scenarios {
err := fsys.CreateThumb(scenario.file, scenario.thumb, "100x100")
for _, s := range scenarios {
t.Run(s.file+"_"+s.thumb+"_"+s.size, func(t *testing.T) {
err := fsys.CreateThumb(s.file, s.thumb, s.size)
hasErr := err != nil
if hasErr != scenario.expectError {
t.Errorf("(%d) Expected hasErr to be %v, got %v (%v)", i, scenario.expectError, hasErr, err)
continue
}
expectErr := s.expectedMimeType == ""
if scenario.expectError {
continue
}
hasErr := err != nil
if hasErr != expectErr {
t.Fatalf("Expected hasErr to be %v, got %v (%v)", expectErr, hasErr, err)
}
if exists, _ := fsys.Exists(scenario.thumb); !exists {
t.Errorf("(%d) Couldn't find %q thumb", i, scenario.thumb)
}
if hasErr {
return
}
f, err := fsys.GetFile(s.thumb)
if err != nil {
t.Fatalf("Missing expected thumb %s (%v)", s.thumb, err)
}
defer f.Close()
mt, err := mimetype.DetectReader(f)
if err != nil {
t.Fatalf("Failed to detect thumb %s mimetype (%v)", s.thumb, err)
}
if mtStr := mt.String(); mtStr != s.expectedMimeType {
t.Fatalf("Expected thumb %s MimeType %q, got %q", s.thumb, s.expectedMimeType, mtStr)
}
})
}
}
@ -810,48 +847,94 @@ func createTestDir(t *testing.T) string {
t.Fatal(err)
}
file3, err := os.OpenFile(filepath.Join(dir, "image.png"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
imgRect := image.Rect(0, 0, 1, 1) // tiny 1x1 png
png.Encode(file3, imgRect)
file3.Close()
err2 := os.WriteFile(filepath.Join(dir, "image.png.attrs"), []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/png","user.metadata":null}`), 0644)
if err2 != nil {
t.Fatal(err2)
// png
{
file, err := os.OpenFile(filepath.Join(dir, "image.png"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
imgRect := image.Rect(0, 0, 1, 1) // tiny 1x1 png
_ = png.Encode(file, imgRect)
file.Close()
err = os.WriteFile(filepath.Join(dir, "image.png.attrs"), []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/png","user.metadata":null}`), 0644)
if err != nil {
t.Fatal(err)
}
}
file4, err := os.OpenFile(filepath.Join(dir, "image.svg"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
// jpg
{
file, err := os.OpenFile(filepath.Join(dir, "image.jpg"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
imgRect := image.Rect(0, 0, 1, 1) // tiny 1x1 jpg
_ = jpeg.Encode(file, imgRect, nil)
file.Close()
err = os.WriteFile(filepath.Join(dir, "image.jpg.attrs"), []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/jpeg","user.metadata":null}`), 0644)
if err != nil {
t.Fatal(err)
}
}
file4.Close()
file5, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
// svg
{
file, err := os.OpenFile(filepath.Join(dir, "image.svg"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
file.Close()
}
file5.Close()
file6, err := os.OpenFile(filepath.Join(dir, "main.js"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
// webp
{
err := os.WriteFile(filepath.Join(dir, "image.webp"), []byte{
82, 73, 70, 70, 36, 0, 0, 0, 87, 69, 66, 80, 86, 80, 56, 32,
24, 0, 0, 0, 48, 1, 0, 157, 1, 42, 1, 0, 1, 0, 2, 0, 52, 37,
164, 0, 3, 112, 0, 254, 251, 253, 80, 0,
}, 0644)
if err != nil {
t.Fatal(err)
}
}
file6.Close()
file7, err := os.OpenFile(filepath.Join(dir, "main.mjs"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
// no extension and invalid characters
{
file, err := os.OpenFile(filepath.Join(dir, "image_! noext"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
_ = png.Encode(file, image.Rect(0, 0, 1, 1)) // tiny 1x1 png
file.Close()
}
file7.Close()
file8, err := os.OpenFile(filepath.Join(dir, "image_! noext"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
// css
{
file, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
file.Close()
}
// js
{
file, err := os.OpenFile(filepath.Join(dir, "main.js"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
file.Close()
}
// mjs
{
file, err := os.OpenFile(filepath.Join(dir, "main.mjs"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
file.Close()
}
png.Encode(file8, image.Rect(0, 0, 1, 1)) // tiny 1x1 png
file8.Close()
return dir
}