@@ -17,64 +17,171 @@ import (
1717 "github.com/crhntr/muxt/example/hypertext/internal/fake"
1818)
1919
20- func TestRoutes (t * testing.T ) {
21- for _ , tt := range []domtest.Case [* testing.T , * fake.Backend ]{
22- {
23- Name : "when the row edit form is submitted" ,
24- Given : domtest .GivenPtr (func (t * testing.T , f * fake.Backend ) {
25- f .SubmitFormEditRowReturns (hypertext.Row {ID : 1 , Name : "a" , Value : 97 }, nil )
26- }),
27- When : func (t * testing.T ) * http.Request {
28- req := httptest .NewRequest (http .MethodPatch , hypertext.TemplateRoutePaths {}.SubmitFormEditRow (1 ), strings .NewReader (url.Values {"count" : []string {"5" }}.Encode ()))
29- req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
30- return req
31- },
32- Then : func (t * testing.T , res * http.Response , f * fake.Backend ) {
33- assert .Equal (t , http .StatusOK , res .StatusCode )
34-
35- domtest .Fragment (atom .Tbody , func (t * testing.T , fragment spec.DocumentFragment , _ * fake.Backend ) {
36- require .Equal (t , 1 , fragment .ChildElementCount ())
37- tdList := fragment .QuerySelectorAll (`tr td` )
38- require .Equal (t , 2 , tdList .Length ())
39- require .Equal (t , "a" , tdList .Item (0 ).TextContent ())
40- require .Equal (t , "97" , tdList .Item (1 ).TextContent ())
41- })(t , res , f )
42-
43- if assert .Equal (t , 1 , f .SubmitFormEditRowCallCount ()) {
44- id , form := f .SubmitFormEditRowArgsForCall (0 )
45- require .EqualValues (t , 1 , id )
46- require .Equal (t , hypertext.EditRow {Value : 5 }, form )
47- }
48- },
20+ // TemplateRoutePaths is a local alias because the muxt generate expects to write the tests in the package scope.
21+ type TemplateRoutePaths = hypertext.TemplateRoutePaths
22+
23+ func TestTemplateRoutes (t * testing.T ) {
24+ // The Given, When, Then, and Case structures and the runCase function are only generated once.
25+ // You may add fields to any structure. Do not alter the signature of any Given, When, or Then function on Case.
26+ // You may edit the body of runCase (and the for case loop body).
27+ //
28+ // Consider if you want your collaborator test seam to be RoutesReceiver or your interface implementation's
29+ // collaborators. This generated test function works well either way. If you use RoutesReceiver as a seam, consider
30+ // using a mock generator like https://pkg.go.dev/github.com/maxbrunsfeld/counterfeiter/v6 or https://pkg.go.dev/github.com/ryanmoran/faux
31+ // If you decide to cover your RoutesReceiver testing with this test function. Add the receiver's collaborator
32+ // test doubles to the Given and Then structures so you can configure and make assertions in the respective
33+ // Given and Then test hooks for each case.
34+ type (
35+ // Given is the scope used for setting up test case collaborators.
36+ Given struct {
37+ receiver * fake.Backend
38+ }
39+
40+ // When is the scope used to create HTTP Requests. It is unlikely you will need to add additional fields.
41+ When struct {}
42+
43+ // Then is the scope used for test case assertions. It will likely have collaborator test doubles.
44+ Then struct {
45+ receiver * fake.Backend
46+ }
47+
48+ Case struct {
49+ // The Name, by default a generated identifier, you may change this.
50+ Name string
51+
52+ // The Template field is the route template being tested. It is used by the test generator to detect
53+ // which templates are being tested. Do not change this.
54+ Template string
55+
56+ // The "Given" function MAY set up collaborators.
57+ // The code generator does not add this field in newly generated test cases.
58+ Given func (t * testing.T , given Given )
59+
60+ // The "When" function MUST set up an HTTP Request.
61+ // The generated function will call httptest.NewRequest using the appropriate method and
62+ // the generated TemplateRoutePaths path constructor method.
63+ When func (t * testing.T , when When ) * http.Request
64+
65+ // The "Then" function MAY make assertions on response or any configured collaborators.
66+ // The generated function will assert that the response.StatusCode matches the expected status code.
67+ //
68+ // Consider using https://pkg.go.dev/github.com/stretchr/testify for assertions
69+ // and https://pkg.go.dev/github.com/crhntr/dom/domtest for interacting with the HTML body.
70+ Then func (t * testing.T , then Then , response * http.Response )
71+ }
72+ )
73+
74+ runCase := func (t * testing.T , tc Case ) {
75+ if tc .When == nil {
76+ t .Fatal ("test case field When must not be nil" )
77+ }
78+ if tc .Then == nil {
79+ t .Fatal ("test case field Then must not be nil" )
80+ }
81+ if tc .Template == "" {
82+ t .Fatal ("test case field Template must not be empty" )
83+ }
84+
85+ // If you need to do universal setup of your receiver, do that here.
86+
87+ receiver := new (fake.Backend )
88+
89+ mux := http .NewServeMux ()
90+ hypertext .TemplateRoutes (mux , receiver )
91+ if tc .Given != nil {
92+ tc .Given (t , Given {
93+ receiver : receiver ,
94+ })
95+ }
96+ request := tc .When (t , When {})
97+ recorder := httptest .NewRecorder ()
98+ mux .ServeHTTP (recorder , request )
99+
100+ // If you want to do universal assertions of all your endpoints, consider writing a helper function
101+ // and calling it here.
102+
103+ if tc .Then != nil {
104+ tc .Then (t , Then {
105+ receiver : receiver ,
106+ }, recorder .Result ())
107+ }
108+ }
109+
110+ for _ , tc := range []Case {{
111+ Name : "SubmitFormEditRow" ,
112+ Template : "PATCH /fruits/{id} SubmitFormEditRow(id, form)" ,
113+ Given : func (t * testing.T , given Given ) {
114+ given .receiver .SubmitFormEditRowReturns (hypertext.Row {ID : 1 , Name : "a" , Value : 97 }, nil )
115+ },
116+ When : func (t * testing.T , when When ) * http.Request {
117+ body := strings .NewReader (url.Values {"count" : []string {"5" }}.Encode ())
118+ request := httptest .NewRequest ("PATCH" , TemplateRoutePaths {}.SubmitFormEditRow (1 ), body )
119+ request .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
120+ return request
121+ },
122+ Then : func (t * testing.T , then Then , response * http.Response ) {
123+ require .Equal (t , http .StatusOK , response .StatusCode )
124+
125+ domtest .Fragment (atom .Tbody , func (t * testing.T , fragment spec.DocumentFragment , _ * fake.Backend ) {
126+ require .Equal (t , 1 , fragment .ChildElementCount ())
127+ tdList := fragment .QuerySelectorAll (`tr td` )
128+ require .Equal (t , 2 , tdList .Length ())
129+ require .Equal (t , "a" , tdList .Item (0 ).TextContent ())
130+ require .Equal (t , "97" , tdList .Item (1 ).TextContent ())
131+ })(t , response , then .receiver )
132+
133+ if assert .Equal (t , 1 , then .receiver .SubmitFormEditRowCallCount ()) {
134+ id , form := then .receiver .SubmitFormEditRowArgsForCall (0 )
135+ require .EqualValues (t , 1 , id )
136+ require .Equal (t , hypertext.EditRow {Value : 5 }, form )
137+ }
138+ },
139+ }, {
140+ Name : "GetFormEditRow" ,
141+ Template : "GET /fruits/{id}/edit GetFormEditRow(id)" ,
142+ Given : func (t * testing.T , given Given ) {
143+ given .receiver .GetFormEditRowReturns (hypertext.Row {ID : 1 , Name : "a" , Value : 97 }, nil )
144+ },
145+ When : func (t * testing.T , when When ) * http.Request {
146+ request := httptest .NewRequest ("GET" , TemplateRoutePaths {}.GetFormEditRow (1 ), nil )
147+ return request
148+ },
149+ Then : func (t * testing.T , then Then , response * http.Response ) {
150+ require .Equal (t , http .StatusOK , response .StatusCode )
151+
152+ domtest .Fragment (atom .Tbody , func (t * testing.T , fragment spec.DocumentFragment , _ * fake.Backend ) {
153+ require .Equal (t , 1 , fragment .ChildElementCount ())
154+ tdList := fragment .QuerySelectorAll (`tr td` )
155+ require .Equal (t , 2 , tdList .Length ())
156+ require .Equal (t , "a" , tdList .Item (0 ).TextContent ())
157+
158+ input := tdList .Item (1 ).QuerySelector (`input[name='count']` )
159+ require .Equal (t , input .GetAttribute ("value" ), "97" )
160+ })(t , response , then .receiver )
161+ },
162+ }, {
163+ Name : "ReadHelp" ,
164+ Template : "GET /help" ,
165+ When : func (t * testing.T , when When ) * http.Request {
166+ request := httptest .NewRequest ("GET" , TemplateRoutePaths {}.ReadHelp (), nil )
167+ return request
168+ },
169+ Then : func (t * testing.T , then Then , response * http.Response ) {
170+ require .Equal (t , http .StatusOK , response .StatusCode )
171+ },
172+ }, {
173+ Name : "List" ,
174+ Template : "GET /{$} List(ctx)" ,
175+ When : func (t * testing.T , when When ) * http.Request {
176+ request := httptest .NewRequest ("GET" , TemplateRoutePaths {}.List (), nil )
177+ return request
49178 },
50- {
51- Name : "when the row edit form is requested" ,
52- Given : domtest .GivenPtr (func (t * testing.T , f * fake.Backend ) {
53- f .GetFormEditRowReturns (hypertext.Row {ID : 1 , Name : "a" , Value : 97 }, nil )
54- }),
55- When : func (t * testing.T ) * http.Request {
56- return httptest .NewRequest (http .MethodGet , hypertext.TemplateRoutePaths {}.GetFormEditRow (1 ), nil )
57- },
58- Then : func (t * testing.T , res * http.Response , f * fake.Backend ) {
59- assert .Equal (t , http .StatusOK , res .StatusCode )
60-
61- domtest .Fragment (atom .Tbody , func (t * testing.T , fragment spec.DocumentFragment , _ * fake.Backend ) {
62- t .Log (fragment )
63- require .Equal (t , 1 , fragment .ChildElementCount ())
64- tdList := fragment .QuerySelectorAll (`tr td` )
65- require .Equal (t , 2 , tdList .Length ())
66- require .Equal (t , "a" , tdList .Item (0 ).TextContent ())
67-
68- input := tdList .Item (1 ).QuerySelector (`input[name='count']` )
69- require .Equal (t , input .GetAttribute ("value" ), "97" )
70- })(t , res , f )
71- },
179+ Then : func (t * testing.T , then Then , response * http.Response ) {
180+ if expected , got := http .StatusOK , response .StatusCode ; expected != got {
181+ t .Errorf ("unexpected status code: got %d expected %d" , got , expected )
182+ }
72183 },
73- } {
74- t .Run (tt .Name , tt .Run (func (f * fake.Backend ) http.Handler {
75- mux := http .NewServeMux ()
76- hypertext .TemplateRoutes (mux , f )
77- return mux
78- }))
184+ }} {
185+ t .Run (tc .Name , func (t * testing.T ) { runCase (t , tc ) })
79186 }
80187}
0 commit comments