* Starting to work on the new specs for MooTools-Core
[mootools/dkf.git] / Specs / SlickSpec / JSSpecHelpers.js
blob9b17ede7f92ddd2ed937256cfd8accdd66ddcabc
1 function $try(){
2         for (var i = 0, l = arguments.length; i < l; i++){
3                 try {
4                         return arguments[i]();
5                 } catch(e){}
6         }
7         return null;
8 };
10 Function.prototype._type = "Function";
12 String.escapeSingle = String.escapeSingle || function escapeSingle(string){
13         return (''+string).replace(/(?=[\\\n'])/g,'\\');
17 var global = this;
18 global.context = this;
19 var specs, spec, it, its;
20 var descriptionParent = '';
21 var uniquespecs = {};
23 function Describe(description,specBuilder){
24         // Backup existing object so we don't override it
25         var old_specs = specs;
26         specs = spec = it = its = {};
27         
28         // Inherit the before and afters of your forefathers
29         if (old_specs) {
30                 if (old_specs.before      ) specs.before      = old_specs.before;
31                 if (old_specs.before_all  ) specs.before_all  = old_specs.before_all;
32                 if (old_specs.before_each ) specs.before_each = old_specs.before_each;
33                 if (old_specs.after       ) specs.after       = old_specs.after;
34                 if (old_specs.after_all   ) specs.after_all   = old_specs.after_all;
35                 if (old_specs.after_each  ) specs.after_each  = old_specs.after_each;
36         }
37         
38         // Inherit the description of your forefathers
39         description = descriptionParent + (descriptionParent ? ': ' : '') + String(description);
40         var old_descriptionParent = descriptionParent;
41         descriptionParent = description;
42         
43         // Build the spec object
44         specBuilder(specs,global.context);
45         
46         // Create the tests and go!
47         var spec_count = 0;
48         var specnames = [];
49         for (var specname in specs){
50                 if (/^(before|after)[_ ](all|each)$/.test(specname)) continue;
51                 if (!specs[specname]) continue;
52                 spec_count++;
53                 specnames.push(description+specname);
54         }
55         if (spec_count && !uniquespecs[specnames]){
56                 describe(description, specs);
57                 uniquespecs[specnames] = true;
58         }
59         
60         // Reset
61         descriptionParent = old_descriptionParent;
62         specs = spec = it = its = old_specs;
66 global.mocks = {};
67 var Mock = (function(){
68         
69         function Mock(mockName, testBuilder){
70                 if (mockName && !testBuilder) throw new Error("Invalid mockName, Mock syntax: `new Mock(/mockName/, function(specs, window){})`");
71                 
72                 if (Object.prototype.toString.call(mockName) != '[object RegExp]')
73                         mockName = new RegExp(mockName);
74                 
75                 this.mockName = mockName;
76                 this.testBuilder = testBuilder;
77                 Mock.mocks.push(this);
78         };
79         
80         Mock.mocks = [];
81         
82         Mock.prototype.run = function(){
83                 var globalContextOld = global.context;
84                 for (var mockName in global.mocks) if (this.mockName.test(mockName)) {
85                         
86                         global.context = global.mocks[mockName];
87                         for (var i = 0, l = global.willDefineEverywhere.length; i  < l; i++) {
88                                 try {
89                                         global.willDefineEverywhere[i](global.context);
90                                 } finally {
91                                         continue;
92                                 }
93                         }
94                         Describe(mockName,this.testBuilder);
95                         
96                 }
97                 global.context = globalContextOld;
98         };
99         
100         Mock.register = function(name, window){
101                 clearTimeout(Mock.register.delay);
102                 global.mocks[name] = window;
103                 Mock.register.delay = setTimeout(Mock.register.done, 1000);
104         };
106         Mock.register.done = function(){
107                 for (var i=0; i < Mock.mocks.length; i++){
108                         try {
109                                 Mock.mocks[i].run();
110                         } finally {
111                                 continue;
112                         }
113                 }
114                 
115                 global.runSpecs();
116         };
117         
118         
119         return Mock;
120 })();
122 Mock.Request = function(mockName, url){
123         if (!this instanceof Mock.Request) throw new Error('Mock.Request is not callable directly. Must use `new Mock.Request`');
124         
125         this.mockName = mockName;
126         this.url = url;
127         
128         var self = this;
129         this.callback = function(html, xml){
130                 Mock.register(self.mockName +': '+ String(self.url).replace(/^.*\//,''), newFakeWinFromDoc(xml));
131         };
132         this.rq = new SimpleRequest();
133         this.rq.send(this.url, this.callback);
136 global.willDefineEverywhere = [];
137 Mock.defineEverywhere = function(definer){
138         global.willDefineEverywhere.push(definer);
141 var TODO = function(){ throw "TODO: This test has not be written yet"; };
143 if(typeof JSSpec == 'undefined') var JSSpec = {};
144 if(!JSSpec.Browser) JSSpec.Browser = {};
145 JSSpec.Browser.NativeConsole = !!(('console' in this) && ('log' in console) && ('toString' in console.log) && console.log.toString().match(/\[native code\]/));
146 JSSpec.Browser.Trident = (JSSpec.Browser.Trident && !JSSpec.Browser.NativeConsole);
148 // Stop the normal JSSpec onload from firing yet
149 var runSpecs_actually = window.onload;
150 // console.time('runSpecs');
151 var runSpecs = function(){
152         // console.timeEnd('runSpecs');
153         // console.time('runSpecs');
154         // console.log('runSpecs');
155         clearTimeout(global.runSpecs_timer);
156         global.runSpecs_timer = setTimeout(runSpecs_actually, 1000);
158 window.onload = function(){
159         window.loaded = true;
160         // setTimeout(runSpecs, 100);
164 // XML
165 // from http://www.webreference.com/programming/javascript/definitive2/
167  * Create a new Document object. If no arguments are specified,
168  * the document will be empty. If a root tag is specified, the document
169  * will contain that single root tag. If the root tag has a namespace
170  * prefix, the second argument must specify the URL that identifies the
171  * namespace.
172  */ 
173 var newXMLDocument = (document.implementation && document.implementation.createDocument)
174 ? function(rootTagName, namespaceURL){
175         return document.implementation.createDocument(namespaceURL||'', rootTagName||'', null); 
177 : function(rootTagName, namespaceURL){
178         if (!rootTagName) rootTagName = ""; 
179         if (!namespaceURL) namespaceURL = ""; 
180         // This is the IE way to do it 
181         // Create an empty document as an ActiveX object 
182         // If there is no root element, this is all we have to do 
183         var doc = new ActiveXObject("MSXML2.DOMDocument"); 
184         // If there is a root tag, initialize the document 
185         if (rootTagName) { 
186                 // Look for a namespace prefix 
187                 var prefix = ""; 
188                 var tagname = rootTagName; 
189                 var p = rootTagName.indexOf(':'); 
190                 if (p != -1) { 
191                         prefix = rootTagName.substring(0, p); 
192                         tagname = rootTagName.substring(p+1); 
193                 } 
194                 // If we have a namespace, we must have a namespace prefix 
195                 // If we don't have a namespace, we discard any prefix 
196                 if (namespaceURL) { 
197                         if (!prefix) prefix = "a0"; // What Firefox uses 
198                 } 
199                 else prefix = ""; 
200                 // Create the root element (with optional namespace) as a 
201                 // string of text 
202                 var text = "<" + (prefix?(prefix+":"):"") +      tagname + 
203                 (namespaceURL 
204                         ?(" xmlns:" + prefix + '="' + namespaceURL +'"') 
205                 :"") + 
206                 "/>"; 
207                 // And parse that text into the empty document 
208                 doc.loadXML(text); 
209         } 
210         return doc; 
211 }; 
214  * Synchronously load the XML document at the specified URL and
215  * return it as a Document object
216  */
217 var loadXML = function(url) {
218         // Create a new document with the previously defined function
219         var xmldoc = newXMLDocument();
220         xmldoc.async = false;  // We want to load synchronously
221         xmldoc.load(url);          // Load and parse
222         return xmldoc;             // Return the document
226  * Parse the XML document contained in the string argument and return
227  * a Document object that represents it.
228  */
229 var parseXML = (function(){
230         
231         // Mozilla, Firefox, and related browsers
232         if (typeof DOMParser != "undefined")
233         return function(rawXML){
234                 return (new DOMParser()).parseFromString(rawXML, "application/xml");
235         };
236         
237         // Internet Explorer.
238         if (typeof ActiveXObject != "undefined")
239         return function(rawXML){
240                 var xmlDocument = new ActiveXObject("Microsoft.XMLDOM");
241                 xmlDocument.async = false;
242                 xmlDocument.loadXML(rawXML);
243                 
244                 if (xmlDocument.parseError && xmlDocument.parseError.errorCode)
245                         xmlDocument.loadXML(rawXML.replace(/<!DOCTYPE[^>]*?>/i,''));
246                 
247                 if (xmlDocument.parseError && xmlDocument.parseError.errorCode)
248                 throw new Error([''
249                         ,("Error code: " + xmlDocument.parseError.errorCode)
250                         ,("Error reason: " + xmlDocument.parseError.reason)
251                         ,("Error line: " + xmlDocument.parseError.line)
252                         ,rawXML
253                 ].join('\n'));
254                 
255                 return xmlDocument;
256         };
257         
258         // As a last resort, try loading the document from a data: URL
259         // This is supposed to work in Safari. Thanks to Manos Batsis and
260         // his Sarissa library (sarissa.sourceforge.net) for this technique.
261         return function(rawXML){
262                 var url = "data:text/xml;charset=utf-8," + encodeURIComponent(rawXML);
263                 var request = new XMLHttpRequest();
264                 request.open("GET", url, false);
265                 request.send(null);
266                 return request.responseXML;
267         };
268         
269 })();
272 function getXML(url,mime){
273         if (!mime && url && /\.(svg|xml|xhtml)/i.test(url))
274                 mime = 'text/xml';
275         
276         var request;
277         if (XMLHttpRequest != undefined)
278                 request = new XMLHttpRequest();
279         else
280                 request = new ActiveXObject("Microsoft.XMLHTTP");
281         
282         request.open("GET", url, false);
283         if (mime && request.overrideMimeType) request.overrideMimeType(mime);
284         request.send(null);
285         return request;
286         return request.responseXML || parseXML(request.responseText);
287         
291 function newFakeWinFromDoc(document){
292         var fakeWin = { fake:true };
293         fakeWin.document = document;
294         // fakeWin.document = getXML('/test/tools/MooTools_Logo.svg');
295         // fakeWin.document = loadXML('tools/MooTools_Logo.svg');
296         // fakeWin.document = document.getElementById('svg_logo_data_island').document;
297         // fakeWin.document = parseXML('<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="MooTools_Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"><style type="text/css"><![CDATA[#Tools { fill : #949494; }#Moo, #L { fill : #2A2A2A; }]]></style><g id="MooTools"><g id="Moo"><path id="M" d="M125.088,203.521l3.903-66.119c0.447-7.272-6.365-13.168-13.494-13.168 s-14.396,5.896-14.842,13.168l-3.903,66.119H70.34l3.903-66.119c0.446-7.272-7.139-13.497-14.268-13.497 c-7.128,0-13.621,6.224-14.067,13.497l-3.903,66.119H16.686l6.327-100.854h19.361c5.186-2.681,11.832-4.204,17.892-4.204 c11.246,0,22.651,5.22,28.805,13.413c7.159-8.193,16.685-13.413,27.931-13.413c20.042,0,38.635,16.574,37.38,37.02l-4.176,68.038 H125.088z"/><path id="O" d="M227.522,187.858c-11.484,10.17-24.632,15.253-39.442,15.249 c-14.694-0.004-27.082-5.094-37.163-15.271c-9.829-10.402-14.255-22.692-13.278-36.867c0.985-14.288,7.108-26.631,18.371-37.03 c11.483-10.171,24.572-15.253,39.266-15.249c14.812,0.004,27.258,5.093,37.339,15.269c9.83,10.405,14.251,22.751,13.267,37.039 C244.905,165.172,238.786,177.459,227.522,187.858L227.522,187.858z M214.042,130.595c-5.422-5.603-12.22-8.406-20.398-8.408 c-8.177-0.003-15.422,2.797-21.734,8.397c-6.202,5.715-9.573,12.516-10.117,20.403c-0.544,7.889,1.889,14.692,7.304,20.41 c5.54,5.604,12.399,8.404,20.576,8.407c8.177,0.003,15.361-2.796,21.556-8.396c6.319-5.716,9.752-12.519,10.296-20.406 C222.068,143.116,219.572,136.314,214.042,130.595L214.042,130.595z"/><use xlink:href="#O" x="91.37" /></g><g id="Tools"><path id="T" d="M469.423,98.331l-1.57,22.859h-85.685l-2.843,41.408c-0.849,12.352,2.383,16.424,12.221,16.424 c4.814,0,9.171,0.014,9.171,0.014l-1.341,23.274c0,0-9.587-0.05-17.75-0.05c-9.421,0-17.168-3.027-21.624-8.262 c-5.041-5.861-6.92-15.072-5.999-28.471l1.785-44.339h-13.395l1.57-22.859L469.423,98.331L469.423,98.331z"/><use xlink:href="#O" x="273.478" /><use xlink:href="#O" x="364.934" /><path id="L" d="M676.194,94.185c-0.427-14.357-23.928-28.556-23.928-28.556l-4.106,0.987l7.701,22.652 c0,0-0.213,6.14-6.333,7.911c-6.119,1.772-10.41-2.811-10.41-2.811l-6.004-22.748l-4.254,1.751c0,0-11.687,31.459-10.13,35.383 c2.228,10.152,8.763,19.051,9.499,34.381c0.736,15.329-9.942,50.875-10.978,60.084c-1.034,9.21,7.069,16.527,15.058,16.734 s15.757-6.582,15.991-13.98c0.235-7.398-0.562-43.084,1.339-58.836C651.543,131.386,676.62,108.541,676.194,94.185z  M633.087,212.549c-4.286,0.24-7.955-3.041-8.195-7.33c-0.239-4.288,3.04-7.959,7.326-8.199s7.954,3.042,8.195,7.33 C640.652,208.639,637.373,212.31,633.087,212.549z"/><path id="S" d="M685.639,183.224c0,0-6.281,7.173-14.436,17.089c16.747,11.898,39.931,14.514,54.724-1.746 c4.312-4.736,12.999-16.967,3.743-34.596c-9.255-17.628-33.862-26.104-25.837-37.344c6.08-8.513,21.438-0.832,27.451,5.181 c2.423-2.204,10.114-9.64,13.642-13.827c-16.314-20.394-51.276-22.47-63.328-1.166c-19.93,35.229,37.275,51.109,26.337,67.658 C700.7,195.417,685.639,183.224,685.639,183.224z"/></g></g></svg>');
298         
299         fakeWin.SELECT = function(context, expression){
300                 return global.SELECT.call(fakeWin, context, expression);
301         };
302         // if (fakeWin.document) fakeWin.document.search = function(expression){
303         //      return SELECT(fakeWin.document, expression);
304         // };
305         
306         return fakeWin;