diff --git a/internal/web/web_test.go b/internal/web/web_test.go new file mode 100644 index 0000000..f6ba3e8 --- /dev/null +++ b/internal/web/web_test.go @@ -0,0 +1,226 @@ +package web_test + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "git.kapelle.org/niklas/s3share/internal/client" + "git.kapelle.org/niklas/s3share/internal/db" + "git.kapelle.org/niklas/s3share/internal/s3" + "git.kapelle.org/niklas/s3share/internal/web" + "github.com/stretchr/testify/assert" +) + +func setup(t *testing.T) (*httptest.Server, *assert.Assertions) { + client := client.NewClient(db.NewMock(), s3.NewMockS3()) + router := web.CreateRouter(client, "admin", "hunter2") + + ts := httptest.NewServer(router) + + assert := assert.New(t) + + return ts, assert +} + +func genCreateShareRequest(ts *httptest.Server, key string) *http.Request { + body := "{\"key\": \"" + key + "\"}" + req, _ := http.NewRequest("POST", ts.URL+"/api/share", bytes.NewReader([]byte(body))) + req.Header.Add("Authorization", "Basic YWRtaW46aHVudGVyMg==") + req.Header.Add("Content-Type", "application/json") + + return req +} + +func TestCreateShare(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "test.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusCreated, res.StatusCode) + + // check json response + var jsonResponse map[string]interface{} + err = json.NewDecoder(res.Body).Decode(&jsonResponse) + assert.NoError(err) + assert.Equal("test.txt", jsonResponse["key"]) + assert.NotNil(jsonResponse["slug"]) + assert.NotEmpty(jsonResponse["slug"]) +} + +func TestCreateShareInvalidKey(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "not_existing.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusBadRequest, res.StatusCode) +} + +func TestGetShare(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "test.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusCreated, res.StatusCode) + + var jsonResponse map[string]string + err = json.NewDecoder(res.Body).Decode(&jsonResponse) + assert.NoError(err) + + req, err = http.NewRequest("GET", ts.URL+"/s/"+jsonResponse["slug"], nil) + assert.NoError(err) + + res, err = http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusOK, res.StatusCode) + + // check response + + assert.Equal("inline; filename=\"test.txt\"", res.Header.Get("Content-Disposition")) + assert.Equal("text/plain", res.Header.Get("Content-Type")) + + body, err := ioutil.ReadAll(res.Body) + assert.NoError(err) + assert.Equal("test.txt", string(body)) +} + +func TestGetShareInvalidSlug(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req, err := http.NewRequest("GET", ts.URL+"/s/123456", nil) + assert.NoError(err) + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusNotFound, res.StatusCode) +} + +func TestGetShareFileExt(t *testing.T) { + // Basically the same as TestGetShare, but with a file extension in the slug + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "test.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusCreated, res.StatusCode) + + var jsonResponse map[string]string + err = json.NewDecoder(res.Body).Decode(&jsonResponse) + assert.NoError(err) + + req, err = http.NewRequest("GET", ts.URL+"/s/"+jsonResponse["slug"]+".txt", nil) + assert.NoError(err) + + res, err = http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusOK, res.StatusCode) + + // check response + assert.Equal("inline; filename=\"test.txt\"", res.Header.Get("Content-Disposition")) + assert.Equal("text/plain", res.Header.Get("Content-Type")) + + body, err := ioutil.ReadAll(res.Body) + assert.NoError(err) + assert.Equal("test.txt", string(body)) +} + +func TestDeleteShare(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "test.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusCreated, res.StatusCode) + + var jsonResponse map[string]string + err = json.NewDecoder(res.Body).Decode(&jsonResponse) + assert.NoError(err) + + req, err = http.NewRequest("DELETE", ts.URL+"/api/share/"+jsonResponse["slug"], nil) + req.Header.Add("Authorization", "Basic YWRtaW46aHVudGVyMg==") + assert.NoError(err) + + res, err = http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusNoContent, res.StatusCode) + + req, err = http.NewRequest("GET", ts.URL+"/s/"+jsonResponse["slug"], nil) + assert.NoError(err) + + res, err = http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusNotFound, res.StatusCode) +} + +func TestDeleteShareInvalidSlug(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req, err := http.NewRequest("DELETE", ts.URL+"/api/share/123456", nil) + req.Header.Add("Authorization", "Basic YWRtaW46aHVudGVyMg==") + assert.NoError(err) + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusNotFound, res.StatusCode) +} + +func TestGetAll(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req := genCreateShareRequest(ts, "test.txt") + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusCreated, res.StatusCode) + + var jsonResponse map[string]string + err = json.NewDecoder(res.Body).Decode(&jsonResponse) + assert.NoError(err) + + req, err = http.NewRequest("GET", ts.URL+"/api/share", nil) + req.Header.Add("Authorization", "Basic YWRtaW46aHVudGVyMg==") + assert.NoError(err) + + res, err = http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusOK, res.StatusCode) + + // check response + var jsonResponse2 []map[string]string + err = json.NewDecoder(res.Body).Decode(&jsonResponse2) + assert.NoError(err) + assert.Equal(1, len(jsonResponse2)) + assert.Equal(jsonResponse["slug"], jsonResponse2[0]["slug"]) +} + +func TestInvalidAuth(t *testing.T) { + ts, assert := setup(t) + defer ts.Close() + + req, err := http.NewRequest("GET", ts.URL+"/api/share", nil) + req.Header.Add("Authorization", "Basic YWRtaW46aHVudGVyMw==") + assert.NoError(err) + + res, err := http.DefaultClient.Do(req) + assert.NoError(err) + assert.Equal(http.StatusUnauthorized, res.StatusCode) +}