package router import ( "net/http" "net/http/httptest" "regexp" "strings" "testing" "vctp/version" ) var externalAssetRefPattern = regexp.MustCompile(`\b(?:src|href)=["']https?://`) func TestHomePageUsesLocalVersionedAssets(t *testing.T) { orig := version.Value version.Value = "1.2.3" defer func() { version.Value = orig }() app := testRouter(t, testRouterSettings(t, false)) req := httptest.NewRequest(http.MethodGet, "/", nil) rr := httptest.NewRecorder() app.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("expected status %d, got %d", http.StatusOK, rr.Code) } body := rr.Body.String() for _, want := range []string{ `href="/favicon.ico?v=1.2.3"`, `href="/favicon-16x16.png?v=1.2.3"`, `href="/favicon-32x32.png?v=1.2.3"`, `src="/assets/js/htmx@v2.0.2.min.js"`, `src="/assets/js/web3-charts.js?v=1.2.3"`, `href="/assets/css/output@1.2.3.css"`, `href="/assets/css/web3.css?v=1.2.3"`, } { if !strings.Contains(body, want) { t.Fatalf("expected response body to contain %q", want) } } if externalAssetRefPattern.MatchString(body) { t.Fatalf("home page contains external asset URL: %s", body) } } func TestSwaggerUIUsesLocalAssetsOnly(t *testing.T) { app := testRouter(t, testRouterSettings(t, false)) req := httptest.NewRequest(http.MethodGet, "/swagger/", nil) rr := httptest.NewRecorder() app.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("expected status %d, got %d", http.StatusOK, rr.Code) } body := rr.Body.String() for _, want := range []string{ `href="./swagger-ui.css"`, `src="./swagger-ui-bundle.js"`, `src="./swagger-ui-standalone-preset.js"`, `src="./swagger-initializer.js"`, } { if !strings.Contains(body, want) { t.Fatalf("expected swagger index to contain %q", want) } } if externalAssetRefPattern.MatchString(body) { t.Fatalf("swagger index contains external asset URL: %s", body) } } func TestStaticResourcesAreCacheableInReleaseMode(t *testing.T) { orig := version.Value version.Value = "1.2.3" defer func() { version.Value = orig }() app := testRouter(t, testRouterSettings(t, false)) tests := []struct { path string wantCacheControl string }{ {path: "/assets/css/web3.css?v=1.2.3", wantCacheControl: "public, max-age=31536000, immutable"}, {path: "/assets/js/htmx@v2.0.2.min.js", wantCacheControl: "public, max-age=31536000, immutable"}, {path: "/favicon.ico?v=1.2.3", wantCacheControl: "public, max-age=31536000, immutable"}, {path: "/swagger/swagger-ui.css", wantCacheControl: "public, max-age=31536000"}, {path: "/swagger.json", wantCacheControl: "public, max-age=31536000"}, } for _, tc := range tests { t.Run(tc.path, func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, tc.path, nil) rr := httptest.NewRecorder() app.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("expected status %d for %s, got %d", http.StatusOK, tc.path, rr.Code) } if got := rr.Header().Get("Cache-Control"); got != tc.wantCacheControl { t.Fatalf("unexpected Cache-Control for %s: got %q want %q", tc.path, got, tc.wantCacheControl) } if got := rr.Header().Get("Vary"); got != "Accept-Encoding" { t.Fatalf("unexpected Vary for %s: %q", tc.path, got) } if rr.Header().Get("Expires") == "" { t.Fatalf("expected Expires for %s", tc.path) } }) } }