goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/static_test.go (about)

     1  package goyave
     2  
     3  import (
     4  	"io"
     5  	"io/fs"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  	"goyave.dev/goyave/v5/config"
    13  	"goyave.dev/goyave/v5/util/fsutil"
    14  	"goyave.dev/goyave/v5/util/fsutil/osfs"
    15  )
    16  
    17  func TestCleanStaticPath(t *testing.T) {
    18  
    19  	cases := []struct {
    20  		directory string
    21  		file      string
    22  		want      string
    23  	}{
    24  		{directory: ".", file: "config/index.html", want: "config/index.html"},
    25  		{directory: ".", file: "config", want: "config/index.html"},
    26  		{directory: ".", file: "config/", want: "config/index.html"},
    27  		{directory: ".", file: "config/defaults.json", want: "config/defaults.json"},
    28  		{directory: "config", file: "index.html", want: "index.html"},
    29  		{directory: "config", file: "", want: "index.html"},
    30  		{directory: "config", file: "defaults.json", want: "defaults.json"},
    31  		{directory: "resources", file: "lang/en-US/locale.json", want: "lang/en-US/locale.json"},
    32  		{directory: "resources", file: "/lang/en-US/locale.json", want: "lang/en-US/locale.json"},
    33  		{directory: "resources", file: "img/logo", want: "img/logo/index.html"},
    34  		{directory: "resources", file: "img/logo/", want: "img/logo/index.html"},
    35  		{directory: "resources", file: "img", want: "img/index.html"},
    36  		{directory: "resources", file: "img/", want: "img/index.html"},
    37  	}
    38  
    39  	for _, c := range cases {
    40  		c := c
    41  		t.Run(c.want, func(t *testing.T) {
    42  			f, err := fs.Sub(&osfs.FS{}, c.directory)
    43  			require.NoError(t, err)
    44  			assert.Equal(t, c.want, cleanStaticPath(fsutil.NewEmbed(f.(fs.ReadDirFS)), c.file))
    45  		})
    46  	}
    47  }
    48  
    49  func TestStaticHandler(t *testing.T) {
    50  
    51  	cases := []struct {
    52  		expected  func(*testing.T, *Response, *http.Response, []byte)
    53  		uri       string
    54  		directory string
    55  		download  bool
    56  	}{
    57  		{
    58  			uri:       "/custom_config.json",
    59  			directory: "resources",
    60  			download:  false,
    61  			expected: func(t *testing.T, response *Response, result *http.Response, body []byte) {
    62  				assert.Equal(t, http.StatusOK, response.GetStatus())
    63  				assert.Equal(t, "application/json", result.Header.Get("Content-Type"))
    64  				assert.Equal(t, "inline", result.Header.Get("Content-Disposition"))
    65  				assert.Equal(t, "{\n    \"custom-entry\": \"value\"\n}", string(body))
    66  			},
    67  		},
    68  		{
    69  			uri:       "/doesn'texist",
    70  			directory: "resources",
    71  			download:  false,
    72  			expected: func(t *testing.T, response *Response, _ *http.Response, _ []byte) {
    73  				assert.Equal(t, http.StatusNotFound, response.GetStatus())
    74  			},
    75  		},
    76  		{
    77  			uri:       "/custom_config.json",
    78  			directory: "resources",
    79  			download:  true,
    80  			expected: func(t *testing.T, response *Response, result *http.Response, body []byte) {
    81  				assert.Equal(t, http.StatusOK, response.GetStatus())
    82  				assert.Equal(t, "application/json", result.Header.Get("Content-Type"))
    83  				assert.Equal(t, "attachment; filename=\"custom_config.json\"", result.Header.Get("Content-Disposition"))
    84  				assert.Equal(t, "{\n    \"custom-entry\": \"value\"\n}", string(body))
    85  			},
    86  		},
    87  		{
    88  			uri:       "/lang/en-US/fields.json",
    89  			directory: "resources",
    90  			download:  true,
    91  			expected: func(t *testing.T, response *Response, result *http.Response, body []byte) {
    92  				assert.Equal(t, http.StatusOK, response.GetStatus())
    93  				assert.Equal(t, "application/json", result.Header.Get("Content-Type"))
    94  				assert.Equal(t, "attachment; filename=\"fields.json\"", result.Header.Get("Content-Disposition"))
    95  				assert.Equal(t, "{\n    \"email\": \"email address\"\n}", string(body))
    96  			},
    97  		},
    98  	}
    99  
   100  	for _, c := range cases {
   101  		c := c
   102  		t.Run(c.uri, func(t *testing.T) {
   103  
   104  			cfg := config.LoadDefault()
   105  			srv, err := New(Options{Config: cfg})
   106  			require.NoError(t, err)
   107  
   108  			request := NewRequest(httptest.NewRequest(http.MethodGet, c.uri, nil))
   109  			request.RouteParams = map[string]string{"resource": c.uri}
   110  
   111  			recorder := httptest.NewRecorder()
   112  			response := NewResponse(srv, request, recorder)
   113  
   114  			f, err := fs.Sub(&osfs.FS{}, c.directory)
   115  			require.NoError(t, err)
   116  			handler := staticHandler(fsutil.NewEmbed(f.(fs.ReadDirFS)), c.download)
   117  			handler(response, request)
   118  
   119  			result := recorder.Result()
   120  			body, err := io.ReadAll(result.Body)
   121  			assert.NoError(t, result.Body.Close())
   122  			require.NoError(t, err)
   123  			c.expected(t, response, result, body)
   124  		})
   125  	}
   126  }