webr 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/README.md +4 -0
  2. data/Rakefile +19 -0
  3. data/app/webr.rb +57 -0
  4. data/bin/webr +6 -0
  5. data/ext/jasmine/lib/jasmine.js +2423 -0
  6. data/ext/jsdom/lib/jsdom.js +70 -0
  7. data/ext/jsdom/lib/jsdom/browser/domtohtml.js +198 -0
  8. data/ext/jsdom/lib/jsdom/browser/htmlencoding.js +381 -0
  9. data/ext/jsdom/lib/jsdom/browser/htmltodom.js +151 -0
  10. data/ext/jsdom/lib/jsdom/browser/index.js +484 -0
  11. data/ext/jsdom/lib/jsdom/level1/core.js +1610 -0
  12. data/ext/jsdom/lib/jsdom/level2/core.js +406 -0
  13. data/ext/jsdom/lib/jsdom/level2/events.js +358 -0
  14. data/ext/jsdom/lib/jsdom/level2/html.js +1424 -0
  15. data/ext/jsdom/lib/jsdom/level2/index.js +7 -0
  16. data/ext/jsdom/lib/jsdom/level2/languages/javascript.js +17 -0
  17. data/ext/jsdom/lib/jsdom/level3/core.js +514 -0
  18. data/ext/jsdom/lib/jsdom/level3/events.js +296 -0
  19. data/ext/jsdom/lib/jsdom/level3/html.js +5 -0
  20. data/ext/jsdom/lib/jsdom/level3/index.js +7 -0
  21. data/ext/node-htmlparser/lib/node-htmlparser.js +769 -0
  22. data/ext/node-htmlparser/lib/node-htmlparser.min.js +22 -0
  23. data/ext/request/request.js +116 -0
  24. data/js/jasmine-start.js +10 -0
  25. data/js/webr.js +97 -0
  26. data/jspec/jasmine_spec.js +23 -0
  27. data/lib/webr.rb +17 -0
  28. data/lib/webr/browser.rb +44 -0
  29. data/lib/webr/jasmine.rb +6 -0
  30. data/lib/webr/jasmine/browser.rb +15 -0
  31. data/lib/webr/jasmine/reporter.rb +16 -0
  32. data/lib/webr/jasmine/reporter/base.rb +40 -0
  33. data/lib/webr/jasmine/reporter/console.rb +79 -0
  34. data/lib/webr/jasmine/reporter/html.rb +179 -0
  35. data/lib/webr/portal.rb +19 -0
  36. data/lib/webr/runtime.rb +23 -0
  37. data/lib/webr/version.rb +3 -0
  38. data/spec/data/plain.html +13 -0
  39. data/spec/data/script-embedded.html +17 -0
  40. data/spec/data/script-external-onload.html +11 -0
  41. data/spec/data/script-external-onload.js +11 -0
  42. data/spec/data/script-external.html +11 -0
  43. data/spec/data/script-external.js +1 -0
  44. data/spec/data/script-jquery-1.4.2.html +12 -0
  45. data/spec/data/script-jquery-1.4.3.html +12 -0
  46. data/spec/data/script-jquery.js +3 -0
  47. data/spec/lib/webr/browser_spec.rb +133 -0
  48. data/spec/lib/webr/jasmine/browser_spec.rb +22 -0
  49. data/spec/lib/webr/jasmine/reporter/html_spec.rb +15 -0
  50. data/spec/spec_helper.rb +4 -0
  51. data/tasks/spec.rake +16 -0
  52. data/webr.gemspec +30 -0
  53. metadata +207 -0
