fix panic when submitting invalid form on guestbook page #24
| @ -179,9 +179,7 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt | |||||||
| 
 | 
 | ||||||
| 	form.CheckField(validator.NotBlank(form.AuthorName), "authorName", "This field cannot be blank") | 	form.CheckField(validator.NotBlank(form.AuthorName), "authorName", "This field cannot be blank") | ||||||
| 	form.CheckField(validator.MaxChars(form.AuthorName, 256), "authorName", "This field cannot be more than 256 characters long") | 	form.CheckField(validator.MaxChars(form.AuthorName, 256), "authorName", "This field cannot be more than 256 characters long") | ||||||
| 	form.CheckField(validator.NotBlank(form.AuthorEmail), "authorEmail", "This field cannot be blank") |  | ||||||
| 	form.CheckField(validator.MaxChars(form.AuthorEmail, 256), "authorEmail", "This field cannot be more than 256 characters long") | 	form.CheckField(validator.MaxChars(form.AuthorEmail, 256), "authorEmail", "This field cannot be more than 256 characters long") | ||||||
| 	form.CheckField(validator.NotBlank(form.AuthorSite), "authorSite", "This field cannot be blank") |  | ||||||
| 	form.CheckField(validator.MaxChars(form.AuthorSite, 256), "authorSite", "This field cannot be more than 256 characters long") | 	form.CheckField(validator.MaxChars(form.AuthorSite, 256), "authorSite", "This field cannot be more than 256 characters long") | ||||||
| 	form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank") | 	form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank") | ||||||
| 
 | 
 | ||||||
| @ -193,7 +191,8 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		data := app.newCommonData(r) | 		data := app.newCommonData(r) | ||||||
| 		views.GuestbookView("Guestbook", data, website, website.Guestbook, comments, forms.CommentCreateForm{}).Render(r.Context(), w) | 		w.WriteHeader(http.StatusUnprocessableEntity) | ||||||
|  | 		views.GuestbookView("Guestbook", data, website, website.Guestbook, comments, form).Render(r.Context(), w) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -203,7 +202,7 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt | |||||||
| 		app.serverError(w, r, err) | 		app.serverError(w, r, err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!") | 	app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!") | ||||||
| 	http.Redirect(w, r, fmt.Sprintf("/websites/%s/guestbook", slug), http.StatusSeeOther) | 	http.Redirect(w, r, fmt.Sprintf("/websites/%s/guestbook", slug), http.StatusSeeOther) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"git.32bit.cafe/32bitcafe/guestbook/internal/assert" | 	"git.32bit.cafe/32bitcafe/guestbook/internal/assert" | ||||||
| @ -58,3 +59,88 @@ func TestGetGuestbookView(t *testing.T) { | |||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 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) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ func (app *application) routes() http.Handler { | |||||||
| 	standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders) | 	standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders) | ||||||
| 
 | 
 | ||||||
| 	mux.Handle("/{$}", dynamic.ThenFunc(app.home)) | 	mux.Handle("/{$}", dynamic.ThenFunc(app.home)) | ||||||
| 	mux.Handle("POST /websites/{id}/guestbook/comments/create", standard.ThenFunc(app.postGuestbookCommentCreate)) | 	mux.Handle("POST /websites/{id}/guestbook/comments/create", dynamic.ThenFunc(app.postGuestbookCommentCreate)) | ||||||
| 	mux.Handle("GET /websites/{id}/guestbook", dynamic.ThenFunc(app.getGuestbook)) | 	mux.Handle("GET /websites/{id}/guestbook", dynamic.ThenFunc(app.getGuestbook)) | ||||||
| 	mux.Handle("GET /users/register", dynamic.ThenFunc(app.getUserRegister)) | 	mux.Handle("GET /users/register", dynamic.ThenFunc(app.getUserRegister)) | ||||||
| 	mux.Handle("POST /users/register", dynamic.ThenFunc(app.postUserRegister)) | 	mux.Handle("POST /users/register", dynamic.ThenFunc(app.postUserRegister)) | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ type CommentCreateForm struct { | |||||||
| 	AuthorName          string `schema:"authorname"` | 	AuthorName          string `schema:"authorname"` | ||||||
| 	AuthorEmail         string `schema:"authoremail"` | 	AuthorEmail         string `schema:"authoremail"` | ||||||
| 	AuthorSite          string `schema:"authorsite"` | 	AuthorSite          string `schema:"authorsite"` | ||||||
| 	Content             string `schema:"content,required"` | 	Content             string `schema:"content"` | ||||||
| 	validator.Validator `schema:"-"` | 	validator.Validator `schema:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user