@Test
  public void registerUserAccount_SocialSignIn_ShouldCreateNewUserAccountAndRenderHomePage()
      throws Exception {
    TestProviderSignInAttempt socialSignIn =
        new TestProviderSignInAttemptBuilder()
            .connectionData()
            .providerId(SOCIAL_MEDIA_SERVICE)
            .userProfile()
            .email(EMAIL)
            .firstName(FIRST_NAME)
            .lastName(LAST_NAME)
            .build();

    User registered =
        new UserBuilder()
            .id(1L)
            .email(EMAIL)
            .firstName(FIRST_NAME)
            .lastName(LAST_NAME)
            .signInProvider(SIGN_IN_PROVIDER)
            .build();

    when(userServiceMock.registerNewUserAccount(isA(RegistrationForm.class)))
        .thenReturn(registered);

    mockMvc
        .perform(
            post("/user/register")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param(WebTestConstants.FORM_FIELD_EMAIL, EMAIL)
                .param(WebTestConstants.FORM_FIELD_FIRST_NAME, FIRST_NAME)
                .param(WebTestConstants.FORM_FIELD_LAST_NAME, LAST_NAME)
                .param(WebTestConstants.FORM_FIELD_SIGN_IN_PROVIDER, SIGN_IN_PROVIDER.name())
                .sessionAttr(ProviderSignInAttempt.SESSION_ATTRIBUTE, socialSignIn)
                .sessionAttr(WebTestConstants.MODEL_ATTRIBUTE_USER_FORM, new RegistrationForm()))
        .andExpect(status().isMovedTemporarily())
        .andExpect(redirectedUrl("/"));

    assertThat(SecurityContextHolder.getContext())
        .loggedInUserIs(registered)
        .loggedInUserIsSignedInByUsingSocialProvider(SIGN_IN_PROVIDER);
    assertThatSignIn(socialSignIn).createdConnectionForUserId(EMAIL);

    ArgumentCaptor<RegistrationForm> registrationFormArgument =
        ArgumentCaptor.forClass(RegistrationForm.class);
    verify(userServiceMock, times(1)).registerNewUserAccount(registrationFormArgument.capture());
    verifyNoMoreInteractions(userServiceMock);

    RegistrationForm formObject = registrationFormArgument.getValue();
    assertThatRegistrationForm(formObject)
        .isSocialSignInWithSignInProvider(SIGN_IN_PROVIDER)
        .hasEmail(EMAIL)
        .hasFirstName(FIRST_NAME)
        .hasLastName(LAST_NAME)
        .hasNoPassword()
        .hasNoPasswordVerification();
  }
  @Test
  public void
      registerUserAccount_SocialSignInAndTooLongValues_ShouldRenderRegistrationFormWithValidationErrors()
          throws Exception {
    TestProviderSignInAttempt socialSignIn =
        new TestProviderSignInAttemptBuilder()
            .connectionData()
            .providerId(SOCIAL_MEDIA_SERVICE)
            .userProfile()
            .email(EMAIL)
            .firstName(FIRST_NAME)
            .lastName(LAST_NAME)
            .build();

    String email = TestUtil.createStringWithLength(101);
    String firstName = TestUtil.createStringWithLength(101);
    String lastName = TestUtil.createStringWithLength(101);

    mockMvc
        .perform(
            post("/user/register")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param(WebTestConstants.FORM_FIELD_EMAIL, email)
                .param(WebTestConstants.FORM_FIELD_FIRST_NAME, firstName)
                .param(WebTestConstants.FORM_FIELD_LAST_NAME, lastName)
                .param(WebTestConstants.FORM_FIELD_SIGN_IN_PROVIDER, SIGN_IN_PROVIDER.name())
                .sessionAttr(ProviderSignInAttempt.SESSION_ATTRIBUTE, socialSignIn)
                .sessionAttr(WebTestConstants.SESSION_ATTRIBUTE_USER_FORM, new RegistrationForm()))
        .andExpect(status().isOk())
        .andExpect(view().name("user/registrationForm"))
        .andExpect(forwardedUrl("/WEB-INF/jsp/user/registrationForm.jsp"))
        .andExpect(
            model()
                .attribute(
                    WebTestConstants.MODEL_ATTRIBUTE_USER_FORM,
                    allOf(
                        hasProperty(WebTestConstants.FORM_FIELD_EMAIL, is(email)),
                        hasProperty(WebTestConstants.FORM_FIELD_FIRST_NAME, is(firstName)),
                        hasProperty(WebTestConstants.FORM_FIELD_LAST_NAME, is(lastName)),
                        hasProperty(WebTestConstants.FORM_FIELD_PASSWORD, isEmptyOrNullString()),
                        hasProperty(WebTestConstants.FORM_FIELD_PASSWORD, isEmptyOrNullString()),
                        hasProperty(
                            WebTestConstants.FORM_FIELD_SIGN_IN_PROVIDER, is(SIGN_IN_PROVIDER)))))
        .andExpect(
            model()
                .attributeHasFieldErrors(
                    WebTestConstants.MODEL_ATTRIBUTE_USER_FORM,
                    WebTestConstants.FORM_FIELD_EMAIL,
                    WebTestConstants.FORM_FIELD_FIRST_NAME,
                    WebTestConstants.FORM_FIELD_LAST_NAME));

    assertThat(SecurityContextHolder.getContext()).userIsAnonymous();
    assertThatSignIn(socialSignIn).createdNoConnections();
    verifyZeroInteractions(userServiceMock);
  }
  @Test
  public void
      registerUserAccount_SocialSignInAndEmailExist_ShouldRenderRegistrationFormWithFieldError()
          throws Exception {
    TestProviderSignInAttempt socialSignIn =
        new TestProviderSignInAttemptBuilder()
            .connectionData()
            .providerId(SOCIAL_MEDIA_SERVICE)
            .userProfile()
            .email(EMAIL)
            .firstName(FIRST_NAME)
            .lastName(LAST_NAME)
            .build();

    when(userServiceMock.registerNewUserAccount(isA(RegistrationForm.class)))
        .thenThrow(new DuplicateEmailException(""));

    mockMvc
        .perform(
            post("/user/register")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param(WebTestConstants.FORM_FIELD_EMAIL, EMAIL)
                .param(WebTestConstants.FORM_FIELD_FIRST_NAME, FIRST_NAME)
                .param(WebTestConstants.FORM_FIELD_LAST_NAME, LAST_NAME)
                .param(WebTestConstants.FORM_FIELD_SIGN_IN_PROVIDER, SIGN_IN_PROVIDER.name())
                .sessionAttr(ProviderSignInAttempt.SESSION_ATTRIBUTE, socialSignIn)
                .sessionAttr(WebTestConstants.SESSION_ATTRIBUTE_USER_FORM, new RegistrationForm()))
        .andExpect(status().isOk())
        .andExpect(view().name("user/registrationForm"))
        .andExpect(forwardedUrl("/WEB-INF/jsp/user/registrationForm.jsp"))
        .andExpect(
            model()
                .attribute(
                    WebTestConstants.MODEL_ATTRIBUTE_USER_FORM,
                    allOf(
                        hasProperty(WebTestConstants.FORM_FIELD_EMAIL, is(EMAIL)),
                        hasProperty(WebTestConstants.FORM_FIELD_FIRST_NAME, is(FIRST_NAME)),
                        hasProperty(WebTestConstants.FORM_FIELD_LAST_NAME, is(LAST_NAME)),
                        hasProperty(WebTestConstants.FORM_FIELD_PASSWORD, isEmptyOrNullString()),
                        hasProperty(WebTestConstants.FORM_FIELD_PASSWORD, isEmptyOrNullString()),
                        hasProperty(
                            WebTestConstants.FORM_FIELD_SIGN_IN_PROVIDER, is(SIGN_IN_PROVIDER)))))
        .andExpect(
            model()
                .attributeHasFieldErrors(
                    WebTestConstants.MODEL_ATTRIBUTE_USER_FORM, WebTestConstants.FORM_FIELD_EMAIL));

    assertThat(SecurityContextHolder.getContext()).userIsAnonymous();
    assertThatSignIn(socialSignIn).createdNoConnections();

    ArgumentCaptor<RegistrationForm> registrationFormArgument =
        ArgumentCaptor.forClass(RegistrationForm.class);
    verify(userServiceMock, times(1)).registerNewUserAccount(registrationFormArgument.capture());
    verifyNoMoreInteractions(userServiceMock);

    RegistrationForm formObject = registrationFormArgument.getValue();
    assertThatRegistrationForm(formObject)
        .isSocialSignInWithSignInProvider(SIGN_IN_PROVIDER)
        .hasEmail(EMAIL)
        .hasFirstName(FIRST_NAME)
        .hasLastName(LAST_NAME)
        .hasNoPassword()
        .hasNoPasswordVerification();
  }