@@ -0,0 +1,22 @@
1
+ /***********************************************
2
+ Copyright 2010, Chris Winberry <chris@winberry.net>. All rights reserved.
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ IN THE SOFTWARE.
20
+ ***********************************************/
21
+ /* v1.6.3 */
22
+ (function(){function e(a){this.validateHandler(a);this._handler=a;this.reset()}function n(a){n.super_.call(this,a,{ignoreWhitespace:true,verbose:false,enforceEmptyTags:false})}function g(a,c){this.reset();this._options=c?c:{};if(this._options.ignoreWhitespace==undefined)this._options.ignoreWhitespace=false;if(this._options.verbose==undefined)this._options.verbose=true;if(this._options.enforceEmptyTags==undefined)this._options.enforceEmptyTags=true;if(typeof a=="function")this._callback=a}if(!(typeof require== "function"&&typeof exports=="object"&&typeof module=="object"&&typeof __filename=="string"&&typeof __dirname=="string")){if(this.Tautologistics){if(this.Tautologistics.NodeHtmlParser)return}else this.Tautologistics={};this.Tautologistics.NodeHtmlParser={};exports=this.Tautologistics.NodeHtmlParser}var d={Text:"text",Directive:"directive",Comment:"comment",Script:"script",Style:"style",Tag:"tag"};e._reTrim=/(^\s+|\s+$)/g;e._reTrimComment=/(^\!--|--$)/g;e._reWhitespace=/\s/g;e._reTagName=/^\s*(\/?)\s*([^\s\/]+)/; e._reAttrib=/([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g;e._reTags=/[\<\>]/g;e.prototype.parseComplete=function(a){this.reset();this.parseChunk(a);this.done()};e.prototype.parseChunk=function(a){this._done&&this.handleError(Error("Attempted to parse chunk after parsing already done"));this._buffer+=a;this.parseTags()};e.prototype.done=function(){if(!this._done){this._done=true;if(this._buffer.length){var a=this._buffer;this._buffer= "";a={raw:a,data:this._parseState==d.Text?a:a.replace(e._reTrim,""),type:this._parseState};if(this._parseState==d.Tag||this._parseState==d.Script||this._parseState==d.Style)a.name=this.parseTagName(a.data);this.parseAttribs(a);this._elements.push(a)}this.writeHandler();this._handler.done()}};e.prototype.reset=function(){this._buffer="";this._done=false;this._elements=[];this._next=this._current=this._elementsCurrent=0;this._parseState=d.Text;this._prevTagSep="";this._tagStack=[];this._handler.reset()}; e.prototype._handler=null;e.prototype._buffer=null;e.prototype._done=false;e.prototype._elements=null;e.prototype._elementsCurrent=0;e.prototype._current=0;e.prototype._next=0;e.prototype._parseState=d.Text;e.prototype._prevTagSep="";e.prototype._tagStack=null;e.prototype.parseTagAttribs=function(a){for(var c=a.length,b=0;b<c;){var h=a[b++];if(h.type==d.Tag||h.type==d.Script||h.type==d.style)this.parseAttribs(h)}return a};e.prototype.parseAttribs=function(a){if(!(a.type!=d.Script&&a.type!=d.Style&& a.type!=d.Tag)){var c=a.data.split(e._reWhitespace,1)[0];c=a.data.substring(c.length);if(!(c.length<1)){var b;for(e._reAttrib.lastIndex=0;b=e._reAttrib.exec(c);){if(a.attribs==undefined)a.attribs={};if(typeof b[1]=="string"&&b[1].length)a.attribs[b[1]]=b[2];else if(typeof b[3]=="string"&&b[3].length)a.attribs[b[3].toString()]=b[4].toString();else if(typeof b[5]=="string"&&b[5].length)a.attribs[b[5]]=b[6];else if(typeof b[7]=="string"&&b[7].length)a.attribs[b[7]]=b[7]}}}};e.prototype.parseTagName= function(a){if(a==null||a=="")return"";a=e._reTagName.exec(a);if(!a)return"";return(a[1]?"/":"")+a[2]};e.prototype.parseTags=function(){for(var a=this._buffer.length-1;e._reTags.test(this._buffer);){this._next=e._reTags.lastIndex-1;var c=this._buffer.charAt(this._next),b=this._buffer.substring(this._current,this._next);b={raw:b,data:this._parseState==d.Text?b:b.replace(e._reTrim,""),type:this._parseState};var h=this.parseTagName(b.data);if(this._tagStack.length)if(this._tagStack[this._tagStack.length- 1]==d.Script)if(h=="/script")this._tagStack.pop();else{if(b.raw.indexOf("!--")!=0){b.type=d.Text;if(this._elements.length&&this._elements[this._elements.length-1].type==d.Text){var i=this._elements[this._elements.length-1];i.raw=i.data=i.raw+this._prevTagSep+b.raw;b.raw=b.data=""}}}else if(this._tagStack[this._tagStack.length-1]==d.Style)if(h=="/style")this._tagStack.pop();else{if(b.raw.indexOf("!--")!=0){b.type=d.Text;if(this._elements.length&&this._elements[this._elements.length-1].type==d.Text)if(b.raw!= ""){i=this._elements[this._elements.length-1];i.raw=i.data=i.raw+this._prevTagSep+b.raw;b.raw=b.data=""}else i.raw=i.data=i.raw+this._prevTagSep;else if(b.raw!="")b.raw=b.data=b.raw}}else if(this._tagStack[this._tagStack.length-1]==d.Comment){var j=b.raw.length;if(b.raw.charAt(j-2)=="-"&&b.raw.charAt(j-1)=="-"&&c==">"){this._tagStack.pop();if(this._elements.length&&this._elements[this._elements.length-1].type==d.Comment){i=this._elements[this._elements.length-1];i.raw=i.data=(i.raw+b.raw).replace(e._reTrimComment, "");b.raw=b.data="";b.type=d.Text}else b.type=d.Comment}else{b.type=d.Comment;if(this._elements.length&&this._elements[this._elements.length-1].type==d.Comment){i=this._elements[this._elements.length-1];i.raw=i.data=i.raw+b.raw+c;b.raw=b.data="";b.type=d.Text}else b.raw=b.data=b.raw+c}}if(b.type==d.Tag){b.name=h;if(b.raw.indexOf("!--")==0){b.type=d.Comment;delete b.name;j=b.raw.length;if(b.raw.charAt(j-1)=="-"&&b.raw.charAt(j-2)=="-"&&c==">")b.raw=b.data=b.raw.replace(e._reTrimComment,"");else{b.raw+= c;this._tagStack.push(d.Comment)}}else if(b.raw.indexOf("!")==0||b.raw.indexOf("?")==0)b.type=d.Directive;else if(b.name=="script"){b.type=d.Script;b.data.charAt(b.data.length-1)!="/"&&this._tagStack.push(d.Script)}else if(b.name=="/script")b.type=d.Script;else if(b.name=="style"){b.type=d.Style;b.data.charAt(b.data.length-1)!="/"&&this._tagStack.push(d.Style)}else if(b.name=="/style")b.type=d.Style;if(b.name&&b.name.charAt(0)=="/")b.data=b.name}if(b.raw!=""||b.type!=d.Text){this.parseAttribs(b); this._elements.push(b);b.type!=d.Text&&b.type!=d.Comment&&b.type!=d.Directive&&b.data.charAt(b.data.length-1)=="/"&&this._elements.push({raw:"/"+b.name,data:"/"+b.name,name:"/"+b.name,type:b.type})}this._parseState=c=="<"?d.Tag:d.Text;this._current=this._next+1;this._prevTagSep=c}this._buffer=this._current<=a?this._buffer.substring(this._current):"";this._current=0;this.writeHandler()};e.prototype.validateHandler=function(a){if(typeof a!="object")throw Error("Handler is not an object");if(typeof a.reset!= "function")throw Error("Handler method 'reset' is invalid");if(typeof a.done!="function")throw Error("Handler method 'done' is invalid");if(typeof a.writeTag!="function")throw Error("Handler method 'writeTag' is invalid");if(typeof a.writeText!="function")throw Error("Handler method 'writeText' is invalid");if(typeof a.writeComment!="function")throw Error("Handler method 'writeComment' is invalid");if(typeof a.writeDirective!="function")throw Error("Handler method 'writeDirective' is invalid");}; e.prototype.writeHandler=function(a){a=!!a;if(!(this._tagStack.length&&!a))for(;this._elements.length;){a=this._elements.shift();switch(a.type){case d.Comment:this._handler.writeComment(a);break;case d.Directive:this._handler.writeDirective(a);break;case d.Text:this._handler.writeText(a);break;default:this._handler.writeTag(a)}}};e.prototype.handleError=function(a){if(typeof this._handler.error=="function")this._handler.error(a);else throw a;};(function(a,c){var b=function(){};b.prototype=c.prototype; a.super_=c;a.prototype=new b;a.prototype.constructor=a})(n,g);n.prototype.done=function(){var a={},c,b=f.getElementsByTagName(function(k){return k=="rss"||k=="feed"},this.dom,false);if(b.length)c=b[0];if(c){if(c.name=="rss"){a.type="rss";c=c.children[0];a.id="";try{a.title=f.getElementsByTagName("title",c.children,false)[0].children[0].data}catch(h){}try{a.link=f.getElementsByTagName("link",c.children,false)[0].children[0].data}catch(i){}try{a.description=f.getElementsByTagName("description",c.children, false)[0].children[0].data}catch(j){}try{a.updated=new Date(f.getElementsByTagName("lastBuildDate",c.children,false)[0].children[0].data)}catch(m){}try{a.author=f.getElementsByTagName("managingEditor",c.children,false)[0].children[0].data}catch(o){}a.items=[];f.getElementsByTagName("item",c.children).forEach(function(k){var l={};try{l.id=f.getElementsByTagName("guid",k.children,false)[0].children[0].data}catch(q){}try{l.title=f.getElementsByTagName("title",k.children,false)[0].children[0].data}catch(r){}try{l.link= f.getElementsByTagName("link",k.children,false)[0].children[0].data}catch(s){}try{l.description=f.getElementsByTagName("description",k.children,false)[0].children[0].data}catch(t){}try{l.pubDate=new Date(f.getElementsByTagName("pubDate",k.children,false)[0].children[0].data)}catch(u){}a.items.push(l)})}else{a.type="atom";try{a.id=f.getElementsByTagName("id",c.children,false)[0].children[0].data}catch(p){}try{a.title=f.getElementsByTagName("title",c.children,false)[0].children[0].data}catch(v){}try{a.link= f.getElementsByTagName("link",c.children,false)[0].attribs.href}catch(w){}try{a.description=f.getElementsByTagName("subtitle",c.children,false)[0].children[0].data}catch(x){}try{a.updated=new Date(f.getElementsByTagName("updated",c.children,false)[0].children[0].data)}catch(y){}try{a.author=f.getElementsByTagName("email",c.children,true)[0].children[0].data}catch(z){}a.items=[];f.getElementsByTagName("entry",c.children).forEach(function(k){var l={};try{l.id=f.getElementsByTagName("id",k.children, false)[0].children[0].data}catch(q){}try{l.title=f.getElementsByTagName("title",k.children,false)[0].children[0].data}catch(r){}try{l.link=f.getElementsByTagName("link",k.children,false)[0].attribs.href}catch(s){}try{l.description=f.getElementsByTagName("summary",k.children,false)[0].children[0].data}catch(t){}try{l.pubDate=new Date(f.getElementsByTagName("updated",k.children,false)[0].children[0].data)}catch(u){}a.items.push(l)})}this.dom=a}n.super_.prototype.done.call(this)};g._emptyTags={area:1, base:1,basefont:1,br:1,col:1,frame:1,hr:1,img:1,input:1,isindex:1,link:1,meta:1,param:1,embed:1};g.reWhitespace=/^\s*$/;g.prototype.dom=null;g.prototype.reset=function(){this.dom=[];this._done=false;this._tagStack=[];this._tagStack.last=function(){return this.length?this[this.length-1]:null}};g.prototype.done=function(){this._done=true;this.handleCallback(null)};g.prototype.writeTag=function(a){this.handleElement(a)};g.prototype.writeText=function(a){if(this._options.ignoreWhitespace)if(g.reWhitespace.test(a.data))return; this.handleElement(a)};g.prototype.writeComment=function(a){this.handleElement(a)};g.prototype.writeDirective=function(a){this.handleElement(a)};g.prototype.error=function(a){this.handleCallback(a)};g.prototype._options=null;g.prototype._callback=null;g.prototype._done=false;g.prototype._tagStack=null;g.prototype.handleCallback=function(a){if(typeof this._callback!="function")if(a)throw a;else return;this._callback(a,this.dom)};g.prototype.handleElement=function(a){this._done&&this.handleCallback(Error("Writing to the handler after done() called is not allowed without a reset()")); if(!this._options.verbose){delete a.raw;if(a.type=="tag"||a.type=="script"||a.type=="style")delete a.data}if(this._tagStack.last())if(a.type!=d.Text&&a.type!=d.Comment&&a.type!=d.Directive)if(a.name.charAt(0)=="/"){a=a.name.substring(1);if(!this._options.enforceEmptyTags||!g._emptyTags[a]){for(var c=this._tagStack.length-1;c>-1&&this._tagStack[c--].name!=a;);if(c>-1||this._tagStack[0].name==a)for(;c<this._tagStack.length-1;)this._tagStack.pop()}}else{if(!this._tagStack.last().children)this._tagStack.last().children= [];this._tagStack.last().children.push(a);if(!this._options.enforceEmptyTags||!g._emptyTags[a.name])this._tagStack.push(a)}else{if(!this._tagStack.last().children)this._tagStack.last().children=[];this._tagStack.last().children.push(a)}else if(a.type!=d.Text&&a.type!=d.Comment&&a.type!=d.Directive){if(a.name.charAt(0)!="/"){this.dom.push(a);if(!this._options.enforceEmptyTags||!g._emptyTags[a.name])this._tagStack.push(a)}}else this.dom.push(a)};var f={testElement:function(a,c){if(!c)return false;for(var b in a)if(b== "tag_name"){if(c.type!="tag"&&c.type!="script"&&c.type!="style")return false;if(!a.tag_name(c.name))return false}else if(b=="tag_type"){if(!a.tag_type(c.type))return false}else if(b=="tag_contains"){if(c.type!="text"&&c.type!="comment"&&c.type!="directive")return false;if(!a.tag_contains(c.data))return false}else if(!c.attribs||!a[b](c.attribs[b]))return false;return true},getElements:function(a,c,b,h){function i(o){return function(p){return p==o}}b=b===undefined||b===null||!!b;h=isNaN(parseInt(h))? -1:parseInt(h);if(!c)return[];var j=[],m;for(m in a)if(typeof a[m]!="function")a[m]=i(a[m]);f.testElement(a,c)&&j.push(c);if(h>=0&&j.length>=h)return j;if(b&&c.children)c=c.children;else if(c instanceof Array)c=c;else return j;for(m=0;m<c.length;m++){j=j.concat(f.getElements(a,c[m],b,h));if(h>=0&&j.length>=h)break}return j},getElementById:function(a,c,b){a=f.getElements({id:a},c,b,1);return a.length?a[0]:null},getElementsByTagName:function(a,c,b,h){return f.getElements({tag_name:a},c,b,h)},getElementsByTagType:function(a, c,b,h){return f.getElements({tag_type:a},c,b,h)}};exports.Parser=e;exports.DefaultHandler=g;exports.RssHandler=n;exports.ElementType=d;exports.DomUtils=f})();
@@ -0,0 +1,116 @@
1
+ var http = require('http')
2
+ , url = require('url')
3
+ , sys = require('sys')
4
+ ;
5
+
6
+ var toBase64 = function(str) {
7
+ return (new Buffer(str || "", "ascii")).toString("base64");
8
+ };
9
+
10
+ function request (options, callback) {
11
+ if (!options.uri) {
12
+ throw new Error("options.uri is a required argument")
13
+ } else {
14
+ if (typeof options.uri == "string") {
15
+ options.uri = url.parse(options.uri);
16
+ }
17
+ }
18
+
19
+ options._redirectsFollowed = options._redirectsFollowed ? options._redirectsFollowed : 0;
20
+ options.maxRedirects = options.maxRedirects ? options.maxRedirects : 10;
21
+
22
+ options.followRedirect = (options.followRedirect !== undefined) ? options.followRedirect : true;
23
+ options.method = options.method ? options.method : 'GET';
24
+
25
+ options.headers = options.headers ? options.headers : {};
26
+ if (!options.headers.host) {
27
+ options.headers.host = options.uri.hostname;
28
+ if (options.uri.port) {
29
+ if ( !(options.uri.port === 80 && options.uri.protocol === 'http:') &&
30
+ !(options.uri.port === 443 && options.uri.protocol === 'https:') )
31
+ options.headers.host += (':'+options.uri.port)
32
+ }
33
+ var setHost = true;
34
+ } else {
35
+ var setHost = false;
36
+ }
37
+
38
+ if (!options.uri.pathname) {options.uri.pathname = '/'}
39
+ if (!options.uri.port) {
40
+ if (options.uri.protocol == 'http:') {options.uri.port = 80}
41
+ else if (options.uri.protocol == 'https:') {options.uri.port = 443}
42
+ }
43
+
44
+ if (options.uri.protocol == 'https:') {
45
+ var secure = true;
46
+ } else {
47
+ var secure = false;
48
+ }
49
+
50
+ if (options.bodyStream) {
51
+ sys.error('options.bodyStream is deprecated. use options.reponseBodyStream instead.');
52
+ options.responseBodyStream = options.bodyStream;
53
+ }
54
+
55
+ options.client = options.client ? options.client : http.createClient(options.uri.port, options.uri.hostname, secure);
56
+
57
+ var clientErrorHandler = function (error) {
58
+ if (setHost) delete options.headers.host;
59
+ if (callback) callback(error);
60
+ }
61
+ options.client.addListener('error', clientErrorHandler);
62
+
63
+ if (options.uri.auth && !options.headers.authorization) {
64
+ options.headers.authorization = "Basic " + toBase64(options.uri.auth);
65
+ }
66
+ options.fullpath = options.uri.href.replace(options.uri.protocol + '//' + options.uri.host, '');
67
+ if (options.fullpath.length === 0) options.fullpath = '/'
68
+ if (options.body) {options.headers['content-length'] = options.body.length}
69
+ options.request = options.client.request(options.method, options.fullpath, options.headers);
70
+
71
+ options.request.addListener("response", function (response) {
72
+ var buffer;
73
+ if (options.responseBodyStream) {
74
+ buffer = options.responseBodyStream;
75
+ sys.pump(response, options.responseBodyStream);
76
+ }
77
+ else {
78
+ buffer = '';
79
+ response.addListener("data", function (chunk) { buffer += chunk; } )
80
+ }
81
+
82
+ response.addListener("end", function () {
83
+ options.client.removeListener("error", clientErrorHandler);
84
+
85
+ if (response.statusCode > 299 && response.statusCode < 400 && options.followRedirect && response.headers.location && (options._redirectsFollowed < options.maxRedirects) ) {
86
+ options._redirectsFollowed += 1
87
+ options.uri = response.headers.location;
88
+ delete options.client;
89
+ if (options.headers) {
90
+ delete options.headers.host;
91
+ }
92
+ request(options, callback);
93
+ return;
94
+ } else {options._redirectsFollowed = 0}
95
+
96
+ if (setHost) delete options.headers.host;
97
+ if (callback) callback(null, response, buffer);
98
+ })
99
+ })
100
+
101
+ if (options.body) {
102
+ options.request.write(options.body, 'binary');
103
+ options.request.end();
104
+ } else if (options.requestBodyStream) {
105
+ sys.pump(options.requestBodyStream, options.request);
106
+ } else {
107
+ options.request.end();
108
+ }
109
+ }
110
+
111
+ module.exports = request;
112
+
113
+ request.get = request;
114
+ request.post = function () {arguments[0].method = 'POST', request.apply(request, arguments)};
115
+ request.put = function () {arguments[0].method = 'PUT', request.apply(request, arguments)};
116
+ request.head = function () {arguments[0].method = 'HEAD', request.apply(request, arguments)};
@@ -0,0 +1,10 @@
1
+ // need this in the ruby class as I can't identify them there
2
+ jasmine.isSuite = function(suite) {
3
+ return suite instanceof jasmine.Suite
4
+ }
5
+ jasmine.isSpec = function(spec) {
6
+ return spec instanceof jasmine.Spec
7
+ }
8
+
9
+ jasmine.getEnv().addReporter(new WebrReporter(jasmine))
10
+ jasmine.getEnv().execute()
@@ -0,0 +1,97 @@
1
+ ;(function() {
2
+ var fs = require('fs')
3
+ var sys = require("sys")
4
+ var Script = process.binding('evals').Script
5
+ var scripts = {}
6
+
7
+ // update node paths
8
+ var paths = process.webr.require_paths
9
+ for (var i = 0, len = paths.length; i < len; i++) {
10
+ require.paths.push(paths[i])
11
+ }
12
+
13
+ // stick properties added to window in the global object
14
+ // TODO: figure out why I need this instead of doing Script.runInNewContext(data, window, path)
15
+ function copyWindowToGlobal() {
16
+ for (var prop in window) {
17
+ if (!(prop in global) && prop != 'self') {
18
+ global[prop] = window[prop]
19
+ }
20
+ }
21
+ }
22
+
23
+ // load a script from a file, relative to the webr 'root' property
24
+ function script(path) {
25
+ var pre = path.match(/^\//) ? '' : process.webr.root + '/'
26
+ var fullPath = pre + path
27
+ if (fullPath in scripts) {
28
+ // don't load script twice in the same context
29
+ // multiple file loading/reporting messes up otherwise
30
+ // TODO: rethink this
31
+ return
32
+ }
33
+ var data = fs.readFileSync(fullPath)
34
+ scripts[fullPath] = data
35
+ scriptEval(data, path)
36
+ }
37
+
38
+ // evaluate a script
39
+ function scriptEval(data, path) {
40
+ path = path || null
41
+ Script.runInThisContext(data, path)
42
+ copyWindowToGlobal()
43
+ }
44
+
45
+ // expose require and script to the outside world
46
+ global.require = require
47
+ global.script = script
48
+
49
+ // prepare 'browser'
50
+ document = require('jsdom').jsdom(process.webr.html)
51
+ window = document.createWindow()
52
+
53
+ document.location = window.location
54
+ if ('search' in window.location) {
55
+ // nothing
56
+ } else {
57
+ window.location.search = ""
58
+ }
59
+
60
+ // 'emulate' window load
61
+ window.addEventListener = function(type, listener, capturing) {
62
+ if (type == 'load' || type == "DOMContentLoaded") {
63
+ setTimeout(listener, 0)
64
+ }
65
+ }
66
+ window.__defineSetter__("onload", function(listener) {
67
+ setTimeout(listener, 0)
68
+ })
69
+
70
+ // fake XMLHttpRequest so jQuery 1.4.3 loads
71
+ window.XMLHttpRequest = function() {}
72
+
73
+ copyWindowToGlobal()
74
+
75
+ // run all scripts assigned by Webr
76
+ var scripts = process.webr.scripts
77
+ for (var i = 0, len = scripts.length; i < len; i++) {
78
+ script(scripts[i])
79
+ }
80
+
81
+ // run all scripts in the document
82
+ var list = document.getElementsByTagName("script")
83
+ for (var i = 0; i < list.length; i++) {
84
+ var item = list.item(i),
85
+ src = item.getAttribute('src')
86
+ if (src.length == 0) {
87
+ scriptEval(item.textContent)
88
+ } else {
89
+ if (src.match(/^(http|https)\:\/\//)) {
90
+ throw new Error("http support still needs to be implemented")
91
+ } else {
92
+ script(src)
93
+ }
94
+ }
95
+ }
96
+
97
+ })()
@@ -0,0 +1,23 @@
1
+ var JASMINE_PATH = "../ext/jasmine"
2
+
3
+ script(JASMINE_PATH + "/src/html/TrivialReporter.js")
4
+
5
+ script(JASMINE_PATH + "/spec/suites/BaseSpec.js")
6
+ script(JASMINE_PATH + "/spec/suites/CustomMatchersSpec.js")
7
+ script(JASMINE_PATH + "/spec/suites/EnvSpec.js")
8
+ script(JASMINE_PATH + "/spec/suites/ExceptionsSpec.js")
9
+ script(JASMINE_PATH + "/spec/suites/JsApiReporterSpec.js")
10
+ script(JASMINE_PATH + "/spec/suites/MatchersSpec.js")
11
+ script(JASMINE_PATH + "/spec/suites/MockClockSpec.js")
12
+ script(JASMINE_PATH + "/spec/suites/MultiReporterSpec.js")
13
+ script(JASMINE_PATH + "/spec/suites/NestedResultsSpec.js")
14
+ script(JASMINE_PATH + "/spec/suites/PrettyPrintSpec.js")
15
+ script(JASMINE_PATH + "/spec/suites/ReporterSpec.js")
16
+ script(JASMINE_PATH + "/spec/suites/RunnerSpec.js")
17
+ script(JASMINE_PATH + "/spec/suites/QueueSpec.js")
18
+ script(JASMINE_PATH + "/spec/suites/SpecSpec.js")
19
+ script(JASMINE_PATH + "/spec/suites/SpecRunningSpec.js")
20
+ script(JASMINE_PATH + "/spec/suites/SpySpec.js")
21
+ script(JASMINE_PATH + "/spec/suites/SuiteSpec.js")
22
+ script(JASMINE_PATH + "/spec/suites/TrivialReporterSpec.js")
23
+ script(JASMINE_PATH + "/spec/suites/WaitsForBlockSpec.js")
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'rednode'
3
+ require 'date'
4
+ require 'erb'
5
+
6
+ $:.unshift(File.dirname(__FILE__)) unless
7
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
8
+
9
+ module Webr
10
+ HOME_PATH = File.expand_path(File.dirname(__FILE__) + '/../')
11
+ SCRIPT_PATH = "#{HOME_PATH}/js"
12
+
13
+ require 'webr/runtime'
14
+ require 'webr/portal'
15
+ require 'webr/browser'
16
+ require 'webr/jasmine'
17
+ end
@@ -0,0 +1,44 @@
1
+ module Webr
2
+ class Browser
3
+ attr_reader :runtime, :env, :scripts
4
+
5
+ def initialize
6
+ @runtime = Webr::Runtime.new("#{SCRIPT_PATH}/webr.js")
7
+ @portal = @runtime.portal
8
+
9
+ @portal.require_paths << "#{Webr::HOME_PATH}/ext"
10
+ @portal.require_paths << "#{Webr::HOME_PATH}/ext/request"
11
+ @portal.require_paths << "#{Webr::HOME_PATH}/ext/jsdom/lib"
12
+ @portal.html = "<html><head></head><body></body></html>"
13
+
14
+ # not so nice
15
+ @env = @portal.env
16
+ @scripts = @portal.scripts
17
+ end
18
+
19
+ def open(file_or_url)
20
+ path = File.expand_path(file_or_url)
21
+ @portal.root = File.dirname(path)
22
+ @portal.html = File.new(path).read
23
+ end
24
+
25
+ def root
26
+ @portal.root
27
+ end
28
+ def root=(root)
29
+ @portal.root = root
30
+ end
31
+
32
+ def html
33
+ @portal.html
34
+ end
35
+ def html=(html)
36
+ @portal.html = html
37
+ end
38
+
39
+ def start
40
+ @runtime.start
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ module Webr
2
+ module Jasmine
3
+ require 'webr/jasmine/browser'
4
+ require 'webr/jasmine/reporter'
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ module Webr::Jasmine
2
+ class Browser < Webr::Browser
3
+ def initialize(format)
4
+ super()
5
+ @scripts << "#{Webr::HOME_PATH}/ext/jasmine/lib/jasmine.js"
6
+ @env["WebrReporter"] = Reporter[format]
7
+ end
8
+
9
+ def start
10
+ @scripts << "#{Webr::HOME_PATH}/js/jasmine-start.js"
11
+ super
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Webr::Jasmine
2
+ module Reporter
3
+ def self.[](name)
4
+ pascalized_name = name.gsub(/(_|^)(\w)/) {$2.upcase}
5
+ if Webr::Jasmine::Reporter.const_defined?(pascalized_name)
6
+ Webr::Jasmine::Reporter.const_get(pascalized_name)
7
+ else
8
+ raise "Undefined reporter: #{name}"
9
+ end
10
+ end
11
+
12
+ require 'webr/jasmine/reporter/base'
13
+ require 'webr/jasmine/reporter/html'
14
+ require 'webr/jasmine/reporter/console'
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ module Webr::Jasmine::Reporter
2
+ class Base
3
+ def initialize(jasmine)
4
+ @jasmine = jasmine
5
+ @started = false
6
+ @started_at = nil
7
+ @finished = false
8
+ @finished_at = nil
9
+ end
10
+
11
+ def reportRunnerStarting(runner)
12
+ @started = true
13
+ @started_at = DateTime.now
14
+ end
15
+
16
+ def reportRunnerResults(runner)
17
+ @finished_at = DateTime.now
18
+ @finished = true
19
+ end
20
+
21
+ def reportSuiteResults(suite)
22
+ end
23
+
24
+ def reportSpecStarting(spec)
25
+ end
26
+
27
+ def reportSpecResults(spec)
28
+ end
29
+
30
+ def log(s)
31
+ end
32
+
33
+ # helpers
34
+
35
+ def filter_backtrace(s)
36
+ s.lines.inject([]) { |ret, line| line.include?(Webr::HOME_PATH) ? ret : ret << line }.join # filter out internal stuff
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ module Webr::Jasmine::Reporter
2
+ class Console < Webr::Jasmine::Reporter::Base
3
+ def initialize(jasmine)
4
+ super
5
+
6
+ @fail_count = 0
7
+ end
8
+
9
+
10
+ def reportRunnerResults(runner)
11
+ super(runner)
12
+ summarize(runner)
13
+ end
14
+
15
+ def reportSpecResults(spec)
16
+ super
17
+ if spec.results.passed
18
+ $stdout.write('.')
19
+ else
20
+ $stdout.write('F')
21
+ end
22
+ end
23
+
24
+
25
+ def summarize(runner)
26
+ puts "\n"
27
+ render_results(runner.topLevelSuites)
28
+ puts "\n"
29
+ render_summary(runner)
30
+ end
31
+
32
+ def render_results(suites_or_specs)
33
+ suites_or_specs.each do |suite_or_spec|
34
+ render_suite(suite_or_spec) if @jasmine.isSuite(suite_or_spec)
35
+ render_spec(suite_or_spec) if @jasmine.isSpec(suite_or_spec)
36
+ end
37
+ end
38
+
39
+ def render_suite(suite)
40
+ render_results(suite.children)
41
+ end
42
+
43
+ def render_spec(spec)
44
+ unless spec.results.passed
45
+ puts "\nFailures:" if @fail_count == 0
46
+ @fail_count += 1
47
+ puts " #{@fail_count}) #{spec.getFullName}"
48
+ spaces = " " * (4 + @fail_count.to_s.size)
49
+ spec.results.getItems.each do |item|
50
+ unless item.passed
51
+ backtrace = if error = item['error']
52
+ error.respond_to?(:stack) ? error.stack : error
53
+ else
54
+ item.trace.stack
55
+ end
56
+ puts spaces + item.to_s
57
+ filter_backtrace(backtrace).each_line do |line|
58
+ puts spaces + line
59
+ end
60
+ puts ""
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ def render_summary(runner)
67
+ suites = runner.suites
68
+ specs = runner.specs
69
+ results = runner.results
70
+
71
+ hours, minutes, seconds, fraction = Date.day_fraction_to_time(@finished_at - @started_at)
72
+ time_taken = "%0.8f" % (hours*60*60 + minutes*60 + seconds + fraction.to_f)
73
+
74
+ puts "Finished in #{time_taken}s"
75
+ puts "Examples: #{specs.length}, Failure#{'s' unless results.failedCount == 1}: #{results.failedCount}"
76
+ end
77
+ end
78
+
79
+ end