initial checkin
This commit is contained in:
parent
a723f9ca67
commit
582cbe4ce3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<groupId>be.cegeka</groupId>
|
||||
<artifactId>jasminejunitrunner</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>Jasmine Junit Runner</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>rhino</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>1.7R2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<configuration>
|
||||
<buildOutputDirectory>eclipsecompiled</buildOutputDirectory>
|
||||
<downloadSources>true</downloadSources>
|
||||
<downloadJavadocs>true</downloadJavadocs>
|
||||
</configuration>
|
||||
<version>2.5.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<showWarnings>true</showWarnings>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,38 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.runner.Description;
|
||||
|
||||
import be.cegeka.rhino.RhinoContext;
|
||||
|
||||
class JasmineDescriptions {
|
||||
|
||||
private final Description rootDescription;
|
||||
private final Map<String, JasmineSpec> specsMap;
|
||||
private final RhinoContext rhinoContext;
|
||||
|
||||
JasmineDescriptions(Description rootDescription, Map<String, JasmineSpec> specsMap, RhinoContext context) {
|
||||
this.rootDescription = rootDescription;
|
||||
this.specsMap = specsMap;
|
||||
this.rhinoContext = context;
|
||||
}
|
||||
|
||||
public Description getRootDescription() {
|
||||
return rootDescription;
|
||||
}
|
||||
|
||||
public Collection<JasmineSpec> getAllSpecs() {
|
||||
return specsMap.values();
|
||||
}
|
||||
|
||||
public void executeSpec(Description description) {
|
||||
getSpec(description).execute(rhinoContext);
|
||||
}
|
||||
|
||||
public JasmineSpec getSpec(Description description) {
|
||||
return specsMap.get(description.getDisplayName());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.runner.Description;
|
||||
import org.mozilla.javascript.NativeArray;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
|
||||
import be.cegeka.rhino.RhinoContext;
|
||||
|
||||
class JasmineJSSuiteConverter {
|
||||
|
||||
private final NativeArray baseSuites;
|
||||
private final RhinoContext context;
|
||||
|
||||
JasmineJSSuiteConverter(NativeArray baseSuites, RhinoContext context) {
|
||||
this.baseSuites = baseSuites;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public JasmineDescriptions convertToJunitDescriptions(Class<?> testClass) {
|
||||
Description rootDescription = Description.createSuiteDescription(testClass);
|
||||
Map<String, JasmineSpec> specsMap = convertSuiteArrayToDescriptions(this.baseSuites, rootDescription);
|
||||
return new JasmineDescriptions(rootDescription, specsMap, context);
|
||||
}
|
||||
|
||||
private Map<String, JasmineSpec> convertSuiteArrayToDescriptions(NativeArray suiteArray, Description rootDescription) {
|
||||
Map<String, JasmineSpec> specsMap = new HashMap<String, JasmineSpec>();
|
||||
for (Object idObj : suiteArray.getIds()) {
|
||||
NativeObject suite = (NativeObject) suiteArray.get((Integer) idObj, suiteArray);
|
||||
|
||||
Description suiteDescription = Description
|
||||
.createSuiteDescription((String) suite.get("description", suite), (Annotation[]) null);
|
||||
rootDescription.addChild(suiteDescription);
|
||||
specsMap.putAll(convertToJunitDescription(suite, suiteDescription));
|
||||
}
|
||||
|
||||
return specsMap;
|
||||
}
|
||||
|
||||
private Map<String, JasmineSpec> convertToJunitDescription(NativeObject suite, Description description) {
|
||||
Map<String, JasmineSpec> specsMap = new HashMap<String, JasmineSpec>();
|
||||
NativeArray specsArray = (NativeArray) context.executeFunction(suite, "specs");
|
||||
for (Object idObj : specsArray.getIds()) {
|
||||
NativeObject spec = (NativeObject) specsArray.get((Integer) idObj, specsArray);
|
||||
|
||||
JasmineSpec jasmineSpec = new JasmineSpec(spec);
|
||||
specsMap.put(jasmineSpec.toString(), jasmineSpec);
|
||||
description.addChild(jasmineSpec.getDescription());
|
||||
}
|
||||
|
||||
return specsMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.mozilla.javascript.NativeArray;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
|
||||
import be.cegeka.rhino.RhinoContext;
|
||||
import be.cegeka.rhino.RhinoRunnable;
|
||||
|
||||
// TODO rhinoContext als field zetten ipv altijd mee te geven?
|
||||
class JasmineSpec {
|
||||
|
||||
public enum JasmineSpecStatus {
|
||||
PASSED,
|
||||
FAILED,
|
||||
SKIPPED
|
||||
}
|
||||
|
||||
private final Description description;
|
||||
private final NativeObject spec;
|
||||
|
||||
JasmineSpec(NativeObject spec) {
|
||||
this.spec = spec;
|
||||
String descriptionString = (String) spec.get("description", spec);
|
||||
this.description = Description.createSuiteDescription(descriptionString);
|
||||
}
|
||||
|
||||
public Description getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public NativeObject getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public boolean isPassed(RhinoContext context) {
|
||||
return getSpecResultStatus(context) == JasmineSpecStatus.PASSED;
|
||||
}
|
||||
|
||||
public boolean isFailed(RhinoContext context) {
|
||||
return getSpecResultStatus(context) == JasmineSpecStatus.FAILED;
|
||||
}
|
||||
|
||||
public JasmineSpecStatus getSpecResultStatus(RhinoContext context) {
|
||||
assertTrue(isDone());
|
||||
|
||||
NativeObject results = getSpecResults(context);
|
||||
boolean passed = (Boolean) context.executeFunction(results, "passed");
|
||||
boolean skipped = (Boolean) results.get("skipped", results);
|
||||
|
||||
if (skipped) {
|
||||
return JasmineSpecStatus.SKIPPED;
|
||||
}
|
||||
return passed ? JasmineSpecStatus.PASSED : JasmineSpecStatus.FAILED;
|
||||
}
|
||||
|
||||
public Failure getJunitFailure(RhinoContext context) {
|
||||
assertTrue(isFailed(context));
|
||||
return new Failure(description, getFirstFailedStacktrace(context));
|
||||
}
|
||||
|
||||
private Throwable getFirstFailedStacktrace(RhinoContext context) {
|
||||
NativeArray resultItems = (NativeArray) context.executeFunction(getSpecResults(context), "getItems");
|
||||
for (Object resultItemId : resultItems.getIds()) {
|
||||
NativeObject resultItem = (NativeObject) resultItems.get((Integer) resultItemId, resultItems);
|
||||
|
||||
if (!((Boolean) context.executeFunction(resultItem, "passed"))) {
|
||||
return new JasmineSpecFailureException(resultItem);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private NativeObject getSpecResults(RhinoContext context) {
|
||||
return (NativeObject) context.executeFunction(spec, "results");
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
Object doneResult = spec.get("done", spec);
|
||||
return doneResult instanceof Boolean && ((Boolean) doneResult);
|
||||
}
|
||||
|
||||
public void execute(RhinoContext baseContext) {
|
||||
baseContext.runAsync(new RhinoRunnable() {
|
||||
|
||||
@Override
|
||||
public void run(RhinoContext context) {
|
||||
context.executeFunction(spec, "execute");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description.getDisplayName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
public class JasmineSpecFailureException extends Exception {
|
||||
|
||||
private final ScriptableObject trace;
|
||||
|
||||
public JasmineSpecFailureException(NativeObject specResultItem) {
|
||||
this.trace = (ScriptableObject) specResultItem.get("trace", specResultItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return (String) trace.get("message", trace);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
public class JasmineSpecRunnerGenerator {
|
||||
|
||||
private enum TemplatePlaceholders {
|
||||
RELATIVE_PATH("<!--RelativePath-->"),
|
||||
SOURCE_FILES_TO_INCLUDE("<!--SourceFileIncludes-->"),
|
||||
SPEC_FILES_TO_INCLUDE("<!--SpecFileIncludes-->");
|
||||
|
||||
private final String placeholder;
|
||||
|
||||
private TemplatePlaceholders(String placeholder) {
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
public String getPlaceholder() {
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final JasmineSuite suite;
|
||||
private final String[] jasmineSpecs;
|
||||
private final String outputPath;
|
||||
private final String outputFileName;
|
||||
|
||||
public JasmineSpecRunnerGenerator(String[] jasmineSpecs, JasmineSuite suite, String outputPath, String outputFileName) {
|
||||
this.jasmineSpecs = jasmineSpecs;
|
||||
this.suite = suite;
|
||||
this.outputPath = outputPath;
|
||||
this.outputFileName = outputFileName;
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
// TODO hardcoded relative path stuff wat configureerbaar maken
|
||||
String template = loadTemplate();
|
||||
template = replaceRelativePathsForLibs(template);
|
||||
template = template.replaceAll(TemplatePlaceholders.SOURCE_FILES_TO_INCLUDE.getPlaceholder(),
|
||||
getJavascriptFileIncludes("./../../../main/webapp/js", suite.sources()));
|
||||
template = template.replaceAll(TemplatePlaceholders.SPEC_FILES_TO_INCLUDE.getPlaceholder(),
|
||||
getJavascriptFileIncludes("./../specs", jasmineSpecs));
|
||||
|
||||
try {
|
||||
FileUtils.writeStringToFile(new File(outputPath + "/" + outputFileName), template);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("unable to write spec runner contents to destination", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceRelativePathsForLibs(String template) {
|
||||
return template.replaceAll(TemplatePlaceholders.RELATIVE_PATH.getPlaceholder(), suite.jsRootDir());
|
||||
}
|
||||
|
||||
private String getJavascriptFileIncludes(String path, String[] jsFiles) {
|
||||
StringBuilder sourceFileIncludes = new StringBuilder();
|
||||
for (String sourceFile : jsFiles) {
|
||||
sourceFileIncludes.append("\t\t<script type='text/javascript' src='" + path + "/" + sourceFile
|
||||
+ "'></script>\r\n");
|
||||
}
|
||||
return sourceFileIncludes.toString();
|
||||
}
|
||||
|
||||
private String loadTemplate() {
|
||||
String template = null;
|
||||
try {
|
||||
template = FileUtils.readFileToString(new File(suite.jsRootDir() + "/lib/specRunner.tpl"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("spec runner template file not found!", e);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JasmineSuite {
|
||||
|
||||
String jsRootDir() default "src/test/javascript";
|
||||
|
||||
String sourcesRootDir() default "src/main/webapp/js";
|
||||
|
||||
String[] specs() default {};
|
||||
|
||||
String[] sources() default {};
|
||||
|
||||
boolean generateSpecRunner() default false;
|
||||
|
||||
boolean debug() default false;
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.mozilla.javascript.NativeArray;
|
||||
import org.mozilla.javascript.tools.debugger.Main;
|
||||
|
||||
import be.cegeka.rhino.RhinoContext;
|
||||
|
||||
public class JasmineTestRunner extends Runner {
|
||||
|
||||
private static final int SLEEP_TIME_MILISECONDS = 50;
|
||||
private static final String JASMINE_LIB_DIR = "/lib/jasmine-1.0.2/";
|
||||
|
||||
private JasmineDescriptions jasmineSuite;
|
||||
|
||||
private final RhinoContext rhinoContext;
|
||||
private final JasmineSuite suiteAnnotation;
|
||||
private final Class<?> testClass;
|
||||
|
||||
@JasmineSuite
|
||||
private class DefaultSuite {
|
||||
}
|
||||
|
||||
public JasmineTestRunner(Class<?> testClass) {
|
||||
this.testClass = testClass;
|
||||
this.suiteAnnotation = getJasmineSuiteAnnotationFromTestClass();
|
||||
|
||||
Main debugger = null;
|
||||
if (this.suiteAnnotation.debug()) {
|
||||
debugger = this.rhinoContext.createDebugger();
|
||||
}
|
||||
|
||||
this.rhinoContext = setUpRhinoScope();
|
||||
|
||||
if (this.suiteAnnotation.debug()) {
|
||||
debugger.doBreak();
|
||||
}
|
||||
}
|
||||
|
||||
private RhinoContext setUpRhinoScope() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
context.loadEnv(suiteAnnotation.jsRootDir());
|
||||
setUpJasmine(context);
|
||||
|
||||
context.load(suiteAnnotation.sourcesRootDir() + "/", suiteAnnotation.sources());
|
||||
context.load(suiteAnnotation.jsRootDir() + "/specs/", getJasmineSpecs(suiteAnnotation));
|
||||
return context;
|
||||
}
|
||||
|
||||
private void setUpJasmine(RhinoContext context) {
|
||||
context.load(getJsLibDir() + "jasmine.js");
|
||||
context.load(getJsLibDir() + "jasmine.delegator_reporter.js");
|
||||
|
||||
context.evalJS("jasmine.getEnv().addReporter(new jasmine.DelegatorJUnitReporter());");
|
||||
}
|
||||
|
||||
private JasmineSuite getJasmineSuiteAnnotationFromTestClass() {
|
||||
JasmineSuite suiteAnnotation = testClass.getAnnotation(JasmineSuite.class);
|
||||
if (suiteAnnotation == null) {
|
||||
suiteAnnotation = DefaultSuite.class.getAnnotation(JasmineSuite.class);
|
||||
}
|
||||
return suiteAnnotation;
|
||||
}
|
||||
|
||||
private String[] getJasmineSpecs(JasmineSuite suiteAnnotation) {
|
||||
if (suiteAnnotation.specs().length == 0) {
|
||||
return new String[] { StringUtils.uncapitalize(testClass.getSimpleName()).replace("Test", "Spec") + ".js" };
|
||||
}
|
||||
return suiteAnnotation.specs();
|
||||
}
|
||||
|
||||
private void resetEnvjsWindowSpace() {
|
||||
this.rhinoContext.evalJS("window.location = '" + suiteAnnotation.jsRootDir() + "/lib/blank.html';");
|
||||
}
|
||||
|
||||
private String getJsLibDir() {
|
||||
return suiteAnnotation.jsRootDir() + JASMINE_LIB_DIR;
|
||||
}
|
||||
|
||||
private JasmineDescriptions getJasmineDescriptions() {
|
||||
if (this.jasmineSuite == null) {
|
||||
NativeArray baseSuites = (NativeArray) rhinoContext.evalJS("jasmine.getEnv().currentRunner().suites()");
|
||||
this.jasmineSuite = new JasmineJSSuiteConverter(baseSuites, rhinoContext).convertToJunitDescriptions(testClass);
|
||||
}
|
||||
return this.jasmineSuite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description getDescription() {
|
||||
return getJasmineDescriptions().getRootDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(RunNotifier notifier) {
|
||||
generateSpecRunnerIfNeeded();
|
||||
|
||||
for (JasmineSpec spec : getJasmineDescriptions().getAllSpecs()) {
|
||||
Object testClassInstance = createTestClassInstance();
|
||||
fireMethodsWithSpecifiedAnnotationIfAny(testClassInstance, Before.class);
|
||||
|
||||
try {
|
||||
notifier.fireTestStarted(spec.getDescription());
|
||||
spec.execute(rhinoContext);
|
||||
while (!spec.isDone()) {
|
||||
waitALittle();
|
||||
}
|
||||
|
||||
reportSpecResultToNotifier(notifier, spec);
|
||||
resetEnvjsWindowSpace();
|
||||
} finally {
|
||||
fireMethodsWithSpecifiedAnnotationIfAny(testClassInstance, After.class);
|
||||
}
|
||||
}
|
||||
|
||||
this.rhinoContext.exit();
|
||||
}
|
||||
|
||||
private Object createTestClassInstance() {
|
||||
try {
|
||||
return testClass.newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Unable to create a new instance of testClass " + testClass.getSimpleName()
|
||||
+ " using a no-arg constructor", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireMethodsWithSpecifiedAnnotationIfAny(Object testClassInstance, Class<? extends Annotation> annotation) {
|
||||
for (Method method : testClass.getDeclaredMethods()) {
|
||||
|
||||
try {
|
||||
if (method.getAnnotation(annotation) != null) {
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
throw new IllegalStateException("Annotated method should be public!");
|
||||
}
|
||||
|
||||
method.setAccessible(true);
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length == 0) {
|
||||
method.invoke(testClassInstance, (Object[]) null);
|
||||
} else if (parameterTypes.length == 1 && RhinoContext.class.isAssignableFrom(parameterTypes[0])) {
|
||||
method.invoke(testClassInstance, new Object[] { this.rhinoContext });
|
||||
} else {
|
||||
throw new IllegalStateException("Annotated method does not have zero or rhinoContext as parameterTypes");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(
|
||||
"Exception while firing " + annotation.getSimpleName() + " method: " + method.getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSpecRunnerIfNeeded() {
|
||||
if (suiteAnnotation.generateSpecRunner()) {
|
||||
String[] jasmineSpecs = getJasmineSpecs(suiteAnnotation);
|
||||
new JasmineSpecRunnerGenerator(jasmineSpecs, suiteAnnotation, suiteAnnotation.jsRootDir() + "/runners",
|
||||
testClass.getSimpleName()
|
||||
+ "Runner.html")
|
||||
.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private void reportSpecResultToNotifier(RunNotifier notifier, JasmineSpec spec) {
|
||||
if (spec.isPassed(rhinoContext)) {
|
||||
notifier.fireTestFinished(spec.getDescription());
|
||||
} else if (spec.isFailed(rhinoContext)) {
|
||||
notifier.fireTestFailure(spec.getJunitFailure(rhinoContext));
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected spec status received: " + spec);
|
||||
}
|
||||
}
|
||||
|
||||
private void waitALittle() {
|
||||
try {
|
||||
Thread.sleep(SLEEP_TIME_MILISECONDS);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mozilla.javascript.ErrorReporter;
|
||||
import org.mozilla.javascript.EvaluatorException;
|
||||
import org.mozilla.javascript.tools.ToolErrorReporter;
|
||||
|
||||
class ChainedErrorReporter implements ErrorReporter {
|
||||
|
||||
private List<ErrorReporter> chainedReporters = new ArrayList<ErrorReporter>();
|
||||
|
||||
ChainedErrorReporter(ErrorReporter chainedDefaultReporter) {
|
||||
chainedReporters.add(chainedDefaultReporter);
|
||||
chainedReporters.add(new ToolErrorReporter(true, System.err));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
||||
EvaluatorException ex = null;
|
||||
for (ErrorReporter reporter : chainedReporters) {
|
||||
try {
|
||||
reporter.error(message, sourceName, line, lineSource, lineOffset);
|
||||
} catch (EvaluatorException thrownByChainEx) {
|
||||
ex = thrownByChainEx;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex != null) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
||||
EvaluatorException ex = null;
|
||||
for (ErrorReporter reporter : chainedReporters) {
|
||||
EvaluatorException returnedByChainEx = reporter.runtimeError(message, sourceName, line, lineSource, lineOffset);
|
||||
if (returnedByChainEx != null) {
|
||||
ex = returnedByChainEx;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex != null) {
|
||||
throw ex;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
||||
for (ErrorReporter reporter : chainedReporters) {
|
||||
reporter.warning(message, sourceName, line, lineSource, lineOffset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.Function;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.tools.debugger.Main;
|
||||
import org.mozilla.javascript.tools.shell.Global;
|
||||
|
||||
public class RhinoContext {
|
||||
|
||||
private Context jsContext;
|
||||
private Scriptable jsScope;
|
||||
|
||||
public RhinoContext() {
|
||||
this.jsContext = createJavascriptContext();
|
||||
this.jsScope = createJavascriptScopeForContext(this.jsContext);
|
||||
}
|
||||
|
||||
public RhinoContext(Scriptable sharedScope) {
|
||||
this.jsContext = createJavascriptContext();
|
||||
Scriptable newScope = this.jsContext.newObject(sharedScope);
|
||||
newScope.setPrototype(sharedScope);
|
||||
newScope.setParentScope(null);
|
||||
|
||||
this.jsScope = newScope;
|
||||
}
|
||||
|
||||
private RhinoContext createNewRhinoContextBasedOnPrevious() {
|
||||
return new RhinoContext(this.jsScope);
|
||||
}
|
||||
|
||||
public void runAsync(final RhinoRunnable runnable) {
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
RhinoContext newRhinoContextBasedOnPrevious = createNewRhinoContextBasedOnPrevious();
|
||||
try {
|
||||
runnable.run(newRhinoContextBasedOnPrevious);
|
||||
} finally {
|
||||
newRhinoContextBasedOnPrevious.exit();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public Object evalJS(String js) {
|
||||
return this.jsContext.evaluateString(this.jsScope, js, "script", 1, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ScriptableObject> T createClassInJS(Class<T> classToExport) {
|
||||
exportClass(classToExport);
|
||||
T newObj = (T) jsContext.newObject(jsScope, classToExport.getSimpleName());
|
||||
return newObj;
|
||||
}
|
||||
|
||||
public void setProperty(String objectToReceiveProperty, String property, Object value) {
|
||||
Object obj = evalJS(objectToReceiveProperty);
|
||||
if (obj == null || !(obj instanceof ScriptableObject)) {
|
||||
throw new IllegalStateException("object to receive property is no ScriptableObject but a "
|
||||
+ (obj == null ? "" : obj.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
ScriptableObject objectToReceive = (ScriptableObject) obj;
|
||||
objectToReceive.put(property, objectToReceive, value);
|
||||
}
|
||||
|
||||
private void exportClass(Class<? extends ScriptableObject> classToExport) {
|
||||
try {
|
||||
ScriptableObject.defineClass(this.jsScope, classToExport);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void load(String path, String... jsFiles) {
|
||||
for (String jsFile : jsFiles) {
|
||||
load(path + jsFile);
|
||||
}
|
||||
}
|
||||
|
||||
public void load(String fileName) {
|
||||
evalJS("load('" + fileName + "')");
|
||||
// Main.processFile(this.jsContext, this.jsScope, fileName);
|
||||
}
|
||||
|
||||
public Object executeFunction(ScriptableObject object, String fnName, Object[] arguments) {
|
||||
Object fnPointer = object.get(fnName, object);
|
||||
if (fnPointer == null || !(fnPointer instanceof Function)) {
|
||||
fnPointer = object.getPrototype().get(fnName, object);
|
||||
}
|
||||
|
||||
return ((Function) fnPointer).call(jsContext, jsScope, object, arguments);
|
||||
}
|
||||
|
||||
public Object executeFunction(ScriptableObject object, String fnName) {
|
||||
return executeFunction(object, fnName, new Object[] {});
|
||||
}
|
||||
|
||||
public Context getJsContext() {
|
||||
return jsContext;
|
||||
}
|
||||
|
||||
public Scriptable getJsScope() {
|
||||
return jsScope;
|
||||
}
|
||||
|
||||
public void loadEnv(String jsDir) {
|
||||
// TODO ensure rhino 1.7R3 instead of R2 -> geen shim nodig + paths
|
||||
// gedoe in orde zetten hier
|
||||
load(jsDir + "/lib/es5-shim-0.0.4.min.js");
|
||||
load(jsDir + "/lib/env.rhino.1.2.js");
|
||||
load(jsDir + "/lib/env.utils.js");
|
||||
load(jsDir + "/envJsOptions.js");
|
||||
}
|
||||
|
||||
private Global createJavascriptScopeForContext(Context jsContext) {
|
||||
Global scope = new Global();
|
||||
scope.init(jsContext);
|
||||
return scope;
|
||||
}
|
||||
|
||||
private Context createJavascriptContext() {
|
||||
Context jsContext = ContextFactory.getGlobal().enterContext();
|
||||
jsContext.setOptimizationLevel(-1);
|
||||
jsContext.setLanguageVersion(Context.VERSION_1_5); // TODO 1.8 plx
|
||||
jsContext.setErrorReporter(new ChainedErrorReporter(jsContext.getErrorReporter()));
|
||||
return jsContext;
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
public Main createDebugger() {
|
||||
Main debugger = new Main("JS Rhino Debugger");
|
||||
|
||||
debugger.setExitAction(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
debugger.attachTo(ContextFactory.getGlobal());
|
||||
debugger.pack();
|
||||
debugger.setSize(600, 460);
|
||||
debugger.setVisible(true);
|
||||
return debugger;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
public interface RhinoRunnable {
|
||||
|
||||
public void run(RhinoContext context);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mozilla.javascript.EvaluatorException;
|
||||
|
||||
import be.cegeka.junit.jasmine.classes.JasmineTestRunnerExceptionInJSCode;
|
||||
import be.cegeka.junit.jasmine.classes.JasmineTestRunnerExceptionInSpec;
|
||||
import be.cegeka.junit.jasmine.classes.JasmineTestRunnerFailingSpec;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JasmineFailingSpecsTest {
|
||||
|
||||
@Mock
|
||||
private RunNotifier notifierMock;
|
||||
|
||||
@Test
|
||||
public void shouldNotifyOfSingleFailure() {
|
||||
new JasmineTestRunner(JasmineTestRunnerFailingSpec.class).run(notifierMock);
|
||||
|
||||
ArgumentCaptor<Failure> failureCaptor = ArgumentCaptor.forClass(Failure.class);
|
||||
ArgumentCaptor<Description> descriptionCaptor = ArgumentCaptor.forClass(Description.class);
|
||||
verify(notifierMock).fireTestStarted(descriptionCaptor.capture());
|
||||
verify(notifierMock).fireTestFailure(failureCaptor.capture());
|
||||
verifyNoMoreInteractions(notifierMock);
|
||||
|
||||
Failure failure = failureCaptor.getValue();
|
||||
Description startedDescription = descriptionCaptor.getValue();
|
||||
|
||||
assertThat(failure.getDescription()).isEqualTo(startedDescription);
|
||||
assertThat(failure.getDescription().getDisplayName()).isEqualTo("will always fail");
|
||||
assertThat(failure.getMessage()).isEqualTo("Expected true to be false.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotifyOfSingleExceptionWithinSpecFunction() {
|
||||
new JasmineTestRunner(JasmineTestRunnerExceptionInSpec.class).run(notifierMock);
|
||||
|
||||
ArgumentCaptor<Failure> failureCaptor = ArgumentCaptor.forClass(Failure.class);
|
||||
ArgumentCaptor<Description> descriptionCaptor = ArgumentCaptor.forClass(Description.class);
|
||||
verify(notifierMock).fireTestStarted(descriptionCaptor.capture());
|
||||
verify(notifierMock).fireTestFailure(failureCaptor.capture());
|
||||
verifyNoMoreInteractions(notifierMock);
|
||||
|
||||
Failure failure = failureCaptor.getValue();
|
||||
Description startedDescription = descriptionCaptor.getValue();
|
||||
|
||||
assertThat(failure.getDescription()).isEqualTo(startedDescription);
|
||||
assertThat(failure.getDescription().getDisplayName()).isEqualTo("will always crash");
|
||||
assertThat(failure.getMessage()).isEqualTo("ReferenceError: \"OEIWANU\" is not defined. in src/test/javascript/specs/crashingSpec.js (line 3)");
|
||||
}
|
||||
|
||||
@Test(expected = EvaluatorException.class)
|
||||
public void shouldCrashWhileTryingToLoadFaultyJSSpecFile() {
|
||||
new JasmineTestRunner(JasmineTestRunnerExceptionInJSCode.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import be.cegeka.junit.jasmine.classes.JasmineTestRunnerSuccessSpec;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JasmineFinishedSpecsTest {
|
||||
|
||||
@Mock
|
||||
private RunNotifier notifierMock;
|
||||
|
||||
@Test
|
||||
public void shouldNotifyOfSingleSuccess() {
|
||||
new JasmineTestRunner(JasmineTestRunnerSuccessSpec.class).run(notifierMock);
|
||||
|
||||
ArgumentCaptor<Description> descriptionStartedCaptor = ArgumentCaptor.forClass(Description.class);
|
||||
ArgumentCaptor<Description> descriptionFinishedCaptor = ArgumentCaptor.forClass(Description.class);
|
||||
verify(notifierMock).fireTestStarted(descriptionStartedCaptor.capture());
|
||||
verify(notifierMock).fireTestFinished(descriptionFinishedCaptor.capture());
|
||||
verifyNoMoreInteractions(notifierMock);
|
||||
|
||||
Description startedDescription = descriptionStartedCaptor.getValue();
|
||||
Description finishedDescription = descriptionFinishedCaptor.getValue();
|
||||
|
||||
assertThat(startedDescription).isSameAs(finishedDescription);
|
||||
assertThat(startedDescription.getDisplayName()).isEqualTo("will always run");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import be.cegeka.junit.jasmine.classes.JasmineSuiteGeneratorClassWithRunner;
|
||||
import be.cegeka.junit.jasmine.classes.JasmineSuiteGeneratorClassWithoutRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JasmineSuiteGeneratesRunnerTest {
|
||||
|
||||
private static final String RUNNERS_OUTPUT_DIR = "src/test/javascript/runners/";
|
||||
@Mock
|
||||
private RunNotifier notifierMock;
|
||||
|
||||
@Before
|
||||
public void clearRunnersOutputDirectory() throws IOException {
|
||||
FileUtils.cleanDirectory(new File(RUNNERS_OUTPUT_DIR));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void byDefaultDoNotGenerateJasmineTestRunner() {
|
||||
Class<JasmineSuiteGeneratorClassWithoutRunner> testClass = JasmineSuiteGeneratorClassWithoutRunner.class;
|
||||
new JasmineTestRunner(testClass).run(notifierMock);
|
||||
|
||||
File runnerResult = getTestRunnerResultFile(testClass);
|
||||
assertThat(runnerResult.isFile()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateJasmineTestRunnerAfterRunningTests() throws IOException {
|
||||
Class<JasmineSuiteGeneratorClassWithRunner> testClass = JasmineSuiteGeneratorClassWithRunner.class;
|
||||
new JasmineTestRunner(testClass).run(notifierMock);
|
||||
|
||||
File runnerResult = getTestRunnerResultFile(testClass);
|
||||
assertThat(runnerResult.isFile()).isTrue();
|
||||
|
||||
String runnerContent = FileUtils.readFileToString(runnerResult);
|
||||
|
||||
assertThat(runnerContent).contains("jasmine.getEnv().addReporter(new jasmine.TrivialReporter());");
|
||||
assertJSFileIncluded(runnerContent,
|
||||
"./../../../main/webapp/js/source1.js",
|
||||
"./../../../main/webapp/js/source2.js",
|
||||
"./../specs/spec1.js",
|
||||
"./../specs/spec2.js");
|
||||
}
|
||||
|
||||
private File getTestRunnerResultFile(Class<?> testClass) {
|
||||
return new File(RUNNERS_OUTPUT_DIR + testClass.getSimpleName() + "Runner.html");
|
||||
}
|
||||
|
||||
private void assertJSFileIncluded(String rawContent, String... files) {
|
||||
for (String file : files) {
|
||||
assertThat(rawContent).contains("<script type='text/javascript' src='" + file + "'></script>");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package be.cegeka.junit.jasmine;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineTestRunner;
|
||||
import be.cegeka.junit.jasmine.classes.JasmineTestRunnerBeforeAndAfterClass;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JasmineTestRunnerBeforeAndAfterTest {
|
||||
|
||||
@Mock
|
||||
private RunNotifier notifierMock;
|
||||
|
||||
@Test
|
||||
public void useJasmineRunnerOnJasmineTestRunnerBeforeAndAfterClass() {
|
||||
new JasmineTestRunner(JasmineTestRunnerBeforeAndAfterClass.class).run(notifierMock);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(
|
||||
specs = { "spec1.js", "spec2.js" },
|
||||
sources = { "source1.js", "source2.js" },
|
||||
sourcesRootDir = "src/test/javascript/sources/",
|
||||
generateSpecRunner = true)
|
||||
public class JasmineSuiteGeneratorClassWithRunner {
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(specs = { "spec1.js", "spec2.js" }, sources = { "source1.js", "source2.js" }, sourcesRootDir = "src/test/javascript/sources/")
|
||||
public class JasmineSuiteGeneratorClassWithoutRunner {
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
import be.cegeka.rhino.RhinoContext;
|
||||
|
||||
@JasmineSuite(specs = { "emptySpec.js" })
|
||||
public class JasmineTestRunnerBeforeAndAfterClass {
|
||||
|
||||
private static final int RUN_MIJ_FLAG = 0;
|
||||
private static final int RUN_MIJ_OOK_FLAG = 1;
|
||||
|
||||
List<Integer> runs = new ArrayList<Integer>();
|
||||
|
||||
@Before
|
||||
public void runMij() {
|
||||
assertThat(runs).isEmpty();
|
||||
runs.add(RUN_MIJ_FLAG);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void runMijOok(RhinoContext context) {
|
||||
assertThat(runs).containsOnly(RUN_MIJ_FLAG);
|
||||
runs.add(RUN_MIJ_OOK_FLAG);
|
||||
}
|
||||
|
||||
@After
|
||||
public void runMijAfter() {
|
||||
assertThat(runs).containsOnly(RUN_MIJ_FLAG, RUN_MIJ_OOK_FLAG);
|
||||
runs.remove((Object) RUN_MIJ_FLAG);
|
||||
}
|
||||
|
||||
@After
|
||||
public void runMijAfterOok(RhinoContext context) {
|
||||
assertThat(runs).containsOnly(RUN_MIJ_OOK_FLAG);
|
||||
runs.remove((Object) RUN_MIJ_OOK_FLAG);
|
||||
}
|
||||
|
||||
public void runMijNiet() {
|
||||
fail("should not be run");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(specs = { "crashingJSCode.js" })
|
||||
public class JasmineTestRunnerExceptionInJSCode {
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(specs = { "crashingSpec.js" })
|
||||
public class JasmineTestRunnerExceptionInSpec {
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(specs = { "failingSpec.js" })
|
||||
public class JasmineTestRunnerFailingSpec {
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package be.cegeka.junit.jasmine.classes;
|
||||
|
||||
import be.cegeka.junit.jasmine.JasmineSuite;
|
||||
|
||||
@JasmineSuite(specs = { "emptySpec.js" })
|
||||
public class JasmineTestRunnerSuccessSpec {
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
public class ClassInJS extends ScriptableObject {
|
||||
|
||||
private int prop = 0;
|
||||
|
||||
public ClassInJS() {
|
||||
}
|
||||
|
||||
public void increaseProp() {
|
||||
prop++;
|
||||
}
|
||||
|
||||
public String jsFunction_fn() {
|
||||
return "fn";
|
||||
}
|
||||
|
||||
public int jsGet_prop() {
|
||||
return prop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return "ClassInJS";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RhinoContextClassExportingTest {
|
||||
|
||||
@Test
|
||||
public void exposingClassInJS() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
|
||||
ClassInJS newDefaultInstance = context.createClassInJS(ClassInJS.class);
|
||||
assertThat(newDefaultInstance.jsGet_prop()).isEqualTo(0);
|
||||
|
||||
ClassInJS objInJava = (ClassInJS) context.evalJS("var obj = new ClassInJS(); obj");
|
||||
|
||||
objInJava.increaseProp();
|
||||
assertThat(newDefaultInstance.jsGet_prop()).isEqualTo(0);
|
||||
assertThat(context.evalJS("obj.prop")).isEqualTo(1);
|
||||
assertThat(context.evalJS("obj.fn()")).isEqualTo("fn");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mozilla.javascript.EcmaError;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.tools.shell.Global;
|
||||
|
||||
public class RhinoContextEnvjsLoadingTest {
|
||||
|
||||
@Test
|
||||
public void loadEnvShouldSetWindowSpaceAndBeES5Complaint() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
|
||||
context.loadEnv("src/test/javascript");
|
||||
assertThat(context.evalJS("window")).isInstanceOf(Global.class);
|
||||
|
||||
assertThat(context.evalJS("Object.create({ test: 'test' });")).isInstanceOf(NativeObject.class);
|
||||
}
|
||||
|
||||
@Test(expected = EcmaError.class)
|
||||
public void failWithoutLoadingEnvAndManipulatingDOMStuff() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
context.evalJS("document.getElementById");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package be.cegeka.rhino;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
public class RhinoContextTest {
|
||||
|
||||
@Test
|
||||
public void executeFunctionOnPrototypeAndActualObject() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
String js = "" +
|
||||
"var obj = function() {" +
|
||||
" this.actual = function() { " +
|
||||
" return 5; " +
|
||||
" }" +
|
||||
"};" +
|
||||
"obj.prototype = {" +
|
||||
" go : function() {" +
|
||||
" return 3; " +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
context.evalJS(js);
|
||||
ScriptableObject obj = (ScriptableObject) context.evalJS("new obj()");
|
||||
|
||||
assertThat(context.executeFunction(obj, "go")).isEqualTo(3.0);
|
||||
assertThat(context.executeFunction(obj, "actual")).isEqualTo(5.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runAsyncUsesTheSameSharedGlobalScope() throws InterruptedException {
|
||||
RhinoContext baseContext = new RhinoContext();
|
||||
baseContext.evalJS("var base = 'base'");
|
||||
|
||||
baseContext.runAsync(new RhinoRunnable() {
|
||||
|
||||
@Override
|
||||
public void run(RhinoContext context) {
|
||||
assertThat(context.evalJS("base")).isEqualTo("base");
|
||||
}
|
||||
});
|
||||
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setPropertyOnUndefinedNotPossible() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
context.evalJS("var zever");
|
||||
context.setProperty("zever", "prop", 1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setPropertyOnNullNotPossible() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
context.setProperty(null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyOnSomeObj() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
|
||||
NativeObject anObj = (NativeObject) context.evalJS("var obj = { a: 'a'}; obj");
|
||||
context.setProperty("obj", "b", "b");
|
||||
|
||||
assertThat(anObj.get("b", anObj)).isEqualTo("b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadMultipleJSFiles() {
|
||||
RhinoContext context = new RhinoContext();
|
||||
context.load("src/test/javascript/", "loadTest.js", "loadTestTwo.js");
|
||||
|
||||
assertThat(context.evalJS("loaded")).isEqualTo(true);
|
||||
assertThat(context.evalJS("loadedTwo")).isEqualTo(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Basic Envjs options set here (not part of a hack or util)
|
||||
* See http://www.envjs.com/doc/apis
|
||||
*/
|
||||
Envjs({
|
||||
scriptTypes : {
|
||||
'': true, //inline and anonymous
|
||||
'text/javascript': true,
|
||||
'text/envjs': false
|
||||
},
|
||||
appCodeName: 'Mozilla'
|
||||
});
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,76 @@
|
|||
|
||||
/**
|
||||
* Rhino and Envjs additions, filling the missing pieces such as a decent stacktrace
|
||||
* 1) Firefox knows new Error().stack but Envjs does not.
|
||||
*/
|
||||
(function() {
|
||||
var NEWLINE = "\r\n";
|
||||
|
||||
function manuallyTriggerException() {
|
||||
var manuallyTriggeredExMessage = "";
|
||||
try {
|
||||
OEIWABEZIG
|
||||
} catch(e) {
|
||||
// TODO knip- en plakwerk: de eerste lijn moet natuurlijk weg etc...
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
function stripRhinoSpecificExceptionLines(stack) {
|
||||
var ignoreTracingInStackFor = [ "env.utils.js", "org.mozilla.javascript" ];
|
||||
|
||||
return stack.split(NEWLINE).filter(function(stackLine) {
|
||||
return ignoreTracingInStackFor.every(function(ignoreThisInTrace) {
|
||||
return stackLine.indexOf(ignoreThisInTrace) < 0;
|
||||
});
|
||||
}).reduce(function(prev, curr) {
|
||||
return prev + NEWLINE + curr;
|
||||
});
|
||||
}
|
||||
|
||||
window.Error.writeStackTrace = function(e) {
|
||||
var stringWriter = new java.io.StringWriter();
|
||||
var printWriter = new java.io.PrintWriter(stringWriter);
|
||||
e.rhinoException.printStackTrace(printWriter);
|
||||
return stringWriter.toString() + "" // I don't want the java.lang.String object!
|
||||
};
|
||||
|
||||
window.Error.prototype.getStackTrace = function() {
|
||||
// TODO add other stuff from Object.keys(new Error("bla")) (see Firebug)
|
||||
var trace = this.message + NEWLINE;
|
||||
if(this.stack) {
|
||||
trace += this.stack;
|
||||
} else if(this.rhinoException) {
|
||||
trace += window.Error.writeStackTrace(this.rhinoException);
|
||||
} else {
|
||||
trace += stripRhinoSpecificExceptionLines(window.Error.writeStackTrace(manuallyTriggerException()));
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
/**
|
||||
* Envjs specific hacks
|
||||
* 1) Fix Envjs relative path system to work with Windows path systems
|
||||
* 2) Fix window.setTimeout() using Rhino specific functions
|
||||
*/
|
||||
(function() {
|
||||
|
||||
var oldEnvjsUriFn = Envjs.uri;
|
||||
Envjs.uri = function(path, baseDir) {
|
||||
if(baseDir) {
|
||||
return oldEnvjsUriFn(path, baseDir);
|
||||
}
|
||||
return oldEnvjsUriFn(path, "file:///" + ("" + Envjs.getcwd()).replace(/\\/g, '/') + "/");
|
||||
};
|
||||
|
||||
window.setTimeout = function(closure, timeout) {
|
||||
spawn(function() {
|
||||
java.lang.Thread.sleep(timeout);
|
||||
closure();
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,13 @@
|
|||
(function(){var j=Object.prototype.hasOwnProperty;if(!Array.isArray)Array.isArray=function(a){return Object.prototype.toString.call(a)=="[object Array]"};if(!Array.prototype.forEach)Array.prototype.forEach=function(a,c){for(var b=this.length>>>0,d=0;d<b;d++)d in this&&a.call(c,this[d],d,this)};if(!Array.prototype.map)Array.prototype.map=function(a,c){var b=this.length>>>0;if(typeof a!="function")throw new TypeError;for(var d=Array(b),e=0;e<b;e++)if(e in this)d[e]=a.call(c,this[e],e,this);return d};
|
||||
if(!Array.prototype.filter)Array.prototype.filter=function(a,c){for(var b=[],d=0;d<this.length;d++)a.call(c,this[d])&&b.push(this[d]);return b};if(!Array.prototype.every)Array.prototype.every=function(a,c){for(var b=0;b<this.length;b++)if(!a.call(c,this[b]))return false;return true};if(!Array.prototype.some)Array.prototype.some=function(a,c){for(var b=0;b<this.length;b++)if(a.call(c,this[b]))return true;return false};if(!Array.prototype.reduce)Array.prototype.reduce=function(a){var c=this.length>>>
|
||||
0;if(typeof a!="function")throw new TypeError;if(c==0&&arguments.length==1)throw new TypeError;var b=0;if(arguments.length>=2)var d=arguments[1];else{do{if(b in this){d=this[b++];break}if(++b>=c)throw new TypeError;}while(1)}for(;b<c;b++)if(b in this)d=a.call(null,d,this[b],b,this);return d};if(!Array.prototype.reduceRight)Array.prototype.reduceRight=function(a){var c=this.length>>>0;if(typeof a!="function")throw new TypeError;if(c==0&&arguments.length==1)throw new TypeError;c=c-1;if(arguments.length>=
|
||||
2)var b=arguments[1];else{do{if(c in this){b=this[c--];break}if(--c<0)throw new TypeError;}while(1)}for(;c>=0;c--)if(c in this)b=a.call(null,b,this[c],c,this);return b};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(a,c){var b=this.length;if(!b)return-1;var d=c||0;if(d>=b)return-1;if(d<0)d+=b;for(;d<b;d++)if(j.call(this,d))if(a===this[d])return d;return-1};if(!Array.prototype.lastIndexOf)Array.prototype.lastIndexOf=function(a,c){var b=this.length;if(!b)return-1;var d=c||b;if(d<0)d+=
|
||||
b;for(d=Math.min(d,b-1);d>=0;d--)if(j.call(this,d))if(a===this[d])return d;return-1};if(!Object.getPrototypeOf)Object.getPrototypeOf=function(a){return a.__proto__||a.constructor.prototype};if(!Object.getOwnPropertyDescriptor)Object.getOwnPropertyDescriptor=function(){return{}};if(!Object.getOwnPropertyNames)Object.getOwnPropertyNames=function(a){return Object.keys(a)};if(!Object.create)Object.create=function(a,c){var b;if(a===null)b={__proto__:null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+
|
||||
typeof a+"] != 'object'");b=function(){};b.prototype=a;b=new b}typeof c!=="undefined"&&Object.defineProperties(b,c);return b};if(!Object.defineProperty)Object.defineProperty=function(a,c,b){if(typeof b=="object"&&a.__defineGetter__){if(j.call(b,"value")){if(!a.__lookupGetter__(c)&&!a.__lookupSetter__(c))a[c]=b.value;if(j.call(b,"get")||j.call(b,"set"))throw new TypeError("Object doesn't support this action");}else typeof b.get=="function"&&a.__defineGetter__(c,b.get);typeof b.set=="function"&&a.__defineSetter__(c,
|
||||
b.set)}return a};if(!Object.defineProperties)Object.defineProperties=function(a,c){for(var b in c)j.call(c,b)&&Object.defineProperty(a,b,c[b]);return a};if(!Object.seal)Object.seal=function(a){return a};if(!Object.freeze)Object.freeze=function(a){return a};try{Object.freeze(function(){})}catch(u){Object.freeze=function(a){return function(c){return typeof c=="function"?c:a(c)}}(Object.freeze)}if(!Object.preventExtensions)Object.preventExtensions=function(a){return a};if(!Object.isSealed)Object.isSealed=
|
||||
function(){return false};if(!Object.isFrozen)Object.isFrozen=function(){return false};if(!Object.isExtensible)Object.isExtensible=function(){return true};if(!Object.keys){var m=true,n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],p=n.length,q;for(q in{toString:null})m=false;Object.keys=function(a){if(typeof a!=="object"&&typeof a!=="function"||a===null)throw new TypeError("Object.keys called on a non-object");var c=[],b;for(b in a)j.call(a,
|
||||
b)&&c.push(b);if(m)for(b=0;b<p;b++){var d=n[b];j.call(a,d)&&c.push(d)}return c}}if(!Date.prototype.toISOString)Date.prototype.toISOString=function(){return this.getFullYear()+"-"+(this.getMonth()+1)+"-"+this.getDate()+"T"+this.getHours()+":"+this.getMinutes()+":"+this.getSeconds()+"Z"};if(!Date.now)Date.now=function(){return(new Date).getTime()};if(!Date.prototype.toJSON)Date.prototype.toJSON=function(){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()};if(isNaN(Date.parse("T00:00")))Date=
|
||||
function(a){var c=function(e,f,h,g,k,o,r){var i=arguments.length;if(this instanceof a){i=i===1&&String(e)===e?new a(c.parse(e)):i>=7?new a(e,f,h,g,k,o,r):i>=6?new a(e,f,h,g,k,o):i>=5?new a(e,f,h,g,k):i>=4?new a(e,f,h,g):i>=3?new a(e,f,h):i>=2?new a(e,f):i>=1?new a(e):new a;i.constructor=c;return i}return a.apply(this,arguments)},b=RegExp("^(?:((?:[+-]\\d\\d)?\\d\\d\\d\\d)(?:-(\\d\\d)(?:-(\\d\\d))?)?)?(?:T(\\d\\d):(\\d\\d)(?::(\\d\\d)(?:\\.(\\d\\d\\d))?)?)?(?:Z|([+-])(\\d\\d):(\\d\\d))?$"),d;for(d in a)c[d]=
|
||||
a[d];c.now=a.now;c.UTC=a.UTC;c.prototype=a.prototype;c.prototype.constructor=c;c.parse=function(e){var f=b.exec(e);if(f){f.shift();for(var h=f[0]===undefined,g=0;g<10;g++)if(g!==7){f[g]=+(f[g]||(g<3?1:0));g===1&&f[g]--}if(h)return((f[3]*60+f[4])*60+f[5])*1E3+f[6];h=(f[8]*60+f[9])*60*1E3;if(f[6]==="-")h=-h;return a.UTC.apply(this,f.slice(0,7))+h}return a.parse.apply(this,arguments)};return c}(Date);var l=Array.prototype.slice;if(!Function.prototype.bind)Function.prototype.bind=function(a){var c=this;
|
||||
if(typeof c.apply!="function"||typeof c.call!="function")return new TypeError;var b=l.call(arguments),d=function(){if(this instanceof d){var e=Object.create(c.prototype);c.apply(e,b.concat(l.call(arguments)));return e}else return c.call.apply(c,b.concat(l.call(arguments)))};d.bound=c;d.boundTo=a;d.boundArgs=b;d.length=typeof c=="function"?Math.max(c.length-b.length,0):0;return d};if(!String.prototype.trim){var s=/^\s\s*/,t=/\s\s*$/;String.prototype.trim=function(){return String(this).replace(s,"").replace(t,
|
||||
"")}}})();
|
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2008-2010 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,188 @@
|
|||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onclick = function(evt) {
|
||||
if (showPassed.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onclick = function(evt) {
|
||||
if (showSkipped.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
(function() {
|
||||
|
||||
if (! jasmine) {
|
||||
throw new Exception("jasmine library does not exist in global namespace!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic reporter that outputs spec results to the browser console.
|
||||
* Useful if you need to test an html page and don't want the TrivialReporter
|
||||
* markup mucking things up.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* jasmine.getEnv().addReporter(new jasmine.ConsoleReporter());
|
||||
* jasmine.getEnv().execute();
|
||||
*/
|
||||
var ConsoleReporter = function() {
|
||||
this.started = false;
|
||||
this.finished = false;
|
||||
};
|
||||
|
||||
ConsoleReporter.prototype = {
|
||||
reportRunnerResults: function(runner) {
|
||||
this.finished = true;
|
||||
this.log("Runner Finished.");
|
||||
},
|
||||
|
||||
reportRunnerStarting: function(runner) {
|
||||
this.started = true;
|
||||
this.log("Runner Started.");
|
||||
},
|
||||
|
||||
reportSpecResults: function(spec) {
|
||||
var resultText = "Failed.";
|
||||
|
||||
if (spec.results().passed()) {
|
||||
resultText = "Passed.";
|
||||
}
|
||||
|
||||
this.log(resultText);
|
||||
},
|
||||
|
||||
reportSpecStarting: function(spec) {
|
||||
this.log(spec.suite.description + ' : ' + spec.description + ' ... ');
|
||||
},
|
||||
|
||||
reportSuiteResults: function(suite) {
|
||||
var results = suite.results();
|
||||
|
||||
this.log(suite.description + ": " + results.passedCount + " of " + results.totalCount + " passed.");
|
||||
},
|
||||
|
||||
log: function(str) {
|
||||
var console = jasmine.getGlobal().console;
|
||||
|
||||
if (console && console.log) {
|
||||
console.log(str);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// export public
|
||||
jasmine.ConsoleReporter = ConsoleReporter;
|
||||
})();
|
|
@ -0,0 +1,166 @@
|
|||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
(function() {
|
||||
|
||||
if (!jasmine) {
|
||||
throw new Exception("jasmine library does not exist in global namespace!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks up into the JUnit TestRunner system to allow Jasmine tests to run in Eclipse!
|
||||
* Also sets a "done" flag on the spec itself since there is nothing like it in Jasmine
|
||||
*/
|
||||
var DelegatorJUnitReporter = function() {
|
||||
this.javaReporter = jasmine.DelegatorJUnitReporter.javaReporter;
|
||||
};
|
||||
|
||||
DelegatorJUnitReporter.prototype = {
|
||||
reportRunnerStarting: function(runner) {
|
||||
if(this.javaReporter) {
|
||||
this.javaReporter.reportRunnerStarting(runner);
|
||||
}
|
||||
},
|
||||
|
||||
reportSpecStarting: function(spec) {
|
||||
spec.done = false;
|
||||
|
||||
if(this.javaReporter) {
|
||||
this.javaReporter.reportSpecStarting(spec);
|
||||
}
|
||||
},
|
||||
|
||||
reportSpecResults: function(spec) {
|
||||
spec.done = true;
|
||||
|
||||
if(this.javaReporter) {
|
||||
this.javaReporter.reportSpecResults(spec);
|
||||
}
|
||||
},
|
||||
|
||||
reportSuiteResults: function(suite) {
|
||||
if(this.javaReporter) {
|
||||
this.javaReporter.reportSuiteResults(suite);
|
||||
}
|
||||
},
|
||||
|
||||
reportRunnerResults: function(runner) {
|
||||
if(this.javaReporter) {
|
||||
this.javaReporter.reportRunnerResults(runner);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// export public
|
||||
jasmine.DelegatorJUnitReporter = DelegatorJUnitReporter;
|
||||
})();
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,204 @@
|
|||
(function() {
|
||||
|
||||
if (! jasmine) {
|
||||
throw new Exception("jasmine library does not exist in global namespace!");
|
||||
}
|
||||
|
||||
function elapsed(startTime, endTime) {
|
||||
return (endTime - startTime)/1000;
|
||||
}
|
||||
|
||||
function ISODateString(d) {
|
||||
function pad(n) { return n < 10 ? '0'+n : n; }
|
||||
|
||||
return d.getFullYear() + '-'
|
||||
+ pad(d.getMonth()+1) +'-'
|
||||
+ pad(d.getDate()) + 'T'
|
||||
+ pad(d.getHours()) + ':'
|
||||
+ pad(d.getMinutes()) + ':'
|
||||
+ pad(d.getSeconds());
|
||||
}
|
||||
|
||||
function trim(str) {
|
||||
return str.replace(/^\s+/, "" ).replace(/\s+$/, "" );
|
||||
}
|
||||
|
||||
function escapeInvalidXmlChars(str) {
|
||||
return str.replace(/\&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/\>/g, ">")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/\'/g, "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates JUnit XML for the given spec run.
|
||||
* Allows the test results to be used in java based CI
|
||||
* systems like CruiseControl and Hudson.
|
||||
*
|
||||
* @param {string} savePath where to save the files
|
||||
* @param {boolean} consolidate whether to save nested describes within the
|
||||
* same file as their parent; default: true
|
||||
* @param {boolean} useDotNotation whether to separate suite names with
|
||||
* dots rather than spaces (ie "Class.init" not
|
||||
* "Class init"); default: true
|
||||
*/
|
||||
var JUnitXmlReporter = function(savePath, consolidate, useDotNotation) {
|
||||
this.savePath = savePath || '';
|
||||
this.consolidate = consolidate === jasmine.undefined ? true : consolidate;
|
||||
this.useDotNotation = useDotNotation === jasmine.undefined ? true : useDotNotation;
|
||||
};
|
||||
|
||||
JUnitXmlReporter.prototype = {
|
||||
reportRunnerStarting: function(runner) {
|
||||
this.log("Runner Started.");
|
||||
},
|
||||
|
||||
reportSpecStarting: function(spec) {
|
||||
spec.startTime = new Date();
|
||||
|
||||
if (! spec.suite.startTime) {
|
||||
spec.suite.startTime = spec.startTime;
|
||||
}
|
||||
|
||||
this.log(spec.suite.description + ' : ' + spec.description + ' ... ');
|
||||
},
|
||||
|
||||
reportSpecResults: function(spec) {
|
||||
var results = spec.results();
|
||||
spec.didFail = !results.passed();
|
||||
spec.status = spec.didFail ? 'Failed.' : 'Passed.';
|
||||
if (results.skipped) {
|
||||
spec.status = 'Skipped.';
|
||||
}
|
||||
this.log(spec.status);
|
||||
|
||||
spec.duration = elapsed(spec.startTime, new Date());
|
||||
spec.output = '<testcase classname="' + this.getFullName(spec.suite) +
|
||||
'" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + spec.duration + '">';
|
||||
|
||||
var failure = "";
|
||||
var failures = 0;
|
||||
var resultItems = results.getItems();
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
failures += 1;
|
||||
failure += (failures + ": " + escapeInvalidXmlChars(result.trace ? result.trace.getStackTrace() : result.message) + " ");
|
||||
}
|
||||
}
|
||||
if (failure) {
|
||||
spec.output += "<failure>" + trim(failure) + "</failure>";
|
||||
}
|
||||
spec.output += "</testcase>";
|
||||
},
|
||||
|
||||
reportSuiteResults: function(suite) {
|
||||
var results = suite.results();
|
||||
var specs = suite.specs();
|
||||
var specOutput = "";
|
||||
// for JUnit results, let's only include directly failed tests (not nested suites')
|
||||
var failedCount = 0;
|
||||
|
||||
suite.status = results.passed() ? 'Passed.' : 'Failed.';
|
||||
if (results.totalCount === 0) { // todo: change this to check results.skipped
|
||||
suite.status = 'Skipped.';
|
||||
}
|
||||
|
||||
// if a suite has no (active?) specs, reportSpecStarting is never called
|
||||
// and thus the suite has no startTime -- account for that here
|
||||
suite.startTime = suite.startTime || new Date();
|
||||
suite.duration = elapsed(suite.startTime, new Date());
|
||||
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
failedCount += specs[i].didFail ? 1 : 0;
|
||||
specOutput += "\n " + specs[i].output;
|
||||
}
|
||||
suite.output = '\n<testsuite name="' + this.getFullName(suite) +
|
||||
'" errors="0" tests="' + specs.length + '" failures="' + failedCount +
|
||||
'" time="' + suite.duration + '" timestamp="' + ISODateString(suite.startTime) + '">';
|
||||
suite.output += specOutput;
|
||||
suite.output += "\n</testsuite>";
|
||||
this.log(suite.description + ": " + results.passedCount + " of " + results.totalCount + " expectations passed.");
|
||||
},
|
||||
|
||||
reportRunnerResults: function(runner) {
|
||||
this.log("Runner Finished.");
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var fileName = 'TEST-' + this.getFullName(suite, true) + '.xml';
|
||||
var output = '<?xml version="1.0" encoding="UTF-8" ?>';
|
||||
// if we are consolidating, only write out top-level suites
|
||||
if (this.consolidate && suite.parentSuite) {
|
||||
continue;
|
||||
}
|
||||
else if (this.consolidate) {
|
||||
output += "\n<testsuites>";
|
||||
output += this.getNestedOutput(suite);
|
||||
output += "\n</testsuites>";
|
||||
this.writeFile(this.savePath + fileName, output);
|
||||
}
|
||||
else {
|
||||
output += suite.output;
|
||||
this.writeFile(this.savePath + fileName, output);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getNestedOutput: function(suite) {
|
||||
var output = suite.output;
|
||||
for (var i = 0; i < suite.suites().length; i++) {
|
||||
output += this.getNestedOutput(suite.suites()[i]);
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
writeFile: function(filename, text) {
|
||||
// Rhino
|
||||
try {
|
||||
var out = new java.io.BufferedWriter(new java.io.FileWriter(filename));
|
||||
out.write(text);
|
||||
out.close();
|
||||
} catch (e) {}
|
||||
// PhantomJS, via pyphantomjs and the saveToFile plugin
|
||||
// http://dev.umaclan.com/projects/pyphantomjs/wiki/Plugins#Save-to-File
|
||||
try {
|
||||
phantom.saveToFile(text, filename);
|
||||
} catch (f) {
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
getFullName: function(suite, isFilename) {
|
||||
var fullName;
|
||||
if (this.useDotNotation) {
|
||||
fullName = suite.description;
|
||||
for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
|
||||
fullName = parentSuite.description + '.' + fullName;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fullName = suite.getFullName();
|
||||
}
|
||||
|
||||
// Either remove or escape invalid XML characters
|
||||
if (isFilename) {
|
||||
return fullName.replace(/[^\w]/g, "");
|
||||
}
|
||||
return escapeInvalidXmlChars(fullName);
|
||||
},
|
||||
|
||||
log: function(str) {
|
||||
var console = jasmine.getGlobal().console;
|
||||
|
||||
if (console && console.log) {
|
||||
console.log(str);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// export public
|
||||
jasmine.JUnitXmlReporter = JUnitXmlReporter;
|
||||
})();
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="./../lib/jasmine-1.0.2/jasmine.css">
|
||||
<script type="text/javascript" src="./../lib/jasmine-1.0.2/jasmine.js"></script>
|
||||
<script type="text/javascript" src="./../lib/jasmine-1.0.2/jasmine-html.js"></script>
|
||||
|
||||
<!-- dit zijn de productie source js files: -->
|
||||
<!--SourceFileIncludes-->
|
||||
|
||||
<!-- dit zijn de jasmine spec js files: -->
|
||||
<!--SpecFileIncludes-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
var loaded = true;
|
|
@ -0,0 +1 @@
|
|||
var loadedTwo = true;
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="./../lib/jasmine-1.0.2/jasmine.css">
|
||||
<script type="text/javascript" src="./../lib/jasmine-1.0.2/jasmine.js"></script>
|
||||
<script type="text/javascript" src="./../lib/jasmine-1.0.2/jasmine-html.js"></script>
|
||||
|
||||
<!-- dit zijn de productie source js files: -->
|
||||
<script type='text/javascript' src='./../../../main/webapp/js/source1.js'></script>
|
||||
<script type='text/javascript' src='./../../../main/webapp/js/source2.js'></script>
|
||||
|
||||
|
||||
<!-- dit zijn de jasmine spec js files: -->
|
||||
<script type='text/javascript' src='./../specs/spec1.js'></script>
|
||||
<script type='text/javascript' src='./../specs/spec2.js'></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
var source1 = 1;
|
|
@ -0,0 +1 @@
|
|||
var source2 = 2;
|
|
@ -0,0 +1,4 @@
|
|||
var b = {
|
||||
altijdEerstKommasGebruiken = function(){};
|
||||
bla = 3;
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
describe("empty", function() {
|
||||
it("will always crash", function() {
|
||||
OEIWANU
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
describe("empty", function() {
|
||||
it("will always run", function() {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
describe("empty", function() {
|
||||
it("will always fail", function() {
|
||||
expect(true).toBe(false);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
describe("spec 1", function() {
|
||||
it("is green", function() {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
describe("spec 2", function() {
|
||||
it("is green", function() {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
#Generated by Maven
|
||||
#Fri Jun 24 19:13:34 CEST 2011
|
||||
version=1.0-SNAPSHOT
|
||||
groupId=be.cegeka
|
||||
artifactId=jasminejunitrunner
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue