goyave.dev/goyave/v4@v4.4.11/route_test.go (about) 1 package goyave 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "regexp" 7 "testing" 8 9 "goyave.dev/goyave/v4/validation" 10 ) 11 12 type RouteTestSuite struct { 13 TestSuite 14 } 15 16 func (suite *RouteTestSuite) TestNewRoute() { 17 route := newRoute(func(resp *Response, r *Request) {}) 18 suite.NotNil(route) 19 suite.NotNil(route.handler) 20 } 21 22 func (suite *RouteTestSuite) TestMakeParameters() { 23 regexCache := make(map[string]*regexp.Regexp, 5) 24 route := newRoute(func(resp *Response, r *Request) {}) 25 route.compileParameters("/product/{id:[0-9]+}", true, regexCache) 26 suite.Equal([]string{"id"}, route.parameters) 27 suite.NotNil(route.regex) 28 suite.True(route.regex.MatchString("/product/666")) 29 suite.False(route.regex.MatchString("/product/")) 30 suite.False(route.regex.MatchString("/product/qwerty")) 31 } 32 33 func (suite *RouteTestSuite) TestMatch() { 34 regexCache := make(map[string]*regexp.Regexp, 5) 35 handler := func(resp *Response, r *Request) { 36 resp.String(http.StatusOK, "Success") 37 } 38 route := &Route{ 39 name: "test-route", 40 uri: "/product/{id:[0-9]+}", 41 methods: []string{"GET", "POST"}, 42 parent: nil, 43 handler: handler, 44 validationRules: nil, 45 } 46 route.compileParameters(route.uri, true, regexCache) 47 48 rawRequest := httptest.NewRequest("GET", "/product/33", nil) 49 match := routeMatch{currentPath: rawRequest.URL.Path} 50 suite.True(route.match(rawRequest, &match)) 51 suite.Equal("33", match.parameters["id"]) 52 53 rawRequest = httptest.NewRequest("POST", "/product/33", nil) 54 match = routeMatch{currentPath: rawRequest.URL.Path} 55 suite.True(route.match(rawRequest, &match)) 56 suite.Equal("33", match.parameters["id"]) 57 58 rawRequest = httptest.NewRequest("PUT", "/product/33", nil) 59 match = routeMatch{currentPath: rawRequest.URL.Path} 60 suite.False(route.match(rawRequest, &match)) 61 suite.Equal(errMatchMethodNotAllowed, match.err) 62 63 // Test error has not been overridden 64 rawRequest = httptest.NewRequest("PUT", "/product/test", nil) 65 suite.False(route.match(rawRequest, &match)) 66 suite.Equal(errMatchMethodNotAllowed, match.err) 67 68 match = routeMatch{currentPath: rawRequest.URL.Path} 69 suite.False(route.match(rawRequest, &match)) 70 suite.Equal(errMatchNotFound, match.err) 71 72 route = &Route{ 73 name: "test-route", 74 uri: "/product/{id:[0-9]+}/{name}", 75 methods: []string{"GET"}, 76 parent: nil, 77 handler: handler, 78 validationRules: nil, 79 } 80 route.compileParameters(route.uri, true, regexCache) 81 rawRequest = httptest.NewRequest("GET", "/product/666/test", nil) 82 match = routeMatch{currentPath: rawRequest.URL.Path} 83 suite.True(route.match(rawRequest, &match)) 84 suite.Equal("666", match.parameters["id"]) 85 suite.Equal("test", match.parameters["name"]) 86 87 route = &Route{ 88 name: "test-route", 89 uri: "/categories/{category}/{sort:(?:asc|desc|new)}", 90 methods: []string{"GET"}, 91 parent: nil, 92 handler: handler, 93 validationRules: nil, 94 } 95 route.compileParameters(route.uri, true, regexCache) 96 rawRequest = httptest.NewRequest("GET", "/categories/lawn-mower/asc", nil) 97 match = routeMatch{currentPath: rawRequest.URL.Path} 98 suite.True(route.match(rawRequest, &match)) 99 suite.Equal("lawn-mower", match.parameters["category"]) 100 suite.Equal("asc", match.parameters["sort"]) 101 102 rawRequest = httptest.NewRequest("GET", "/categories/lawn-mower/notsort", nil) 103 match = routeMatch{currentPath: rawRequest.URL.Path} 104 suite.False(route.match(rawRequest, &match)) 105 } 106 107 func (suite *RouteTestSuite) TestAccessors() { 108 route := &Route{ 109 name: "route-name", 110 uri: "/product/{id:[0-9+]}", 111 parent: NewRouter(), 112 methods: []string{"GET", "POST"}, 113 } 114 115 suite.Equal("route-name", route.GetName()) 116 117 suite.Panics(func() { 118 route.Name("new-name") // Cannot re-set name 119 }) 120 121 route = &Route{ 122 name: "", 123 uri: "/product/{id:[0-9+]}", 124 parent: NewRouter(), 125 methods: []string{"GET", "POST"}, 126 } 127 route.Name("new-name") 128 suite.Equal("new-name", route.GetName()) 129 130 suite.Equal("/product/{id:[0-9+]}", route.GetURI()) 131 suite.Equal([]string{"GET", "POST"}, route.GetMethods()) 132 } 133 134 func (suite *RouteTestSuite) TestGetFullURIAndParameters() { 135 router := NewRouter().Subrouter("/product").Subrouter("/{id:[0-9+]}") 136 route := router.Route("GET|POST", "/{name}/accessories", func(resp *Response, r *Request) {}).Name("route-name") 137 138 uri, params := route.GetFullURIAndParameters() 139 suite.Equal("/product/{id:[0-9+]}/{name}/accessories", uri) 140 suite.Equal([]string{"id", "name"}, params) 141 } 142 143 func (suite *RouteTestSuite) TestGetFullURI() { 144 router := NewRouter().Subrouter("/product").Subrouter("/{id:[0-9+]}") 145 route := router.Route("GET|POST", "/{name}/accessories", func(resp *Response, r *Request) {}).Name("route-name") 146 147 suite.Equal("/product/{id:[0-9+]}/{name}/accessories", route.GetFullURI()) 148 } 149 150 func (suite *RouteTestSuite) TestBuildURI() { 151 regexCache := make(map[string]*regexp.Regexp, 5) 152 route := &Route{ 153 name: "route-name", 154 uri: "/product/{id:[0-9+]}", 155 methods: []string{"GET", "POST"}, 156 } 157 route.compileParameters(route.uri, true, regexCache) 158 suite.Equal("/product/42", route.BuildURI("42")) 159 160 suite.Panics(func() { 161 route.BuildURI() 162 }) 163 suite.Panics(func() { 164 route.BuildURI("42", "more") 165 }) 166 167 route = &Route{ 168 name: "route-name", 169 uri: "/product/{id:[0-9+]}/{name}/accessories", 170 methods: []string{"GET", "POST"}, 171 } 172 route.compileParameters(route.uri, true, regexCache) 173 suite.Equal("/product/42/screwdriver/accessories", route.BuildURI("42", "screwdriver")) 174 175 router := NewRouter().Subrouter("/product").Subrouter("/{id:[0-9+]}") 176 route = router.Route("GET|POST", "/{name}/accessories", func(resp *Response, r *Request) {}).Name("route-name") 177 178 suite.Equal("/product/42/screwdriver/accessories", route.BuildURI("42", "screwdriver")) 179 } 180 181 func (suite *RouteTestSuite) TestBuildURL() { 182 regexCache := make(map[string]*regexp.Regexp, 5) 183 route := &Route{ 184 name: "route-name", 185 uri: "/product/{id:[0-9+]}", 186 methods: []string{"GET", "POST"}, 187 } 188 route.compileParameters(route.uri, true, regexCache) 189 suite.Equal("http://127.0.0.1:1235/product/42", route.BuildURL("42")) 190 191 suite.Panics(func() { 192 route.BuildURL() 193 }) 194 suite.Panics(func() { 195 route.BuildURL("42", "more") 196 }) 197 198 route = &Route{ 199 name: "route-name", 200 uri: "/product/{id:[0-9+]}/{name}/accessories", 201 methods: []string{"GET", "POST"}, 202 } 203 route.compileParameters(route.uri, true, regexCache) 204 suite.Equal("http://127.0.0.1:1235/product/42/screwdriver/accessories", route.BuildURL("42", "screwdriver")) 205 206 router := NewRouter().Subrouter("/product").Subrouter("/{id:[0-9+]}") 207 route = router.Route("GET|POST", "/{name}/accessories", func(resp *Response, r *Request) {}).Name("route-name") 208 209 suite.Equal("http://127.0.0.1:1235/product/42/screwdriver/accessories", route.BuildURL("42", "screwdriver")) 210 } 211 212 func (suite *RouteTestSuite) TestValidate() { 213 route := &Route{ 214 name: "route-name", 215 uri: "/product/{id:[0-9+]}", 216 methods: []string{"GET", "POST"}, 217 } 218 rules := &validation.Rules{ 219 Fields: validation.FieldMap{ 220 "field": &validation.Field{ 221 Rules: []*validation.Rule{ 222 {Name: "required"}, 223 {Name: "string"}, 224 }, 225 }, 226 }, 227 } 228 route.Validate(rules) 229 suite.Equal(rules, route.validationRules) 230 } 231 232 func (suite *RouteTestSuite) TestMiddleware() { 233 route := &Route{ 234 name: "route-name", 235 uri: "/product/{id:[0-9+]}", 236 methods: []string{"GET", "POST"}, 237 } 238 middelware := func(next Handler) Handler { 239 return func(response *Response, r *Request) {} 240 } 241 middelware2 := func(next Handler) Handler { 242 return func(response *Response, r *Request) {} 243 } 244 route.Middleware(middelware, middelware2) 245 suite.Len(route.middleware, 2) 246 } 247 248 func (suite *RouteTestSuite) TestGetHandler() { 249 executed := false 250 route := &Route{ 251 name: "route-name", 252 uri: "/product/{id:[0-9+]}", 253 methods: []string{"GET", "POST"}, 254 handler: func(resp *Response, r *Request) { 255 executed = true 256 }, 257 } 258 handler := route.GetHandler() 259 suite.NotNil(handler) 260 handler(nil, nil) 261 suite.True(executed) 262 } 263 264 func (suite *RouteTestSuite) TestGetValidationRules() { 265 route := &Route{ 266 name: "route-name", 267 uri: "/product/{id:[0-9+]}", 268 methods: []string{"GET", "POST"}, 269 } 270 rules := &validation.Rules{ 271 Fields: validation.FieldMap{ 272 "email": &validation.Field{ 273 Rules: []*validation.Rule{ 274 {Name: "required"}, 275 {Name: "string"}, 276 {Name: "between", Params: []string{"3", "125"}}, 277 {Name: "email"}, 278 }, 279 }, 280 }, 281 } 282 route.Validate(rules) 283 284 suite.Same(rules, route.GetValidationRules()) 285 } 286 287 func TestRouteTestSuite(t *testing.T) { 288 RunTest(t, new(RouteTestSuite)) 289 }