mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-20 10:00:58 +00:00
3a2f9b48da
* feat(web): add network-only PWA installability Serve the manifest, registration script, network-only service worker, and icons under the runtime web base path so panels remain installable at arbitrary configured URLs. This does not add offline caching or change panel, API, database, or Xray behavior. * chore(docs): remove development planning notes Keep the pull request focused on the PWA implementation, tests, and user-facing verification documentation. * feat(web): adopt the 3X logo PWA icon set from #1865 Replace the two placeholder SVG icons with the six-size PNG set (16/24/32/64/192/512) contributed by @Incognito-Coder in PR #1865. The PNGs have transparent rounded corners, so the manifest entries drop the maskable purpose claim and rely on the default any. --------- Co-authored-by: korsun009 <277924786+korsun009@users.noreply.github.com> Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
package controller
|
|
|
|
import (
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestServePWAAssets(t *testing.T) {
|
|
oldDistFS := distFS
|
|
distFS = fstest.MapFS{
|
|
"dist/manifest.webmanifest": &fstest.MapFile{Data: []byte(`{"name":"3x-ui"}`)},
|
|
"dist/pwa-register.js": &fstest.MapFile{Data: []byte("register")},
|
|
"dist/service-worker.js": &fstest.MapFile{Data: []byte("worker")},
|
|
"dist/icons/3x-ui-192.png": &fstest.MapFile{Data: []byte("icon-192")},
|
|
"dist/icons/3x-ui-512.png": &fstest.MapFile{Data: []byte("icon-512")},
|
|
}
|
|
t.Cleanup(func() { distFS = oldDistFS })
|
|
|
|
tests := []struct {
|
|
name string
|
|
handler gin.HandlerFunc
|
|
contentType string
|
|
body string
|
|
}{
|
|
{name: "manifest", handler: ServePWAManifest, contentType: "application/manifest+json; charset=utf-8", body: `{"name":"3x-ui"}`},
|
|
{name: "registration", handler: ServePWARegister, contentType: "application/javascript; charset=utf-8", body: "register"},
|
|
{name: "worker", handler: ServePWAServiceWorker, contentType: "application/javascript; charset=utf-8", body: "worker"},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
response := httptest.NewRecorder()
|
|
context, _ := gin.CreateTestContext(response)
|
|
test.handler(context)
|
|
|
|
if response.Code != 200 {
|
|
t.Fatalf("status = %d, want 200", response.Code)
|
|
}
|
|
if response.Header().Get("Content-Type") != test.contentType {
|
|
t.Errorf("content type = %q, want %q", response.Header().Get("Content-Type"), test.contentType)
|
|
}
|
|
if response.Header().Get("Cache-Control") != "no-cache, no-store, must-revalidate" {
|
|
t.Errorf("cache control = %q", response.Header().Get("Cache-Control"))
|
|
}
|
|
if strings.TrimSpace(response.Body.String()) != test.body {
|
|
t.Errorf("body = %q, want %q", response.Body.String(), test.body)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestServePWAIconServesPNG(t *testing.T) {
|
|
oldDistFS := distFS
|
|
distFS = fstest.MapFS{
|
|
"dist/icons/3x-ui-192.png": &fstest.MapFile{Data: []byte("icon-192")},
|
|
}
|
|
t.Cleanup(func() { distFS = oldDistFS })
|
|
|
|
gin.SetMode(gin.TestMode)
|
|
response := httptest.NewRecorder()
|
|
context, _ := gin.CreateTestContext(response)
|
|
context.Params = gin.Params{{Key: "name", Value: "3x-ui-192.png"}}
|
|
ServePWAIcon(context)
|
|
|
|
if response.Code != 200 {
|
|
t.Fatalf("status = %d, want 200", response.Code)
|
|
}
|
|
if got := response.Header().Get("Content-Type"); got != "image/png" {
|
|
t.Errorf("content type = %q, want %q", got, "image/png")
|
|
}
|
|
if response.Body.String() != "icon-192" {
|
|
t.Errorf("body = %q, want %q", response.Body.String(), "icon-192")
|
|
}
|
|
}
|
|
|
|
func TestServePWAIconRejectsUnknownName(t *testing.T) {
|
|
oldDistFS := distFS
|
|
distFS = fstest.MapFS{}
|
|
t.Cleanup(func() { distFS = oldDistFS })
|
|
|
|
gin.SetMode(gin.TestMode)
|
|
response := httptest.NewRecorder()
|
|
context, _ := gin.CreateTestContext(response)
|
|
context.Params = gin.Params{{Key: "name", Value: "../../etc/passwd"}}
|
|
ServePWAIcon(context)
|
|
|
|
if response.Code != 404 {
|
|
t.Fatalf("status = %d, want 404", response.Code)
|
|
}
|
|
}
|