func TestSessionCreate(t *testing.T) { record := request.TestServer{t, TestHandler} Describe("when submitting a malformed request", func() { body := url.Values{ "not email": {"asdf"}, "not password": {"asdf"}, } It("should return 400", func() { record.Post("/login", body).Expect(400).Expect(`schema: invalid path`) }) }) Describe("when the request fails validation", func() { body := url.Values{ "email": {"not an actual email"}, "password": {"password"}, } It("should return 422", func() { record.Post("/login", body).Expect(422).Expect("invalid email or password") }) It("should fill in form values after failed submission", func() { record.Post("/login", body). Expect(`value="not an actual email"`). Expect(`value="password"`) }) }) Describe("when signing in", func() { var ( email = "*****@*****.**" password = "******" ) body := url.Values{ "email": {email}, "password": {password}, } BeforeEach(func() { body := url.Values{ "name": {"jason"}, "email": {email}, "password": {password}, "confirm": {password}, } record.Post("/signup", body).Expect(302) }) AfterEach(func() { query := "TRUNCATE TABLE users; ALTER SEQUENCE users_id_seq RESTART WITH 1" _, err := models.DB.Exec(query) if err != nil { t.Error(err) } }) // http://stackoverflow.com/questions/15721238/go-serial-execution-of-package-tests It("should return 302", func() { user := &models.User{ID: 1} if err := models.DB.Read(user); err != nil { t.Error(err) } record.Post("/login", body).Expect(302) }) It("should return a session cookie", func() { c := record.Post("/login", body).ResponseRecorder.Header().Get("Set-Cookie") assert.NotEmpty(t, c) }) It("regression :: should fill in the user's remember digest", func() { user := &models.User{ID: 1} if err := models.DB.Read(user); err != nil { t.Error(err) } user.RememberDigest = "" if err := models.DB.Update(user); err != nil { t.Error(err) } record.Post("/login", body) if err := models.DB.Read(user); err != nil { t.Error(err) } assert.NotEmpty(t, user.RememberDigest) }) It("should show a flash message", func() { h := record.Post("/login", body).ResponseRecorder.Header() h["Cookie"] = h["Set-Cookie"] h.Del("Set-Cookie") record.GetWithHeaders("/user/1", h).Expect("welcome jason!") }) It("should not show signup and login links", func() { h := record.Post("/login", body).ResponseRecorder.Header() h["Cookie"] = h["Set-Cookie"] h.Del("Set-Cookie") ctx := record.GetWithHeaders(h.Get("Location"), h) reader := strings.NewReader(ctx.ResponseRecorder.Body.String()) doc, err := goquery.NewDocumentFromReader(reader) if err != nil { t.Error(err) } doc.Find(".nav-item").Each(func(_ int, sel *goquery.Selection) { text := sel.Text() if strings.Contains(text, "Signup") || strings.Contains(text, "Login") { t.Error("whoops, you're logged in but signup and login links are present") } }) }) }) }
func TestUserCreate(t *testing.T) { record := request.TestServer{t, TestHandler} Describe("when the request is malformed", func() { body := url.Values{} body.Set("name", "jason") body.Set("not a user field", "asdf") It("should return 400", func() { record.Post("/signup", body).Expect(400).Expect(`bad request`) }) }) Describe("when the request fails validation", func() { body := url.Values{} body.Set("name", "jesse") body.Set("email", "*****@*****.**") body.Set("password", "some random password") body.Set("confirm", "fail confirm") It("should return 422", func() { record.Post("/signup", body).Expect(422).Expect("password does not match") }) It("should fill in form values after failed submission", func() { record.Post("/signup", body). Expect(`value="jesse"`). Expect(`value="*****@*****.**"`). Expect(`value="some random password"`). Expect(`value="fail confirm"`) }) }) Describe("when creating a user that already exists", func() { var ( name = "jason" email = "*****@*****.**" ) BeforeEach(func() { user := &models.User{Name: name, Email: email} _, err := models.DB.Create(user) if err != nil { t.Error(err) } }) AfterEach(func() { query := "TRUNCATE TABLE users; ALTER SEQUENCE users_id_seq RESTART WITH 1" _, err := models.DB.Exec(query) if err != nil { t.Error(err) } }) It("should return a 409 for an existing email", func() { body := url.Values{} body.Set("name", name) body.Set("email", email) body.Set("password", "somepassword") body.Set("confirm", "somepassword") record.Post("/signup", body).Expect(409).Expect("email is taken") }) }) Describe("when creating a user that doesn't exist", func() { body := url.Values{ "name": {"jason"}, "email": {"*****@*****.**"}, "password": {"somepassword"}, "confirm": {"somepassword"}, } AfterEach(func() { query := "TRUNCATE TABLE users; ALTER SEQUENCE users_id_seq RESTART WITH 1" _, err := models.DB.Exec(query) if err != nil { t.Error(err) } }) It("should sign in", func() { ctx := record.Post("/signup", body) assert.NotEmpty(t, ctx.ResponseRecorder.Header().Get("Set-Cookie")) }) It("should redirect to the newly created profile", func() { ctx := record.Post("/signup", body).Expect(302) redirect := ctx.ResponseRecorder.Header().Get("Location") assert.Equal(t, "/user/1", redirect) }) It("should work regardless of the current session cookie", func() { ctx := record.Post("/signup", body) header := ctx.ResponseRecorder.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") models.Store = sessions.NewCookieStore( securecookie.GenerateRandomKey(64), securecookie.GenerateRandomKey(16), ) b2 := url.Values{ "name": {"jesse"}, "email": {"coolstory@bro"}, "password": {"somepassword"}, "confirm": {"somepassword"}, } record.PostWithHeaders("/signup", header, b2).Expect(302) }) It("regression :: should set the password and remember digest", func() { record.Post("/signup", body) user := &models.User{ID: 1} err := models.DB.Read(user) if err != nil { t.Error(err) } assert.NotEmpty(t, user.PasswordDigest) assert.NotEmpty(t, user.RememberDigest) }) It("should show a welcome flash message", func() { ctx := record.Post("/signup", body) h := ctx.ResponseRecorder.Header() h["Cookie"] = h["Set-Cookie"] h.Del("Set-Cookie") record.GetWithHeaders("/user/1", h).Expect("welcome jason!") }) }) Describe("when redirected after successful signup", func() { ctx := record.Post("/signup", url.Values{ "name": {"jason"}, "email": {"*****@*****.**"}, "password": {"somepassword"}, "confirm": {"somepassword"}, }) h := ctx.ResponseRecorder.Header() h["Cookie"] = h["Set-Cookie"] h.Del("Set-Cookie") ctx = record.GetWithHeaders("/user/1", h) reader := strings.NewReader(ctx.ResponseRecorder.Body.String()) doc, err := goquery.NewDocumentFromReader(reader) if err != nil { t.Error(err) } It("should not show signup and login links", func() { doc.Find(".nav-item").Each(func(_ int, sel *goquery.Selection) { text := sel.Text() if strings.Contains(text, "Signup") || strings.Contains(text, "Login") { t.Errorf("whoops, you're logged in but signup and login links are present") } }) }) }) }
func TestSessionDestroy(t *testing.T) { record := request.TestServer{t, TestHandler} Describe("when logging out after logging in", func() { // Create a user. body := url.Values{ "name": {"jason"}, "email": {"*****@*****.**"}, "password": {"password"}, "confirm": {"password"}, } record.Post("/signup", body).Expect(302) // Defer cleanup. defer func() { clearTable := "TRUNCATE TABLE users; ALTER SEQUENCE users_id_seq RESTART WITH 1" _, err := models.DB.Exec(clearTable) if err != nil { t.Error(err) } }() // Login. b2 := url.Values{ "email": {"*****@*****.**"}, "password": {"password"}, } ctx := record.Post("/login", b2).Expect(302) header := ctx.ResponseRecorder.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") ctx = record.GetWithHeaders("/logout", header).Expect(302) It("should redirect to the home page", func() { assert.Equal(t, ctx.ResponseRecorder.Header().Get("Location"), "/") }) It("should show a flash message", func() { redirect := ctx.ResponseRecorder.Header().Get("Location") header = ctx.ResponseRecorder.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") record.GetWithHeaders(redirect, header).Expect("you have been logged out") }) }) Describe("when the session is invalid", func() { // Make an invalid cookie. w, _ := NewReqRes(t) http.SetCookie(w, &http.Cookie{Name: models.SessionName, Value: "asdf"}) // Do a GET with the invalid cookie. header := w.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") ctx := record.GetWithHeaders("/logout", header) It("should redirect to the home page", func() { assert.Equal(t, "/", ctx.ResponseRecorder.Header().Get("Location")) }) }) Describe("when the session is valid but the user ID is absent", func() { // Create a valid session cookie. w, r := NewReqRes(t) session, err := models.Store.Get(r, models.SessionName) if err != nil { t.Error(err) } if session.Save(r, w); err != nil { t.Error(err) } // Do a GET with the valid session cookie. header := w.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") ctx := record.GetWithHeaders("/logout", header) It("should clear the session cookie", func() { assert.NotEmpty(t, ctx.ResponseRecorder.Header().Get("Set-Cookie")) }) It("should redirect to the home page", func() { assert.Equal(t, "/", ctx.ResponseRecorder.Header().Get("Location")) }) }) Describe("when the session is valid and the user ID is present", func() { // Create a user. body := url.Values{ "name": {"jason"}, "email": {"*****@*****.**"}, "password": {"password"}, "confirm": {"password"}, } record.Post("/signup", body).Expect(302) // Defer cleanup. defer func() { clearTable := "TRUNCATE TABLE users; ALTER SEQUENCE users_id_seq RESTART WITH 1" _, err := models.DB.Exec(clearTable) if err != nil { t.Error(err) } }() // Create a valid session cookie. w, r := NewReqRes(t) session, err := models.Store.Get(r, models.SessionName) if err != nil { t.Error(err) } session.Values[models.UserID] = 1 if session.Save(r, w); err != nil { t.Error(err) } // Do a GET with the valid session cookie. header := w.Header() header["Cookie"] = header["Set-Cookie"] header.Del("Set-Cookie") ctx := record.GetWithHeaders("/logout", header) It("should clear the session cookie", func() { assert.NotEmpty(t, ctx.ResponseRecorder.Header().Get("Set-Cookie")) }) It("should redirect to the home page", func() { assert.Equal(t, "/", ctx.ResponseRecorder.Header().Get("Location")) }) It("should clear the remember fields", func() { user := &models.User{ID: 1} if err := models.DB.Read(user); err != nil { t.Error(err) } assert.Empty(t, user.RememberToken) assert.Empty(t, user.RememberDigest) }) }) }