guestbook/cmd/web/handlers_guestbook_test.go

250 lines
5.9 KiB
Go

package main
import (
"bytes"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"testing"
"git.32bit.cafe/32bitcafe/guestbook/internal/assert"
)
func TestPing(t *testing.T) {
app := newTestApplication(t)
ts := newTestServer(t, app.routes())
defer ts.Close()
code, _, body := ts.get(t, "/ping")
assert.Equal(t, code, http.StatusOK)
assert.Equal(t, body, "OK")
}
func TestGetGuestbookView(t *testing.T) {
app := newTestApplication(t)
ts := newTestServer(t, app.routes())
defer ts.Close()
tests := []struct {
name string
urlPath string
wantCode int
wantBody string
}{
{
name: "Valid id",
urlPath: fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(1)),
wantCode: http.StatusOK,
wantBody: "Guestbook for Example",
},
{
name: "Non-existent ID",
urlPath: fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(2)),
wantCode: http.StatusNotFound,
},
{
name: "String ID",
urlPath: "/websites/abcd/guestbook",
wantCode: http.StatusNotFound,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
code, _, body := ts.get(t, tt.urlPath)
assert.Equal(t, code, tt.wantCode)
if tt.wantBody != "" {
assert.StringContains(t, body, tt.wantBody)
}
})
}
}
func TestPostGuestbookCommentCreate(t *testing.T) {
app := newTestApplication(t)
ts := newTestServer(t, app.routes())
defer ts.Close()
_, _, body := ts.get(t, fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(1)))
validCSRFToken := extractCSRFToken(t, body)
const (
validAuthorName = "John Test"
validAuthorEmail = "test@example.com"
validAuthorSite = "example.com"
validContent = "This is a comment"
)
tests := []struct {
name string
authorName string
authorEmail string
authorSite string
content string
csrfToken string
wantCode int
}{
{
name: "Valid input",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank name",
authorName: "",
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusUnprocessableEntity,
},
{
name: "Blank email",
authorName: validAuthorName,
authorEmail: "",
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank site",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: "",
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank content",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: "",
csrfToken: validCSRFToken,
wantCode: http.StatusUnprocessableEntity,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
form := url.Values{}
form.Add("authorname", tt.authorName)
form.Add("authoremail", tt.authorEmail)
form.Add("authorsite", tt.authorSite)
form.Add("content", tt.content)
form.Add("csrf_token", tt.csrfToken)
code, _, body := ts.postForm(t, fmt.Sprintf("/websites/%s/guestbook/comments/create", shortIdToSlug(1)), form)
assert.Equal(t, code, tt.wantCode)
assert.Equal(t, body, body)
})
}
}
func TestPostGuestbookCommentCreateRemote(t *testing.T) {
app := newTestApplication(t)
ts := newTestServer(t, app.routes())
defer ts.Close()
const (
validAuthorName = "John Test"
validAuthorEmail = "test@example.com"
validAuthorSite = "example.com"
validContent = "This is a comment"
)
tests := []struct {
name string
authorName string
authorEmail string
authorSite string
content string
wantCode int
wantBody string
}{
{
name: "Valid input",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
wantCode: http.StatusOK,
wantBody: "Comment successfully posted",
},
{
name: "Blank name",
authorName: "",
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
wantCode: http.StatusOK,
wantBody: "An error occurred",
},
{
name: "Blank email",
authorName: validAuthorName,
authorEmail: "",
authorSite: validAuthorSite,
content: validContent,
wantCode: http.StatusOK,
wantBody: "Comment successfully posted",
},
{
name: "Blank site",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: "",
content: validContent,
wantCode: http.StatusOK,
wantBody: "Comment successfully posted",
},
{
name: "Blank content",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: "",
wantCode: http.StatusOK,
wantBody: "An error occurred",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
form := url.Values{}
form.Add("authorname", tt.authorName)
form.Add("authoremail", tt.authorEmail)
form.Add("authorsite", tt.authorSite)
form.Add("content", tt.content)
r, err := http.NewRequest("POST", ts.URL, strings.NewReader(form.Encode()))
if err != nil {
t.Fatal(err)
}
r.URL.Path = fmt.Sprintf("/websites/%s/guestbook/comments/create/remote", shortIdToSlug(1))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
r.Header.Set("Origin", "http://example.com")
resp, err := ts.Client().Do(r)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
body = bytes.TrimSpace(body)
assert.Equal(t, resp.StatusCode, tt.wantCode)
assert.StringContains(t, string(body), tt.wantBody)
})
}
}