From 51ed9e53a4e72ac998c8c762db4a530a52d46e12 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Thu, 28 Nov 2024 21:33:28 +0100 Subject: [PATCH] Implement static handler tests --- .../static_handler_integration_test.go | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 server/internal/handlers/static_handler_integration_test.go diff --git a/server/internal/handlers/static_handler_integration_test.go b/server/internal/handlers/static_handler_integration_test.go new file mode 100644 index 0000000..e6205ec --- /dev/null +++ b/server/internal/handlers/static_handler_integration_test.go @@ -0,0 +1,145 @@ +//go:build integration + +package handlers_test + +import ( + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "novamd/internal/handlers" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestStaticHandler_Integration(t *testing.T) { + // Create temporary directory for test static files + tempDir, err := os.MkdirTemp("", "novamd-static-test-*") + require.NoError(t, err) + defer os.RemoveAll(tempDir) + + // Create test files + files := map[string][]byte{ + "index.html": []byte("Index"), + "assets/style.css": []byte("body { color: blue; }"), + "assets/style.css.gz": []byte("gzipped css content"), + "assets/script.js": []byte("console.log('test');"), + "assets/script.js.gz": []byte("gzipped js content"), + "subdir/page.html": []byte("Page"), + "subdir/page.html.gz": []byte("gzipped html content"), + } + + for path, content := range files { + fullPath := filepath.Join(tempDir, path) + err := os.MkdirAll(filepath.Dir(fullPath), 0755) + require.NoError(t, err) + err = os.WriteFile(fullPath, content, 0644) + require.NoError(t, err) + } + + // Create static handler + handler := handlers.NewStaticHandler(tempDir) + + tests := []struct { + name string + path string + acceptEncoding string + wantStatus int + wantBody []byte + wantType string + wantEncoding string + wantCacheHeader string + }{ + { + name: "serve index.html", + path: "/", + wantStatus: http.StatusOK, + wantBody: []byte("Index"), + wantType: "text/html; charset=utf-8", + }, + { + name: "serve CSS with gzip support", + path: "/assets/style.css", + acceptEncoding: "gzip", + wantStatus: http.StatusOK, + wantBody: []byte("gzipped css content"), + wantType: "text/css", + wantEncoding: "gzip", + wantCacheHeader: "public, max-age=31536000", + }, + { + name: "serve JS with gzip support", + path: "/assets/script.js", + acceptEncoding: "gzip", + wantStatus: http.StatusOK, + wantBody: []byte("gzipped js content"), + wantType: "application/javascript", + wantEncoding: "gzip", + wantCacheHeader: "public, max-age=31536000", + }, + { + name: "serve CSS without gzip", + path: "/assets/style.css", + wantStatus: http.StatusOK, + wantBody: []byte("body { color: blue; }"), + wantType: "text/css; charset=utf-8", + wantCacheHeader: "public, max-age=31536000", + }, + { + name: "SPA routing - nonexistent path", + path: "/nonexistent", + wantStatus: http.StatusOK, + wantBody: []byte("Index"), + wantType: "text/html; charset=utf-8", + }, + { + name: "SPA routing - deep path", + path: "/some/deep/path", + wantStatus: http.StatusOK, + wantBody: []byte("Index"), + wantType: "text/html; charset=utf-8", + }, + { + name: "block directory traversal", + path: "/../../../etc/passwd", + wantStatus: http.StatusBadRequest, + }, + { + name: "nonexistent file in assets", + path: "/assets/nonexistent.js", + wantStatus: http.StatusOK, // Should serve index.html + wantBody: []byte("Index"), + wantType: "text/html; charset=utf-8", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + req := httptest.NewRequest("GET", tc.path, nil) + if tc.acceptEncoding != "" { + req.Header.Set("Accept-Encoding", tc.acceptEncoding) + } + + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + assert.Equal(t, tc.wantStatus, w.Code) + + if tc.wantStatus == http.StatusOK { + assert.Equal(t, tc.wantBody, w.Body.Bytes()) + assert.Equal(t, tc.wantType, w.Header().Get("Content-Type")) + + if tc.wantEncoding != "" { + assert.Equal(t, tc.wantEncoding, w.Header().Get("Content-Encoding")) + } + + if tc.wantCacheHeader != "" { + assert.Equal(t, tc.wantCacheHeader, w.Header().Get("Cache-Control")) + } + } + }) + } +}