package com.atlassian.stash.internal.json;

import com.atlassian.json.marshal.Jsonable;
import com.atlassian.bitbucket.json.JsonRenderer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.IOException;
import java.io.StringWriter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.*;

@SuppressWarnings("unchecked")
@RunWith(MockitoJUnitRunner.class)
public class JsonRendererMarshallerTest {

    @Mock
    private JsonRenderer jsonRenderer;
    @InjectMocks
    private JsonRendererMarshaller marshaller;

    @Test
    public void testMarshalHappyPath() throws Exception {
        Object object = new Object();
        String json = "\"hello\"";
        when(jsonRenderer.render(same(object), anyMap())).thenReturn(json);
        Jsonable jsonable = marshaller.marshal(object);
        assertNotNull(jsonable);
        assertEquals(json, asString(jsonable));
    }

    @Test
    public void testMarshalJsonable() throws Exception {
        Jsonable object = mock(Jsonable.class);
        Jsonable jsonable = marshaller.marshal(object);
        assertSame(object, jsonable);
        verifyZeroInteractions(jsonRenderer);
    }

    @Test
    public void testMarshalRendererReturnsNull() throws Exception {
        Object object = new Object();
        Jsonable jsonable = marshaller.marshal(object);
        assertNotNull(jsonable);
        assertEquals("null", asString(jsonable));
    }

    @Test
    public void testMarshalNull() throws Exception {
        Jsonable jsonable = marshaller.marshal(null);
        assertNotNull(jsonable);
        assertEquals("null", asString(jsonable));
    }

    private String asString(Jsonable jsonable) throws IOException {
        StringWriter writer = new StringWriter();
        jsonable.write(writer);
        return writer.toString();
    }
}
