/*
* Copyright (c) 2008. All rights reserved.
*/
package ro.isdc.wro.model.resource.processor;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.config.Context;
import ro.isdc.wro.model.resource.ResourceType;
import ro.isdc.wro.model.resource.processor.impl.js.JSMinProcessor;
import ro.isdc.wro.model.resource.processor.support.JSMin;
import ro.isdc.wro.util.WroTestUtils;
/**
* TestJsMinProcessor.
*
* @author Alex Objelean
* @created Created on Nov 28, 2008
*/
public class TestJsMinProcessor {
private ResourcePreProcessor processor;
@BeforeClass
public static void onBeforeClass() {
assertEquals(0, Context.countActive());
}
@AfterClass
public static void onAfterClass() {
assertEquals(0, Context.countActive());
}
@Before
public void setUp() {
processor = new JSMinProcessor();
Context.set(Context.standaloneContext());
WroTestUtils.createInjector().inject(processor);
}
@After
public void tearDown() {
Context.unset();
}
@Test
public void testFromFolder()
throws IOException {
final URL url = getClass().getResource("jsmin");
final File testFolder = new File(url.getFile(), "test");
final File expectedFolder = new File(url.getFile(), "expected");
WroTestUtils.compareFromDifferentFoldersByExtension(testFolder, expectedFolder, "js", processor);
}
/**
* Tests a known issue with JsMin.
*/
@Test(expected = WroRuntimeException.class)
public void shoudlFailWhenCompilingAnExpressionWithNewLines()
throws Exception {
processor.process(null, new StringReader("Math.round(4\n/3);"), new StringWriter());
}
@Test
public void shouldSupportCorrectResourceTypes() {
WroTestUtils.assertProcessorSupportResourceTypes(processor, ResourceType.JS);
}
@Test
public void shouldHandleSlashAndIsolatedSingleQuoteInRegexes()
throws Exception {
final String script = "var slashOrDoubleQuote=/[/']/g;";
assertEquals("\n" + script, jsmin(script));
}
@Test
public void shouldNotMinifyInsideQuasiLiterals()
throws Exception {
assertEquals("\nvar a=`x = y`;", jsmin("var a = `x = y`;"));
}
@Test
public void shouldRemoveByteOrderMark()
throws Exception {
assertEquals("\nvar a=1;", jsmin("\uFEFFvar a = 1;"));
}
@Test
public void shouldNotRemoveLineBreakBeforeExclamationMark()
throws Exception {
assertEquals("\nvar a=1\n!true\nconsole.log(a)", jsmin("var a = 1\n!true\nconsole.log(a)"));
}
@Test
public void shouldNotRemoveLineBreakBeforeTilde()
throws Exception {
assertEquals("\nvar a=1\n~true\nconsole.log(a)", jsmin("var a = 1\n~true\nconsole.log(a)"));
}
@Test
public void shouldNotRemoveSpaceBetweenPlusSigns()
throws Exception {
assertEquals("\nconsole.log(1\n+ +1)", jsmin("console.log(1\n+ +1)"));
}
@Test
public void shouldNotRemoveSpaceBetweenMinusSigns()
throws Exception {
assertEquals("\nconsole.log(1\n- -1)", jsmin("console.log(1\n- -1)"));
}
@Test
public void shouldRemoveInlineComments()
throws Exception {
assertEquals("\nvar r=1;", jsmin("var r = 1; // some comment"));
}
@Test
public void shouldRemoveBlockComments()
throws Exception {
assertEquals("\nvar r=1;", jsmin("var r = 1; /* some comment */"));
}
@Test
public void shouldNotProcessRegexpAfterOperator()
throws Exception {
assertEquals("\n1+/a a/;", jsmin("1 + /a a/;"));
assertEquals("\n1-/a a/;", jsmin("1 - /a a/;"));
assertEquals("\n1* /a a/;", jsmin("1 * /a a/;"));
assertEquals("\n1/ /a a/;", jsmin("1 / /a a/;"));
// Not sure why this should work, ~ was added in the original JSMin but the expression below is not valid
// Javascript.
assertEquals("\n1~/a a/;", jsmin("1 ~ /a a/;"));
}
@Test
public void shouldProcessRegexpContainingCurlyBraces()
throws Exception {
assertEquals("\nreturn/\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4}/.test(s);",
jsmin("return /\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4}/.test(s);"));
}
@Test
public void shouldProcessRegexpContainingSemicolumn()
throws Exception {
assertEquals("\nreturn/a;/.test(s);", jsmin("return /a;/.test(s);"));
}
@Test(expected = Exception.class)
public void shouldFailOnInlineCommentAfterUnclosedRegexp()
throws Exception {
// Make this fail to be consistent with the original JSMin, although this is in fact valid Javascript if comment is
// a defined variable.
jsmin("var r = /a //comment");
}
@Test(expected = Exception.class)
public void shouldFailOnUnclosedBlockCommentAfterUnclosedRegexp()
throws Exception {
// same comment as above
jsmin("var r = /a/*comment");
}
private String jsmin(final String inputScript)
throws Exception {
final StringReader reader = new StringReader(inputScript);
final InputStream is = new ReaderInputStream(reader, "UTF-8");
final StringWriter writer = new StringWriter();
final OutputStream os = new WriterOutputStream(writer, "UTF-8");
new JSMin(is, os).jsmin();
return writer.toString();
}
}