')
.html(
'Passed: ' + keys(passed).length
+ ' — Failed:
' + keys(failed).length
+ ' — Elapsed:
' + elapsed
+ ' seconds — '
)
.append(
$('
Show details')
.attr('href', '#')
.click(function () {
li.toggleClass('cases');
$(this).text(
li.hasClass('cases')
? 'Hide details'
: 'Show details'
);
return false;
})
)
);
var casesUl = $('
').appendTo(li);
for (var i = 0, l = cases.length; i < l; i++) {
var detail = $('- ')
.text(cases[i])
.addClass(failed[cases[i]] ? 'failed' : '')
.appendTo(casesUl);
if (failed[cases[i]]) {
if (window.console && console.log) {
console.log(failed[cases[i]]);
}
detail.append($('').text(String(failed[cases[i]])));
}
}
// fire callback
fn({
status: ok
, passed: passed
, failed: failed
});
};
var cases = keys(suite)
, i = 0;
if (!cases.length) {
return complete();
}
currentCase = cases[i];
test(suite[cases[i]], function check (err) {
if (err) {
failed[cases[i]] = err;
} else {
passed[cases[i]] = true;
}
if (cases[++i]) {
currentCase = cases[i];
test(suite[cases[i]], check);
} else {
complete();
}
});
});
};
// runs a test
function test (testcase, fn) {
var timer;
window.onerror = function (err) {
complete(err);
};
function complete (err) {
if (complete.run) return;
if (timer) clearTimeout(timer);
complete.run = true;
window.onerror = null;
fn(err);
};
try {
if (testcase.length > 0) {
var timer = setTimeout(function () {
complete(new Error('Timeout'));
}, 2000);
testcase(complete);
} else {
testcase();
complete();
}
} catch (e) {
complete(e);
}
};
// exposes a function to easily create a server for the current test
function create (nsp) {
if (!testsPorts[currentSuite]) {
throw new Error('No socket server defined for suite "' + currentSuite + '"');
}
if (!testsPorts[currentSuite][currentCase]) {
throw new Error('No socket server defined for suite "' + currentSuite
+ '" and case "' + currentCase + '"');
}
return io.connect(
document.location.protocol + '//' + document.location.hostname
+ ':' + testsPorts[currentSuite][currentCase] + (nsp || '')
);
};