Last active
November 3, 2015 18:16
-
-
Save mildmojo/c5753466efd74cb0622a to your computer and use it in GitHub Desktop.
Jasmine-node helpers: per-describe `setup` and `teardown` functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
setup_teardown_helper.js | |
Setup and teardown helper functions for jasmine-node (jasmine 1.3). | |
IMNSHO, every damn test runner should provide the following hooks: | |
startup (global; runs once before any setups or specs begin) | |
setup (describe-local; runs once before any specs in a `describe`) | |
beforeEach (describe-local; runs once before each spec in a `describe`) | |
afterEach (describe-local; runs once after each spec in a `describe`) | |
teardown (describe-local; runs once after all specs in a `describe`) | |
shutdown (global; runs once after all specs and teardowns are finished) | |
This helper adds jasmine-node `setup` and `teardown` helpers to do work | |
before any specs and after all specs, respectively (ha!), inside a | |
`describe` block. | |
Jasmine-node looks for these helper scripts in a directory that ends in | |
'helper' or 'helpers' in the spec dir or spec parent dir (I think). | |
*/ | |
(function(){ | |
var specCounters = {}; | |
// Monkeypatch `it` to keep track of how many specs are in the current `describe`. | |
var originalIt = jasmine.Env.prototype.it; | |
jasmine.Env.prototype.it = function() { | |
var suiteName = getSuiteName(); | |
specCounters[suiteName] = specCounters[suiteName] || 0; | |
specCounters[suiteName]++; | |
originalIt.apply(this, arguments); | |
}; | |
// Run the function argument once before any specs in this `describe` block. | |
// Timeout is an optional override. | |
global.setup = function(setupFunc, timeout) { | |
setupFunc._name = setupFunc.name || 'setup'; | |
var wasCalled = false; | |
this.beforeEach(function() { | |
if (wasCalled) return; | |
asyncify(setupFunc, timeout).call(null, function setupDone() { | |
// Add code here if you need to do elapsed time or something. | |
}); | |
wasCalled = true; | |
}); | |
}; | |
// Run the function argument once after all specs in this `describe` block. | |
// Timeout is an optional override. | |
global.teardown = function(teardownFunc, timeout) { | |
teardownFunc._name = teardownFunc.name || 'teardown'; | |
this.afterEach(function() { | |
if (--specCounters[getSuiteName()] > 0) return; | |
asyncify(teardownFunc, timeout).call(null, function teardownDone() { | |
// Add code here if you need to do elapsed time or something. | |
}); | |
}); | |
}; | |
// If `func` is sync, return it as an async function with one callback arg. | |
// If `func` is async, wrap it in jasmine runs/waitsFor and return it. | |
// Resulting function *can* be called synchronously. | |
function asyncify(func, timeout) { | |
var funcIsAsync = !!func.length; | |
function asyncWrapper(done) { | |
var isFinished = false; | |
var resultArgs; | |
runs(function runFunc() { | |
if (funcIsAsync) { | |
func.call(null, function() { | |
resultArgs = Array.prototype.slice.call(arguments); | |
isFinished = true; | |
}); | |
} else { | |
resultArgs = func.call(); | |
resultArgs = [].concat(resultArgs); | |
isFinished = true; | |
} | |
}); | |
var waitingForMsg = 'function `' + (func.name || func._name) + '` to finish'; | |
waitsFor(waitingForMsg, function() { return isFinished; }, timeout); | |
runs(function() { | |
if (typeof done === 'function') done.apply(null, resultArgs); | |
}); | |
}; | |
return asyncWrapper; | |
} | |
function getSuiteName() { | |
var env = jasmine.getEnv(); | |
var currentSuiteDesc = env.currentSuite && env.currentSuite.description; | |
var currentSpecSuiteDesc = env.currentSpec && env.currentSpec.suite.description; | |
return currentSuiteDesc || currentSpecSuiteDesc; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment