go.sdls.io/sin@v0.0.9/pkg/sin/routes_test.go (about)

     1  // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sin
     6  
     7  import (
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  type header struct {
    16  	Key   string
    17  	Value string
    18  }
    19  
    20  func performRequest(r http.Handler, method, path string, headers ...header) *httptest.ResponseRecorder {
    21  	req := httptest.NewRequest(method, path, nil)
    22  	for _, h := range headers {
    23  		req.Header.Add(h.Key, h.Value)
    24  	}
    25  	w := httptest.NewRecorder()
    26  	r.ServeHTTP(w, req)
    27  	return w
    28  }
    29  
    30  func testRouteOK(method string, t *testing.T) {
    31  	passed := false
    32  	passedAny := false
    33  	r := New()
    34  	r.Any("/test2", func(c *Context) {
    35  		passedAny = true
    36  	})
    37  	r.Handle(method, "/test", func(c *Context) {
    38  		passed = true
    39  	})
    40  
    41  	w := performRequest(r, method, "/test")
    42  	assert.True(t, passed)
    43  	assert.Equal(t, http.StatusOK, w.Code)
    44  
    45  	performRequest(r, method, "/test2")
    46  	assert.True(t, passedAny)
    47  }
    48  
    49  // TestSingleRouteOK tests that POST route is correctly invoked.
    50  func testRouteNotOK(method string, t *testing.T) {
    51  	passed := false
    52  	router := New()
    53  	router.Handle(method, "/test_2", func(c *Context) {
    54  		passed = true
    55  	})
    56  
    57  	w := performRequest(router, method, "/test")
    58  
    59  	assert.False(t, passed)
    60  	assert.Equal(t, http.StatusNotFound, w.Code)
    61  }
    62  
    63  // TestSingleRouteOK tests that POST route is correctly invoked.
    64  func testRouteNotOK2(method string, t *testing.T) {
    65  	passed := false
    66  	router := New()
    67  	router.HandleMethodNotAllowed = true
    68  	var methodRoute string
    69  	if method == http.MethodPost {
    70  		methodRoute = http.MethodGet
    71  	} else {
    72  		methodRoute = http.MethodPost
    73  	}
    74  	router.Handle(methodRoute, "/test", func(c *Context) {
    75  		passed = true
    76  	})
    77  
    78  	w := performRequest(router, method, "/test")
    79  
    80  	assert.False(t, passed)
    81  	assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
    82  }
    83  
    84  func TestRouterMethod(t *testing.T) {
    85  	router := New()
    86  	router.PUT("/hey2", func(c *Context) {
    87  		c.String(http.StatusOK, "sup2")
    88  	})
    89  
    90  	router.PUT("/hey", func(c *Context) {
    91  		c.String(http.StatusOK, "called")
    92  	})
    93  
    94  	router.PUT("/hey3", func(c *Context) {
    95  		c.String(http.StatusOK, "sup3")
    96  	})
    97  
    98  	w := performRequest(router, http.MethodPut, "/hey")
    99  
   100  	assert.Equal(t, http.StatusOK, w.Code)
   101  	assert.Equal(t, "called", w.Body.String())
   102  }
   103  
   104  func TestRouterGroupRouteOK(t *testing.T) {
   105  	testRouteOK(http.MethodGet, t)
   106  	testRouteOK(http.MethodPost, t)
   107  	testRouteOK(http.MethodPut, t)
   108  	testRouteOK(http.MethodPatch, t)
   109  	testRouteOK(http.MethodHead, t)
   110  	testRouteOK(http.MethodOptions, t)
   111  	testRouteOK(http.MethodDelete, t)
   112  	testRouteOK(http.MethodConnect, t)
   113  	testRouteOK(http.MethodTrace, t)
   114  }
   115  
   116  func TestRouteNotOK(t *testing.T) {
   117  	testRouteNotOK(http.MethodGet, t)
   118  	testRouteNotOK(http.MethodPost, t)
   119  	testRouteNotOK(http.MethodPut, t)
   120  	testRouteNotOK(http.MethodPatch, t)
   121  	testRouteNotOK(http.MethodHead, t)
   122  	testRouteNotOK(http.MethodOptions, t)
   123  	testRouteNotOK(http.MethodDelete, t)
   124  	testRouteNotOK(http.MethodConnect, t)
   125  	testRouteNotOK(http.MethodTrace, t)
   126  }
   127  
   128  func TestRouteNotOK2(t *testing.T) {
   129  	testRouteNotOK2(http.MethodGet, t)
   130  	testRouteNotOK2(http.MethodPost, t)
   131  	testRouteNotOK2(http.MethodPut, t)
   132  	testRouteNotOK2(http.MethodPatch, t)
   133  	testRouteNotOK2(http.MethodHead, t)
   134  	testRouteNotOK2(http.MethodOptions, t)
   135  	testRouteNotOK2(http.MethodDelete, t)
   136  	testRouteNotOK2(http.MethodConnect, t)
   137  	testRouteNotOK2(http.MethodTrace, t)
   138  }
   139  
   140  // TestContextParamsGet tests that a parameter can be parsed from the URL.
   141  func TestRouteParamsByName(t *testing.T) {
   142  	name := ""
   143  	lastName := ""
   144  	wild := ""
   145  	router := New()
   146  	router.GET("/test/:name/:last_name/*wild", func(c *Context) {
   147  		name = c.Params.ByName("name")
   148  		lastName = c.Params.ByName("last_name")
   149  		var ok bool
   150  		wild, ok = c.Params.Get("wild")
   151  
   152  		assert.True(t, ok)
   153  		assert.Equal(t, name, c.Param("name"))
   154  		assert.Equal(t, lastName, c.Param("last_name"))
   155  
   156  		assert.Empty(t, c.Param("wtf"))
   157  		assert.Empty(t, c.Params.ByName("wtf"))
   158  
   159  		wtf, ok := c.Params.Get("wtf")
   160  		assert.Empty(t, wtf)
   161  		assert.False(t, ok)
   162  	})
   163  
   164  	w := performRequest(router, http.MethodGet, "/test/john/smith/is/super/great")
   165  
   166  	assert.Equal(t, http.StatusOK, w.Code)
   167  	assert.Equal(t, "john", name)
   168  	assert.Equal(t, "smith", lastName)
   169  	assert.Equal(t, "/is/super/great", wild)
   170  }
   171  
   172  func TestRouteNotAllowedEnabled(t *testing.T) {
   173  	router := New()
   174  	router.HandleMethodNotAllowed = true
   175  	router.POST("/path", func(c *Context) {})
   176  	w := performRequest(router, http.MethodGet, "/path")
   177  	assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
   178  
   179  	router.NoMethod(func(c *Context) {
   180  		c.String(http.StatusTeapot, "responseText")
   181  	})
   182  	w = performRequest(router, http.MethodGet, "/path")
   183  	assert.Equal(t, "responseText", w.Body.String())
   184  	assert.Equal(t, http.StatusTeapot, w.Code)
   185  }
   186  
   187  func TestRouteNotAllowedEnabled2(t *testing.T) {
   188  	router := New()
   189  	router.HandleMethodNotAllowed = true
   190  	// add one methodTree to trees
   191  	router.addRoute(http.MethodPost, "/", HandlersChain{func(_ *Context) {}})
   192  	router.GET("/path2", func(c *Context) {})
   193  	w := performRequest(router, http.MethodPost, "/path2")
   194  	assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
   195  }
   196  
   197  func TestRouteNotAllowedDisabled(t *testing.T) {
   198  	router := New()
   199  	router.HandleMethodNotAllowed = false
   200  	router.POST("/path", func(c *Context) {})
   201  	w := performRequest(router, http.MethodGet, "/path")
   202  	assert.Equal(t, http.StatusNotFound, w.Code)
   203  
   204  	router.NoMethod(func(c *Context) {
   205  		c.String(http.StatusTeapot, "responseText")
   206  	})
   207  	w = performRequest(router, http.MethodGet, "/path")
   208  	assert.Equal(t, "404 page not found", w.Body.String())
   209  	assert.Equal(t, http.StatusNotFound, w.Code)
   210  }
   211  
   212  func TestRouteRawPath(t *testing.T) {
   213  	route := New()
   214  	route.UseRawPath = true
   215  
   216  	route.POST("/project/:name/build/:num", func(c *Context) {
   217  		name := c.Params.ByName("name")
   218  		num := c.Params.ByName("num")
   219  
   220  		assert.Equal(t, name, c.Param("name"))
   221  		assert.Equal(t, num, c.Param("num"))
   222  
   223  		assert.Equal(t, "Some/Other/Project", name)
   224  		assert.Equal(t, "222", num)
   225  	})
   226  
   227  	w := performRequest(route, http.MethodPost, "/project/Some%2FOther%2FProject/build/222")
   228  	assert.Equal(t, http.StatusOK, w.Code)
   229  }
   230  
   231  func TestRouteRawPathNoUnescape(t *testing.T) {
   232  	route := New()
   233  	route.UseRawPath = true
   234  	route.UnescapePathValues = false
   235  
   236  	route.POST("/project/:name/build/:num", func(c *Context) {
   237  		name := c.Params.ByName("name")
   238  		num := c.Params.ByName("num")
   239  
   240  		assert.Equal(t, name, c.Param("name"))
   241  		assert.Equal(t, num, c.Param("num"))
   242  
   243  		assert.Equal(t, "Some%2FOther%2FProject", name)
   244  		assert.Equal(t, "333", num)
   245  	})
   246  
   247  	w := performRequest(route, http.MethodPost, "/project/Some%2FOther%2FProject/build/333")
   248  	assert.Equal(t, http.StatusOK, w.Code)
   249  }
   250  
   251  func TestRouteServeErrorWithWriteHeader(t *testing.T) {
   252  	route := New()
   253  	route.Use(func(c *Context) {
   254  		c.Status(421)
   255  		c.Next()
   256  	})
   257  
   258  	w := performRequest(route, http.MethodGet, "/NotFound")
   259  	assert.Equal(t, 421, w.Code)
   260  	assert.Equal(t, 0, w.Body.Len())
   261  }
   262  
   263  func TestRouteContextHoldsFullPath(t *testing.T) {
   264  	router := New()
   265  
   266  	// Test routes
   267  	routes := []string{
   268  		"/simple",
   269  		"/project/:name",
   270  		"/",
   271  		"/news/home",
   272  		"/news",
   273  		"/simple-two/one",
   274  		"/simple-two/one-two",
   275  		"/project/:name/build/*params",
   276  		"/project/:name/bui",
   277  		"/user/:id/status",
   278  		"/user/:id",
   279  		"/user/:id/profile",
   280  	}
   281  
   282  	for _, route := range routes {
   283  		actualRoute := route
   284  		router.GET(route, func(c *Context) {
   285  			// For each defined route context should contain its full path
   286  			assert.Equal(t, actualRoute, c.FullPath())
   287  			c.AbortWithStatus(http.StatusOK)
   288  		})
   289  	}
   290  
   291  	for _, route := range routes {
   292  		w := performRequest(router, http.MethodGet, route)
   293  		assert.Equal(t, http.StatusOK, w.Code)
   294  	}
   295  
   296  	// Test not found
   297  	router.Use(func(c *Context) {
   298  		// For not found routes full path is empty
   299  		assert.Equal(t, "", c.FullPath())
   300  	})
   301  
   302  	w := performRequest(router, http.MethodGet, "/not-found")
   303  	assert.Equal(t, http.StatusNotFound, w.Code)
   304  }