Initial commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-09-29 11:47:47 +07:00
co-authored by Claude Opus 5.5
commit 0fbdba5ccf
622 changed files with 72105 additions and 0 deletions
+176
View File
@@ -0,0 +1,176 @@
package web
import (
"net/http"
"net/http/httptest"
"testing"
"videoweb/app/service/configser"
"videoweb/app/service/playletser"
"github.com/gin-gonic/gin"
)
func TestAttachPageSEOUsesPageTypeInsteadOfRequestDomain(t *testing.T) {
gin.SetMode(gin.TestMode)
tests := []struct {
name string
requestURL string
foreverURL string
status int
data gin.H
wantRobots string
wantRobotsHeader string
wantCanonical string
wantJSONLD bool
}{
{
name: "public page on alternate domain remains indexable",
requestURL: "https://alternate.example/",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{},
wantRobots: "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1",
wantCanonical: "https://primary.example/",
wantJSONLD: true,
},
{
name: "public page without permanent address remains indexable",
requestURL: "https://alternate.example/about",
status: http.StatusOK,
data: gin.H{},
wantRobots: "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1",
wantCanonical: "https://alternate.example/about",
wantJSONLD: true,
},
{
name: "search page is not indexable",
requestURL: "https://alternate.example/search/short-drama",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
{
name: "private page is neither indexed nor followed",
requestURL: "https://alternate.example/profile",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{},
wantRobots: "noindex,nofollow",
wantRobotsHeader: "noindex, nofollow",
},
{
name: "navigation page is not indexable",
requestURL: "https://alternate.example/",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{"isNavPage": true},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
{
name: "missing public entity is not indexable",
requestURL: "https://alternate.example/tags/missing",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{"seoEntityValid": false},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
{
name: "error page is not indexable",
requestURL: "https://alternate.example/about",
foreverURL: "https://primary.example",
status: http.StatusNotFound,
data: gin.H{},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
{
name: "canonical play page stays indexable",
requestURL: "https://alternate.example/play/zhuazou",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{},
wantRobots: "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1",
wantCanonical: "https://primary.example/play/zhuazou",
wantJSONLD: true,
},
{
name: "play page with chapter still canonicalizes to two-segment path",
requestURL: "https://alternate.example/play/zhuazou",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{
"playlet": playletser.PlayletInfoResp{ID: 12, Slug: "zhuazou"},
"chapter": playletser.PlayletChapterInfoResp{ID: 901, PlayletID: 12},
},
wantRobots: "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1",
wantCanonical: "https://primary.example/play/zhuazou",
wantJSONLD: true,
},
{
name: "episode play page is not indexable",
requestURL: "https://alternate.example/play/zhuazou/12",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
{
name: "unwatchable series play page is not indexable",
requestURL: "https://alternate.example/series-play/film-1",
foreverURL: "https://primary.example",
status: http.StatusOK,
data: gin.H{"canWatch": false},
wantRobots: "noindex,follow",
wantRobotsHeader: "noindex, follow",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
response := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(response)
ctx.Request = httptest.NewRequest(http.MethodGet, tt.requestURL, nil)
data := gin.H{
"appConfig": configser.AppConfigVM{
ForeverURLAddr: tt.foreverURL,
},
}
for key, value := range tt.data {
data[key] = value
}
attachPageSEO(ctx, tt.status, data)
if got := data["robots"]; got != tt.wantRobots {
t.Fatalf("robots = %q, want %q", got, tt.wantRobots)
}
if got := response.Header().Get("X-Robots-Tag"); got != tt.wantRobotsHeader {
t.Fatalf("X-Robots-Tag = %q, want %q", got, tt.wantRobotsHeader)
}
canonicalValue, hasCanonical := data["canonicalURL"]
if tt.wantCanonical == "" {
if hasCanonical {
t.Fatalf("canonicalURL must be absent, got %#v", canonicalValue)
}
} else {
canonical, ok := canonicalValue.(string)
if !hasCanonical || !ok || canonical != tt.wantCanonical {
t.Fatalf("canonicalURL = %#v, want %q", canonicalValue, tt.wantCanonical)
}
}
jsonLD, hasJSONLD := data["jsonLD"]
if hasJSONLD != tt.wantJSONLD {
t.Fatalf("jsonLD presence = %v, want %v (value %#v)", hasJSONLD, tt.wantJSONLD, jsonLD)
}
})
}
}