// Class: Loki.Runner
// Runs Crucible tests.
Loki.Runner = Loki.Class.create({
	tests: null,
	
	events: null,
	
	// Constructor: Runner
	// Creates a new test runner.
	//
	// Parameters:
	//     (Crucible.Test[]) tests - the tests to be run
	initialize: function Runner(tests) {
		this.tests = tests;
		
		this.events = {
			run: new Crucible.Delegator("test started"),
			pass: new Crucible.Delegator("test passed"),
			fail: new Crucible.Delegator("test failed"),
			exception: new Crucible.Delegator("test threw an exception"),
			result: new Crucible.Delegator("test finished"),
			finish: new Crucible.Delegator("finished testing")
		};
	}
});

@@ -3,20 +3,24 @@
  Class: 
-Loki
+Crucible
 .Runner%0A
@@ -43,20 +43,24 @@
  tests.%0A
-Loki
+Crucible
 .Runner 
@@ -65,12 +65,16 @@
 r = 
-Loki
+Crucible
 .Cla
@@ -85,16 +85,32 @@
 reate(%7B%0A
+%09product: null,%0A
 %09tests: 
@@ -292,16 +292,25 @@
  Runner(
+product, 
 tests) %7B
@@ -321,43 +321,205 @@
 his.
-tests = tests;%0A%09%09%0A%09%09this.events = %7B
+product = product %7C%7C '(unknown product)';%0A%09%09this.tests = %5B%5D;%0A%09%09if (tests) %7B%0A%09%09%09Crucible.forEach(tests, this.add, this);%0A%09%09%7D%0A%09%09%0A%09%09this.events = %7B%0A%09%09%09start: new Crucible.Delegator(%22started testing%22),
 %0A%09%09%09
@@ -835,15 +835,1055 @@
 %22)%0A%09%09%7D;%0A
+%09%7D,%0A%09%0A%09// Method: add%0A%09// Adds a test to the runner.%0A%09//%0A%09// Parameters:%0A%09//     (Crucible.Test) test - the test to add%0A%09add: function add_to_runner(test) %7B%0A%09%09test.events.result.add(this, '_processResult');%0A%09%09this.tests.push(test);%0A%09%7D,%0A%09%0A%09// Method: run%0A%09// Runs the tests.%0A%09run: function run_tests() %7B%0A%09%09if (this.running) %7B%0A%09%09%09throw new Error('Already running!');%0A%09%09%7D%0A%09%09%0A%09%09this.queue = this.tests.slice(0); // clone%0A%09%09this.queue.reverse();%0A%09%09this.running = true;%0A%09%09%0A%09%09this.events.start.call();%0A%09%09this._runTest();%0A%09%7D,%0A%09%0A%09_runTest: function _runner_run_test() %7B%0A%09%09if (this.queue.length == 0) %7B%0A%09%09%09this.events.finish.call();%0A%09%09%09this.running = false;%0A%09%09%09delete this.queue;%0A%09%09%09return;%0A%09%09%7D%0A%09%09%0A%09%09var test = this.queue.pop();%0A%09%09this.events.run.call(test);%0A%09%09Crucible.defer(function() %7B%0A%09%09%09test.run();%0A%09%09%7D);%0A%09%7D,%0A%09%0A%09_processResult: function _process_test_result(test, status, result) %7B%0A%09%09this.events%5Bstatus%5D.call(test, result %7C%7C null);%0A%09%09this.events.result.call(test, status, result %7C%7C null);%0A%09%09Crucible.defer(function() %7B%0A%09%09%09this._runTest();%0A%09%09%7D);%0A
 %09%7D%0A%7D);%0A

Implement Runner.