package de.uni_hamburg.fs;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class JavaClassTypeTest {

    @Test
    void testUniteWithParsedTop() throws UnificationFailure {
        // given
        JavaClassType javaClassTypeMock = mock(JavaClassType.class);

        when(javaClassTypeMock.unite(ParsedType.PARSED_TOP)).thenCallRealMethod();

        // when
        ParsedType result = javaClassTypeMock.unite(ParsedType.PARSED_TOP);

        // then
        assertThat(result).isSameAs(javaClassTypeMock);
    }

    @Test
    void testUniteWithBasicType() throws UnificationFailure {
        // given
        JavaClassType javaClassTypeMock = mock(JavaClassType.class);
        BasicType mockBasicType = mock(BasicType.class);
        BasicType expectedResult = mock(BasicType.class);

        when(javaClassTypeMock.unify(mockBasicType)).thenReturn(expectedResult);
        when(javaClassTypeMock.unite(mockBasicType)).thenCallRealMethod();

        // when
        ParsedType result = javaClassTypeMock.unite(mockBasicType);

        // then
        assertThat(result).isSameAs(expectedResult);
    }


    @Test
    void testUniteWithOtherParsedTypeThrowsException() throws UnificationFailure {
        // given
        JavaClassType javaClassTypeMock = mock(JavaClassType.class);
        ParsedType mockOtherParsedType = mock(ParsedType.class);

        when(javaClassTypeMock.unite(mockOtherParsedType)).thenCallRealMethod();

        // when & then
        assertThatThrownBy(() -> javaClassTypeMock.unite(mockOtherParsedType))
            .isInstanceOf(UnificationFailure.class);
    }

    @Test
    void testAsType() throws UnificationFailure {
        // given
        JavaClassType javaClassTypeMock = mock(JavaClassType.class);

        when(javaClassTypeMock.asType()).thenCallRealMethod();

        // when
        Type result = javaClassTypeMock.asType();

        // then
        assertThat(result).isSameAs(javaClassTypeMock);
    }
}