From 87c0586e223ae8247fc86c18af720c66ec6dad6d Mon Sep 17 00:00:00 2001 From: Chrstopher Hunter <8398225+crhntr@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:52:50 -0700 Subject: [PATCH] consolidate happy path tests into higher level --- generate_internal_test.go | 104 ------------------ generate_test.go | 216 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+), 104 deletions(-) diff --git a/generate_internal_test.go b/generate_internal_test.go index ecf02e1..2c663da 100644 --- a/generate_internal_test.go +++ b/generate_internal_test.go @@ -6,112 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/crhntr/muxt/internal/source" ) -func TestTemplateName_funcLit(t *testing.T) { - for _, tt := range []struct { - Name string - In string - Out string - Imports []string - Method *ast.FuncType - }{ - { - Name: "get", - In: "GET /", - Out: `func(response http.ResponseWriter, request *http.Request) { - execute(response, request, true, "GET /", http.StatusOK, request) -}`, - }, - { - Name: "call F", - In: "GET / F()", - Out: `func(response http.ResponseWriter, request *http.Request) { - data := receiver.F() - execute(response, request, true, "GET / F()", http.StatusOK, data) -}`, - }, - { - Name: "call F with argument request", - In: "GET / F(request)", - Method: &ast.FuncType{ - Params: &ast.FieldList{List: []*ast.Field{{Type: httpRequestField().Type}}}, - Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("any")}}}, - }, - Out: `func(response http.ResponseWriter, request *http.Request) { - data := receiver.F(request) - execute(response, request, true, "GET / F(request)", http.StatusOK, data) -}`, - }, - { - Name: "call F with argument response", - In: "GET / F(response)", - Method: &ast.FuncType{ - Params: &ast.FieldList{List: []*ast.Field{{Type: httpResponseField().Type, Names: []*ast.Ident{{Name: "res"}}}}}, - Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("any")}}}, - }, - Out: `func(response http.ResponseWriter, request *http.Request) { - data := receiver.F(response) - execute(response, request, false, "GET / F(response)", http.StatusOK, data) -}`, - }, - { - Name: "call F with argument context", - In: "GET / F(ctx)", - Method: &ast.FuncType{ - Params: &ast.FieldList{List: []*ast.Field{{Type: contextContextField().Type, Names: []*ast.Ident{{Name: "reqCtx"}}}}}, - Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("any")}}}, - }, - Out: `func(response http.ResponseWriter, request *http.Request) { - ctx := request.Context() - data := receiver.F(ctx) - execute(response, request, true, "GET / F(ctx)", http.StatusOK, data) -}`, - }, - { - Name: "call F with argument path param", - In: "GET /{param} F(param)", - Method: &ast.FuncType{ - Params: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("string")}}}, - Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("any")}}}, - }, - Out: `func(response http.ResponseWriter, request *http.Request) { - param := request.PathValue("param") - data := receiver.F(param) - execute(response, request, true, "GET /{param} F(param)", http.StatusOK, data) -}`, - }, - { - Name: "call F with multiple arguments", - In: "GET /{userName} F(ctx, userName)", - Method: &ast.FuncType{ - Params: &ast.FieldList{List: []*ast.Field{ - {Type: contextContextField().Type, Names: []*ast.Ident{{Name: "ctx"}}}, - {Type: ast.NewIdent("string"), Names: []*ast.Ident{{Name: "n"}}}, - }}, - Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("any")}}}, - }, - Out: `func(response http.ResponseWriter, request *http.Request) { - ctx := request.Context() - userName := request.PathValue("userName") - data := receiver.F(ctx, userName) - execute(response, request, true, "GET /{userName} F(ctx, userName)", http.StatusOK, data) -}`, - }, - } { - t.Run(tt.Name, func(t *testing.T) { - pat, err, ok := NewTemplateName(tt.In) - require.True(t, ok) - require.NoError(t, err) - out, _, err := pat.funcLit(tt.Method, nil) - require.NoError(t, err) - assert.Equal(t, tt.Out, source.Format(out)) - }) - } -} - func TestTemplateName_HandlerFuncLit_err(t *testing.T) { for _, tt := range []struct { Name string diff --git a/generate_test.go b/generate_test.go index 8dbeabb..613cef4 100644 --- a/generate_test.go +++ b/generate_test.go @@ -1002,6 +1002,222 @@ func (T) F(form In) int { return 0 } Receiver: "T", ExpectedError: "failed to generate parse statements for form field ts: unsupported type: time.Time", }, + { + Name: "call F", + Templates: `{{define "GET / F()"}}Hello, world!{{end}}`, + Receiver: "T", + PackageName: "main", + ReceiverPackage: `-- in.go -- +package main + +type T struct{} +`, + ExpectedFile: `package main + +import ( + "net/http" + "bytes" +) + +type RoutesReceiver interface { + F() any +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /", func(response http.ResponseWriter, request *http.Request) { + data := receiver.F() + execute(response, request, true, "GET / F()", http.StatusOK, data) + }) +} +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) { + buf := bytes.NewBuffer(nil) + if err := templates.ExecuteTemplate(buf, name, data); err != nil { + http.Error(response, err.Error(), http.StatusInternalServerError) + return + } + if writeHeader { + response.WriteHeader(code) + } + _, _ = buf.WriteTo(response) +} +`, + }, + { + Name: "no handler", + Templates: `{{define "GET /"}}Hello, world!{{end}}`, + Receiver: "T", + PackageName: "main", + ReceiverPackage: `-- in.go -- +package main + +type T struct{} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import "net/http" + +type RoutesReceiver interface { +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /", func(response http.ResponseWriter, request *http.Request) { + execute(response, request, true, "GET /", http.StatusOK, request) + }) +} +`, + }, + { + Name: "no handler", + Templates: `{{define "GET /"}}Hello, world!{{end}}`, + Receiver: "T", + PackageName: "main", + ReceiverPackage: `-- in.go -- +package main + +type T struct{} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import "net/http" + +type RoutesReceiver interface { +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /", func(response http.ResponseWriter, request *http.Request) { + execute(response, request, true, "GET /", http.StatusOK, request) + }) +} +`, + }, + { + Name: "call F with argument response", + Templates: `{{define "GET / F(response)"}}{{end}}`, + ReceiverPackage: `-- in.go -- +package main + +type T struct{} + +func (T) F(http.ResponseWriter) any {return nil} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import "net/http" + +type RoutesReceiver interface { + F(response http.ResponseWriter) any +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /", func(response http.ResponseWriter, request *http.Request) { + data := receiver.F(response) + execute(response, request, false, "GET / F(response)", http.StatusOK, data) + }) +} +`, + }, + { + Name: "call F with argument context", + Templates: `{{define "GET / F(ctx)"}}{{end}}`, + ReceiverPackage: `-- in.go -- +package main + +type T struct{} + +func (T) F(ctx context.Context) any {return nil} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import ( + "context" + "net/http" +) + +type RoutesReceiver interface { + F(ctx context.Context) any +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /", func(response http.ResponseWriter, request *http.Request) { + ctx := request.Context() + data := receiver.F(ctx) + execute(response, request, true, "GET / F(ctx)", http.StatusOK, data) + }) +} +`, + }, + { + Name: "call F with argument path param", + Templates: `{{define "GET /{param} F(param)"}}{{end}}`, + ReceiverPackage: `-- in.go -- +package main + +type T struct{} + +func (T) F(param string) any {return nil} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import "net/http" + +type RoutesReceiver interface { + F(param string) any +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /{param}", func(response http.ResponseWriter, request *http.Request) { + param := request.PathValue("param") + data := receiver.F(param) + execute(response, request, true, "GET /{param} F(param)", http.StatusOK, data) + }) +} +`, + }, + { + Name: "call F with multiple arguments", + Templates: `{{define "GET /{userName} F(ctx, userName)"}}{{end}}`, + ReceiverPackage: `-- in.go -- +package main + +import "context" + +type T struct{} + +func (T) F(ctx context.Context, userName string) any {return nil} + +func execute(response http.ResponseWriter, request *http.Request, writeHeader bool, name string, code int, data any) {} +`, + ExpectedFile: `package main + +import ( + "context" + "net/http" +) + +type RoutesReceiver interface { + F(ctx context.Context, userName string) any +} + +func routes(mux *http.ServeMux, receiver RoutesReceiver) { + mux.HandleFunc("GET /{userName}", func(response http.ResponseWriter, request *http.Request) { + ctx := request.Context() + userName := request.PathValue("userName") + data := receiver.F(ctx, userName) + execute(response, request, true, "GET /{userName} F(ctx, userName)", http.StatusOK, data) + }) +} +`, + }, } { t.Run(tt.Name, func(t *testing.T) { ts := template.Must(template.New(tt.Name).Parse(tt.Templates))