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() );
}
}