You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

434 lines
11 KiB

var Q = require('../kew')
var originalQ = require('q')
// test that fin() works with a synchronous resolve
exports.testSynchronousThenAndFin = function (test) {
var vals = ['a', 'b']
var counter = 0
var promise1 = Q.resolve(vals[0])
var promise2 = promise1.fin(function () {
counter++
})
var promise3 = promise2.then(function (data) {
if (data === vals[0]) return vals[1]
})
var promise4 = promise3.fin(function () {
counter++
})
Q.all([promise2, promise4])
.then(function (data) {
test.equal(counter, 2, "fin() should have been called twice")
test.equal(data[0], vals[0], "first fin() should return the first val")
test.equal(data[1], vals[1], "second fin() should return the second val")
test.done()
})
}
// test that fin() works with a synchronous reject
exports.testSynchronousFailAndFin = function (test) {
var errs = []
errs.push(new Error('nope 1'))
errs.push(new Error('nope 2'))
var counter = 0
var promise1 = Q.reject(errs[0])
var promise2 = promise1.fin(function () {
counter++
})
var promise3 = promise2.fail(function (e) {
if (e === errs[0]) throw errs[1]
})
var promise4 = promise3.fin(function () {
counter++
})
Q.all([
promise2.fail(function (e) {
return e === errs[0]
}),
promise4.fail(function (e) {
return e === errs[1]
})
])
.then(function (data) {
test.equal(counter, 2, "fin() should have been called twice")
test.equal(data[0] && data[1], true, "all promises should return true")
test.done()
})
}
// test that fin() works with an asynchrnous resolve
exports.testAsynchronousThenAndFin = function (test) {
var vals = ['a', 'b']
var counter = 0
var defer = Q.defer()
setTimeout(function () {
defer.resolve(vals[0])
})
var promise1 = defer.promise
var promise2 = promise1.fin(function () {
counter++
})
var promise3 = promise2.then(function (data) {
if (data !== vals[0]) return
var defer = Q.defer()
setTimeout(function () {
defer.resolve(vals[1])
})
return defer.promise
})
var promise4 = promise3.fin(function () {
counter++
})
Q.all([promise2, promise4])
.then(function (data) {
test.equal(counter, 2, "fin() should have been called twice")
test.equal(data[0], vals[0], "first fin() should return the first val")
test.equal(data[1], vals[1], "second fin() should return the second val")
test.done()
})
}
// test that fin() works with an asynchronous reject
exports.testAsynchronousFailAndFin = function (test) {
var errs = []
errs.push(new Error('nope 1'))
errs.push(new Error('nope 2'))
var counter = 0
var defer = Q.defer()
setTimeout(function () {
defer.reject(errs[0])
}, 10)
var promise1 = defer.promise
var promise2 = promise1.fin(function () {
counter++
})
var promise3 = promise2.fail(function (e) {
if (e !== errs[0]) return
var defer = Q.defer()
setTimeout(function () {
defer.reject(errs[1])
}, 10)
return defer.promise
})
var promise4 = promise3.fin(function () {
counter++
})
Q.all([
promise2.fail(function (e) {
return e === errs[0]
}),
promise4.fail(function (e) {
return e === errs[1]
})
])
.then(function (data) {
test.equal(counter, 2, "fin() should have been called twice")
test.equal(data[0] && data[1], true, "all promises should return true")
test.done()
})
}
// test several thens chaining
exports.testChainedThens = function (test) {
var promise1 = Q.resolve('a')
var promise2 = promise1.then(function(data) {
return data + 'b'
})
var promise3 = promise2.then(function (data) {
return data + 'c'
})
// testing the same promise again to make sure they can run side by side
var promise4 = promise2.then(function (data) {
return data + 'c'
})
Q.all([promise1, promise2, promise3, promise4])
.then(function (data) {
test.equal(data[0], 'a')
test.equal(data[1], 'ab')
test.equal(data[2], 'abc')
test.equal(data[3], 'abc')
test.done()
})
}
// test several fails chaining
exports.testChainedFails = function (test) {
var errs = []
errs.push(new Error("first err"))
errs.push(new Error("second err"))
errs.push(new Error("third err"))
var promise1 = Q.reject(errs[0])
var promise2 = promise1.fail(function (e) {
if (e === errs[0]) throw errs[1]
})
var promise3 = promise2.fail(function (e) {
if (e === errs[1]) throw errs[2]
})
var promise4 = promise2.fail(function (e) {
if (e === errs[1]) throw errs[2]
})
Q.all([
promise1.fail(function (e) {
return e === errs[0]
}),
promise2.fail(function (e) {
return e === errs[1]
}),
promise3.fail(function (e) {
return e === errs[2]
}),
promise4.fail(function (e) {
return e === errs[2]
})
])
.then(function (data) {
test.equal(data[0] && data[1] && data[2] && data[3], true)
test.done()
})
}
// test that we can call end without callbacks and not fail
exports.testEndNoCallbacks = function (test) {
Q.resolve(true).end()
test.ok("Ended successfully")
test.done()
}
// test that we can call end with callbacks and fail
exports.testEndNoCallbacksThrows = function (test) {
var testError = new Error('Testing')
try {
Q.reject(testError).end()
test.fail("Should throw an error")
} catch (e) {
test.equal(e, testError, "Should throw the correct error")
}
test.done()
}
// test chaining when a promise returns a promise
exports.testChainedPromises = function (test) {
var err = new Error('nope')
var val = 'ok'
var shouldFail = Q.reject(err)
var shouldSucceed = Q.resolve(val)
Q.resolve("start")
.then(function () {
return shouldFail
})
.fail(function (e) {
if (e === err) return shouldSucceed
else throw e
})
.then(function (data) {
test.equal(data, val, "val should be returned")
test.done()
})
}
// test .end() is called with no parent scope (causing an uncaught exception)
exports.testChainedEndUncaught = function (test) {
var uncaughtErrors = 0
var errs = []
errs.push(new Error('nope 1'))
errs.push(new Error('nope 2'))
errs.push(new Error('nope 3'))
var cb = function (e) {
uncaughtErrors++
if (e === errs[2]) {
test.equal(uncaughtErrors, 3, "Errors should be uncaught")
process.removeListener('uncaughtException', cb)
test.done()
}
}
process.on('uncaughtException', cb)
var defer = Q.defer()
defer.promise.end()
var promise1 = defer.promise
var promise2 = promise1.fail(function (e) {
if (e === errs[0]) throw errs[1]
})
var promise3 = promise2.fail(function (e) {
if (e === errs[1]) throw errs[2]
})
promise1.end()
promise2.end()
promise3.end()
setTimeout(function () {
defer.reject(errs[0])
}, 10)
}
// test .end() is called with a parent scope and is caught
exports.testChainedCaught = function (test) {
var err = new Error('nope')
try {
Q.reject(err).end()
} catch (e) {
test.equal(e, err, "Error should be caught")
test.done()
}
}
// test a mix of fails and thens
exports.testChainedMixed = function (test) {
var errs = []
errs.push(new Error('nope 1'))
errs.push(new Error('nope 2'))
errs.push(new Error('nope 3'))
var vals = [3, 2, 1]
var promise1 = Q.reject(errs[0])
var promise2 = promise1.fail(function (e) {
if (e === errs[0]) return vals[0]
})
var promise3 = promise2.then(function (data) {
if (data === vals[0]) throw errs[1]
})
var promise4 = promise3.fail(function (e) {
if (e === errs[1]) return vals[1]
})
var promise5 = promise4.then(function (data) {
if (data === vals[1]) throw errs[2]
})
var promise6 = promise5.fail(function (e) {
if (e === errs[2]) return vals[2]
})
Q.all([
promise1.fail(function (e) {
return e === errs[0]
}),
promise2.then(function (data) {
return data === vals[0]
}),
promise3.fail(function (e) {
return e === errs[1]
}),
promise4.then(function (data) {
return data === vals[1]
}),
promise5.fail(function (e) {
return e === errs[2]
}),
promise6.then(function (data) {
return data === vals[2]
})
])
.then(function (data) {
test.equal(data[0] && data[1] && data[2] && data[3] && data[4] && data[5], true, "All values should return true")
test.done()
})
}
exports.testInteroperabilityWithOtherPromises = function(test) {
var promise1 = Q.defer()
promise1.then(function(value) {
return originalQ(1 + value)
}).then(function(result) {
test.equal(result, 11)
})
var promise2 = Q.defer(),
errToThrow = new Error('error')
promise2.then(function() {
return originalQ.reject(errToThrow)
}).fail(function(err) {
test.equal(err, errToThrow)
})
promise1.resolve(10)
promise2.resolve()
Q.all([promise1, promise2]).then(function() {
test.done()
})
}
exports.testAllSettled = function(test) {
var promise1 = Q.resolve('woot')
var promise2 = Q.reject(new Error('oops'))
Q.allSettled([promise1, promise2, 'just a string'])
.then(function (data) {
test.equals('fulfilled', data[0].state)
test.equals('woot', data[0].value)
test.equals('rejected', data[1].state)
test.equals('oops', data[1].reason.message)
test.equals('fulfilled', data[2].state)
test.equals('just a string', data[2].value)
})
Q.allSettled([])
.then(function (data) {
test.equals(0, data.length)
test.done()
})
}
exports.testTimeout = function(test) {
var promise = Q.delay(50).timeout(45, 'Timeout message')
promise.then(function () {
test.fail('The promise is supposed to be timeout')
})
.fail(function (e) {
test.equals('Timeout message', e.message, 'The error message should be the one passed into timeout()')
})
.fin(test.done)
}
exports.testNotTimeout = function(test) {
var promise = Q.delay('expected data', 40).timeout(45, 'Timeout message')
promise.then(function (data) {
test.equals('expected data', data, 'The data should be the data from the original promise')
})
.fail(function (e) {
test.fail('The promise is supposed to be resolved before the timeout')
})
.fin(test.done)
}
exports.testNotTimeoutButReject = function(test) {
var promise = Q.delay(40).then(function() {throw new Error('Reject message')}).timeout(45, 'Timeout message')
promise.then(function (data) {
test.fail('The promise is supposed to be rejected')
})
.fail(function (e) {
test.equals('Reject message', e.message, 'The error message should be from the original promise')
})
.fin(test.done)
}
exports.testDelay = function (test) {
var timePassed = false
setTimeout(function () {
timePassed = true
}, 10)
Q.resolve('expected').delay(20).then(function (result) {
test.equal('expected', result)
test.ok(timePassed)
test.done()
})
}