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.
234 lines
6.0 KiB
234 lines
6.0 KiB
'use strict'; |
|
|
|
var common = require('./common'); |
|
var EventEmitter = require('../').EventEmitter; |
|
var once = require('../').once; |
|
var has = require('has'); |
|
var assert = require('assert'); |
|
|
|
function Event(type) { |
|
this.type = type; |
|
} |
|
|
|
function EventTargetMock() { |
|
this.events = {}; |
|
|
|
this.addEventListener = common.mustCall(this.addEventListener); |
|
this.removeEventListener = common.mustCall(this.removeEventListener); |
|
} |
|
|
|
EventTargetMock.prototype.addEventListener = function addEventListener(name, listener, options) { |
|
if (!(name in this.events)) { |
|
this.events[name] = { listeners: [], options: options || {} } |
|
} |
|
this.events[name].listeners.push(listener); |
|
}; |
|
|
|
EventTargetMock.prototype.removeEventListener = function removeEventListener(name, callback) { |
|
if (!(name in this.events)) { |
|
return; |
|
} |
|
var event = this.events[name]; |
|
var stack = event.listeners; |
|
|
|
for (var i = 0, l = stack.length; i < l; i++) { |
|
if (stack[i] === callback) { |
|
stack.splice(i, 1); |
|
if (stack.length === 0) { |
|
delete this.events[name]; |
|
} |
|
return; |
|
} |
|
} |
|
}; |
|
|
|
EventTargetMock.prototype.dispatchEvent = function dispatchEvent(arg) { |
|
if (!(arg.type in this.events)) { |
|
return true; |
|
} |
|
|
|
var event = this.events[arg.type]; |
|
var stack = event.listeners.slice(); |
|
|
|
for (var i = 0, l = stack.length; i < l; i++) { |
|
stack[i].call(null, arg); |
|
if (event.options.once) { |
|
this.removeEventListener(arg.type, stack[i]); |
|
} |
|
} |
|
return !arg.defaultPrevented; |
|
}; |
|
|
|
function onceAnEvent() { |
|
var ee = new EventEmitter(); |
|
|
|
process.nextTick(function () { |
|
ee.emit('myevent', 42); |
|
}); |
|
|
|
return once(ee, 'myevent').then(function (args) { |
|
var value = args[0] |
|
assert.strictEqual(value, 42); |
|
assert.strictEqual(ee.listenerCount('error'), 0); |
|
assert.strictEqual(ee.listenerCount('myevent'), 0); |
|
}); |
|
} |
|
|
|
function onceAnEventWithTwoArgs() { |
|
var ee = new EventEmitter(); |
|
|
|
process.nextTick(function () { |
|
ee.emit('myevent', 42, 24); |
|
}); |
|
|
|
return once(ee, 'myevent').then(function (value) { |
|
assert.strictEqual(value.length, 2); |
|
assert.strictEqual(value[0], 42); |
|
assert.strictEqual(value[1], 24); |
|
}); |
|
} |
|
|
|
function catchesErrors() { |
|
var ee = new EventEmitter(); |
|
|
|
var expected = new Error('kaboom'); |
|
var err; |
|
process.nextTick(function () { |
|
ee.emit('error', expected); |
|
}); |
|
|
|
return once(ee, 'myevent').then(function () { |
|
throw new Error('should reject') |
|
}, function (err) { |
|
assert.strictEqual(err, expected); |
|
assert.strictEqual(ee.listenerCount('error'), 0); |
|
assert.strictEqual(ee.listenerCount('myevent'), 0); |
|
}); |
|
} |
|
|
|
function stopListeningAfterCatchingError() { |
|
var ee = new EventEmitter(); |
|
|
|
var expected = new Error('kaboom'); |
|
var err; |
|
process.nextTick(function () { |
|
ee.emit('error', expected); |
|
ee.emit('myevent', 42, 24); |
|
}); |
|
|
|
// process.on('multipleResolves', common.mustNotCall()); |
|
|
|
return once(ee, 'myevent').then(common.mustNotCall, function (err) { |
|
// process.removeAllListeners('multipleResolves'); |
|
assert.strictEqual(err, expected); |
|
assert.strictEqual(ee.listenerCount('error'), 0); |
|
assert.strictEqual(ee.listenerCount('myevent'), 0); |
|
}); |
|
} |
|
|
|
function onceError() { |
|
var ee = new EventEmitter(); |
|
|
|
var expected = new Error('kaboom'); |
|
process.nextTick(function () { |
|
ee.emit('error', expected); |
|
}); |
|
|
|
var promise = once(ee, 'error'); |
|
assert.strictEqual(ee.listenerCount('error'), 1); |
|
return promise.then(function (args) { |
|
var err = args[0] |
|
assert.strictEqual(err, expected); |
|
assert.strictEqual(ee.listenerCount('error'), 0); |
|
assert.strictEqual(ee.listenerCount('myevent'), 0); |
|
}); |
|
} |
|
|
|
function onceWithEventTarget() { |
|
var et = new EventTargetMock(); |
|
var event = new Event('myevent'); |
|
process.nextTick(function () { |
|
et.dispatchEvent(event); |
|
}); |
|
return once(et, 'myevent').then(function (args) { |
|
var value = args[0]; |
|
assert.strictEqual(value, event); |
|
assert.strictEqual(has(et.events, 'myevent'), false); |
|
}); |
|
} |
|
|
|
function onceWithEventTargetError() { |
|
var et = new EventTargetMock(); |
|
var error = new Event('error'); |
|
process.nextTick(function () { |
|
et.dispatchEvent(error); |
|
}); |
|
return once(et, 'error').then(function (args) { |
|
var err = args[0]; |
|
assert.strictEqual(err, error); |
|
assert.strictEqual(has(et.events, 'error'), false); |
|
}); |
|
} |
|
|
|
function prioritizesEventEmitter() { |
|
var ee = new EventEmitter(); |
|
ee.addEventListener = assert.fail; |
|
ee.removeAllListeners = assert.fail; |
|
process.nextTick(function () { |
|
ee.emit('foo'); |
|
}); |
|
return once(ee, 'foo'); |
|
} |
|
|
|
var allTests = [ |
|
onceAnEvent(), |
|
onceAnEventWithTwoArgs(), |
|
catchesErrors(), |
|
stopListeningAfterCatchingError(), |
|
onceError(), |
|
onceWithEventTarget(), |
|
onceWithEventTargetError(), |
|
prioritizesEventEmitter() |
|
]; |
|
|
|
var hasBrowserEventTarget = false; |
|
try { |
|
hasBrowserEventTarget = typeof (new window.EventTarget().addEventListener) === 'function' && |
|
new window.Event('xyz').type === 'xyz'; |
|
} catch (err) {} |
|
|
|
if (hasBrowserEventTarget) { |
|
var onceWithBrowserEventTarget = function onceWithBrowserEventTarget() { |
|
var et = new window.EventTarget(); |
|
var event = new window.Event('myevent'); |
|
process.nextTick(function () { |
|
et.dispatchEvent(event); |
|
}); |
|
return once(et, 'myevent').then(function (args) { |
|
var value = args[0]; |
|
assert.strictEqual(value, event); |
|
assert.strictEqual(has(et.events, 'myevent'), false); |
|
}); |
|
} |
|
|
|
var onceWithBrowserEventTargetError = function onceWithBrowserEventTargetError() { |
|
var et = new window.EventTarget(); |
|
var error = new window.Event('error'); |
|
process.nextTick(function () { |
|
et.dispatchEvent(error); |
|
}); |
|
return once(et, 'error').then(function (args) { |
|
var err = args[0]; |
|
assert.strictEqual(err, error); |
|
assert.strictEqual(has(et.events, 'error'), false); |
|
}); |
|
} |
|
|
|
common.test.comment('Testing with browser built-in EventTarget'); |
|
allTests.push([ |
|
onceWithBrowserEventTarget(), |
|
onceWithBrowserEventTargetError() |
|
]); |
|
} |
|
|
|
module.exports = Promise.all(allTests);
|
|
|