go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/web/static_fileserver_test.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package web
     9  
    10  import (
    11  	"bytes"
    12  	"io"
    13  	"io/fs"
    14  	"net/http"
    15  	"net/http/httptest"
    16  	"os"
    17  	"testing"
    18  	"time"
    19  
    20  	. "go.charczuk.com/sdk/assert"
    21  )
    22  
    23  type mockFS map[string][]byte
    24  
    25  func (m mockFS) Open(path string) (http.File, error) {
    26  	if contents, ok := m[path]; ok {
    27  		return mockFile{
    28  			Reader: bytes.NewReader(contents),
    29  			Name:   path,
    30  		}, nil
    31  	}
    32  	return nil, os.ErrNotExist
    33  }
    34  
    35  type mockFile struct {
    36  	*bytes.Reader
    37  	Name    string
    38  	ModTime time.Time
    39  }
    40  
    41  func (mf mockFile) Close() error { return nil }
    42  
    43  func (mf mockFile) Readdir(_ int) ([]fs.FileInfo, error) { return nil, nil }
    44  
    45  func (mf mockFile) Stat() (os.FileInfo, error) {
    46  	return mockFileInfo{
    47  		name:    mf.Name,
    48  		size:    int64(mf.Reader.Len()),
    49  		modTime: mf.ModTime,
    50  	}, nil
    51  }
    52  
    53  type mockFileInfo struct {
    54  	name    string
    55  	size    int64
    56  	modTime time.Time
    57  }
    58  
    59  func (mfi mockFileInfo) Name() string       { return mfi.name }
    60  func (mfi mockFileInfo) Size() int64        { return mfi.size }
    61  func (mfi mockFileInfo) Mode() os.FileMode  { return 0444 }        // Read for all
    62  func (mfi mockFileInfo) ModTime() time.Time { return mfi.modTime } // Return anything
    63  func (mfi mockFileInfo) IsDir() bool        { return false }
    64  func (mfi mockFileInfo) Sys() interface{}   { return nil }
    65  
    66  func Test_StaticFileServer(t *testing.T) {
    67  	testFileSystem0 := mockFS{
    68  		"/foo/index.html": []byte(`index 0`),
    69  		"/foo/bar":        []byte(`test file 0`),
    70  		"/foo/baz":        []byte(`test file 1`),
    71  	}
    72  	testFileSystem1 := mockFS{
    73  		"/moo/index.html": []byte(`index 1`),
    74  		"/moo/bar":        []byte(`test file 2`),
    75  		"/moo/baz":        []byte(`test file 3`),
    76  		"/moo/buzz":       []byte(`test file 4`),
    77  	}
    78  
    79  	staticServer := &StaticFileServer{
    80  		SearchPaths: []http.FileSystem{
    81  			testFileSystem0,
    82  			testFileSystem1,
    83  		},
    84  	}
    85  	var didRewrite bool
    86  	err := staticServer.AddRegexPathRewrite("/$", func(path string, _ ...string) string {
    87  		didRewrite = true
    88  		return path + "index.html"
    89  	})
    90  	ItsNil(t, err)
    91  
    92  	httpServer := httptest.NewServer(staticServer)
    93  	defer httpServer.Close()
    94  
    95  	res, err := http.Get(httpServer.URL + "/moo/")
    96  	ItsNil(t, err)
    97  	ItsEqual(t, true, didRewrite)
    98  	ItsEqual(t, http.StatusOK, res.StatusCode)
    99  	defer res.Body.Close()
   100  
   101  	contents, err := io.ReadAll(res.Body)
   102  	ItsNil(t, err)
   103  	ItsEqual(t, "index 1", string(contents))
   104  }