1 /**	Manages views, providing methods for loading, templating, caching and swapping.
  2  *	@constructor Creates a new TestSuite instance.
  3  *	@augments puredom.EventEmitter
  4  *	@param {Object} options		Hashmap of options to be given to the instance.
  5  */
  6 puredom.TestSuite = function(options) {
  7 	puredom.EventEmitter.call(this);
  8 	this.list = {};
  9 };
 10 
 11 
 12 puredom.inherits(puredom.TestSuite, puredom.EventEmitter);
 13 
 14 	
 15 puredom.extend(puredom.TestSuite.prototype, /** @lends puredom.TestSuite# */ {
 16 	
 17 	/** Add a test to the suite.
 18 	 *	@param {String} name	A human-readable name for the test
 19 	 *	@param {Object} test	The test definition
 20 	 *	@example:
 21 	 *		suite.add("Example", {
 22 	 *			prepare : function(test){},
 23 	 *			run : function(test){
 24 	 *				//-- *async* testing here --
 25 	 *				test.finish(results);
 26 	 *			},
 27 	 *			cleanup : function(test){}
 28 	 *		});
 29 	 */
 30 	add : function(name, test) {
 31 		var id = this._getIdFromName(name);
 32 		this.list[id] = {
 33 			name : name,
 34 			test : test,
 35 			results : []
 36 		};
 37 	},
 38 	
 39 
 40 	/** Run the test that matches <code>name</code>.
 41 	 *	@param {String} name	The name of a registered test to run
 42 	 */
 43 	run : function(name, callback, messageHandler) {
 44 		var self = this,
 45 			ob = this.get(name),
 46 			test = ob && ob.test,
 47 			passed = null,
 48 			finish, onMessage, sandboxController, sandbox, finalResult;
 49 		
 50 		// Prepare-run-cleanup model:
 51 		if (test && test.run) {
 52 			onMessage = function(type, message) {
 53 				if (type==='status') {
 54 					finalResult = message;
 55 				}
 56 				if (type==='result') {
 57 					passed = message===true;
 58 				}
 59 				else if (messageHandler) {
 60 					self.fireEvent(type, name, message);
 61 					messageHandler(type, message);
 62 					return false;
 63 				}
 64 			};
 65 			
 66 			finish = function(results) {
 67 				if (test.cleanup) {
 68 					test.cleanup(sandbox);
 69 				}
 70 				
 71 				if (results) {
 72 					finalResult = results;
 73 				}
 74 				else if (sandbox.results) {
 75 					finalResult = sandbox.results;
 76 				}
 77 				
 78 				// Archive results:
 79 				if (results) {
 80 					ob.results.push({
 81 						time : new Date().getTime(),
 82 						results : results
 83 					});
 84 				}
 85 				
 86 				self.fireEvent('finish', name, finalResult, passed);
 87 				if (callback) {
 88 					callback(finalResult, passed);
 89 				}
 90 				sandboxController.destroy();
 91 				self = finish = onMessage = finalResult = ob = test = sandboxController = sandbox = callback = messageHandler = null;
 92 			};
 93 			
 94 			// Get a new sandbox controller:
 95 			sandboxController = this._createSandboxController(ob);
 96 			// simple events:
 97 			sandboxController.messageHandler = onMessage;
 98 			sandboxController.onfinish = finish;
 99 			// get the sandbox itself:
100 			sandbox = sandboxController.getSandbox();
101 			
102 			if (test.prepare) {
103 				test.prepare(sandbox);
104 			}
105 			
106 			results = test.run(sandbox);
107 		}
108 	},
109 	
110 
111 	/** Retrieve the test that matches <code>name</code>.
112 	 *	@param {String} name	The name of a registered test to find
113 	 */
114 	get : function(name) {
115 		var id = this._getIdFromName(name);
116 		return this.list.hasOwnProperty(id) && this.list[id] || false;
117 	},
118 	
119 
120 	/** Get a list of test names available in the suite. */
121 	getList : function() {
122 		var names = [],
123 			i;
124 		for (i in this.list) {
125 			if (this.list.hasOwnProperty(i) && this.list[i].name) {
126 				names.push(this.list[i].name);
127 			}
128 		}
129 		return names;
130 	},
131 	
132 
133 	/** @private */
134 	_getIdFromName : function(name) {
135 		return (name+'').toLowerCase().replace(/[^a-z0-9_]+/gm,'');
136 	},
137 	
138 
139 	/** @private */
140 	_createSandboxController : function(testObj) {
141 		/**	@exports sandbox as puredom.TestSuite.test */
142 
143 			/**	@private */
144 		var self = this,
145 			/**	@private */
146 			controller = {},
147 			/**	@name puredom.TestSuite.test */
148 			sandbox = {};
149 		
150 		/**	@private */
151 		controller.getSandbox = function() {
152 			return sandbox;
153 		};
154 		/**	@private */
155 		controller.destroy = function() {
156 			sandbox = controller = self = testObj = null;
157 		};
158 		
159 		sandbox.status = sandbox.setStatus = function(message) {
160 			var r;
161 			if (controller.messageHandler) {
162 				r = controller.messageHandler.call(self, 'status', message);
163 			}
164 			if (r!==false) {
165 				puredom.log('tests["'+testObj.name+'"] >> ' + message);
166 			}
167 		};
168 		sandbox.log = sandbox.postMessage = function(message) {
169 			var r;
170 			if (controller.messageHandler) {
171 				r = controller.messageHandler.call(self, 'log', message);
172 			}
173 			if (r!==false) {
174 				puredom.log('tests["'+testObj.name+'"] >> ' + message);
175 			}
176 		};
177 		sandbox.done = sandbox.finish = sandbox.complete = function(results) {
178 			if (controller.onfinish) {
179 				setTimeout(function() {
180 					if (controller.messageHandler) {
181 						controller.messageHandler.call(self, 'status', results);
182 					}
183 					if (controller.onfinish) {
184 						controller.onfinish.call(self,results);
185 					}
186 					results = null;
187 				}, 1);
188 			}
189 		};
190 		sandbox.pass = function(results) {
191 			if (controller.messageHandler) {
192 				controller.messageHandler.call(self, 'result', true);
193 			}
194 			if (controller.onpass) {
195 				controller.onpass.call(self, true);
196 			}
197 			sandbox.done(results);
198 		};
199 		sandbox.fail = function(results) {
200 			if (controller.messageHandler) {
201 				controller.messageHandler.call(self, 'result', false);
202 			}
203 			if (controller.onfail) {
204 				controller.onfail.call(self, fail);
205 			}
206 			sandbox.done(results);
207 		};
208 		
209 		return controller;
210 	},
211 	
212 
213 	/** @private */
214 	list : {}
215 
216 });