package com.atlassian.stash.internal.validation;

import com.atlassian.bitbucket.validation.annotation.FieldEquals;
import com.atlassian.bitbucket.validation.FieldEqualsValidator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.validation.ConstraintValidatorContext;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class FieldEqualsValidatorTest {

    @Mock
    private FieldEquals constraint;

    @Mock
    private ConstraintValidatorContext context;

    @Mock
    private ConstraintValidatorContext.ConstraintViolationBuilder builder;

    @Mock
    private ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderDefinedContext value;

    @Test
    public void testEquals() throws Exception {
        testValidator(new Tuple("a", "a"), true);
        testValidator(new Tuple("a", "b"), false);
    }

    @Test(expected = IllegalStateException.class)
    public void testNonexistentFields() throws Exception {
        testValidator(new Object(), false);
    }

    private void testValidator(Object object, boolean result) {
        when(constraint.fields()).thenReturn(new String[]{"a", "b"});
        when(constraint.reportingField()).thenReturn("b");
        when(constraint.message()).thenReturn("abc");
        when(context.buildConstraintViolationWithTemplate(eq("abc"))).thenReturn(builder);
        when(builder.addNode(eq("b"))).thenReturn(value);

        FieldEqualsValidator validator = new FieldEqualsValidator();
        validator.initialize(constraint);
        assertEquals(result, validator.isValid(object, context));
    }

    private static class Tuple {
        private final String a;
        private final String b;

        private Tuple(String a, String b) {
            this.a = a;
            this.b = b;
        }
    }
}
