package hudson.plugins.jira;

import hudson.EnvVars;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.IOException;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.*;

/**
 * @author Artem Koshelev artkoshelev@gmail.com
 */
public class JiraVersionCreatorTest {
    private static final String JIRA_VER = Long.toString(System.currentTimeMillis());
    private static final String JIRA_PRJ = "TEST_PRJ";
    private static final String JIRA_VER_PARAM = "${JIRA_VER}";
    private static final String JIRA_PRJ_PARAM = "${JIRA_PRJ}";

    AbstractBuild build;
    Launcher launcher;
    BuildListener listener;
    PrintStream logger;
    EnvVars env;
    AbstractProject project;
    JiraSite site;
    JiraVersionCreator jvc;

    @Before
    public void createCommonMocks() throws IOException, InterruptedException {
        build = mock(AbstractBuild.class);
        launcher = mock(Launcher.class);
        listener = mock(BuildListener.class);
        env = mock(EnvVars.class);
        project = mock(AbstractProject.class);
        site = mock(JiraSite.class);
        jvc = spy(new JiraVersionCreator(JIRA_VER, JIRA_PRJ));
        logger = mock(PrintStream.class);

        doReturn(site).when(jvc).getSiteForProject((AbstractProject<?, ?>) Mockito.any());

        when(build.getProject()).thenReturn(project);
        when(build.getEnvironment(listener)).thenReturn(env);
        when(env.expand(Mockito.anyString())).thenAnswer(new Answer<String>() {
            @Override
            public String answer(InvocationOnMock invocationOnMock) throws Throwable {
                Object[] args = invocationOnMock.getArguments();
                String expanded = (String) args[0];
               if (expanded.equals(JIRA_PRJ_PARAM))
                    return JIRA_PRJ;
               else if (expanded.equals(JIRA_VER_PARAM))
                   return JIRA_VER;
               else
                   return expanded;
            }
        });
        when(listener.getLogger()).thenReturn(logger);
    }

    @Test
    public void jiraApiCalledWithSpecifiedParameters() throws InterruptedException, IOException {
        when(site.getVersions(JIRA_PRJ)).thenReturn(new HashSet<JiraVersion>());

        boolean result = jvc.perform(build, launcher, listener);
        verify(site).addVersion(JIRA_VER, JIRA_PRJ);
        assertThat(result, is(true));
    }

    @Test
    public void buildDidNotFailWhenVersionExists() throws IOException, InterruptedException {
        Set<JiraVersion> existingVersions = new HashSet<JiraVersion>();
        existingVersions.add(new JiraVersion(JIRA_VER, null, false, false));

        when(site.getVersions(JIRA_PRJ)).thenReturn(existingVersions);

        PrintStream logger = mock(PrintStream.class);
        when(listener.getLogger()).thenReturn(logger);

        boolean result = jvc.perform(build, launcher, listener);
        verify(site, times(0)).addVersion(JIRA_VER, JIRA_PRJ);
        assertThat(result, is(true));
    }

    @Test
    public void buildDidNotFailWhenVersionExistsExpanded() throws IOException, InterruptedException {
        // Same test as the previous one but here the version and project are contained in a Jenkins parameter
        JiraVersionCreator jvc = spy(new JiraVersionCreator(JIRA_VER_PARAM, JIRA_PRJ_PARAM));
        doReturn(site).when(jvc).getSiteForProject((AbstractProject<?, ?>) Mockito.any());

        when(build.getProject()).thenReturn(project);
        when(build.getEnvironment(listener)).thenReturn(env);
        when(env.expand(JIRA_VER_PARAM)).thenReturn(JIRA_VER);

        Set<JiraVersion> existingVersions = new HashSet<JiraVersion>();
        existingVersions.add(new JiraVersion(JIRA_VER, null, false, false));

        when(site.getVersions(JIRA_PRJ)).thenReturn(existingVersions);

        PrintStream logger = mock(PrintStream.class);
        when(listener.getLogger()).thenReturn(logger);

        boolean result = jvc.perform(build, launcher, listener);
        verify(site, times(0)).addVersion(JIRA_VER, JIRA_PRJ);
        assertThat(result, is(true));
    }
}


@@ -173,24 +173,53 @@
 ldListener;%0A
+import hudson.model.Result;%0A%0A
 import org.j
@@ -423,16 +423,44 @@
 Stream;%0A
+import java.io.PrintWriter;%0A
 import j
@@ -2820,32 +2820,504 @@
 (true));%0A    %7D%0A%0A
+    @Test%0A    public void jiraApiCalledWithInvalidParameters() throws InterruptedException, IOException %7B%0A        jvc.setJiraProjectKey(%22%22);%0A        jvc.setJiraVersion(%22%22);%0A        when(listener.fatalError(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(mock(PrintWriter.class));%0A        boolean result = jvc.perform(build, launcher, listener);%0A        verify(listener).finished(Result.FAILURE);%0A        assertThat(result, is(false));%0A    %7D%0A%0A
     @Test%0A    pu
@@ -3630,118 +3630,8 @@
 );%0A%0A
-        PrintStream logger = mock(PrintStream.class);%0A        when(listener.getLogger()).thenReturn(logger);%0A%0A
     
@@ -4614,118 +4614,8 @@
 );%0A%0A
-        PrintStream logger = mock(PrintStream.class);%0A        when(listener.getLogger()).thenReturn(logger);%0A%0A
     

increase test coverage