Esempio n. 1
0
// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *FacebookTestSuite) SetupSuite() {
	// Initialise the config
	suite.cnf = config.NewConfig(false, false)

	// Create the test database
	db, err := database.CreateTestDatabasePostgres(
		testDbUser,
		testDbName,
		testMigrations,
		testFixtures,
	)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = db

	// Fetch test accounts
	suite.accounts = make([]*accounts.Account, 0)
	err = accounts.AccountPreload(suite.db).Order("id").Find(&suite.accounts).Error
	if err != nil {
		log.Fatal(err)
	}

	// Fetch test users
	suite.users = make([]*accounts.User, 0)
	err = accounts.UserPreload(suite.db).Order("id").Find(&suite.users).Error
	if err != nil {
		log.Fatal(err)
	}

	// Initialise mocks
	suite.adapterMock = new(facebook.AdapterMock)

	// Initialise the service
	suite.service = facebook.NewService(
		suite.cnf,
		suite.db,
		accounts.NewService(
			suite.cnf,
			suite.db,
			oauth.NewService(suite.cnf, suite.db),
			new(emailMocks.ServiceInterface),
			new(accountsMocks.EmailFactoryInterface),
		),
		suite.adapterMock,
	)

	// Register routes
	suite.router = mux.NewRouter()
	suite.service.RegisterRoutes(suite.router, "/v1/facebook")
}
func (suite *AccountsTestSuite) TestGetMyUser() {
	// Prepare a request
	r, err := http.NewRequest("GET", "http://1.2.3.4/v1/me", nil)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set("Authorization", "Bearer test_user_token")

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "get_my_user", match.Route.GetName())
	}

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Check that the mock object expectations were met
	suite.assertMockExpectations()

	// Check the status code
	if !assert.Equal(suite.T(), 200, w.Code) {
		log.Print(w.Body.String())
	}

	// Fetch the user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).First(user, suite.users[1].ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Check the response
	expected := &accounts.UserResponse{
		Hal: jsonhal.Hal{
			Links: map[string]*jsonhal.Link{
				"self": &jsonhal.Link{
					Href: fmt.Sprintf("/v1/users/%d", user.ID),
				},
			},
		},
		ID:        user.ID,
		Email:     user.OauthUser.Username,
		FirstName: user.FirstName.String,
		LastName:  user.LastName.String,
		Role:      roles.User,
		Confirmed: user.Confirmed,
		CreatedAt: util.FormatTime(&user.CreatedAt),
		UpdatedAt: util.FormatTime(&user.UpdatedAt),
	}
	testutil.TestResponseObject(suite.T(), w, expected, 200)
}
Esempio n. 3
0
func (suite *AccountsTestSuite) TestListUsers() {
	var users []*accounts.User
	err := accounts.UserPreload(suite.db).Order("id").Find(&users).Error
	assert.NoError(suite.T(), err, "Fetching test users should not fail")

	userResponses := make([]interface{}, len(users))

	for i, user := range users {
		userResponse, err := accounts.NewUserResponse(user)
		assert.NoError(suite.T(), err, "Creating user response should not fail")
		userResponses[i] = userResponse
	}

	testutil.TestListValidResponse(
		suite.T(),
		suite.router,
		"users",                // path
		"users",                // entity
		"test_superuser_token", // from fixtures
		userResponses,
		suite.assertMockExpectations,
	)
}
func (suite *AccountsTestSuite) TestCreateUserOnlyRequiredFields() {
	// Prepare a request
	payload, err := json.Marshal(&accounts.UserRequest{
		Email:    "test@newuser",
		Password: "******",
	})
	assert.NoError(suite.T(), err, "JSON marshalling failed")
	r, err := http.NewRequest(
		"POST",
		"http://1.2.3.4/v1/users",
		bytes.NewBuffer(payload),
	)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set(
		"Authorization",
		fmt.Sprintf(
			"Basic %s",
			b64.StdEncoding.EncodeToString([]byte("test_client_1:test_secret")),
		),
	)

	suite.service.WaitForNotifications(1)
	// Mock confirmation email
	suite.mockConfirmationEmail()

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "create_user", match.Route.GetName())
	}

	// Count before
	var (
		countBefore              int
		confirmationsCountBefore int
	)
	suite.db.Model(new(accounts.User)).Count(&countBefore)
	suite.db.Model(new(accounts.Confirmation)).Count(&confirmationsCountBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)
	// block until email goroutine has finished
	assert.True(suite.T(), <-suite.service.GetNotifications(), "The email goroutine should have run")

	// Count after
	var (
		countAfter              int
		confirmationsCountAfter int
	)
	suite.db.Model(new(accounts.User)).Count(&countAfter)
	suite.db.Model(new(accounts.Confirmation)).Count(&confirmationsCountAfter)
	assert.Equal(suite.T(), countBefore+1, countAfter)
	assert.Equal(suite.T(), confirmationsCountBefore+1, confirmationsCountAfter)

	// Fetch the created user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).Last(user).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Fetch the created confirmation
	confirmation := new(accounts.Confirmation)
	assert.False(suite.T(), suite.db.Preload("User.OauthUser").
		Last(confirmation).RecordNotFound())

	// And correct data was saved
	assert.Equal(suite.T(), user.ID, user.OauthUser.MetaUserID)
	assert.Equal(suite.T(), "test@newuser", user.OauthUser.Username)
	assert.False(suite.T(), user.FirstName.Valid)
	assert.False(suite.T(), user.LastName.Valid)
	assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String)
	assert.False(suite.T(), user.Confirmed)
	assert.Equal(suite.T(), "test@newuser", confirmation.User.OauthUser.Username)

	// Check the Location header
	assert.Equal(
		suite.T(),
		fmt.Sprintf("/v1/users/%d", user.ID),
		w.Header().Get("Location"),
	)

	// Check the response
	expected := &accounts.UserResponse{
		Hal: jsonhal.Hal{
			Links: map[string]*jsonhal.Link{
				"self": &jsonhal.Link{
					Href: fmt.Sprintf("/v1/users/%d", user.ID),
				},
			},
		},
		ID:        user.ID,
		Email:     "test@newuser",
		Role:      roles.User,
		Confirmed: false,
		CreatedAt: util.FormatTime(&user.CreatedAt),
		UpdatedAt: util.FormatTime(&user.UpdatedAt),
	}
	testutil.TestResponseObject(suite.T(), w, expected, 201)

	// Check that the mock object expectations were met
	suite.assertMockExpectations()
}
func (suite *AccountsTestSuite) TestConfirmEmail() {
	var (
		testOauthUser    *oauth.User
		testUser         *accounts.User
		testConfirmation *accounts.Confirmation
		err              error
	)

	// Insert a test user
	testOauthUser, err = suite.service.GetOauthService().CreateUser(
		roles.User,
		"harold@finch",
		"test_password",
	)
	assert.NoError(suite.T(), err, "Failed to insert a test oauth user")
	testUser, err = accounts.NewUser(
		suite.accounts[0],
		testOauthUser,
		"",    //facebook ID
		false, // confirmed
		&accounts.UserRequest{
			FirstName: "Harold",
			LastName:  "Finch",
		},
	)
	assert.NoError(suite.T(), err, "Failed to create a new user object")
	err = suite.db.Create(testUser).Error
	assert.NoError(suite.T(), err, "Failed to insert a test user")
	testUser.Account = suite.accounts[0]
	testUser.OauthUser = testOauthUser

	// Insert a test confirmation
	testConfirmation, err = accounts.NewConfirmation(
		testUser,
		suite.cnf.AppSpecific.ConfirmationLifetime,
	)
	assert.NoError(suite.T(), err, "Failed to create a new confirmation object")
	err = suite.db.Create(testConfirmation).Error
	assert.NoError(suite.T(), err, "Failed to insert a test confirmation")
	testConfirmation.User = testUser

	// Prepare a request
	r, err := http.NewRequest(
		"GET",
		fmt.Sprintf(
			"http://1.2.3.4/v1/confirmations/%s",
			testConfirmation.Reference,
		),
		nil,
	)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set(
		"Authorization",
		fmt.Sprintf(
			"Basic %s",
			b64.StdEncoding.EncodeToString([]byte("test_client_1:test_secret")),
		),
	)

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "confirm_email", match.Route.GetName())
	}

	// Count before
	var (
		countBefore              int
		accessTokensCountBefore  int
		refreshTokensCountBefore int
	)
	suite.db.Model(new(accounts.Confirmation)).Count(&countBefore)
	suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountBefore)
	suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Count after
	var (
		countAfter              int
		accessTokensCountAfter  int
		refreshTokensCountAfter int
	)
	suite.db.Model(new(accounts.Confirmation)).Count(&countAfter)
	suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountAfter)
	suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountAfter)
	assert.Equal(suite.T(), countBefore-1, countAfter)
	assert.Equal(suite.T(), accessTokensCountBefore, accessTokensCountAfter)
	assert.Equal(suite.T(), refreshTokensCountBefore, refreshTokensCountAfter)

	// Fetch the updated user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Confirmation should have been soft deleteted
	assert.True(suite.T(), suite.db.Last(new(accounts.Confirmation)).RecordNotFound())

	// And correct data was saved
	assert.True(suite.T(), user.Confirmed)

	// Check the response
	expected, err := accounts.NewConfirmationResponse(testConfirmation)
	assert.NoError(suite.T(), err, "Failed to create expected response object")
	testutil.TestResponseObject(suite.T(), w, expected, 200)
}
func (suite *AccountsTestSuite) TestUpdateUser() {
	testUser, testAccessToken, err := suite.insertTestUser(
		"harold@finch", "test_password", "Harold", "Finch")
	assert.NoError(suite.T(), err, "Failed to insert a test user")

	payload, err := json.Marshal(&accounts.UserRequest{
		FirstName: "John",
		LastName:  "Reese",
	})
	assert.NoError(suite.T(), err, "JSON marshalling failed")
	r, err := http.NewRequest(
		"PUT",
		fmt.Sprintf("http://1.2.3.4/v1/users/%d", testUser.ID),
		bytes.NewBuffer(payload),
	)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", testAccessToken.Token))

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "update_user", match.Route.GetName())
	}

	// Count before
	var countBefore int
	suite.db.Model(new(accounts.User)).Count(&countBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Check that the mock object expectations were met
	suite.assertMockExpectations()

	// Count after
	var countAfter int
	suite.db.Model(new(accounts.User)).Count(&countAfter)
	assert.Equal(suite.T(), countBefore, countAfter)

	// Fetch the updated user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Check that the password has NOT changed
	assert.NoError(suite.T(), password.VerifyPassword(
		user.OauthUser.Password.String,
		"test_password",
	))

	// And correct data was saved
	assert.Equal(suite.T(), "harold@finch", user.OauthUser.Username)
	assert.Equal(suite.T(), "John", user.FirstName.String)
	assert.Equal(suite.T(), "Reese", user.LastName.String)
	assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String)
	assert.False(suite.T(), user.Confirmed)

	// Check the response
	expected := &accounts.UserResponse{
		Hal: jsonhal.Hal{
			Links: map[string]*jsonhal.Link{
				"self": &jsonhal.Link{
					Href: fmt.Sprintf("/v1/users/%d", user.ID),
				},
			},
		},
		ID:        user.ID,
		Email:     "harold@finch",
		FirstName: "John",
		LastName:  "Reese",
		Role:      roles.User,
		Confirmed: false,
		CreatedAt: util.FormatTime(&user.CreatedAt),
		UpdatedAt: util.FormatTime(&user.UpdatedAt),
	}
	testutil.TestResponseObject(suite.T(), w, expected, 200)
}
func (suite *AccountsTestSuite) TestConfirmInvitation() {
	var (
		testOauthUser  *oauth.User
		testUser       *accounts.User
		testInvitation *accounts.Invitation
		err            error
	)

	// Insert a test user
	testOauthUser, err = suite.service.GetOauthService().CreateUser(
		roles.User,
		"harold@finch",
		"", // blank password
	)
	assert.NoError(suite.T(), err, "Failed to insert a test oauth user")
	testUser, err = accounts.NewUser(
		suite.accounts[0],
		testOauthUser,
		"",    //facebook ID
		false, // confirmed
		&accounts.UserRequest{
			FirstName: "Harold",
			LastName:  "Finch",
		},
	)
	assert.NoError(suite.T(), err, "Failed to create a new user object")
	err = suite.db.Create(testUser).Error
	assert.NoError(suite.T(), err, "Failed to insert a test user")
	testUser.Account = suite.accounts[0]
	testUser.OauthUser = testOauthUser

	// Insert a test invitation
	testInvitation, err = accounts.NewInvitation(
		testUser,
		suite.users[0],
		suite.cnf.AppSpecific.InvitationLifetime,
	)
	assert.NoError(suite.T(), err, "Failed to create a new invitation object")
	err = suite.db.Create(testInvitation).Error
	assert.NoError(suite.T(), err, "Failed to insert a test invitation")
	testInvitation.InvitedUser = testUser
	testInvitation.InvitedByUser = suite.users[0]

	// Prepare a request
	payload, err := json.Marshal(&accounts.ConfirmInvitationRequest{
		PasswordRequest: accounts.PasswordRequest{Password: "******"},
	})
	assert.NoError(suite.T(), err, "JSON marshalling failed")
	r, err := http.NewRequest(
		"POST",
		fmt.Sprintf("http://1.2.3.4/v1/invitations/%s", testInvitation.Reference),
		bytes.NewBuffer(payload),
	)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set(
		"Authorization",
		fmt.Sprintf(
			"Basic %s",
			b64.StdEncoding.EncodeToString([]byte("test_client_1:test_secret")),
		),
	)

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "confirm_invitation", match.Route.GetName())
	}

	// Count before
	var countBefore int
	suite.db.Model(new(accounts.Invitation)).Count(&countBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Count after
	var countAfter int
	suite.db.Model(new(accounts.Invitation)).Count(&countAfter)
	assert.Equal(suite.T(), countBefore-1, countAfter)

	// Fetch the updated user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Invitation should have been soft deleted
	assert.True(suite.T(), suite.db.First(new(accounts.Invitation), testInvitation.ID).RecordNotFound())

	// And correct data was saved
	assert.Nil(suite.T(), pass.VerifyPassword(user.OauthUser.Password.String, "test_password"))

	// Check the response
	expected, err := accounts.NewInvitationResponse(testInvitation)
	assert.NoError(suite.T(), err, "Failed to create expected response object")
	testutil.TestResponseObject(suite.T(), w, expected, 200)
}
func (suite *AccountsTestSuite) TestUpdateUserPassword() {
	var (
		testOauthUser   *oauth.User
		testUser        *accounts.User
		testAccessToken *oauth.AccessToken
		err             error
	)

	// Insert a test user
	testOauthUser, err = suite.service.GetOauthService().CreateUser(
		roles.User,
		"harold@finch",
		"test_password",
	)
	assert.NoError(suite.T(), err, "Failed to insert a test oauth user")
	testUser, err = accounts.NewUser(
		suite.accounts[0],
		testOauthUser,
		"",    //facebook ID
		false, // confirmed
		&accounts.UserRequest{
			FirstName: "Harold",
			LastName:  "Finch",
		},
	)
	assert.NoError(suite.T(), err, "Failed to create a new user object")
	err = suite.db.Create(testUser).Error
	assert.NoError(suite.T(), err, "Failed to insert a test user")
	testUser.Account = suite.accounts[0]
	testUser.OauthUser = testOauthUser

	// Login the test user
	testAccessToken, _, err = suite.service.GetOauthService().Login(
		suite.accounts[0].OauthClient,
		testUser.OauthUser,
		"read_write", // scope
	)
	assert.NoError(suite.T(), err, "Failed to login the test user")

	payload, err := json.Marshal(&accounts.UserRequest{
		Password:    "******",
		NewPassword: "******",
	})
	assert.NoError(suite.T(), err, "JSON marshalling failed")
	r, err := http.NewRequest(
		"PUT",
		fmt.Sprintf("http://1.2.3.4/v1/users/%d", testUser.ID),
		bytes.NewBuffer(payload),
	)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", testAccessToken.Token))

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "update_user", match.Route.GetName())
	}

	// Count before
	var countBefore int
	suite.db.Model(new(accounts.User)).Count(&countBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Check that the mock object expectations were met
	suite.assertMockExpectations()

	// Count after
	var countAfter int
	suite.db.Model(new(accounts.User)).Count(&countAfter)
	assert.Equal(suite.T(), countBefore, countAfter)

	// Fetch the updated user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// Check that the password has changed
	assert.Error(suite.T(), password.VerifyPassword(
		user.OauthUser.Password.String,
		"test_password",
	))
	assert.NoError(suite.T(), password.VerifyPassword(
		user.OauthUser.Password.String,
		"some_new_password",
	))

	// And the user meta data is unchanged
	assert.Equal(suite.T(), "harold@finch", user.OauthUser.Username)
	assert.Equal(suite.T(), "Harold", user.FirstName.String)
	assert.Equal(suite.T(), "Finch", user.LastName.String)
	assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String)
	assert.False(suite.T(), user.Confirmed)

	// Check the response
	expected := &accounts.UserResponse{
		Hal: jsonhal.Hal{
			Links: map[string]*jsonhal.Link{
				"self": &jsonhal.Link{
					Href: fmt.Sprintf("/v1/users/%d", user.ID),
				},
			},
		},
		ID:        user.ID,
		Email:     "harold@finch",
		FirstName: "Harold",
		LastName:  "Finch",
		Role:      roles.User,
		Confirmed: false,
		CreatedAt: util.FormatTime(&user.CreatedAt),
		UpdatedAt: util.FormatTime(&user.UpdatedAt),
	}
	testutil.TestResponseObject(suite.T(), w, expected, 200)
}
Esempio n. 9
0
func (suite *FacebookTestSuite) TestLoginCreatesNewUserNoPicture() {
	// Prepare a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/v1/facebook/login", nil)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.PostForm = url.Values{
		"access_token": {"facebook_token"},
		"scope":        {"read_write"},
	}
	r.SetBasicAuth("test_client_1", "test_secret")

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "facebook_login", match.Route.GetName())
	}

	// Mock fetching profile data from facebook
	suite.mockFacebookGetMe(fb.Result{
		"id":         "new_facebook_id",
		"email":      "new@user",
		"name":       "John Reese",
		"first_name": "John",
		"last_name":  "Reese",
		"picture":    nil,
	}, nil)

	// Count before
	var countBefore int
	suite.db.Model(new(accounts.User)).Count(&countBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Check mock expectations were met
	suite.adapterMock.AssertExpectations(suite.T())

	// Check the status code
	if !assert.Equal(suite.T(), 200, w.Code) {
		log.Print(w.Body.String())
	}

	// Count after
	var countAfter int
	suite.db.Model(new(accounts.User)).Count(&countAfter)
	assert.Equal(suite.T(), countBefore+1, countAfter)

	// Fetch the created user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).
		Last(user).RecordNotFound()
	assert.False(suite.T(), notFound)

	// And correct data was saved
	assert.Equal(suite.T(), user.ID, user.OauthUser.MetaUserID)
	assert.Equal(suite.T(), "new@user", user.OauthUser.Username)
	assert.Equal(suite.T(), "John", user.FirstName.String)
	assert.Equal(suite.T(), "Reese", user.LastName.String)
	assert.Equal(suite.T(), "new_facebook_id", user.FacebookID.String)
	assert.False(suite.T(), user.Picture.Valid)
	assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String)

	// Fetch oauth tokens
	accessToken := new(oauth.AccessToken)
	assert.False(suite.T(), oauth.AccessTokenPreload(suite.db).
		First(accessToken).RecordNotFound())
	refreshToken := new(oauth.RefreshToken)
	assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db).
		First(refreshToken).RecordNotFound())

	// Check the response body
	expected, err := json.Marshal(&oauth.AccessTokenResponse{
		UserID:       user.ID,
		AccessToken:  accessToken.Token,
		ExpiresIn:    3600,
		TokenType:    tokentypes.Bearer,
		Scope:        "read_write",
		RefreshToken: refreshToken.Token,
	})
	if assert.NoError(suite.T(), err, "JSON marshalling failed") {
		assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
	}
}
Esempio n. 10
0
func (suite *FacebookTestSuite) TestLoginUpdatesExistingUser() {
	var (
		testOauthUser *oauth.User
		testUser      *accounts.User
		err           error
	)

	// Insert a test user
	testOauthUser, err = suite.service.GetAccountsService().GetOauthService().CreateUser(
		roles.User,
		"harold@finch",
		"", // empty password
	)
	assert.NoError(suite.T(), err, "Failed to insert a test oauth user")
	testUser, err = accounts.NewUser(
		suite.accounts[0],
		testOauthUser,
		"some_facebook_id", // facebook ID
		true,               // confirmed
		&accounts.UserRequest{
			FirstName: "Harold",
			LastName:  "Finch",
			Picture:   "some_picture",
		},
	)
	assert.NoError(suite.T(), err, "Failed to create a new test account user object")
	err = suite.db.Create(testUser).Error
	assert.NoError(suite.T(), err, "Failed to insert a test user")
	testUser.OauthUser = testOauthUser

	// Prepare a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/v1/facebook/login", nil)
	assert.NoError(suite.T(), err, "Request setup should not get an error")
	r.PostForm = url.Values{
		"access_token": {"facebook_token"},
		"scope":        {"read_write"},
	}
	r.SetBasicAuth("test_client_1", "test_secret")

	// Check the routing
	match := new(mux.RouteMatch)
	suite.router.Match(r, match)
	if assert.NotNil(suite.T(), match.Route) {
		assert.Equal(suite.T(), "facebook_login", match.Route.GetName())
	}

	// Mock fetching profile data from facebook
	suite.mockFacebookGetMe(fb.Result{
		"id":         "new_facebook_id",
		"email":      testUser.OauthUser.Username,
		"name":       "New Name",
		"first_name": "New First Name",
		"last_name":  "New Last Name",
		"picture": map[string]interface{}{
			"data": map[string]interface{}{
				"url": "new_picture",
			},
		},
	}, nil)

	// Count before
	var countBefore int
	suite.db.Model(new(accounts.User)).Count(&countBefore)

	// And serve the request
	w := httptest.NewRecorder()
	suite.router.ServeHTTP(w, r)

	// Check mock expectations were met
	suite.adapterMock.AssertExpectations(suite.T())

	// Check the status code
	if !assert.Equal(suite.T(), 200, w.Code) {
		log.Print(w.Body.String())
	}

	// Count after
	var countAfter int
	suite.db.Model(new(accounts.User)).Count(&countAfter)
	assert.Equal(suite.T(), countBefore, countAfter)

	// Fetch the updated user
	user := new(accounts.User)
	notFound := accounts.UserPreload(suite.db).
		First(user, testUser.ID).RecordNotFound()
	assert.False(suite.T(), notFound)

	// And correct data was saved
	assert.Equal(suite.T(), testUser.OauthUser.Username, user.OauthUser.Username)
	assert.Equal(suite.T(), "New First Name", user.FirstName.String)
	assert.Equal(suite.T(), "New Last Name", user.LastName.String)
	assert.Equal(suite.T(), "new_facebook_id", user.FacebookID.String)
	assert.Equal(suite.T(), "new_picture", user.Picture.String)
	assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String)

	// Fetch oauth tokens
	accessToken := new(oauth.AccessToken)
	assert.False(suite.T(), oauth.AccessTokenPreload(suite.db).
		First(accessToken).RecordNotFound())
	refreshToken := new(oauth.RefreshToken)
	assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db).
		First(refreshToken).RecordNotFound())

	// Check the response body
	expected, err := json.Marshal(&oauth.AccessTokenResponse{
		UserID:       user.ID,
		AccessToken:  accessToken.Token,
		ExpiresIn:    3600,
		TokenType:    tokentypes.Bearer,
		Scope:        "read_write",
		RefreshToken: refreshToken.Token,
	})
	if assert.NoError(suite.T(), err, "JSON marshalling failed") {
		assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
	}
}