Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge guest link post tests #651

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 49 additions & 55 deletions handlers/guest_links_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import (
"github.com/mtlynch/picoshare/v2/store/test_sqlite"
)

func TestGuestLinksPostAcceptsValidRequest(t *testing.T) {
func TestGuestLinksPost(t *testing.T) {
for _, tt := range []struct {
description string
payload string
currentTime time.Time
expected picoshare.GuestLink
status int
}{
{
description: "minimally populated request",
Expand All @@ -42,6 +43,7 @@ func TestGuestLinksPostAcceptsValidRequest(t *testing.T) {
MaxFileBytes: picoshare.GuestUploadUnlimitedFileSize,
MaxFileUploads: picoshare.GuestUploadUnlimitedFileUploads,
},
status: http.StatusOK,
},
{
description: "fully populated request",
Expand All @@ -61,6 +63,7 @@ func TestGuestLinksPostAcceptsValidRequest(t *testing.T) {
MaxFileBytes: makeGuestUploadMaxFileBytes(1048576),
MaxFileUploads: makeGuestUploadCountLimit(1),
},
status: http.StatusOK,
},
{
description: "guest file expires in 1 day",
Expand All @@ -80,6 +83,7 @@ func TestGuestLinksPostAcceptsValidRequest(t *testing.T) {
MaxFileBytes: makeGuestUploadMaxFileBytes(1048576),
MaxFileUploads: makeGuestUploadCountLimit(1),
},
status: http.StatusOK,
},
{
description: "guest file expires in 30 days",
Expand All @@ -99,66 +103,17 @@ func TestGuestLinksPostAcceptsValidRequest(t *testing.T) {
MaxFileBytes: makeGuestUploadMaxFileBytes(1048576),
MaxFileUploads: makeGuestUploadCountLimit(1),
},
status: http.StatusOK,
},
} {
t.Run(tt.description, func(t *testing.T) {
dataStore := test_sqlite.New()
c := mockClock{tt.currentTime}
s := handlers.New(mockAuthenticator{}, &dataStore, nilSpaceChecker, nilGarbageCollector, c)

req, err := http.NewRequest("POST", "/api/guest-links", strings.NewReader(tt.payload))
if err != nil {
t.Fatal(err)
}
req.Header.Add("Content-Type", "text/json")

rec := httptest.NewRecorder()
s.Router().ServeHTTP(rec, req)
res := rec.Result()

if status := res.StatusCode; status != http.StatusOK {
t.Fatalf("%s: handler returned wrong status code: got %v want %v",
tt.description, status, http.StatusOK)
}

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("failed to read response body")
}

var response handlers.GuestLinkPostResponse
err = json.Unmarshal(body, &response)
if err != nil {
t.Fatalf("response is not valid JSON: %v", body)
}

gl, err := dataStore.GetGuestLink(picoshare.GuestLinkID(response.ID))
if err != nil {
t.Fatalf("%s: failed to retrieve guest link from datastore: %v", tt.description, err)
}

// Copy the ID, which we can't predict in advance.
tt.expected.ID = picoshare.GuestLinkID(response.ID)

if got, want := gl, tt.expected; !reflect.DeepEqual(got, want) {
t.Fatalf("guestLink=%+v, want=%+v", got, want)
}
})
}
}

func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
for _, tt := range []struct {
description string
payload string
}{
{
description: "empty string",
payload: "",
status: http.StatusBadRequest,
},
{
description: "empty payload",
payload: "{}",
status: http.StatusBadRequest,
},
{
description: "invalid label field (non-string)",
Expand All @@ -168,6 +123,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "invalid label field (too long)",
Expand All @@ -177,6 +133,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": null
}`, strings.Repeat("A", 201)),
status: http.StatusBadRequest,
},
{
description: "missing urlExpirationTime field",
Expand All @@ -185,6 +142,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "invalid expirationTime field",
Expand All @@ -194,6 +152,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "negative maxFileBytes field",
Expand All @@ -203,6 +162,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": -5,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "decimal maxFileBytes field",
Expand All @@ -212,6 +172,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": 1.5,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "too low a maxFileBytes field",
Expand All @@ -221,6 +182,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": 1,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "zero maxFileBytes field",
Expand All @@ -230,6 +192,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": 0,
"maxFileUploads": null
}`,
status: http.StatusBadRequest,
},
{
description: "negative maxFileUploads field",
Expand All @@ -239,6 +202,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": -5
}`,
status: http.StatusBadRequest,
},
{
description: "decimal maxFileUploads field",
Expand All @@ -248,6 +212,7 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": 1.5
}`,
status: http.StatusBadRequest,
},
{
description: "zero maxFileUploads field",
Expand All @@ -257,11 +222,13 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
"maxFileBytes": null,
"maxFileUploads": 0
}`,
status: http.StatusBadRequest,
},
} {
t.Run(tt.description, func(t *testing.T) {
dataStore := test_sqlite.New()
s := handlers.New(mockAuthenticator{}, &dataStore, nilSpaceChecker, nilGarbageCollector, handlers.NewClock())
c := mockClock{tt.currentTime}
s := handlers.New(mockAuthenticator{}, &dataStore, nilSpaceChecker, nilGarbageCollector, c)

req, err := http.NewRequest("POST", "/api/guest-links", strings.NewReader(tt.payload))
if err != nil {
Expand All @@ -273,9 +240,36 @@ func TestGuestLinksPostRejectsInvalidRequest(t *testing.T) {
s.Router().ServeHTTP(rec, req)
res := rec.Result()

if got, want := res.StatusCode, http.StatusBadRequest; got != want {
if got, want := res.StatusCode, tt.status; got != want {
t.Fatalf("status=%d, want=%d", got, want)
}

if tt.status != http.StatusOK {
return
}

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatal("failed to read response body")
}

var response handlers.GuestLinkPostResponse
err = json.Unmarshal(body, &response)
if err != nil {
t.Fatalf("response is not valid JSON: %v", body)
}

gl, err := dataStore.GetGuestLink(picoshare.GuestLinkID(response.ID))
if err != nil {
t.Fatalf("failed to retrieve guest link from datastore: %v", err)
}

// Copy the ID, which we can't predict in advance.
tt.expected.ID = picoshare.GuestLinkID(response.ID)

if got, want := gl, tt.expected; !reflect.DeepEqual(got, want) {
t.Fatalf("guestLink=%+v, want=%+v", got, want)
}
})
}
}
Expand Down
Loading