Merge branch 'master', remote-tracking branch 'origin/master'
This commit is contained in:
commit
c6a4265bba
61
README.md
61
README.md
|
@ -41,7 +41,9 @@ So let's rephrase:
|
|||
* Talks like a duck-erhm, any other Junit Java test. Just use a custom annotation (see below)
|
||||
* Executes super-fast. No browser required. Hocus-pocus. (Rhino + Envjs magic)
|
||||
|
||||
## Does this thing generate Junit XML?
|
||||
## Does this thing support ...
|
||||
|
||||
### Generation of Junit XML Results?
|
||||
|
||||
Yes and no. Not explicitly using the Jasmine Junit XML Reporter, but since it's a Java Junit Result, your build process will do that for you.
|
||||
Maven surefire plugins will generate the needed result files, for Jenkins to pick up. Your stacktrace/failure message will be something like:
|
||||
|
@ -49,17 +51,51 @@ Maven surefire plugins will generate the needed result files, for Jenkins to pic
|
|||
> Expected x to be y (zz.js, #458)
|
||||
|
||||
Just like the default Jasmine HTML reporter.
|
||||
(So, to answer the question: yes!)
|
||||
|
||||
## What Do I need to do?
|
||||
### GUI Testing with Envjs?
|
||||
|
||||
Yes! It allows you to test your jQuery plugins or your spaghetti GUI+Logic code, neatly woven together.
|
||||
You can use <a href="https://github.com/velesin/jasmine-jquery" target="_blank">jasmine-jquery</a> matchers. I've modified `jasmine.Fixtures` to support Envjs+Rhino. This means you can test stuff like this:
|
||||
|
||||
```javascript
|
||||
beforeEach(function() {
|
||||
loadFixtures("myFixture.html");
|
||||
});
|
||||
|
||||
it("should be visible and blue", function() {
|
||||
var div = $('#myDivInFixtureHtml');
|
||||
expect(div).toBeVisible();
|
||||
expect(div.css('color')).toBe('blue');
|
||||
});
|
||||
```
|
||||
|
||||
Fixtures are automatically cleaned up. See src/test/javascript/lib/jasminedir/jasmine-jquery-rhino.js
|
||||
|
||||
#### But wait, CSS Style Parsing does not work in Envjs 1.2, how come this does?
|
||||
|
||||
See env.utils.js. Cover your eyes - hacks present.
|
||||
|
||||
### Debugging 'n stuff?
|
||||
|
||||
Yes! When the debug mode flag in `@JasmineSuite` has been set to `true`, you can use the <a href="http://www.mozilla.org/rhino/debugger.html" target="_blank">Rhino Debugger</a> to set breakpoints.
|
||||
After pressing "GO", the tests will run and you can inspect stuff and step through the code.
|
||||
|
||||
#### What about integrated debugging inside my IDE?
|
||||
|
||||
Tough luck. I've tried to get <a href="http://wiki.eclipse.org/JSDT" target="_blank">JSDT</a> working but no avail.
|
||||
You can still use Firebug to debug when generating a specRunner HTML file (see below).
|
||||
|
||||
## Excellent! What Do I need to do?
|
||||
|
||||
1. Fork this project.
|
||||
2. Create some Jasmine specs, place them in some folder.
|
||||
3. Create a Junit test class, annotate it with _@RunWith(JasmineTestRunner.class)_
|
||||
4. Fill in the blanks using @JasmineSuite
|
||||
3. Create a Junit test class, annotate it with `@RunWith(JasmineTestRunner.class)`
|
||||
4. Fill in the blanks using `@JasmineSuite`
|
||||
|
||||
## More options
|
||||
|
||||
_@JasmineSuite_ allows you to set these options:
|
||||
`@JasmineSuite` allows you to set these options:
|
||||
|
||||
* debug: use the built-in Rhino debugger (gives you the chance to set a breakpoint before firing the test suite)
|
||||
* jsRootDir: the javascript install root dir. Jasmine and other should be installed here (see source)
|
||||
|
@ -74,7 +110,7 @@ Currently, Jasmine Junit Runner relies on Rhino 1.7R2 (+ es5-shim) & Envjs 1.2 t
|
|||
|
||||
### Dependencies Overview
|
||||
|
||||
See the _pom.xml_ (Maven2) - you can build the whole thing using:
|
||||
See the `pom.xml` (Maven2) - you can build the whole thing using:
|
||||
|
||||
> mvn clean install
|
||||
|
||||
|
@ -113,7 +149,7 @@ describe("my awesome code", function() {
|
|||
});
|
||||
```
|
||||
|
||||
### Using Junit's _@Before_ and _@After_
|
||||
### Using Junit's `@Before` and `@After_`
|
||||
|
||||
It's possible to do some extra work before and after each spec run:
|
||||
|
||||
|
@ -142,8 +178,8 @@ public class MyAwesomeTest {
|
|||
|
||||
What's happening?
|
||||
|
||||
* You can define n number of _PUBLIC_ methods annotated with @Before or @After
|
||||
* You can, but don't have to, take the _RhinoContext_ object as the only parameter. This allows you to set stuff up in JS space before running the spec.
|
||||
* You can define n number of _PUBLIC_ methods annotated with `@Before` or `@After`
|
||||
* You can, but don't have to, take the `RhinoContext` object as the only parameter. This allows you to set stuff up in JS space before running the spec.
|
||||
|
||||
### Generating a spec runner
|
||||
|
||||
|
@ -175,10 +211,3 @@ Your awesome test (example 1) would for instance generate this html file:
|
|||
```
|
||||
|
||||
You can inspect the output using firefox, or debug in your spec file using firebug.
|
||||
|
||||
### Debugging in Java
|
||||
|
||||
When the debug mode flag has been set to _true_, you can use the <a href="http://www.mozilla.org/rhino/debugger.html" target="_blank">Rhino Debugger</a> to set breakpoints.
|
||||
After pressing "GO", the tests will run and you can inspect stuff and step through the code.
|
||||
|
||||
Integrated debugging into for example Eclipse does not work for the moment.
|
||||
|
|
|
@ -2,7 +2,7 @@ load("./../src/test/javascript/lib/env.rhino.1.2.js");
|
|||
load("./../src/test/javascript/lib/env.utils.js");
|
||||
load("./../src/test/javascript/envJsOptions.js");
|
||||
|
||||
load("jquery-1.6.1.js");
|
||||
load("./../src/test/javascript/jquery-1.6.1.js");
|
||||
|
||||
function append(itm) {
|
||||
$('body').append($(itm));
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
package be.klak.env;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import be.klak.junit.jasmine.JasmineSuite;
|
||||
import be.klak.junit.jasmine.JasmineTestRunner;
|
||||
import be.klak.rhino.RhinoContext;
|
||||
|
||||
@RunWith(JasmineTestRunner.class)
|
||||
@JasmineSuite
|
||||
@JasmineSuite(sources = "jquery-1.6.1.js", sourcesRootDir = "src/test/javascript")
|
||||
public class EnvUtilsTest {
|
||||
|
||||
@Before
|
||||
public void loadJasmineJQueryMatchers(RhinoContext context) {
|
||||
context.load("src/test/javascript/lib/jasmine-1.0.2/jasmine-jquery-rhino.js");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@
|
|||
* Envjs specific hacks
|
||||
* 1) Fix Envjs relative path system to work with Windows path systems
|
||||
* 2) Fix window.setTimeout() using Rhino specific functions
|
||||
* 3) Fix CSS2Properties support: all properties have the same objmaps, wtf?
|
||||
* 3) Fix CSS2Properties support for parsing style attributes: get from raw node context.
|
||||
* 4) Fix CSS2Properties support for setting values: all properties have the same objmaps, wtf?
|
||||
*/
|
||||
(function() {
|
||||
|
||||
|
@ -74,6 +75,29 @@
|
|||
});
|
||||
};
|
||||
|
||||
(function(Element) {
|
||||
|
||||
var style = "style";
|
||||
function lookupStyleInNodeAttributes(el) {
|
||||
if(el.attributes) {
|
||||
for(var i = 0; i < el.attributes.length; i++) {
|
||||
if(el.attributes[i].nodeName === style) {
|
||||
return el.attributes[i].nodeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var styleSetFn = Element.__lookupGetter__(style);
|
||||
Element.__defineGetter__(style, function() {
|
||||
if(!this.cssText) {
|
||||
this.cssText = lookupStyleInNodeAttributes(this);
|
||||
}
|
||||
return styleSetFn.apply(this);
|
||||
});
|
||||
|
||||
})(HTMLElement.prototype);
|
||||
|
||||
(function(css) {
|
||||
|
||||
var setCssProperty = css.prototype.setProperty;
|
||||
|
@ -82,9 +106,8 @@
|
|||
if(Object.keys(Object.getPrototypeOf(this.styleIndex)).length === 0) {
|
||||
this.styleIndex = Object.create(this.styleIndex);
|
||||
}
|
||||
|
||||
|
||||
return setCssProperty.call(this, name, value);
|
||||
}
|
||||
})(CSS2Properties);
|
||||
|
||||
})();
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
importPackage(org.apache.commons.io);
|
||||
importPackage(java.io);
|
||||
|
||||
var loadFixtures = function() {
|
||||
jasmine.getFixtures().load.apply(jasmine.getFixtures(), arguments);
|
||||
};
|
||||
|
||||
var appendToBody = function(el) {
|
||||
$('body').append(el);
|
||||
};
|
||||
|
||||
jasmine.getFixtures = function() {
|
||||
return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures();
|
||||
};
|
||||
|
||||
jasmine.Fixtures = function() {
|
||||
this.fixturesPath = 'src/test/javascript/specs/fixtures';
|
||||
};
|
||||
|
||||
jasmine.Fixtures.prototype.load = function() {
|
||||
appendToBody(this.read.apply(this, arguments));
|
||||
};
|
||||
|
||||
jasmine.Fixtures.prototype.read = function() {
|
||||
var read = "";
|
||||
for(var i = 0; i < arguments.length; i++) {
|
||||
read += FileUtils.readFileToString(new File(this.fixturesPath, arguments[i]));
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
jasmine.Fixtures.prototype.cleanUp = function() {
|
||||
$('body').children().remove();
|
||||
};
|
||||
|
||||
jasmine.JQuery = function() {};
|
||||
|
||||
jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
|
||||
return $('<div/>').append(html).html();
|
||||
};
|
||||
|
||||
jasmine.JQuery.elementToString = function(element) {
|
||||
return $('<div />').append(element.clone()).html();
|
||||
};
|
||||
|
||||
jasmine.JQuery.matchersClass = {};
|
||||
|
||||
(function(namespace) {
|
||||
var data = {
|
||||
spiedEvents: {},
|
||||
handlers: []
|
||||
};
|
||||
|
||||
namespace.events = {
|
||||
spyOn: function(selector, eventName) {
|
||||
var handler = function(e) {
|
||||
data.spiedEvents[[selector, eventName]] = e;
|
||||
};
|
||||
$(selector).bind(eventName, handler);
|
||||
data.handlers.push(handler);
|
||||
},
|
||||
|
||||
wasTriggered: function(selector, eventName) {
|
||||
return !!(data.spiedEvents[[selector, eventName]]);
|
||||
},
|
||||
|
||||
cleanUp: function() {
|
||||
data.spiedEvents = {};
|
||||
data.handlers = [];
|
||||
}
|
||||
}
|
||||
})(jasmine.JQuery);
|
||||
|
||||
(function(){
|
||||
var jQueryMatchers = {
|
||||
toHaveClass: function(className) {
|
||||
return this.actual.hasClass(className);
|
||||
},
|
||||
|
||||
toBeVisible: function() {
|
||||
return this.actual.is(':visible');
|
||||
},
|
||||
|
||||
toBeHidden: function() {
|
||||
return this.actual.is(':hidden');
|
||||
},
|
||||
|
||||
toBeSelected: function() {
|
||||
return this.actual.is(':selected');
|
||||
},
|
||||
|
||||
toBeChecked: function() {
|
||||
return this.actual.is(':checked');
|
||||
},
|
||||
|
||||
toBeEmpty: function() {
|
||||
return this.actual.is(':empty');
|
||||
},
|
||||
|
||||
toExist: function() {
|
||||
return this.actual.size() > 0;
|
||||
},
|
||||
|
||||
toHaveAttr: function(attributeName, expectedAttributeValue) {
|
||||
return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
|
||||
},
|
||||
|
||||
toHaveId: function(id) {
|
||||
return this.actual.attr('id') == id;
|
||||
},
|
||||
|
||||
toHaveHtml: function(html) {
|
||||
return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
|
||||
},
|
||||
|
||||
toHaveText: function(text) {
|
||||
if (text && jQuery.isFunction(text.test)) {
|
||||
return text.test(this.actual.text());
|
||||
} else {
|
||||
return this.actual.text() == text;
|
||||
}
|
||||
},
|
||||
|
||||
toHaveValue: function(value) {
|
||||
return this.actual.val() == value;
|
||||
},
|
||||
|
||||
toHaveData: function(key, expectedValue) {
|
||||
return hasProperty(this.actual.data(key), expectedValue);
|
||||
},
|
||||
|
||||
toBe: function(selector) {
|
||||
return this.actual.is(selector);
|
||||
},
|
||||
|
||||
toContain: function(selector) {
|
||||
return this.actual.find(selector).size() > 0;
|
||||
},
|
||||
|
||||
toBeDisabled: function(selector){
|
||||
return this.actual.attr("disabled") == true;
|
||||
}
|
||||
};
|
||||
|
||||
var hasProperty = function(actualValue, expectedValue) {
|
||||
if (expectedValue === undefined) {
|
||||
return actualValue !== undefined;
|
||||
}
|
||||
return actualValue == expectedValue;
|
||||
};
|
||||
|
||||
var bindMatcher = function(methodName) {
|
||||
var builtInMatcher = jasmine.Matchers.prototype[methodName];
|
||||
|
||||
jasmine.JQuery.matchersClass[methodName] = function() {
|
||||
if (this.actual instanceof jQuery) {
|
||||
var result = jQueryMatchers[methodName].apply(this, arguments);
|
||||
this.actual = jasmine.JQuery.elementToString(this.actual);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (builtInMatcher) {
|
||||
return builtInMatcher.apply(this, arguments);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
for(var methodName in jQueryMatchers) {
|
||||
bindMatcher(methodName);
|
||||
}
|
||||
})();
|
||||
|
||||
beforeEach(function() {
|
||||
this.addMatchers(jasmine.JQuery.matchersClass);
|
||||
this.addMatchers({
|
||||
toHaveBeenTriggeredOn: function(selector) {
|
||||
this.message = function() {
|
||||
return [
|
||||
"Expected event " + this.actual + " to have been triggered on" + selector,
|
||||
"Expected event " + this.actual + " not to have been triggered on" + selector
|
||||
];
|
||||
};
|
||||
return jasmine.JQuery.events.wasTriggered(selector, this.actual);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.getFixtures().cleanUp();
|
||||
jasmine.JQuery.events.cleanUp();
|
||||
});
|
|
@ -1,7 +1,26 @@
|
|||
|
||||
describe("envjs fixes", function() {
|
||||
|
||||
describe("CSS2 style property support", function() {
|
||||
describe("CSS2 style property support for parsing style attributes", function() {
|
||||
beforeEach(function() {
|
||||
loadFixtures("styleAttributes.html");
|
||||
});
|
||||
|
||||
it("should get a style attribute from a static DOM element", function() {
|
||||
var div = document.getElementById("div");
|
||||
expect(div.style.color).toBe("blue");
|
||||
});
|
||||
|
||||
it("should get a style attribute with dashes using camelCasing properties", function() {
|
||||
var spanStyle = document.getElementById("span").style;
|
||||
|
||||
expect(spanStyle.backgroundColor).toBe("green");
|
||||
expect(spanStyle.fontSize).toBe("8pt");
|
||||
expect(spanStyle.fontFamily).toBe("verdana");
|
||||
});
|
||||
});
|
||||
|
||||
describe("CSS2 style property support for setting values", function() {
|
||||
|
||||
var someColor = "#FFFFFF";
|
||||
var someFont = "12px 'Bitstream Vera Sans Mono','Courier',monospace";
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<div id="div" style="color: blue">
|
||||
This is blue and in Verdana. Cool? Right!
|
||||
<br/>
|
||||
|
||||
<span id="span" style="background-color: green; font-size: 8pt; font-family: verdana">
|
||||
Right makes might! (They say)
|
||||
</span>
|
||||
</div>
|
Reference in New Issue