test improvements and some refactor
This commit is contained in:
parent
774d1d28a0
commit
eb9c8d955c
17
ron.go
17
ron.go
@ -43,10 +43,12 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
contentType string = "Content-Type"
|
ContentType string = "Content-Type"
|
||||||
headerJSON string = "application/json"
|
HeaderJSON string = "application/json"
|
||||||
headerHTML_UTF8 string = "text/html; charset=utf-8"
|
HeaderHTML_UTF8 string = "text/html; charset=utf-8"
|
||||||
headerPlain_UTF8 string = "text/plain; charset=utf-8"
|
HeaderCSS_UTF8 string = "text/css; charset=utf-8"
|
||||||
|
HeaderJS_UTF8 string = "text/javascript; charset=utf-8"
|
||||||
|
HeaderPlain_UTF8 string = "text/plain; charset=utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultEngine() *Engine {
|
func defaultEngine() *Engine {
|
||||||
@ -166,9 +168,14 @@ func (e *Engine) Static(path, dir string) {
|
|||||||
dir = "./" + dir
|
dir = "./" + dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
slog.Error("static directory does not exist", "path", path, "dir", dir)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
fs := http.FileServer(http.Dir(dir))
|
fs := http.FileServer(http.Dir(dir))
|
||||||
e.mux.Handle(path, http.StripPrefix(path, fs))
|
e.mux.Handle(path, http.StripPrefix(path, fs))
|
||||||
slog.Info("Static files served", "path", path, "dir", dir)
|
slog.Info("static files served", "path", path, "dir", dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) JSON(code int, data any) {
|
func (c *Context) JSON(code int, data any) {
|
||||||
|
|||||||
166
ron_test.go
166
ron_test.go
@ -1,10 +1,12 @@
|
|||||||
package ron
|
package ron
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
"ron/testhelpers"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,9 +16,20 @@ func TestMain(m *testing.M) {
|
|||||||
f.WriteString("<h1>{{.Data.heading1}}</h1><h2>{{.Data.heading2}}</h2>")
|
f.WriteString("<h1>{{.Data.heading1}}</h1><h2>{{.Data.heading2}}</h2>")
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
|
os.Mkdir("assets", os.ModePerm)
|
||||||
|
f, _ = os.Create("assets/style.css")
|
||||||
|
f.WriteString("body { background-color: red; }")
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
f, _ = os.Create("assets/script.js")
|
||||||
|
f.WriteString("console.log('Hello, World!');")
|
||||||
|
f.Close()
|
||||||
|
|
||||||
code := m.Run()
|
code := m.Run()
|
||||||
|
|
||||||
os.RemoveAll("templates")
|
os.RemoveAll("templates")
|
||||||
|
os.RemoveAll("assets")
|
||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,21 +289,56 @@ func Test_GROUPPOST(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_Static(t *testing.T) {
|
func Test_Static(t *testing.T) {
|
||||||
os.Mkdir("assets", os.ModePerm)
|
tests := map[string]struct {
|
||||||
f, _ := os.Create("assets/style.css")
|
givenPath string
|
||||||
f.WriteString("body { background-color: red; }")
|
givenFile string
|
||||||
f.Close()
|
givenDirectory string
|
||||||
defer os.RemoveAll("assets")
|
expectedResponse testhelpers.ExpectedResponse
|
||||||
|
}{
|
||||||
|
"valid css path": {
|
||||||
|
givenPath: "assets",
|
||||||
|
givenFile: "style.css",
|
||||||
|
givenDirectory: "assets",
|
||||||
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
Header: HeaderCSS_UTF8,
|
||||||
|
Body: "body { background-color: red; }",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"valid js path": {
|
||||||
|
givenPath: "assets",
|
||||||
|
givenFile: "script.js",
|
||||||
|
givenDirectory: "assets",
|
||||||
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
Header: HeaderJS_UTF8,
|
||||||
|
Body: "console.log('Hello, World!');",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid path": {
|
||||||
|
givenPath: "assets",
|
||||||
|
givenFile: "nonexistent.css",
|
||||||
|
givenDirectory: "assets",
|
||||||
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
|
Code: http.StatusNotFound,
|
||||||
|
Header: HeaderPlain_UTF8,
|
||||||
|
Body: "404 page not found\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
e := New()
|
for name, tt := range tests {
|
||||||
e.Static("assets", "assets")
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
e := New()
|
||||||
|
e.Static(tt.givenPath, tt.givenDirectory)
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
req, _ := http.NewRequest("GET", "/assets/style.css", nil)
|
req, _ := http.NewRequest("GET", fmt.Sprintf("/%s/%s", tt.givenPath, tt.givenFile), nil)
|
||||||
e.ServeHTTP(rr, req)
|
e.ServeHTTP(rr, req)
|
||||||
|
|
||||||
if status := rr.Code; status != http.StatusOK {
|
testhelpers.VerifyResponse(t, rr, tt.expectedResponse)
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", http.StatusOK, status)
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,25 +350,27 @@ type Foo struct {
|
|||||||
|
|
||||||
func Test_JSON(t *testing.T) {
|
func Test_JSON(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
givenCode int
|
givenCode int
|
||||||
givenData any
|
givenData any
|
||||||
expectedCode int
|
expectedResponse testhelpers.ExpectedResponse
|
||||||
expectedHeader string
|
|
||||||
expectedBody string
|
|
||||||
}{
|
}{
|
||||||
"valid JSON": {
|
"valid JSON": {
|
||||||
givenCode: http.StatusOK,
|
givenCode: http.StatusOK,
|
||||||
givenData: Foo{Bar: "bar", Taz: 30, Car: nil},
|
givenData: Foo{Bar: "bar", Taz: 30, Car: nil},
|
||||||
expectedCode: http.StatusOK,
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
expectedHeader: headerJSON,
|
Code: http.StatusOK,
|
||||||
expectedBody: `{"bar":"bar","something":30,"car":null}` + "\n",
|
Header: HeaderJSON,
|
||||||
|
Body: `{"bar":"bar","something":30,"car":null}` + "\n",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"invalid JSON": {
|
"invalid JSON": {
|
||||||
givenCode: http.StatusOK,
|
givenCode: http.StatusOK,
|
||||||
givenData: make(chan int),
|
givenData: make(chan int),
|
||||||
expectedCode: http.StatusInternalServerError,
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
expectedHeader: headerPlain_UTF8,
|
Code: http.StatusInternalServerError,
|
||||||
expectedBody: "json: unsupported type: chan int\n",
|
Header: HeaderPlain_UTF8,
|
||||||
|
Body: "json: unsupported type: chan int\n",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,45 +384,37 @@ func Test_JSON(t *testing.T) {
|
|||||||
|
|
||||||
c.JSON(tt.givenCode, tt.givenData)
|
c.JSON(tt.givenCode, tt.givenData)
|
||||||
|
|
||||||
if status := rr.Code; status != tt.expectedCode {
|
testhelpers.VerifyResponse(t, rr, tt.expectedResponse)
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedCode, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Header().Get(contentType) != tt.expectedHeader {
|
|
||||||
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get(contentType))
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Body.String() != tt.expectedBody {
|
|
||||||
t.Errorf("Expected body: %q, Actual: %q", tt.expectedBody, rr.Body.String())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_HTML(t *testing.T) {
|
func Test_HTML(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
givenCode int
|
givenCode int
|
||||||
givenTemplate string
|
givenTemplate string
|
||||||
givenData *TemplateData
|
givenData *TemplateData
|
||||||
expectedCode int
|
expectedResponse testhelpers.ExpectedResponse
|
||||||
expectedHeader string
|
|
||||||
expectedBody string
|
|
||||||
}{
|
}{
|
||||||
"valid HTML": {
|
"valid HTML": {
|
||||||
givenCode: http.StatusOK,
|
givenCode: http.StatusOK,
|
||||||
givenTemplate: "page.index.gohtml",
|
givenTemplate: "page.index.gohtml",
|
||||||
givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
||||||
expectedCode: http.StatusOK,
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
expectedHeader: headerHTML_UTF8,
|
Code: http.StatusOK,
|
||||||
expectedBody: "<h1>foo</h1><h2>bar</h2>",
|
Header: HeaderHTML_UTF8,
|
||||||
|
Body: "<h1>foo</h1><h2>bar</h2>",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"template not found": {
|
"template not found": {
|
||||||
givenCode: http.StatusOK,
|
givenCode: http.StatusOK,
|
||||||
givenTemplate: "nonexistent.gohtml",
|
givenTemplate: "nonexistent.gohtml",
|
||||||
givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
givenData: &TemplateData{Data: Data{"heading1": "foo", "heading2": "bar"}},
|
||||||
expectedCode: http.StatusInternalServerError,
|
expectedResponse: testhelpers.ExpectedResponse{
|
||||||
expectedHeader: headerPlain_UTF8,
|
Code: http.StatusInternalServerError,
|
||||||
expectedBody: "can't get template from cache\n",
|
Header: HeaderPlain_UTF8,
|
||||||
|
Body: "can't get template from cache\n",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,17 +431,7 @@ func Test_HTML(t *testing.T) {
|
|||||||
|
|
||||||
c.HTML(tt.givenCode, tt.givenTemplate, tt.givenData)
|
c.HTML(tt.givenCode, tt.givenTemplate, tt.givenData)
|
||||||
|
|
||||||
if status := rr.Code; status != tt.expectedCode {
|
testhelpers.VerifyResponse(t, rr, tt.expectedResponse)
|
||||||
t.Errorf("Expected status code: %d, Actual: %d", tt.expectedCode, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Header().Get(contentType) != tt.expectedHeader {
|
|
||||||
t.Errorf("Expected Content-Type: %s, Actual: %s", tt.expectedHeader, rr.Header().Get(contentType))
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Body.String() != tt.expectedBody {
|
|
||||||
t.Errorf("Expected body: %q, Actual: %q", tt.expectedBody, rr.Body.String())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
package testhelpers
|
package testhelpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func CheckSlicesEquality(a []any, b []any) bool {
|
func CheckSlicesEquality(a []any, b []any) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
@ -31,3 +36,29 @@ func StringSliceToAnySlice(s []string) []any {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExpectedResponse struct {
|
||||||
|
Code int
|
||||||
|
Header string
|
||||||
|
Body string
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerifyResponse(t *testing.T, rr *httptest.ResponseRecorder, expectedResponse ExpectedResponse) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
expectedCode := expectedResponse.Code
|
||||||
|
expectedHeader := expectedResponse.Header
|
||||||
|
expectedBody := expectedResponse.Body
|
||||||
|
|
||||||
|
if status := rr.Code; status != expectedCode {
|
||||||
|
t.Errorf("Expected status code: %d, Actual: %d", expectedCode, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header := rr.Header().Get("Content-Type"); header != expectedHeader {
|
||||||
|
t.Errorf("Expected Content-Type: %s, Actual: %s", expectedHeader, header)
|
||||||
|
}
|
||||||
|
|
||||||
|
if body := rr.Body.String(); body != expectedBody {
|
||||||
|
t.Errorf("Expected body: %q, Actual: %q", expectedBody, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user