diff --git a/lib/screw.assets.js b/lib/screw.assets.js new file mode 100644 index 0000000..5caec45 --- /dev/null +++ b/lib/screw.assets.js @@ -0,0 +1,36 @@ +(function() { + Screw.Assets = {}; + Screw.Assets.use_cache_buster = false; // TODO: NS/CTI - make this configurable from the UI. + var required_paths = []; + var included_stylesheets = {}; + var cache_buster = parseInt(new Date().getTime()/(1*1000)); + + Screw.Assets.require = function(javascript_path, onload) { + if(!required_paths[javascript_path]) { + var full_path = javascript_path + ".js"; + if (Screw.Assets.use_cache_buster) { + full_path += '?' + cache_buster; + } + document.write(""); + if(onload) { + var scripts = document.getElementsByTagName('script'); + scripts[scripts.length-1].onload = onload; + } + required_paths[javascript_path] = true; + } + }; + + Screw.Assets.stylesheet = function(stylesheet_path) { + if(!included_stylesheets[stylesheet_path]) { + var full_path = stylesheet_path + ".css"; + if(Screw.Assets.use_cache_buster) { + full_path += '?' + cache_buster; + } + document.write(""); + included_stylesheets[stylesheet_path] = true; + } + }; + + window.require = Screw.Assets.require; + window.stylesheet = Screw.Assets.stylesheet; +})(); diff --git a/lib/screw.events.js b/lib/screw.events.js index 3461ff6..78128c1 100644 --- a/lib/screw.events.js +++ b/lib/screw.events.js @@ -27,6 +27,10 @@ $(this) .addClass('failed') .append($('

').text(reason.toString())); + if (reason.fileName || reason.lineNumber) { + $(this) + .append($('

').text(reason.fileName + " : " + reason.lineNumber)); + } }) }) .bind('before', function() { diff --git a/lib/screw.matchers.js b/lib/screw.matchers.js index a4f9371..a27597b 100644 --- a/lib/screw.matchers.js +++ b/lib/screw.matchers.js @@ -60,6 +60,86 @@ Screw.Matchers = (function($) { failure_message: function(expected, actual, not) { return 'expected ' + $.print(actual) + (not ? ' to not be empty' : ' to be empty'); } + }, + + have_length: { + match: function(expected, actual) { + if (actual.length == undefined) throw(actual.toString() + " does not respond to length"); + + return actual.length == expected; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not' : ' to') + ' have length ' + expected; + } + }, + + be_null: { + match: function(expected, actual) { + return actual == null; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not be null' : ' to be null'); + } + }, + + be_undefined: { + match: function(expected, actual) { + return actual == undefined; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not be undefined' : ' to be undefined'); + } + }, + + be_true: { + match: function(expected, actual) { + return actual; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not be true' : ' to be true'); + } + }, + + be_false: { + match: function(expected, actual) { + return !actual; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not be false' : ' to be false'); + } + }, + + match_selector: { + match: function(expected, actual) { + if (!(actual instanceof jQuery)) { + throw expected.toString() + " must be an instance of jQuery to match against a selector" + } + + return actual.is(expected); + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not match selector ' : ' to match selector ') + expected; + } + }, + + contain_selector: { + match: function(expected, actual) { + if (!(actual instanceof jQuery)) { + throw expected.toString() + " must be an instance of jQuery to match against a selector" + } + + return actual.find(expected).length > 0; + }, + + failure_message: function(expected, actual, not) { + return 'expected ' + $.print(actual) + (not ? ' to not contain selector ' : ' to contain selector ') + expected; + } } } })(jQuery); \ No newline at end of file diff --git a/lib/screw.server.js b/lib/screw.server.js new file mode 100644 index 0000000..50b169e --- /dev/null +++ b/lib/screw.server.js @@ -0,0 +1,21 @@ +(function($) { + var ajax = $.ajax; + $(Screw).bind('after', function() { + var error_text = $(".error").map(function(i, element) { + return element.innerHTML; + }).get().join("\n"); + + var suite_id; + if(top.runOptions) { + suite_id = top.runOptions.getSessionId(); + } else { + suite_id = 'user'; + } + + ajax({ + type: "POST", + url: '/suites/' + suite_id + '/finish', + data: {"text": error_text} + }); + }); +})(jQuery); diff --git a/spec/matchers_spec.js b/spec/matchers_spec.js index 0a24df3..205fcb4 100644 --- a/spec/matchers_spec.js +++ b/spec/matchers_spec.js @@ -89,5 +89,149 @@ Screw.Unit(function() { }); }); }); + + describe('#have_length', function() { + it("matches Arrays of the expected length", function() { + expect([]).to(have_length, 0); + expect([1]).to(have_length, 1); + expect([1, 2, 3]).to_not(have_length, 4); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) have length [expected]", function() { + var message = null; + try { expect([1, 2]).to(have_length, 4) } catch(e) { message = e } + expect(message).to(equal, 'expected [ 1, 2 ] to have length 4'); + + try { expect([1]).to_not(have_length, 1) } catch(e) { message = e } + expect(message).to(equal, 'expected [ 1 ] to not have length 1'); + }); + }); + }); + + describe('#be_null', function() { + it("matches null", function() { + expect(null).to(be_null); + expect(1).to_not(be_null); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) be null", function() { + var message = null; + try { expect(1).to(be_null) } catch(e) { message = e } + expect(message).to(equal, 'expected 1 to be null'); + + try { expect(null).to_not(be_null) } catch(e) { message = e } + expect(message).to(equal, 'expected null to not be null'); + }); + }); + }); + + describe('#be_undefined', function() { + it("matches undefined", function() { + expect(undefined).to(be_undefined); + expect(1).to_not(be_undefined); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) be undefined", function() { + var message = undefined; + try { expect(1).to(be_undefined) } catch(e) { message = e } + expect(message).to(equal, 'expected 1 to be undefined'); + + try { expect(undefined).to_not(be_undefined) } catch(e) { message = e } + expect(message).to(equal, 'expected undefined to not be undefined'); + }); + }); + }); + + describe('#be_true', function() { + it("matches values that are considered true conditions", function() { + expect(true).to(be_true); + expect(1).to(be_true); + expect(false).to_not(be_true); + expect(undefined).to_not(be_true); + expect(null).to_not(be_true); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) be true", function() { + var message = true; + try { expect(false).to(be_true) } catch(e) { message = e } + expect(message).to(equal, 'expected false to be true'); + + try { expect(true).to_not(be_true) } catch(e) { message = e } + expect(message).to(equal, 'expected true to not be true'); + }); + }); + }); + + describe('#be_false', function() { + it("matches values that are considered false conditions", function() { + expect(false).to(be_false); + expect(undefined).to(be_false); + expect(null).to(be_false); + expect(true).to_not(be_false); + expect(1).to_not(be_false); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) be false", function() { + var message = false; + try { expect(true).to(be_false) } catch(e) { message = e } + expect(message).to(equal, 'expected true to be false'); + + try { expect(false).to_not(be_false) } catch(e) { message = e } + expect(message).to(equal, 'expected false to not be false'); + }); + }); + }); + + describe('#match_selector', function() { + var elt; + before(function() { + elt = $("

"); + }); + + it("matches a jQuery element against the expected selector", function() { + expect(elt).to(match_selector, 'div.foo'); + expect(elt).to_not(match_selector, 'div.bar'); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) match selector [expected]", function() { + var message = false; + try { expect(elt).to(match_selector, 'div.bar') } catch(e) { message = e } + expect(message).to(equal, 'expected $([
]) to match selector div.bar'); + + try { expect(elt).to_not(match_selector, 'div.foo') } catch(e) { message = e } + expect(message).to(equal, 'expected $([
]) to not match selector div.foo'); + }); + }); + }); + + describe('#contain_selector', function() { + var elt; + before(function() { + elt = $("
"); + }); + + it("matches a jQuery element against the expected selector", function() { + expect(elt).to(contain_selector, 'div.foo'); + expect(elt).to_not(contain_selector, 'div.bar'); + }); + + describe(".failure_message", function() { + it("prints 'expected [actual] to (not) match selector [expected]", function() { + var message = false; + try { expect(elt).to(contain_selector, 'div.bar') } catch(e) { message = e } + expect(message).to(equal, 'expected $([
]) to contain selector div.bar'); + + try { expect(elt).to_not(contain_selector, 'div.foo') } catch(e) { message = e } + expect(message).to(equal, 'expected $([
]) to not contain selector div.foo'); + }); + }); + }); + }); }); \ No newline at end of file