/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.frontend.web.forms.validate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.junit.Before;
import org.junit.Test;
import org.orcid.frontend.web.forms.ChangePasswordForm;
import org.springframework.test.context.web.WebAppConfiguration;
@WebAppConfiguration
public class ChangePasswordFormValidatorTest extends AbstractConstraintValidator<ChangePasswordForm> {
Validator validator;
@Before
public void resetValidator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void allValuesPopulatedHappyPath() {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("0ldPassw$rd");
form.setPassword("passw0rd");
form.setRetypedPassword("passw0rd");
Set<ConstraintViolation<ChangePasswordForm>> errors = validator.validate(form);
assertEquals("Should be no errors", 0, errors.size());
}
@Test
public void testPasswordNumbersOnlyInvalid() {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("12345678");
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String password = allErrorValues.get("oldPassword");
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", password);
//add in a char
form.setOldPassword("12345678b");
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
password = allErrorValues.get("oldPassword");
assertNull(password);
}
@Test
public void testPasswordLengthMin8() {
ChangePasswordForm form = new ChangePasswordForm();
form.setPassword("a$1");
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String password = allErrorValues.get("password");
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", password);
form.setPassword("a$1a$1a$1");
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
password = allErrorValues.get("password");
assertNull(password);
}
@Test
public void testPasswordMissingNumberInvalid() {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("£$$$$$$r");
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String password = allErrorValues.get("oldPassword");
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", password);
//add in a number
form.setOldPassword("£$$$$$r1");
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
password = allErrorValues.get("oldPassword");
assertNull(password);
}
@Test
public void testPasswordWithSymbolButNotCharacterValid() {
ChangePasswordForm form = new ChangePasswordForm();
form.setPassword("£$$$$$$$");
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String password = allErrorValues.get("password");
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", password);
form.setPassword("£$$$$$$7");
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
password = allErrorValues.get("password");
assertNull(password);
}
@Test
public void testNonUsAsciiCharsPermitted() throws Exception {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("passw0rd");
form.setPassword("ååååååå1å");
form.setRetypedPassword("ååååååå1å");
Set<ConstraintViolation<ChangePasswordForm>> errors = validator.validate(form);
assertEquals("Should be no errors", 0, errors.size());
}
@Test
public void testSpacesPermittted() throws Exception {
ChangePasswordForm form = new ChangePasswordForm();
form.setPassword("Ben Kingsley is my no. 1 actor");
form.setRetypedPassword("Ben Kingsley is my no. 1 actor");
form.setOldPassword("ååååååå1å");
Set<ConstraintViolation<ChangePasswordForm>> errors = validator.validate(form);
assertEquals("Should be no errors", 0, errors.size());
}
@Test
public void testSymbolsPermitttedButNotRequired() throws Exception {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("Ben Kingsley is my no. 1 actor");
form.setPassword("passw0rd");
form.setRetypedPassword("passw0rd");
Set<ConstraintViolation<ChangePasswordForm>> errors = validator.validate(form);
assertEquals("Should be no errors", 0, errors.size());
//check that the test doesn't break when symbols introduced
form.setPassword("p$ssw0rd");
form.setRetypedPassword("p$ssw0rd");
errors = validator.validate(form);
assertEquals("Should be no errors", 0, errors.size());
}
@Test
public void testPasswordFormMissingData() {
ChangePasswordForm form = new ChangePasswordForm();
form.setOldPassword("");
form.setPassword("");
form.setRetypedPassword("");
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String password = allErrorValues.get("password");
String confirmedPassword = allErrorValues.get("retypedPassword");
String oldPassword = allErrorValues.get("oldPassword");
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", password);
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", confirmedPassword);
assertEquals("Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol", oldPassword);
}
@Test
public void testPasswordFormatValidation() throws Exception {
String pwErrorMessage = "Passwords must be 8 or more characters and contain at least 1 number and at least 1 alpha character or symbol";
String tooShortPassword = "pssword";
ChangePasswordForm form = new ChangePasswordForm();
form.setPassword(tooShortPassword);
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String passwordValidationError = allErrorValues.get("password");
assertEquals(pwErrorMessage, passwordValidationError);
String eightDigitsButLowerCaseAlphaOnly = "password";
form.setPassword(eightDigitsButLowerCaseAlphaOnly);
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordValidationError = allErrorValues.get("password");
assertEquals(pwErrorMessage, passwordValidationError);
String eightDigitsLowerUpperCaseButAlphaOnly = "pAssword";
form.setPassword(eightDigitsLowerUpperCaseButAlphaOnly);
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordValidationError = allErrorValues.get("password");
assertEquals(pwErrorMessage, passwordValidationError);
String eightCharactersLowerUpperCaseSymbol = "pAssw%rd";
form.setPassword(eightCharactersLowerUpperCaseSymbol);
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordValidationError = allErrorValues.get("password");
assertEquals(pwErrorMessage, passwordValidationError);
String eightMixedCharactersDigitsAndSymbol = "p4ssW&rd";
form.setPassword(eightMixedCharactersDigitsAndSymbol);
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordValidationError = allErrorValues.get("password");
assertNull(passwordValidationError);
String eightUpperCaseCharactersOnlyDigitsAndSymbol = "P4SSW&RD";
form.setPassword(eightUpperCaseCharactersOnlyDigitsAndSymbol);
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordValidationError = allErrorValues.get("password");
assertNull(passwordValidationError);
}
@Test
public void testPasswordsMatchValidation() throws Exception {
String eightMixedCharactersDigitsAndSymbol = "p4s]sW[rd";
String incorrectRetype = "p4s]sT]rd";
ChangePasswordForm form = new ChangePasswordForm();
form.setPassword(eightMixedCharactersDigitsAndSymbol);
form.setRetypedPassword(incorrectRetype);
Set<ConstraintViolation<ChangePasswordForm>> violations = validator.validate(form);
Map<String, String> allErrorValues = retrieveErrorKeyAndMessage(violations);
String passwordFormatError = allErrorValues.get("password");
String retypedPasswordFormatError = allErrorValues.get("retypedPassword");
allErrorValues = retrieveErrorKeyAndMessage(violations);
// the passwords themselves should be ok as they conform to the format,
// problem is they don't match
assertNull(passwordFormatError);
assertNull(retypedPasswordFormatError);
Set<String> fieldLevelErrors = retrieveErrorValuesOnly(violations);
assertTrue(fieldLevelErrors.contains("New password values don’t match. Please try again"));
// now match them
form.setRetypedPassword("p4s]sW[rd");
violations = validator.validate(form);
allErrorValues = retrieveErrorKeyAndMessage(violations);
passwordFormatError = allErrorValues.get("password");
retypedPasswordFormatError = allErrorValues.get("retypedPassword");
allErrorValues = retrieveErrorKeyAndMessage(violations);
assertNull(passwordFormatError);
assertNull(retypedPasswordFormatError);
fieldLevelErrors = retrieveErrorValuesOnly(violations);
assertFalse(fieldLevelErrors.contains("The password and confirmed password must match"));
}
}