ch14.6-14.7
This commit is contained in:
@@ -134,8 +134,9 @@ func (app *application) snippetCreatePost(w http.ResponseWriter, r *http.Request
|
||||
func (app *application) userSignupPost(w http.ResponseWriter, r *http.Request) {
|
||||
var form userSignupForm
|
||||
err := app.decodePostForm(r, &form)
|
||||
|
||||
if err != nil {
|
||||
app.clientError(w, http.StatusBadRequest)
|
||||
app.notFound(w)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"gitea.local.lab/Lbenedar/snippetbox/internal/assert"
|
||||
@@ -76,3 +77,118 @@ func TestSnippetView(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserSignup(t *testing.T) {
|
||||
app := newTestApplication(t)
|
||||
ts := newTestServer(t, app.routes())
|
||||
defer ts.Close()
|
||||
|
||||
_, _, body := ts.get(t, "/user/signup")
|
||||
validCsrfToken := extractCSRFToken(t, body)
|
||||
t.Logf("CsrfToken: %s", validCsrfToken)
|
||||
|
||||
const (
|
||||
validName = "Bob"
|
||||
validPassword = "validPa$$word"
|
||||
validEmail = "bob@example.com"
|
||||
formTag = "<form action='/user/signup' method='POST' novalidate>"
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
userName string
|
||||
userEmail string
|
||||
userPassword string
|
||||
csrfToken string
|
||||
wantCode int
|
||||
wantFormTag string
|
||||
}{
|
||||
{
|
||||
name: "Valid submission",
|
||||
userName: validName,
|
||||
userEmail: validEmail,
|
||||
userPassword: validPassword,
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusSeeOther,
|
||||
},
|
||||
{
|
||||
name: "Invalid CSRF Token",
|
||||
userName: validName,
|
||||
userEmail: validEmail,
|
||||
userPassword: validPassword,
|
||||
csrfToken: "wrongToken",
|
||||
wantCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "Empty name",
|
||||
userName: "",
|
||||
userEmail: validEmail,
|
||||
userPassword: validPassword,
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
{
|
||||
name: "Empty email",
|
||||
userName: validName,
|
||||
userEmail: "",
|
||||
userPassword: validPassword,
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
{
|
||||
name: "Empty password",
|
||||
userName: validName,
|
||||
userEmail: validEmail,
|
||||
userPassword: "",
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
{
|
||||
name: "Invalid email",
|
||||
userName: validName,
|
||||
userEmail: "bob@example.",
|
||||
userPassword: validPassword,
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
{
|
||||
name: "Short password",
|
||||
userName: validName,
|
||||
userEmail: validEmail,
|
||||
userPassword: "pa$$",
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
{
|
||||
name: "Duplicate email",
|
||||
userName: validName,
|
||||
userEmail: "dupe@example.com",
|
||||
userPassword: validPassword,
|
||||
csrfToken: validCsrfToken,
|
||||
wantCode: http.StatusUnprocessableEntity,
|
||||
wantFormTag: formTag,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
form := url.Values{}
|
||||
form.Add("name", tt.userName)
|
||||
form.Add("email", tt.userEmail)
|
||||
form.Add("password", tt.userPassword)
|
||||
form.Add("csrf_token", tt.csrfToken)
|
||||
|
||||
code, _, body := ts.postForm(t, "/user/signup", form)
|
||||
|
||||
assert.Equal(t, code, tt.wantCode)
|
||||
if tt.wantFormTag != "" {
|
||||
assert.StringContains(t, body, tt.wantFormTag)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -15,6 +18,18 @@ import (
|
||||
"github.com/go-playground/form/v4"
|
||||
)
|
||||
|
||||
var csrfTokenRX = regexp.MustCompile(`<input type='hidden' name='csrf_token' value='(.+)'>`)
|
||||
|
||||
func extractCSRFToken(t *testing.T, body string) string {
|
||||
t.Logf("Body: %s", body)
|
||||
matches := csrfTokenRX.FindStringSubmatch(body)
|
||||
if len(matches) < 2 {
|
||||
t.Fatal("no csrf token found in body")
|
||||
}
|
||||
|
||||
return html.UnescapeString(string(matches[1]))
|
||||
}
|
||||
|
||||
func newTestApplication(t *testing.T) *application {
|
||||
templateCache, err := newTemplateCache()
|
||||
if err != nil {
|
||||
@@ -72,3 +87,18 @@ func (ts *testServer) get(t *testing.T, urlPath string) (int, http.Header, strin
|
||||
|
||||
return rs.StatusCode, rs.Header, string(body)
|
||||
}
|
||||
|
||||
func (ts *testServer) postForm(t *testing.T, urlPath string, form url.Values) (int, http.Header, string) {
|
||||
rs, err := ts.Client().PostForm(ts.URL+urlPath, form)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer rs.Body.Close()
|
||||
body, err := io.ReadAll(rs.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bytes.TrimSpace(body)
|
||||
return rs.StatusCode, rs.Header, string(body)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user