package com.googlecode.jslint4java.cli;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Rule;
import org.junit.Test;

import com.google.common.base.Joiner;

public class MainTest {

    private static final String NEWLINE = System.getProperty("line.separator");
    private static final String RESOURCE_PREFIX = "com/googlecode/jslint4java/";
    private static final List<String> NO_OUTPUT = new ArrayList<String>();

    @Rule
    public StdioResource stdio = new StdioResource();

    private final Main main = new Main();

    private void assertLintOutput(int actualExit, int expectedExit, List<String> expectedStdoutLines,
            List<String> expectedStderrLines) throws IOException, URISyntaxException {
        Joiner nl = Joiner.on(NEWLINE);
        assertThat(stdio.getStdout(), is(nl.join(expectedStdoutLines)));
        assertThat(stdio.getStderr(), is(nl.join(expectedStderrLines)));
        // Do this last so that we see stdout/stderr errors first.
        assertThat(actualExit, is(expectedExit));
    }

    private String pathTo(String js) throws URISyntaxException {
        URL resource = getClass().getClassLoader().getResource(RESOURCE_PREFIX + js);
        return new File(resource.toURI()).getAbsolutePath();
    }

    /** Coerce arguments to an array of strings. */
    private int runLint(String... args) throws IOException {
        return main.run(args);
    }

    @Test
    public void testAllOk() throws IOException, URISyntaxException {
        int exit = runLint(pathTo("good.js"));
        assertLintOutput(exit, 0, NO_OUTPUT, NO_OUTPUT);
    }

    @Test
    public void testOneBad() throws IOException, URISyntaxException {
        String path = pathTo("bad.js");

        List<String> expectedStdout = Arrays.asList(
                "jslint:" + path + ":1:1:'alert' was used before it was defined.",
                "jslint:" + path + ":1:10:Expected ';' and instead saw '(end)'.",
                "");
        int exit = runLint(path);
        assertLintOutput(exit, 1, expectedStdout, NO_OUTPUT);
    }
}

@@ -232,61 +232,8 @@
 RL;%0A
-import java.util.ArrayList;%0Aimport java.util.Arrays;%0A
 impo
@@ -336,16 +336,108 @@
 .Joiner;
+%0Aimport com.google.common.collect.ImmutableList;%0Aimport com.google.common.collect.Iterables;
 %0A%0Apublic
@@ -670,29 +670,24 @@
 T = 
-new ArrayList%3CString%3E
+ImmutableList.of
 ();%0A
@@ -791,24 +791,97 @@
 ew Main();%0A%0A
+    /** Check that the exit value, stdout and stderr are as expected. */%0A
     private 
@@ -963,21 +963,16 @@
 edStdout
-Lines
 ,%0A      
@@ -1008,53 +1008,9 @@
 derr
-Lines) throws IOException, URISyntaxException
+)
  %7B%0A 
@@ -1089,32 +1089,48 @@
 t(), is(nl.join(
+maybeAddTrailer(
 expectedStdoutLi
@@ -1127,21 +1127,17 @@
 edStdout
-Lines
+)
 )));%0A   
@@ -1182,16 +1182,32 @@
 nl.join(
+maybeAddTrailer(
 expected
@@ -1216,13 +1216,9 @@
 derr
-Lines
+)
 )));
@@ -1338,24 +1338,290 @@
 t));%0A    %7D%0A%0A
+    /** All because join() won't append a trailing newline. */%0A    private Iterable%3CString%3E maybeAddTrailer(List%3CString%3E lines) %7B%0A        if (lines.isEmpty()) %7B%0A            return lines;%0A        %7D%0A        return Iterables.concat(lines, ImmutableList.of(%22%22));%0A    %7D%0A%0A
     private 
@@ -2331,21 +2331,24 @@
 t = 
-Arrays.as
+Immutable
 List
+.of
 (%0A  
@@ -2512,28 +2512,8 @@
 )'.%22
-,%0A                %22%22
 );%0A 

Make assertLintOutput add extra newlines.