Skip to content

Commit

Permalink
(feat) add Cleanup clause
Browse files Browse the repository at this point in the history
this commit is a experimental solution to issue #4
each `Cleanup` is ensured to be executed no matter previous clauses pass or fail.
  • Loading branch information
cades committed Jul 13, 2016
1 parent 63f68b6 commit 9727490
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
12 changes: 11 additions & 1 deletion lib/block-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ var BlockManager = {
whens: [],
thens: [],
invariants: [],
ands: []
ands: [],
cleanups: []
})
},
exit: function() { this._blockStack.pop() },
Expand All @@ -26,6 +27,7 @@ var BlockManager = {
addThenToCurrent: function(fn) { this.current().thens.push(fn) },
addInvariantToCurrent: function(fn) { this.current().invariants.push(fn) },
addAndToCurrent: function(fn) { this.current().ands.push(fn) },
addCleanupToCurrent: function(fn) { this.current().cleanups.push(fn) },

allGivens: function() {
return this._collectAllClausesBy(function(blk){ return blk.givens })
Expand All @@ -42,6 +44,14 @@ var BlockManager = {
currentAnds: function() {
return this.current().ands
},
snapshot: function() {
var cleanupRefs = this._blockStack.toArray().map(function(blk){ return blk.cleanups })
return {
allCleanups: function() {
return cleanupRefs.reduceRight(concat)
}
}
},
_collectAllClausesBy: function(fn) {
return this._blockStack.toArray().map(fn).reduceRight(concat)
}
Expand Down
21 changes: 20 additions & 1 deletion lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ function createCore(opts, blockManager) {
givens = blockManager.allGivens(),
whens = blockManager.allWhens(),
invariants = blockManager.allInvariants(),
ands = blockManager.currentAnds() // keep reference at this moment. `ands` is a empty array at this moment
ands = blockManager.currentAnds(), // keep reference at this moment. `ands` is a empty array at this moment
snapshot = blockManager.snapshot()

blockManager.addThenToCurrent(thenFn)

Expand All @@ -212,6 +213,7 @@ function createCore(opts, blockManager) {
.then(runExpectations)
.then(function(res){ done() })
.catch(done)
.then(runCleanups)

function runPreparations() {
return sequencialExecute(givens.concat(whens), function(fn) {
Expand All @@ -231,6 +233,18 @@ function createCore(opts, blockManager) {
})
}

function runCleanups() {
var cleanups = snapshot.allCleanups()
return sequencialExecute(cleanups, function(fn) {
function noop() {}
if (fn.length > 0)
return toPromise(fn.bind(ctx)).catch(noop)
return Promise.resolve().then(function(){
return fn.call(ctx)
}).catch(noop)
})
}

function goodHabitGuard(fn) {
if (isGoodHabitModeEnabled() && fn.length > 0)
throw new GoodHabitViolationError('async ' + fn._keyword + ' is discouraged')
Expand Down Expand Up @@ -303,6 +317,10 @@ function createCore(opts, blockManager) {
blockManager.addAndToCurrent(fn)
}

function Cleanup(fn) {
blockManager.addCleanupToCurrent(fn)
}

function createFnFromArgs(args, opts) {
opts = opts || {}
var fn = u.findFirstThatIsFunction(args)
Expand All @@ -326,6 +344,7 @@ function createCore(opts, blockManager) {
Then: Then,
Invariant: Invariant,
And: And,
Cleanup: Cleanup,

ThenError: ThenError,
ThenFail: ThenFail,
Expand Down
1 change: 1 addition & 0 deletions mocha/register-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module.exports = function(Mocha, Suite, Test) {
context.Then = core.Then
context.Invariant = core.Invariant
context.And = core.And
context.Cleanup = core.Cleanup
context.Then.skip = context.xit
context.Failure = core.Failure

Expand Down
44 changes: 44 additions & 0 deletions test/1SAFE/cleanup_spec.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
expect = require 'expect.js'

describe "Cleanup(fn)", ->

describe "cleanup is run", ->

context 'when Then pass', ->
info = []
Then -> 'pass'
And -> info.push 'A'
Cleanup -> info.push "C"

describe "verify", ->
Then -> expect(["A", "C"]).to.eql info

context 'when Then fail', ->
info = []
ThenFail -> false
And -> info.push 'A'
Cleanup -> info.push "C"

describe "verify", ->
Then -> expect(["C"]).to.eql info

context 'when other Cleanup fail', ->
info = []
ThenFail -> false
Cleanup -> throw new Error 'oops!'
Cleanup -> info.push "C"

describe "verify", ->
Then -> expect(["C"]).to.eql info

describe "with nested cleanups", ->
info = []
Cleanup -> info.push "C-OUTER"

context "inner", ->
Then -> info.push "T-INNER"
And -> info.push "A-INNER"
Cleanup -> info.push "C-INNER"

context "verify", ->
Then -> expect(info).to.eql ["T-INNER", "A-INNER", "C-OUTER", "C-INNER"]

0 comments on commit 9727490

Please sign in to comment.