added jasmine jquery matchers, modified for envjs/rhino support
This commit is contained in:
parent
d0a6f2b556
commit
1868b831d4
28
README.md
28
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)
|
* 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)
|
* 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.
|
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:
|
Maven surefire plugins will generate the needed result files, for Jenkins to pick up. Your stacktrace/failure message will be something like:
|
||||||
|
@ -49,6 +51,30 @@ Maven surefire plugins will generate the needed result files, for Jenkins to pic
|
||||||
> Expected x to be y (zz.js, #458)
|
> Expected x to be y (zz.js, #458)
|
||||||
|
|
||||||
Just like the default Jasmine HTML reporter.
|
Just like the default Jasmine HTML reporter.
|
||||||
|
(So, to answer the question: yes!)
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
## What Do I need to do?
|
## What Do I need to do?
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
package be.klak.env;
|
package be.klak.env;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import be.klak.junit.jasmine.JasmineSuite;
|
import be.klak.junit.jasmine.JasmineSuite;
|
||||||
import be.klak.junit.jasmine.JasmineTestRunner;
|
import be.klak.junit.jasmine.JasmineTestRunner;
|
||||||
|
import be.klak.rhino.RhinoContext;
|
||||||
|
|
||||||
@RunWith(JasmineTestRunner.class)
|
@RunWith(JasmineTestRunner.class)
|
||||||
@JasmineSuite
|
@JasmineSuite(sources = "jquery-1.6.1.js", sourcesRootDir = "src/test/javascript")
|
||||||
public class EnvUtilsTest {
|
public class EnvUtilsTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void loadJasmineJQueryMatchers(RhinoContext context) {
|
||||||
|
context.load("src/test/javascript/lib/jasmine-1.0.2/jasmine-jquery-rhino.js");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,31 +1,11 @@
|
||||||
|
|
||||||
importPackage(org.apache.commons.io);
|
|
||||||
importPackage(java.io);
|
|
||||||
|
|
||||||
var loadFixtures = function() {
|
|
||||||
this.fixturesPath = "src/test/javascript/specs/fixtures";
|
|
||||||
|
|
||||||
var read = "";
|
|
||||||
for(var i = 0; i < arguments.length; i++) {
|
|
||||||
read += FileUtils.readFileToString(new File(this.fixturesPath, arguments[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
document.body.innerHTML = document.body.innerHTML + read;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cleanupFixtures = function() {
|
|
||||||
document.body.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("envjs fixes", function() {
|
describe("envjs fixes", function() {
|
||||||
|
|
||||||
describe("CSS2 style property support for parsing style attributes", function() {
|
describe("CSS2 style property support for parsing style attributes", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
loadFixtures("styleAttributes.html");
|
loadFixtures("styleAttributes.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(cleanupFixtures);
|
|
||||||
|
|
||||||
it("should get a style attribute from a static DOM element", function() {
|
it("should get a style attribute from a static DOM element", function() {
|
||||||
var div = document.getElementById("div");
|
var div = document.getElementById("div");
|
||||||
expect(div.style.color).toBe("blue");
|
expect(div.style.color).toBe("blue");
|
||||||
|
|
|
@ -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