github.com/mayra-cabrera/buffalo@v0.9.4-0.20170814145312-66d2e7772f11/router_test.go (about)

     1  package buffalo
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/gobuffalo/buffalo/render"
    12  	"github.com/gobuffalo/packr"
    13  	"github.com/gobuffalo/plush"
    14  	"github.com/markbates/willie"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func testApp() *App {
    19  	a := New(Options{})
    20  	a.Redirect(301, "/foo", "/bar")
    21  	a.GET("/bar", func(c Context) error {
    22  		return c.Render(200, render.String("bar"))
    23  	})
    24  
    25  	rt := a.Group("/router/tests")
    26  
    27  	h := func(c Context) error {
    28  		return c.Render(200, render.String(c.Request().Method+"|"+c.Value("current_path").(string)))
    29  	}
    30  
    31  	rt.GET("/", h)
    32  	rt.POST("/", h)
    33  	rt.PUT("/", h)
    34  	rt.DELETE("/", h)
    35  	rt.OPTIONS("/", h)
    36  	rt.PATCH("/", h)
    37  	return a
    38  }
    39  
    40  func Test_Router(t *testing.T) {
    41  	r := require.New(t)
    42  
    43  	table := []string{
    44  		"GET",
    45  		"POST",
    46  		"PUT",
    47  		"DELETE",
    48  		"OPTIONS",
    49  		"PATCH",
    50  	}
    51  
    52  	ts := httptest.NewServer(testApp())
    53  	defer ts.Close()
    54  
    55  	for _, v := range table {
    56  		req, err := http.NewRequest(v, fmt.Sprintf("%s/router/tests", ts.URL), nil)
    57  		r.NoError(err)
    58  		res, err := http.DefaultClient.Do(req)
    59  		r.NoError(err)
    60  		b, _ := ioutil.ReadAll(res.Body)
    61  		r.Equal(fmt.Sprintf("%s|/router/tests", v), string(b))
    62  	}
    63  }
    64  
    65  func Test_Router_Group(t *testing.T) {
    66  	r := require.New(t)
    67  
    68  	a := testApp()
    69  	g := a.Group("/api/v1")
    70  	g.GET("/users", func(c Context) error {
    71  		return c.Render(201, nil)
    72  	})
    73  
    74  	w := willie.New(a)
    75  	res := w.Request("/api/v1/users").Get()
    76  	r.Equal(201, res.Code)
    77  }
    78  
    79  func Test_Router_Group_on_Group(t *testing.T) {
    80  	r := require.New(t)
    81  
    82  	a := testApp()
    83  	g := a.Group("/api/v1")
    84  	g.GET("/users", func(c Context) error {
    85  		return c.Render(201, nil)
    86  	})
    87  	f := g.Group("/foo")
    88  	f.GET("/bar", func(c Context) error {
    89  		return c.Render(420, nil)
    90  	})
    91  
    92  	w := willie.New(a)
    93  	res := w.Request("/api/v1/foo/bar").Get()
    94  	r.Equal(420, res.Code)
    95  }
    96  
    97  func Test_Router_Group_Middleware(t *testing.T) {
    98  	r := require.New(t)
    99  
   100  	a := testApp()
   101  	a.Use(func(h Handler) Handler { return h })
   102  	r.Len(a.Middleware.stack, 1)
   103  
   104  	g := a.Group("/api/v1")
   105  	r.Len(a.Middleware.stack, 1)
   106  	r.Len(g.Middleware.stack, 1)
   107  
   108  	g.Use(func(h Handler) Handler { return h })
   109  	r.Len(a.Middleware.stack, 1)
   110  	r.Len(g.Middleware.stack, 2)
   111  }
   112  
   113  func Test_Router_Redirect(t *testing.T) {
   114  	r := require.New(t)
   115  	w := willie.New(testApp())
   116  	res := w.Request("/foo").Get()
   117  	r.Equal(301, res.Code)
   118  	r.Equal("/bar", res.Location())
   119  }
   120  
   121  func Test_Router_ServeFiles(t *testing.T) {
   122  	r := require.New(t)
   123  
   124  	tmpFile, err := ioutil.TempFile("", "assets")
   125  	r.NoError(err)
   126  
   127  	af := []byte("hi")
   128  	_, err = tmpFile.Write(af)
   129  	r.NoError(err)
   130  
   131  	a := New(Options{})
   132  	a.ServeFiles("/assets", http.Dir(filepath.Dir(tmpFile.Name())))
   133  
   134  	w := willie.New(a)
   135  	res := w.Request("/assets/%s", filepath.Base(tmpFile.Name())).Get()
   136  
   137  	r.Equal(200, res.Code)
   138  	r.Equal(af, res.Body.Bytes())
   139  }
   140  
   141  func Test_App_NamedRoutes(t *testing.T) {
   142  
   143  	type CarsResource struct {
   144  		*BaseResource
   145  	}
   146  
   147  	r := require.New(t)
   148  	a := Automatic(Options{})
   149  
   150  	var carsResource Resource
   151  	carsResource = CarsResource{&BaseResource{}}
   152  
   153  	rr := render.New(render.Options{
   154  		HTMLLayout:     "application.html",
   155  		TemplateEngine: plush.BuffaloRenderer,
   156  		TemplatesBox:   packr.NewBox("../templates"),
   157  		Helpers:        map[string]interface{}{},
   158  	})
   159  
   160  	sampleHandler := func(c Context) error {
   161  		c.Set("opts", map[string]interface{}{})
   162  		return c.Render(200, rr.String(`
   163  			1. <%= rootPath() %>
   164  			2. <%= usersPath() %>
   165  			3. <%= userPath({user_id: 1}) %>
   166  			4. <%= myPeepsPath() %>
   167  			5. <%= userPath(opts) %>
   168  			6. <%= carPath({car_id: 1}) %>
   169  			7. <%= newCarPath() %>
   170  			8. <%= editCarPath({car_id: 1}) %>
   171  			9. <%= editCarPath({car_id: 1, other: 12}) %>
   172  			10. <%= rootPath({"some":"variable","other": 12}) %>
   173  			11. <%= rootPath() %>
   174  			12. <%= rootPath({"special/":"12=ss"}) %>
   175  		`))
   176  	}
   177  
   178  	a.GET("/", sampleHandler)
   179  	a.GET("/users", sampleHandler)
   180  	a.GET("/users/{user_id}", sampleHandler)
   181  	a.GET("/peeps", sampleHandler).Name("myPeeps")
   182  	a.Resource("/car", carsResource)
   183  
   184  	w := willie.New(a)
   185  	res := w.Request("/").Get()
   186  
   187  	r.Equal(200, res.Code)
   188  	r.Contains(res.Body.String(), "1. /")
   189  	r.Contains(res.Body.String(), "2. /users")
   190  	r.Contains(res.Body.String(), "3. /users/1")
   191  	r.Contains(res.Body.String(), "4. /peeps")
   192  	r.Contains(res.Body.String(), "5. /users/{user_id}")
   193  	r.Contains(res.Body.String(), "6. /car/1")
   194  	r.Contains(res.Body.String(), "7. /car/new")
   195  	r.Contains(res.Body.String(), "8. /car/1/edit")
   196  	r.Contains(res.Body.String(), "9. /car/1/edit?other=12")
   197  	r.Contains(res.Body.String(), "10. /?other=12&some=variable")
   198  	r.Contains(res.Body.String(), "11. /")
   199  	r.Contains(res.Body.String(), "12. /?special%2F=12%3Dss")
   200  }
   201  
   202  func Test_Resource(t *testing.T) {
   203  	r := require.New(t)
   204  
   205  	type trs struct {
   206  		Method string
   207  		Path   string
   208  		Result string
   209  	}
   210  
   211  	tests := []trs{
   212  		{
   213  			Method: "GET",
   214  			Path:   "",
   215  			Result: "list",
   216  		},
   217  		{
   218  			Method: "GET",
   219  			Path:   "/new",
   220  			Result: "new",
   221  		},
   222  		{
   223  			Method: "GET",
   224  			Path:   "/1",
   225  			Result: "show 1",
   226  		},
   227  		{
   228  			Method: "GET",
   229  			Path:   "/1/edit",
   230  			Result: "edit 1",
   231  		},
   232  		{
   233  			Method: "POST",
   234  			Path:   "",
   235  			Result: "create",
   236  		},
   237  		{
   238  			Method: "PUT",
   239  			Path:   "/1",
   240  			Result: "update 1",
   241  		},
   242  		{
   243  			Method: "DELETE",
   244  			Path:   "/1",
   245  			Result: "destroy 1",
   246  		},
   247  	}
   248  
   249  	a := Automatic(Options{})
   250  	a.Resource("/users", &userResource{})
   251  	a.Resource("/api/v1/users", &userResource{})
   252  
   253  	ts := httptest.NewServer(a)
   254  	defer ts.Close()
   255  
   256  	c := http.Client{}
   257  	for _, path := range []string{"/users", "/api/v1/users"} {
   258  		for _, test := range tests {
   259  			u := ts.URL + path + test.Path
   260  			req, err := http.NewRequest(test.Method, u, nil)
   261  			r.NoError(err)
   262  			res, err := c.Do(req)
   263  			r.NoError(err)
   264  			b, err := ioutil.ReadAll(res.Body)
   265  			r.NoError(err)
   266  			r.Equal(test.Result, string(b))
   267  		}
   268  	}
   269  
   270  }
   271  
   272  type userResource struct{}
   273  
   274  func (u *userResource) List(c Context) error {
   275  	return c.Render(200, render.String("list"))
   276  }
   277  
   278  func (u *userResource) Show(c Context) error {
   279  	return c.Render(200, render.String(`show <%=params["user_id"] %>`))
   280  }
   281  
   282  func (u *userResource) New(c Context) error {
   283  	return c.Render(200, render.String("new"))
   284  }
   285  
   286  func (u *userResource) Create(c Context) error {
   287  	return c.Render(200, render.String("create"))
   288  }
   289  
   290  func (u *userResource) Edit(c Context) error {
   291  	return c.Render(200, render.String(`edit <%=params["user_id"] %>`))
   292  }
   293  
   294  func (u *userResource) Update(c Context) error {
   295  	return c.Render(200, render.String(`update <%=params["user_id"] %>`))
   296  }
   297  
   298  func (u *userResource) Destroy(c Context) error {
   299  	return c.Render(200, render.String(`destroy <%=params["user_id"] %>`))
   300  }
   301  
   302  func Test_buildRouteName(t *testing.T) {
   303  	r := require.New(t)
   304  	cases := map[string]string{
   305  		"/":                                          "root",
   306  		"/users":                                     "users",
   307  		"/users/new":                                 "newUsers",
   308  		"/users/{user_id}":                           "user",
   309  		"/users/{user_id}/children":                  "userChildren",
   310  		"/users/{user_id}/children/{child_id}":       "userChild",
   311  		"/users/{user_id}/children/new":              "newUserChildren",
   312  		"/users/{user_id}/children/{child_id}/build": "userChildBuild",
   313  		"/admin/planes":                              "adminPlanes",
   314  		"/admin/planes/{plane_id}":                   "adminPlane",
   315  		"/admin/planes/{plane_id}/edit":              "editAdminPlane",
   316  	}
   317  
   318  	a := Automatic(Options{})
   319  
   320  	for input, result := range cases {
   321  		fResult := a.buildRouteName(input)
   322  		r.Equal(result, fResult, input)
   323  	}
   324  
   325  	a = Automatic(Options{Prefix: "/test"})
   326  	cases = map[string]string{
   327  		"/test":       "test",
   328  		"/test/users": "testUsers",
   329  	}
   330  
   331  	for input, result := range cases {
   332  		fResult := a.buildRouteName(input)
   333  		r.Equal(result, fResult, input)
   334  	}
   335  }
   336  
   337  func Test_CatchAll_Route(t *testing.T) {
   338  	r := require.New(t)
   339  	rr := render.New(render.Options{})
   340  
   341  	a := Automatic(Options{})
   342  	a.GET("/{name:.+}", func(c Context) error {
   343  		name := c.Param("name")
   344  		return c.Render(200, rr.String(name))
   345  	})
   346  
   347  	w := willie.New(a)
   348  	res := w.Request("/john").Get()
   349  
   350  	r.Contains(res.Body.String(), "john")
   351  }