Test the snippetCreate handler
Your goal in this exercise is to create an end-to-end test for the GET /snippet/create
route. Specifically, you want to test that:
- Unauthenticated users are redirected to the login form.
- Authenticated users are shown the form to create a new snippet.
Step 1
Create a new TestSnippetCreate
test in your cmd/web/handlers_test.go
file. In this test, use the pattern and helpers from the end-to-end testing chapter to initialize a new test server using the application routes and mocked dependencies.
Step 2
Create a sub-test with the name "Unauthenticated"
. In this sub-test, make a GET /snippet/create
request against the test server as an unauthenticated user. Verify that the response has the status code 303
and a Location: /user/login
header. Again, reuse the helpers that we made in the end-to-end testing chapter.
Step 3
Create another sub-test with the name "Authenticated
”. In this sub-test, mimic the workflow of logging in as a user to authenticate. Specifically, you’ll need to make a GET /user/login
request, extract the CSRF token from the response body, then make a POST /user/login
request using the credentials in the mock user model (email of "alice@example.com"
, password of "pa$$word"
).
Then once you’ve authenticated, make a GET /snippet/create
request and verify that you receive the status code 200
and an HTML body including the text <form action='/snippet/create' method='POST'>
.
Suggested code
Suggested code for step 1
... func TestSnippetCreate(t *testing.T) { app := newTestApplication(t) ts := newTestServer(t, app.routes()) defer ts.Close() }
Suggested code for step 2
... func TestSnippetCreate(t *testing.T) { app := newTestApplication(t) ts := newTestServer(t, app.routes()) defer ts.Close() t.Run("Unauthenticated", func(t *testing.T) { code, headers, _ := ts.get(t, "/snippet/create") assert.Equal(t, code, http.StatusSeeOther) assert.Equal(t, headers.Get("Location"), "/user/login") }) }
$ go test -v -run=TestSnippetCreate ./cmd/web/ === RUN TestSnippetCreate === RUN TestSnippetCreate/Unauthenticated --- PASS: TestSnippetCreate (0.01s) --- PASS: TestSnippetCreate/Unauthenticated (0.00s) PASS ok snippetbox.alexedwards.net/cmd/web 0.010s
Suggested code for step 3
... func TestSnippetCreate(t *testing.T) { app := newTestApplication(t) ts := newTestServer(t, app.routes()) defer ts.Close() t.Run("Unauthenticated", func(t *testing.T) { code, headers, _ := ts.get(t, "/snippet/create") assert.Equal(t, code, http.StatusSeeOther) assert.Equal(t, headers.Get("Location"), "/user/login") }) t.Run("Authenticated", func(t *testing.T) { // Make a GET /user/login request and extract the CSRF token from the // response. _, _, body := ts.get(t, "/user/login") csrfToken := extractCSRFToken(t, body) // Make a POST /user/login request using the extracted CSRF token and // credentials from our the mock user model. form := url.Values{} form.Add("email", "alice@example.com") form.Add("password", "pa$$word") form.Add("csrf_token", csrfToken) ts.postForm(t, "/user/login", form) // Then check that the authenticated user is shown the create snippet // form. code, _, body := ts.get(t, "/snippet/create") assert.Equal(t, code, http.StatusOK) assert.StringContains(t, body, "<form action='/snippet/create' method='POST'>") }) }
$ go test -v -run=TestSnippetCreate ./cmd/web/ === RUN TestSnippetCreate === RUN TestSnippetCreate/Unauthenticated === RUN TestSnippetCreate/Authenticated --- PASS: TestSnippetCreate (0.01s) --- PASS: TestSnippetCreate/Unauthenticated (0.00s) --- PASS: TestSnippetCreate/Authenticated (0.00s) PASS ok snippetbox.alexedwards.net/cmd/web 0.012s