github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/webapp/web/routes_test.go (about) 1 // +build small 2 3 // Copyright 2017 The WPT Dashboard Project. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 package main 8 9 import ( 10 "fmt" 11 "net/http" 12 "net/http/httptest" 13 "testing" 14 15 "github.com/gorilla/mux" 16 "github.com/stretchr/testify/assert" 17 "github.com/web-platform-tests/wpt.fyi/shared" 18 ) 19 20 func TestLandingPageBound(t *testing.T) { 21 // Note that init() is always called by the Golang runtime. 22 assertHandlerIs(t, "/", "results-legacy") 23 assertHSTS(t, "/") 24 assertHandlerIs(t, "/2dcontext", "results-legacy") 25 assertHandlerIs(t, "/BackgroundSync/interfaces.any.html", "results-legacy") 26 } 27 28 func TestAboutBound(t *testing.T) { 29 assertHandlerIs(t, "/about", "about") 30 } 31 32 func TestAnalyzerBound(t *testing.T) { 33 assertHandlerIs(t, "/analyzer", "analyzer") 34 } 35 36 func TestFlagsBound(t *testing.T) { 37 assertHandlerIs(t, "/flags", "flags") 38 } 39 40 func TestRunsBound(t *testing.T) { 41 assertHandlerIs(t, "/test-runs", "test-runs") 42 } 43 44 func TestApiDiffBound(t *testing.T) { 45 assertHandlerIs(t, "/api/diff", "api-diff") 46 } 47 48 func TestApiManifestBound(t *testing.T) { 49 assertHandlerIs(t, "/api/manifest", "api-manifest") 50 } 51 52 func TestApiRunsBound(t *testing.T) { 53 assertHandlerIs(t, "/api/runs", "api-test-runs") 54 } 55 56 func TestApiShasBound(t *testing.T) { 57 assertHandlerIs(t, "/api/shas", "api-shas") 58 } 59 60 func TestApiRunBound(t *testing.T) { 61 assertHandlerIs(t, "/api/run", "api-test-run") 62 assertHandlerIs(t, "/api/runs/123", "api-test-run") 63 } 64 65 func TestApiStatusBound(t *testing.T) { 66 assertHandlerIs(t, "/api/status", "api-pending-test-runs") 67 assertHandlerIs(t, "/api/status/pending", "api-pending-test-runs") 68 assertHandlerIs(t, "/api/status/invalid", "api-pending-test-runs") 69 assertHandlerIs(t, "/api/status/123", "api-pending-test-run-update") 70 assertHandlerIsDefault(t, "/api/status/notavalidfilter") 71 } 72 73 func TestApiResultsBoundCORS(t *testing.T) { 74 assertHandlerIs(t, "/api/results", "api-results") 75 assertHSTS(t, "/api/results/upload") 76 assertCORS(t, "/api/results") 77 } 78 79 func TestApiScreenshotBoundCORS(t *testing.T) { 80 assertHandlerIs(t, "/api/screenshot/sha1:abc", "api-screenshot") 81 assertHSTS(t, "/api/screenshot/sha1:abc") 82 assertCORS(t, "/api/screenshot/sha1:abc") 83 } 84 85 func TestApiResultsUploadBoundHSTS(t *testing.T) { 86 assertHandlerIs(t, "/api/results/upload", "api-results-upload") 87 assertHSTS(t, "/api/results/upload") 88 assertNoCORS(t, "/api/results/upload") 89 } 90 91 func TestApiResultsCreateBoundHSTS(t *testing.T) { 92 assertHandlerIs(t, "/api/results/create", "api-results-create") 93 assertHSTS(t, "/api/results/create") 94 assertNoCORS(t, "/api/results/create") 95 } 96 97 func TestResultsBound(t *testing.T) { 98 assertHandlerIs(t, "/results", "results") 99 assertHandlerIs(t, "/results/", "results") 100 assertHandlerIs(t, "/results/2dcontext", "results") 101 assertHandlerIs(t, "/results/BackgroundSync/interfaces.any.html", "results") 102 } 103 104 func TestAdminResultsUploadBound(t *testing.T) { 105 assertHandlerIs(t, "/admin/results/upload", "admin-results-upload") 106 } 107 108 func TestAdminCacheFlushBound(t *testing.T) { 109 assertHandlerIs(t, "/admin/cache/flush", "admin-cache-flush") 110 } 111 112 func TestApiMetadataCORS(t *testing.T) { 113 // TODO(kyleju): Test CORS for POST/GET request. 114 assertHandlerIs(t, "/api/metadata", "api-metadata") 115 successPost := httptest.NewRequest("OPTIONS", "/api/metadata", nil) 116 successPost.Header.Set("Access-Control-Request-Headers", "content-type") 117 successPost.Header.Add("Origin", "https://jgraham.github.io") 118 successPost.Header.Add("Access-Control-Request-Method", "POST") 119 120 rr := sendHttptestRequest(successPost) 121 122 assert.Equal(t, http.StatusOK, rr.StatusCode) 123 assert.Equal(t, "Content-Type", rr.Header.Get("Access-Control-Allow-Headers")) 124 assert.Equal(t, "*", rr.Header.Get("Access-Control-Allow-Origin")) 125 assert.Equal(t, "", rr.Header.Get("Access-Control-Allow-Credentials")) 126 } 127 128 func TestApiMetadataTriageCORS(t *testing.T) { 129 // TODO(kyleju): Test CORS for PATCH request. 130 assertHandlerIs(t, "/api/metadata/triage", "api-metadata-triage") 131 132 successReq := httptest.NewRequest("OPTIONS", "/api/metadata/triage", nil) 133 successReq.Header.Set("Access-Control-Request-Headers", "content-type") 134 successReq.Header.Add("Origin", "https://jgraham.github.io") 135 successReq.Header.Add("Access-Control-Request-Method", "PATCH") 136 137 rr := sendHttptestRequest(successReq) 138 139 assert.Equal(t, http.StatusOK, rr.StatusCode) 140 assert.Equal(t, "Content-Type", rr.Header.Get("Access-Control-Allow-Headers")) 141 assert.Equal(t, "PATCH", rr.Header.Get("Access-Control-Allow-Methods")) 142 assert.Equal(t, "https://jgraham.github.io", rr.Header.Get("Access-Control-Allow-Origin")) 143 assert.Equal(t, "true", rr.Header.Get("Access-Control-Allow-Credentials")) 144 145 invalidOriginReq := httptest.NewRequest("OPTIONS", "/api/metadata/triage", nil) 146 invalidOriginReq.Header.Add("Origin", "https://foo") 147 148 rr = sendHttptestRequest(invalidOriginReq) 149 150 assert.Equal(t, "", rr.Header.Get("Access-Control-Allow-Origin")) 151 152 invalidMethodReq := httptest.NewRequest("OPTIONS", "/api/metadata/triage", nil) 153 invalidMethodReq.Header.Set("Access-Control-Request-Headers", "content-type") 154 invalidMethodReq.Header.Add("Origin", "https://jgraham.github.io") 155 invalidMethodReq.Header.Add("Access-Control-Request-Method", "POST") 156 157 rr = sendHttptestRequest(invalidMethodReq) 158 159 assert.Equal(t, http.StatusMethodNotAllowed, rr.StatusCode) 160 } 161 162 func TestApiBSFBound(t *testing.T) { 163 assertHandlerIs(t, "/api/bsf", "api-bsf") 164 assertHSTS(t, "/api/bsf") 165 } 166 167 func TestApiPendingMetadataBound(t *testing.T) { 168 assertHandlerIs(t, "/api/metadata/pending", "api-pending-metadata") 169 assertHSTS(t, "/api/metadata/pending") 170 } 171 172 func assertBound(t *testing.T, path string) mux.RouteMatch { 173 req := httptest.NewRequest("GET", path, nil) 174 router := shared.Router() 175 match := mux.RouteMatch{} 176 assert.Truef(t, router.Match(req, &match), "%s should match a route", path) 177 return match 178 } 179 180 func assertHandlerIs(t *testing.T, path string, name string) { 181 match := assertBound(t, path) 182 if match.Route != nil { 183 assert.Equal(t, name, match.Route.GetName()) 184 } 185 } 186 187 func assertHSTS(t *testing.T, path string) { 188 req := httptest.NewRequest("GET", path, nil) 189 rr := httptest.NewRecorder() 190 handler, _ := http.DefaultServeMux.Handler(req) 191 handler.ServeHTTP(rr, req) 192 res := rr.Result() 193 assert.Equal( 194 t, 195 "[max-age=31536000; preload]", 196 fmt.Sprintf("%s", res.Header["Strict-Transport-Security"])) 197 } 198 199 func sendHttptestRequest(req *http.Request) *http.Response { 200 rr := httptest.NewRecorder() 201 handler, _ := http.DefaultServeMux.Handler(req) 202 handler.ServeHTTP(rr, req) 203 return rr.Result() 204 } 205 206 func assertCORS(t *testing.T, path string) { 207 req := httptest.NewRequest("OPTIONS", path, nil) 208 req.Header.Set("Access-Control-Request-Headers", "content-type") 209 rr := httptest.NewRecorder() 210 handler, _ := http.DefaultServeMux.Handler(req) 211 handler.ServeHTTP(rr, req) 212 assert.Equal(t, http.StatusOK, rr.Result().StatusCode) 213 214 req = httptest.NewRequest("GET", path, nil) 215 req.Header.Add("Origin", "localhost:8080") 216 rr = httptest.NewRecorder() 217 handler, _ = http.DefaultServeMux.Handler(req) 218 handler.ServeHTTP(rr, req) 219 res := rr.Result() 220 assert.Equal( 221 t, 222 "*", 223 res.Header.Get("Access-Control-Allow-Origin")) 224 } 225 226 func assertNoCORS(t *testing.T, path string) { 227 req := httptest.NewRequest("GET", path, nil) 228 rr := httptest.NewRecorder() 229 handler, _ := http.DefaultServeMux.Handler(req) 230 handler.ServeHTTP(rr, req) 231 res := rr.Result() 232 assert.Equal(t, "", res.Header.Get("Access-Control-Allow-Origin")) 233 } 234 235 func assertHandlerIsDefault(t *testing.T, path string) { 236 assertHandlerIs(t, path, "results-legacy") 237 }