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) } }) } }