View Javadoc

1   /*
2    * Copyright 2011 SOFTEC sa. All rights reserved.
3    *
4    * This source code is licensed under the Creative Commons
5    * Attribution-NonCommercial-NoDerivs 3.0 Luxembourg
6    * License.
7    *
8    * To view a copy of this license, visit
9    * http://creativecommons.org/licenses/by-nc-nd/3.0/lu/
10   * or send a letter to Creative Commons, 171 Second Street,
11   * Suite 300, San Francisco, California, 94105, USA.
12   */
13  
14  package searls.jasmine.runner;
15  
16  import org.antlr.stringtemplate.StringTemplate;
17  import org.antlr.stringtemplate.language.DefaultTemplateLexer;
18  import org.codehaus.plexus.util.DirectoryScanner;
19  import org.codehaus.plexus.util.IOUtil;
20  import searls.jasmine.io.FileUtilsWrapper;
21  import searls.jasmine.io.IOUtilsWrapper;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.PrintWriter;
26  import java.util.Arrays;
27  import java.util.List;
28  
29  /**
30   * Class generating the titanium app.js file.
31   */
32  public class SpecRunnerTitaniumGenerator {
33      private static final String JASMINE_JS = "/vendor/js/jasmine.js";
34      private static final String JASMINE_TITANIUM_JS = "/vendor/js/jasmine-titanium.js";
35  
36      /**
37       * The name of the javascript dependencies placeholder in the template document.
38       */
39      private static final String JAVASCRIPT_DEPENDENCIES_TEMPLATE_ATTR_NAME = "javascriptDependencies";
40  
41      /**
42       * The name of the sources placeholder in the template document.
43       */
44      private static final String SOURCES_TEMPLATE_ATTR_NAME = "sources";
45  
46      /**
47       * The name of the specs placeholder in the template document.
48       */
49      private static final String SPECS_TEMPLATE_ATTR_NAME = "specs";
50  
51      /**
52       * The name of the reporter placeholder in the template document.
53       */
54      private static final String REPORTER_ATTR_NAME = "reporter";
55  
56      /**
57       * The template of the app.js file.
58       */
59      private static final String RUNNER_JS_TEMPLATE = "(function(){\n" +
60              "  $" + JAVASCRIPT_DEPENDENCIES_TEMPLATE_ATTR_NAME + "$\n" +
61              "\n" +
62              "  $"+ SOURCES_TEMPLATE_ATTR_NAME +"$\n" +
63              "  \n" +
64              "  // Include all the test files\n" +
65              "  $" + SPECS_TEMPLATE_ATTR_NAME + "$\n" +
66              "  \n" +
67              "  var reporter = new jasmine.$" + REPORTER_ATTR_NAME + "$();\n" +
68              "  jasmine.getEnv().addReporter(reporter);\n" +
69              "})();";
70  
71      private List<String> sourcesToLoadFirst;
72      private List<String> sourceFiles;
73      private File specDir;
74      private String specDirName;
75      private File libDir;
76      private String libDirName;
77      private File baseDir;
78  
79      private FileUtilsWrapper fileUtilsWrapper = new FileUtilsWrapper();
80      private IOUtilsWrapper ioUtilsWrapper = new IOUtilsWrapper();
81  
82      /**
83       * Jasmine reporter type.
84       */
85      public enum ReporterType {
86          /**
87           * Titanium specific reporter.
88           */
89          TITANIUM
90      };
91  
92      public SpecRunnerTitaniumGenerator(List<String> sourcesToLoadFirst, List<String> sourceFiles,
93                                         File baseDir,
94                                         String libDirName, String specDirName) {
95          this.sourcesToLoadFirst = sourcesToLoadFirst;
96          this.sourceFiles = sourceFiles;
97          this.baseDir = baseDir;
98          this.specDirName = specDirName;
99          this.specDir = new File(baseDir, specDirName);
100         this.libDir = new File(baseDir, libDirName);
101         this.libDirName = libDirName;
102     }
103 
104     /**
105      * Generate the jasmine tests runner.
106      *
107      * @param reporterType The reporter to use.
108      */
109     public String generate(ReporterType reporterType) {
110         try {
111             StringTemplate template = new StringTemplate(RUNNER_JS_TEMPLATE, DefaultTemplateLexer.class);
112             includeDependencies(Arrays.asList(JASMINE_JS, JASMINE_TITANIUM_JS), template);
113             includeSources(template);
114             includeSpecs(template);
115             switch (reporterType) {
116                 case TITANIUM:
117                     template.setAttribute(REPORTER_ATTR_NAME,"TitaniumReporter");
118             }
119 
120             return template.toString();
121         } catch (IOException t) {
122             throw new RuntimeException("Failed to load file names for dependencies or scripts", t);
123         }
124     }
125 
126     /**
127      * Include the dependencies in the templates.
128      * @param dependencies The dependencies to add.
129      * @param template The template where the dependencies should be added.
130      * @throws IOException
131      */
132     private void includeDependencies(List<String> dependencies, StringTemplate template)
133             throws IOException {
134         StringBuilder jsDependencies = new StringBuilder();
135 
136         PrintWriter writer = null;
137         try {
138             writer = new PrintWriter(new File(baseDir, "dependencies.js"));
139             if (dependencies != null) {
140                 for (String dep : dependencies) {
141                     writer.append(ioUtilsWrapper.toString(dep));
142                     writer.append("\n");
143                 }
144             }
145         } finally {
146             IOUtil.close(writer);
147         }
148         jsDependencies.append("Ti.include(\"dependencies.js\");\n");
149         template.setAttribute(JAVASCRIPT_DEPENDENCIES_TEMPLATE_ATTR_NAME, jsDependencies.toString());
150     }
151 
152     private void includeSources(StringTemplate template) {
153         StringBuilder sourcesDependencies = new StringBuilder();
154 
155         if (sourcesToLoadFirst != null) {
156             for (String source : sourcesToLoadFirst) {
157                 File sourceFile = new File(baseDir, source);
158                 if (sourceFile.exists()) {
159                     sourcesDependencies.append("Ti.include(\"");
160                     sourcesDependencies.append(source);
161                     sourcesDependencies.append("\");\n");
162                 } else {
163                     sourceFile = new File(libDir, source);
164                     if (sourceFile.exists()) {
165                         sourcesDependencies.append("Ti.include(\"");
166                         sourcesDependencies.append(libDirName);
167                         sourcesDependencies.append("/");
168                         sourcesDependencies.append(source);
169                         sourcesDependencies.append("\");\n");
170 
171                     }
172                 }
173             }
174         }
175         sourcesDependencies.append("\n");
176 
177         if (sourceFiles != null) {
178             for (String source : sourceFiles) {
179                 if (sourcesToLoadFirst == null || !sourcesToLoadFirst.contains(source)) {
180                     sourcesDependencies.append("Ti.include(\"");
181                     sourcesDependencies.append(source);
182                     sourcesDependencies.append("\");\n");
183                 }
184             }
185         }
186         template.setAttribute(SOURCES_TEMPLATE_ATTR_NAME, sourcesDependencies.toString());
187     }
188 
189     private void includeSpecs(StringTemplate template) {
190         StringBuilder specBuilder = new StringBuilder();
191 
192         String[] specFiles = null;
193         if (specDir != null && specDir.exists()) {
194             DirectoryScanner scanner = new DirectoryScanner();
195             scanner.setBasedir(specDir);
196             scanner.setIncludes(new String[] {"**/*.js"});
197             scanner.addDefaultExcludes();
198             scanner.scan();
199             specFiles = scanner.getIncludedFiles();
200         }
201 
202         if (specFiles != null) {
203             for (String spec : specFiles) {
204                 specBuilder.append("Ti.include(\"");
205                 specBuilder.append(specDirName);
206                 specBuilder.append("/");
207                 specBuilder.append(spec);
208                 specBuilder.append("\");\n");
209             }
210         }
211 
212         template.setAttribute(SPECS_TEMPLATE_ATTR_NAME, specBuilder.toString());
213     }
214 }