/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.model.internal.validators;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.collect.Maps;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.FieldDefinition;
import com.qcadoo.model.api.validators.ErrorMessage;
import com.qcadoo.model.internal.api.FieldHookDefinition;
public class CustomValidatorTest {
private static final String FIELD_NAME = "someFieldWithValidator";
private static final String DEFAULT_MSG = "qcadooView.validate.field.error.custom";
private static final String CUSTOM_MSG = "qcadoo.testing.custom.field.error.message";
private CustomValidator customValidator;
@Mock
private FieldHookDefinition fieldHookDef;
@Mock
private Entity entity;
@Mock
private DataDefinition dataDefinition;
@Mock
private FieldDefinition fieldDefinition;
@Mock
private Object oldValue, newValue;
@Before
public final void init() {
MockitoAnnotations.initMocks(this);
customValidator = new CustomValidator(fieldHookDef);
customValidator.initialize(dataDefinition, fieldDefinition);
given(fieldDefinition.getName()).willReturn(FIELD_NAME);
}
@Test
public final void shouldNotAddDefaultMessageIfValidationSuccess() {
// given
stubFieldHookDef(true, Maps.<String, ErrorMessage> newHashMap());
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertTrue(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
verify(entity, never()).addError(Mockito.eq(fieldDefinition), Mockito.anyString(), Mockito.<String> anyVararg());
}
@Test
public final void shouldAddDefaultMessageIfValidationFailAndThereIsNoMessageAssignedToField() {
// given
stubFieldHookDef(false, Maps.<String, ErrorMessage> newHashMap());
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertFalse(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
verify(entity, times(1)).addError(Mockito.eq(fieldDefinition), argCaptor.capture(), Mockito.<String> anyVararg());
assertEquals(DEFAULT_MSG, argCaptor.getValue());
}
@Test
public final void shouldNotAddDefaultMessageIfValidationFailAndThereIsAlreadyMessageAssignedToField() {
// given
Map<String, ErrorMessage> errors = Maps.newHashMap();
errors.put(FIELD_NAME, new ErrorMessage(CUSTOM_MSG));
stubFieldHookDef(false, errors);
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertFalse(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
verify(entity, times(1)).addError(Mockito.eq(fieldDefinition), argCaptor.capture(), Mockito.<String> anyVararg());
assertEquals(CUSTOM_MSG, argCaptor.getValue());
}
@Test
public final void shouldAddDefaultMessageIfValidationFailAndThereIsAlreadyMessageAssignedToOtherField() {
// given
Map<String, ErrorMessage> errors = Maps.newHashMap();
errors.put("another" + FIELD_NAME, new ErrorMessage(CUSTOM_MSG));
stubFieldHookDef(false, errors);
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertFalse(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
verify(entity, times(1)).addError(Mockito.eq(fieldDefinition), argCaptor.capture(), Mockito.<String> anyVararg());
assertEquals(DEFAULT_MSG, argCaptor.getValue());
}
@Test
public final void shouldNotAddDefaultMessageIfValidationSuccessAndThereIsAlreadyMessageAssignedToField() {
// given
Map<String, ErrorMessage> errors = Maps.newHashMap();
errors.put("another" + FIELD_NAME, new ErrorMessage(CUSTOM_MSG));
stubFieldHookDef(true, errors);
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertTrue(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
verify(entity, never()).addError(Mockito.eq(fieldDefinition), Mockito.eq(CUSTOM_MSG), Mockito.<String> anyVararg());
verify(entity, never()).addError(Mockito.eq(fieldDefinition), Mockito.eq(DEFAULT_MSG), Mockito.<String> anyVararg());
}
@Test
public final void shouldNotAddDefaultMessageIfValidationSuccessAndThereIsAlreadyMessageAssignedToOtherField() {
// given
Map<String, ErrorMessage> errors = Maps.newHashMap();
errors.put(FIELD_NAME, new ErrorMessage(CUSTOM_MSG));
stubFieldHookDef(true, errors);
// when
boolean isValid = customValidator.call(entity, oldValue, newValue);
// then
assertTrue(isValid);
verify(fieldHookDef, times(1)).call(entity, oldValue, newValue);
ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
verify(entity, times(1)).addError(Mockito.eq(fieldDefinition), argCaptor.capture(), Mockito.<String> anyVararg());
assertEquals(CUSTOM_MSG, argCaptor.getValue());
}
private void stubFieldHookDef(final Boolean result, final Map<String, ErrorMessage> errors) {
given(fieldHookDef.call(Mockito.eq(entity), any(), any())).willAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(final InvocationOnMock invocation) throws Throwable {
given(entity.getErrors()).willReturn(Collections.unmodifiableMap(errors));
for (Entry<String, ErrorMessage> fieldErrorEntry : errors.entrySet()) {
ErrorMessage errorMsg = fieldErrorEntry.getValue();
if (fieldErrorEntry.getKey().equals(fieldDefinition.getName())) {
entity.addError(fieldDefinition, errorMsg.getMessage(), errorMsg.getVars());
}
given(entity.getError(fieldErrorEntry.getKey())).willReturn(errorMsg);
}
return result;
}
});
}
}