View Javadoc

1   package org.codehaus.mojo.javascript;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.File;
20  import java.io.FileWriter;
21  import java.io.IOException;
22  import java.io.Writer;
23  import java.net.URL;
24  import java.util.Arrays;
25  import java.util.Collections;
26  
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.apache.maven.surefire.junit.JUnitTestSet;
30  import org.apache.maven.surefire.report.FileReporter;
31  import org.apache.maven.surefire.report.ReportEntry;
32  import org.apache.maven.surefire.report.Reporter;
33  import org.apache.maven.surefire.report.ReporterManager;
34  import org.apache.maven.surefire.testset.AbstractTestSet;
35  import org.codehaus.plexus.util.DirectoryScanner;
36  import org.codehaus.plexus.util.IOUtil;
37  import org.mortbay.util.MultiException;
38  
39  import junit.framework.TestSuite;
40  import net.jsunit.Configuration;
41  import net.jsunit.ConfigurationException;
42  import net.jsunit.JsUnitServer;
43  
44  /**
45   * Goal which runs javascript tests using jsunit framework. Tests can be writter
46   * either inside an html page, as documented by jsunit, or simply as javascript.
47   * 
48   * @goal jsunit
49   * @phase test
50   * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
51   */
52  public class JsUnitMojo
53      extends AbstractJavascriptMojo
54  {
55      /**
56       * Set this to 'true' to bypass unit tests entirely. Its use is NOT
57       * RECOMMENDED, but quite convenient on occasion.
58       *
59       * @parameter expression="${maven.test.skip}"
60       */
61      private boolean skipTests;
62  
63      /**
64       * Set this to true to ignore a failure during testing. Its use is NOT
65       * RECOMMENDED, but quite convenient on occasion.
66       * 
67       * @parameter expression="${maven.test.failure.ignore}"
68       */
69      private boolean testFailureIgnore;
70  
71      /**
72       * Base directory where all reports are written to.
73       * 
74       * @parameter expression="${project.build.directory}${file.separator}surefire-reports"
75       */
76      private File reportsDirectory;
77  
78      /**
79       * Base directory where jsunit will run.
80       * 
81       * @parameter expression="${project.build.directory}${file.separator}test-scripts"
82       */
83      private File workDirectory;
84  
85      /**
86       * Base directory for jsunit test.
87       * 
88       * @parameter default-value="${project.basedir}${file.separator}src${file.separator}test${file.separator}javascript" expression="${testSourceDirectory}"
89       */
90      private File jsunitTestSourceDirectory;
91  
92      /**
93       * @parameter default-value="${project.basedir}${file.separator}src${file.separator}test${file.separator}javascript" expression="${testSourceDirectory}"
94       */
95      private File jasmineTestSourceDirectory;
96  
97      /**
98       * Browsers to run the jsunit tests
99       * 
100      * @parameter
101      */
102     private String[] browsers;
103 
104     private String[] DEFAULT_BROWSERS = { "firefox" };
105 
106     /**
107      * The local port to use for the jsunit HTTP server
108      * 
109      * @parameter default-value="8080"
110      */
111     private int port;
112 
113     /**
114      * Exclusion pattern.
115      * 
116      * @parameter
117      */
118     private String[] excludes;
119 
120     /**
121      * Inclusion pattern.
122      * 
123      * @parameter
124      */
125     private String[] includes;
126 
127     private static final String[] DEFAULT_INCLUDES = { "**/*.html", "**/*.htm", "**/*.js" };
128     
129     
130     /**
131      * @parameter expression="${javascript.jsunit.firefox.path}" default-value="c:/program files/Mozilla Firefox/firefox.exe"
132      */
133     private String firefoxPath;
134     
135     /**
136      * @parameter expression="${javascript.jsunit.ie.path}" default-value="c:/program files/internet explorer/iexplore.exe"
137      */    
138     private String iePath;
139 
140     /**
141      * {@inheritDoc}
142      * 
143      * @see org.apache.maven.plugin.Mojo#execute()
144      */
145     public void execute()
146         throws MojoExecutionException, MojoFailureException
147     {
148         if(jsunitTestSourceDirectory.equals(jasmineTestSourceDirectory) || !jsunitTestSourceDirectory.exists()) {
149             getLog().info("No JsUnit tests, skipping JsUnit tests execution.");
150             return;
151         }
152 
153         if (skipTests)
154         {
155             getLog().warn( "Skipping JsUnit tests." );
156             return;
157         }
158 
159         String[] tests = getTestsToRun();
160 
161 		if ( tests == null || tests.length == 0 )
162 		{
163 			getLog().info( "no jsunit tests to run." );
164 			return;
165 		}
166 
167         unpackJavascriptDependency( "net.jsunit:jsunit-testRunner", workDirectory );
168 
169         if ( browsers == null )
170         {
171             browsers = DEFAULT_BROWSERS;
172         }
173 
174         for ( int i = 0; i < browsers.length; i++ )
175         {
176             if ( new File( browsers[i] ).exists() )
177             {
178                 continue;
179             }
180             if ( "firefox".equalsIgnoreCase( browsers[i] ) )
181             {
182                 browsers[i] = firefoxPath;
183             }
184             if ( "iexplorer".equalsIgnoreCase( browsers[i] ) )
185             {
186                 browsers[i] = iePath;
187             }
188         }
189 
190         JsUnitServer server = new JsUnitServer();
191         try
192         {
193             runJsUnitTests( server, tests );
194         }
195         catch ( Exception e )
196         {
197             throw new MojoExecutionException( "Failed to run JsUnit tests", e );
198         }
199         finally
200         {
201             try
202             {
203                 server.stop();
204             }
205             catch ( InterruptedException e )
206             {
207                 // Ignore;
208             }
209         }
210     }
211 
212     private void runJsUnitTests( JsUnitServer server, String[] tests )
213         throws Exception
214     {
215         setupServer( server );
216 
217         Reporter reporter = new FileReporter( reportsDirectory, Boolean.FALSE );
218         ReporterManager reportManager = new ReporterManager( Collections.singletonList( reporter ) );
219         ReportEntry report = new ReportEntry( this, "jsunit", "test Starting" );
220         reportManager.testSetStarting( report );
221 
222         for ( int i = 0; i < tests.length; i++ )
223         {
224             String test = tests[i];
225             String path = workDirectory.toURI().getPath();
226             String name = test.substring( 0, test.lastIndexOf( '.' ) );
227             if ( test.toLowerCase().endsWith( ".js" ) )
228             {
229                 test = buildMinimalHtml( test );
230             }
231             server.setTestURL( new URL( "file://" + path
232                 + "testRunner.html?autoRun=true&submitresults=true" + "&resultid=TEST-" + name
233                 + "&testPage=" + path.substring( 1 ) + test ) );
234 
235             JsUnitTestCase.setSuite( new TestSuite( JsUnitTestCase.class, name ) );
236             AbstractTestSet testSet = new JUnitTestSet( JsUnitTestCase.class );
237 
238             testSet.execute( reportManager, getClass().getClassLoader() );
239         }
240 
241         report = new ReportEntry( this, "jsunit", "test Completed" );
242         reportManager.testSetCompleted( report );
243         checkFailure( reportManager );
244     }
245 
246     /**
247      * @param test
248      * @return
249      * @throws IOException
250      */
251     private String buildMinimalHtml( String test )
252         throws IOException
253     {
254         String name = test.substring( 0, test.lastIndexOf( '.' ) );
255         String html = name + ".html";
256         File file = new File( workDirectory, html );
257         file.getParentFile().mkdirs();
258 
259         test = test.replace( '\\', '/' );
260         String basedir = "";
261         int i = 0;
262         while ( ( i = test.indexOf( "/" ) ) > 0 )
263         {
264             test = test.substring( i );
265             basedir += "../";
266         }
267         if ( basedir.trim().length() == 0 )
268         {
269             basedir = ".";
270         }
271 
272         Writer w = new FileWriter( file );
273         w.write( "<html>\n" );
274         w.write( "<head>\n" );
275         w.write( "<script type='text/javascript' src='" + basedir
276             + "/app/jsUnitCore.js'></script>\n" );
277         w.write( "<script type='text/javascript' src='" + test + "'></script>\n" );
278         w.write( "</head>\n" );
279         w.write( "<body>\n" );
280         w.write( "</body>\n" );
281         w.write( "</html>\n" );
282 
283         IOUtil.close( w );
284         return html;
285     }
286 
287     private String[] getTestsToRun()
288     {
289 		if ( !jsunitTestSourceDirectory.exists() )
290 		{
291 			return null;
292 		}
293         DirectoryScanner scanner = new DirectoryScanner();
294         scanner.setBasedir(jsunitTestSourceDirectory);
295         scanner.setExcludes( excludes );
296         scanner.addDefaultExcludes();
297         if ( includes == null )
298         {
299             includes = DEFAULT_INCLUDES;
300         }
301         scanner.setIncludes( includes );
302         scanner.scan();
303         String[] tests = scanner.getIncludedFiles();
304         return tests;
305     }
306 
307     private void checkFailure( ReporterManager reportManager )
308         throws MojoFailureException
309     {
310         if ( reportManager.getNumErrors() + reportManager.getNumFailures() > 0 )
311         {
312             String msg =
313                 "There are test failures.\n\nPlease refer to " + reportsDirectory
314                     + " for the individual test results.";
315             if ( testFailureIgnore )
316             {
317                 getLog().error( msg );
318             }
319             else
320             {
321                 throw new MojoFailureException( msg );
322             }
323         }
324     }
325 
326     private void setupServer( JsUnitServer server )
327         throws ConfigurationException, MultiException
328     {
329         System.setProperty( Configuration.URL, "http://localhost:" + port + "/jsunit/" );
330         System.setProperty( Configuration.PORT, String.valueOf( port ) );
331         System.setProperty( Configuration.LOGS_DIRECTORY, reportsDirectory.getAbsolutePath() );
332         server.initialize();
333         server.setResourceBase( workDirectory );
334         server.setLocalBrowserFileNames( Arrays.asList( browsers ) );
335         server.start();
336         JsUnitTestCase.setSharedServer( server );
337     }
338 }