package org.codehaus.mojo.jslint; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.codehaus.plexus.util.Scanner; import org.junit.Before; import org.junit.Test; import org.sonatype.plexus.build.incremental.BuildContext; import com.googlecode.jslint4java.Issue; import com.googlecode.jslint4java.JSLint; import com.googlecode.jslint4java.JSLintResult; /** * Test linting. * * @author huntc */ public class JSLintMojoTest { /** * The mojo to test. */ private JSLintMojo jsLintMojo; /** * Set up a our mojo for testing. */ @Before public void setUpMojo() { jsLintMojo = new JSLintMojo(); } /** * Set up the mojo for execution. Sensible linting defaults are used. The source and target folders are relative to * our target/testClasses path. We also set up JSLint so that it requires variables to be defined. This will permit * some expectations on JSLint when parsing badTest.js in the resources folder. * * @throws URISyntaxException if something goes wrong. * @throws IOException */ private void setUpMojoForExecution() throws URISyntaxException, IOException { Log log = mock( Log.class ); jsLintMojo.setLog( log ); jsLintMojo.setJsFileExtensions( "*.js" ); File sourceJsFolder = new File( JSLintMojoTest.class.getResource( "test.js" ).toURI() ).getParentFile(); jsLintMojo.setSourceJsFolder( sourceJsFolder ); Scanner scanner = mock( Scanner.class ); String[] jsFileExtensions = { "js" }; Collection<?> includedFiles = FileUtils.listFiles( sourceJsFolder, jsFileExtensions, false ); Collection<String> includedFilenames = new ArrayList<String>( includedFiles.size() ); for ( Object includedFile : includedFiles ) { includedFilenames.add( ( (File) includedFile ).getName() ); } String[] includedFilenamesArray = new String[includedFilenames.size()]; includedFilenames.toArray( includedFilenamesArray ); when( scanner.getIncludedFiles() ).thenReturn( includedFilenamesArray ); BuildContext buildContext = mock( BuildContext.class ); when( buildContext.newScanner( sourceJsFolder ) ).thenReturn( scanner ); jsLintMojo.setBuildContext( buildContext ); jsLintMojo.setADsafe( false ); jsLintMojo.setAllowOneVarStatementPerFunction( false ); jsLintMojo.setAssumeABrowser( false ); jsLintMojo.setAssumeAYahooWidget( false ); jsLintMojo.setAssumeConsoleAlertEtc( false ); jsLintMojo.setAssumeRhino( false ); jsLintMojo.setAssumeWindows( false ); jsLintMojo.setDisallowBitwiseOperators( false ); jsLintMojo.setDisallowDanglingUnderbarInIdentifiers( false ); jsLintMojo.setDisallowEQNE( false ); jsLintMojo.setDisallowIncrAndDecr( false ); jsLintMojo.setDisallowInsecureCharsInRegExp( false ); jsLintMojo.setDisallowUndefinedVariables( true ); jsLintMojo.setFailOnIssues( false ); final int maxErrors = 50; jsLintMojo.setMaximumNumberOfErrors( maxErrors ); jsLintMojo.setPredefinedVars( "" ); jsLintMojo.setRequireInitialCapsForConstructors( false ); jsLintMojo.setRequireParensAroundImmediateInvocations( false ); jsLintMojo.setRequireUseStrict( false ); jsLintMojo.setSafeSubset( false ); jsLintMojo.setStopOnFirstError( false ); jsLintMojo.setStrictWhiteSpace( false ); jsLintMojo.setStrictWhiteSpaceIndentation( 4 ); jsLintMojo.setTolerateCSSWorkarounds( false ); jsLintMojo.setTolerateDebuggerStatements( false ); jsLintMojo.setTolerateES5Syntax( false ); jsLintMojo.setTolerateEval( false ); jsLintMojo.setTolerateHTMLCase( false ); jsLintMojo.setTolerateHTMLEventHandlers( false ); jsLintMojo.setTolerateHTMLFragments( false ); jsLintMojo.setTolerateInefficientSubscripting( false ); jsLintMojo.setTolerateSloppyLineBreaking( false ); jsLintMojo.setTolerateUnfilteredForIn( false ); } /** * Test execution for all files. The lint problem should be reported as a warning given that we're not expecting the * mojo to halt on lint issues. * * @throws URISyntaxException is something goes wrong. * @throws MojoExecutionException should not occur either. * @throws IOException should not occur. */ @Test public void testExecution() throws URISyntaxException, MojoExecutionException, IOException { setUpMojoForExecution(); jsLintMojo.execute(); Log log = jsLintMojo.getLog(); verify( log ).info( "Parsing: badTest.js" ); verify( log ).info( "Parsing: test.js" ); verify( log ).warn( "badTest.js:2:1:'a' is not defined." ); } /** * Test execution for all files and stop on error. The lint problem should be reported as an error given that we're * not expecting the mojo to halt on lint issues. * * @throws URISyntaxException is something goes wrong. * @throws MojoExecutionException should not occur either. * @throws IOException should not occur. */ @Test public void testExecutionWithStoppage() throws URISyntaxException, MojoExecutionException, IOException { setUpMojoForExecution(); jsLintMojo.setFailOnIssues( true ); try { jsLintMojo.execute(); fail( "Should have failed" ); } catch ( MojoExecutionException e ) { Log log = jsLintMojo.getLog(); verify( log ).info( "Parsing: badTest.js" ); verify( log ).info( "Parsing: test.js" ); verify( log ).error( "badTest.js:2:1:'a' is not defined." ); } } /** * Test the initialisation of JSLint. * * @throws URISyntaxException if something goes wrong. * @throws MojoExecutionException if something goes wrong with JSLint initialisation. */ @Test public void testJSLintInit() throws URISyntaxException, MojoExecutionException { jsLintMojo.setADsafe( true ); jsLintMojo.setAllowOneVarStatementPerFunction( true ); jsLintMojo.setAssumeABrowser( true ); jsLintMojo.setAssumeAYahooWidget( true ); jsLintMojo.setAssumeConsoleAlertEtc( true ); jsLintMojo.setAssumeRhino( true ); jsLintMojo.setAssumeWindows( true ); jsLintMojo.setDisallowBitwiseOperators( true ); jsLintMojo.setDisallowDanglingUnderbarInIdentifiers( true ); jsLintMojo.setDisallowEQNE( true ); jsLintMojo.setDisallowIncrAndDecr( true ); jsLintMojo.setDisallowInsecureCharsInRegExp( true ); jsLintMojo.setDisallowUndefinedVariables( true ); jsLintMojo.setFailOnIssues( true ); jsLintMojo.setMaximumNumberOfErrors( 1 ); jsLintMojo.setPredefinedVars( "a,b" ); jsLintMojo.setRequireInitialCapsForConstructors( true ); jsLintMojo.setRequireParensAroundImmediateInvocations( true ); jsLintMojo.setRequireUseStrict( true ); jsLintMojo.setSafeSubset( true ); jsLintMojo.setStopOnFirstError( true ); jsLintMojo.setStrictWhiteSpace( true ); jsLintMojo.setStrictWhiteSpaceIndentation( 4 ); jsLintMojo.setTolerateCSSWorkarounds( true ); jsLintMojo.setTolerateDebuggerStatements( true ); jsLintMojo.setTolerateES5Syntax( true ); jsLintMojo.setTolerateEval( true ); jsLintMojo.setTolerateHTMLCase( true ); jsLintMojo.setTolerateHTMLEventHandlers( true ); jsLintMojo.setTolerateHTMLFragments( true ); jsLintMojo.setTolerateInefficientSubscripting( true ); jsLintMojo.setTolerateSloppyLineBreaking( true ); jsLintMojo.setTolerateUnfilteredForIn( true ); // The method we want to exercise. jsLintMojo.initJSLint(); /* * This isn't a great test - it is tricky to test the code to ensure that all options are set given that the * JSLint object gives us no access to the options. All we can do is a weak smoke test to see that the options * are set. */ JSLint jsLint = jsLintMojo.getJsLint(); JSLintResult result = jsLint.lint( "", "" ); List<Issue> issues = result.getIssues(); assertEquals( 2, issues.size() ); assertEquals( ":1:1:Expected '<div>' and instead saw ''.", issues.get( 0 ).toString() ); assertEquals( ":1:1:Stopping. (0% scanned).", issues.get( 1 ).toString() ); } }