package static import ( "io" "io/fs" "net/http" "net/http/httptest" "testing" "testing/fstest" "time" "github.com/stretchr/testify/require" ) func TestAssetHandler(t *testing.T) { t.Parallel() defaultData := []byte("this is the default file") otherData := []byte("this is a different file") m := http.FS(fstest.MapFS{ defaultFile: { Data: defaultData, ModTime: time.Now(), }, "somethingElse.js": { Data: otherData, ModTime: time.Now(), }, }) tests := []struct { name string reqPath string newPath string wantData []byte }{ { name: "path matches default", reqPath: "/" + defaultFile, newPath: "/" + defaultFile, wantData: defaultData, }, { name: "root path", reqPath: "/", newPath: "/" + defaultFile, wantData: defaultData, }, { name: "path matches a file", reqPath: "/somethingElse.js", newPath: "/somethingElse.js", wantData: otherData, }, { name: "path matches nothing", reqPath: "/something_random", newPath: fallbackPathSlug, wantData: defaultData, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { h := assetHandler(m) r := httptest.NewRequest("GET", tt.reqPath, nil) w := httptest.NewRecorder() h.ServeHTTP(w, r) b, err := io.ReadAll(w.Result().Body) require.NoError(t, err) require.Equal(t, http.StatusOK, w.Result().StatusCode) require.Equal(t, tt.wantData, b) require.Equal(t, tt.newPath, r.URL.Path) }) } } func TestModTimeFromInfo(t *testing.T) { t.Parallel() nowTime := time.Now() timeFunc := func() (time.Time, error) { return nowTime, nil } fsys := fstest.MapFS{ "zeroTime.file": { ModTime: time.Time{}, }, "notZeroTime.file": { ModTime: nowTime, }, } info1, err := fsys.Stat("zeroTime.file") require.NoError(t, err) info2, err := fsys.Stat("notZeroTime.file") require.NoError(t, err) tests := []struct { name string info fs.FileInfo want time.Time }{ { "zero time returns fallback time", info1, nowTime, }, { "non-zero time returns same time", info2, nowTime, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := modTimeFromInfo(tt.info, timeFunc) require.NoError(t, err) require.Equal(t, tt.want, got) }) } } func TestOpenAsset(t *testing.T) { t.Parallel() defaultData := []byte("this is the default file") otherData := []byte("this is a different file") m := http.FS(fstest.MapFS{ defaultFile: { Data: defaultData, }, "somethingElse.js": { Data: otherData, }, }) tests := []struct { name string file string fallback bool want []byte }{ { "default file by name", defaultFile, false, defaultData, }, { "other file by name", "somethingElse.js", false, otherData, }, { "falls back to default if can't find", "badFile.exe", true, defaultData, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotFile, fallback, err := openAsset(m, tt.file) require.NoError(t, err) require.Equal(t, tt.fallback, fallback) got, err := io.ReadAll(gotFile) require.NoError(t, err) require.Equal(t, tt.want, got) }) } } func TestEtag(t *testing.T) { t.Parallel() testTime := time.Time{} testTime = testTime.Add(26 * time.Hour) testTime = testTime.Add(15 * time.Minute) testTime = testTime.Add(20 * time.Second) testSize := int64(1500) got := etag(testSize, testTime) want := `"1500221520"` require.Equal(t, got, want) }