Comparing version 1.1.2 to 1.2.0
@@ -21,3 +21,3 @@ # EventsHub | ||
events.on('my-event', () => { | ||
console.log('The event listener was called!); | ||
console.log('The event listener was called!'); | ||
}); | ||
@@ -47,2 +47,25 @@ // Emit the event | ||
And you can even use the same listener for multiple events: | ||
```js | ||
// Add the listener | ||
events.on(['logout-route', 'unauthorized-request'], () => { | ||
someAuthService.signout(); | ||
}); | ||
... | ||
events.emit('logout-route'); | ||
// or | ||
someRequest() | ||
.then(() => ... ) | ||
.catch((error) => { | ||
if (error.code === 401) { | ||
events.emit('unauthorized-request'); | ||
} | ||
}) | ||
``` | ||
> All methods that support an event name also support an `Array` with a list of them. | ||
### Reduce a variable | ||
@@ -49,0 +72,0 @@ |
{ | ||
"name": "wootils", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "A set of Javascript utilities for building Node and browser apps.", | ||
"homepage": "https://homer0.github.io/wootils/", | ||
"scripts": { | ||
"install-hooks": "./utils/hooks/install", | ||
"hooks": "./utils/hooks/install", | ||
"test": "./utils/scripts/test", | ||
@@ -9,0 +9,0 @@ "lint": "./utils/scripts/lint", |
@@ -106,3 +106,3 @@ # Wootils | ||
# You can either use npm or yarn, it doesn't matter | ||
npm run install-hooks | ||
yarn run hooks | ||
``` | ||
@@ -112,10 +112,10 @@ | ||
| Task | Description | | ||
|-------------------------|-------------------------------------| | ||
| `npm run install-hooks` | Install the GIT repository hooks. | | ||
| `npm test` | Run the project unit tests. | | ||
| `npm run lint` | Lint the modified files. | | ||
| `npm run lint:full` | Lint the project code. | | ||
| `npm run docs` | Generate the project documentation. | | ||
| `npm run todo` | List all the pending to-do's. | | ||
| Task | Description | | ||
|--------------------------|-------------------------------------| | ||
| `yarn run install-hooks` | Install the GIT repository hooks. | | ||
| `yarn test` | Run the project unit tests. | | ||
| `yarn run lint` | Lint the modified files. | | ||
| `yarn run lint:full` | Lint the project code. | | ||
| `yarn run docs` | Generate the project documentation. | | ||
| `yarn run todo` | List all the pending to-do's. | | ||
@@ -122,0 +122,0 @@ ### Testing |
@@ -19,11 +19,14 @@ /** | ||
* Adds a new event listener. | ||
* @param {String} event The name of the event. | ||
* @param {Function} fn The listener function. | ||
* @return {Function} An unsubscribe function to remove the listener. | ||
* @param {String|Array} event An event name or a list of them. | ||
* @param {Function} fn The listener function. | ||
* @return {Function} An unsubscribe function to remove the listener or listeners. | ||
*/ | ||
on(event, fn) { | ||
const subscribers = this.subscribers(event); | ||
if (!subscribers.includes(fn)) { | ||
subscribers.push(fn); | ||
} | ||
const events = Array.isArray(event) ? event : [event]; | ||
events.forEach((name) => { | ||
const subscribers = this.subscribers(name); | ||
if (!subscribers.includes(fn)) { | ||
subscribers.push(fn); | ||
} | ||
}); | ||
@@ -34,4 +37,4 @@ return () => this.off(event, fn); | ||
* Adds an event listener that will only be executed once. | ||
* @param {String} event The name of the event. | ||
* @param {Function} fn The listener function. | ||
* @param {String|Array} event An event name or a list of them. | ||
* @param {Function} fn The listener function. | ||
* @return {Function} An unsubscribe function to remove the listener. | ||
@@ -46,32 +49,46 @@ */ | ||
* Removes an event listener. | ||
* @param {String} event The name of the event. | ||
* @param {Function} fn The listener function. | ||
* @return {Boolean} Whether or not the listener was found and removed. | ||
* @param {String|Array} event An event name or a list of them. | ||
* @param {Function} fn The listener function. | ||
* @return {Boolean|Array} If `event` was a `string`, it will return whether or not the listener | ||
* was found and removed; but if `event` was an `Array`, it will return | ||
* a list of boolean values. | ||
*/ | ||
off(event, fn) { | ||
const subscribers = this.subscribers(event); | ||
const index = subscribers.indexOf(fn); | ||
let result = false; | ||
if (index > -1) { | ||
result = true; | ||
subscribers.splice(index, 1); | ||
} | ||
const isArray = Array.isArray(event); | ||
const events = isArray ? event : [event]; | ||
const result = events.map((name) => { | ||
const subscribers = this.subscribers(name); | ||
let found = false; | ||
const index = subscribers.indexOf(fn); | ||
if (index > -1) { | ||
found = true; | ||
subscribers.splice(index, 1); | ||
} | ||
return result; | ||
return found; | ||
}); | ||
return isArray ? result : result[0]; | ||
} | ||
/** | ||
* Emits an event and call all its listeners. | ||
* @param {String} event The name of the event. | ||
* @param {Array} args A list of parameters to send to the listeners. | ||
* @param {String|Array} event An event name or a list of them. | ||
* @param {Array} args A list of parameters to send to the listeners. | ||
*/ | ||
emit(event, ...args) { | ||
const toClean = []; | ||
this.subscribers(event).forEach((subscriber) => { | ||
subscriber(...args); | ||
if (subscriber.once) { | ||
toClean.push(subscriber); | ||
} | ||
const events = Array.isArray(event) ? event : [event]; | ||
events.forEach((name) => { | ||
this.subscribers(name).forEach((subscriber) => { | ||
subscriber(...args); | ||
if (subscriber.once) { | ||
toClean.push({ | ||
event: name, | ||
fn: subscriber, | ||
}); | ||
} | ||
}); | ||
}); | ||
toClean.forEach((subscriber) => this.off(event, subscriber)); | ||
toClean.forEach((info) => this.off(info.event, info.fn)); | ||
} | ||
@@ -81,32 +98,38 @@ /** | ||
* a modified (or not) version of the `target`. | ||
* @param {String} event The name of the event. | ||
* @param {*} target The variable to reduce with the listeners. | ||
* @param {Array} args A list of parameters to send to the listeners. | ||
* @param {String|Array} event An event name or a list of them. | ||
* @param {*} target The variable to reduce with the listeners. | ||
* @param {Array} args A list of parameters to send to the listeners. | ||
* @return {*} A version of the `target` processed by the listeners. | ||
*/ | ||
reduce(event, target, ...args) { | ||
const subscribers = this.subscribers(event); | ||
const events = Array.isArray(event) ? event : [event]; | ||
let result = target; | ||
if (subscribers.length) { | ||
const toClean = []; | ||
let processed; | ||
if (Array.isArray(target)) { | ||
processed = target.slice(); | ||
} else if (typeof target === 'object') { | ||
processed = Object.assign({}, target); | ||
} else { | ||
processed = target; | ||
} | ||
this.subscribers(event).forEach((subscriber) => { | ||
processed = subscriber(...[processed, ...args]); | ||
if (subscriber.once) { | ||
toClean.push(subscriber); | ||
events.forEach((name) => { | ||
const subscribers = this.subscribers(name); | ||
if (subscribers.length) { | ||
const toClean = []; | ||
let processed; | ||
if (Array.isArray(result)) { | ||
processed = result.slice(); | ||
} else if (typeof result === 'object') { | ||
processed = Object.assign({}, result); | ||
} else { | ||
processed = result; | ||
} | ||
}); | ||
toClean.forEach((subscriber) => this.off(event, subscriber)); | ||
result = processed; | ||
} | ||
subscribers.forEach((subscriber) => { | ||
processed = subscriber(...[processed, ...args]); | ||
if (subscriber.once) { | ||
toClean.push({ | ||
event: name, | ||
fn: subscriber, | ||
}); | ||
} | ||
}); | ||
toClean.forEach((info) => this.off(info.event, info.fn)); | ||
result = processed; | ||
} | ||
}); | ||
return result; | ||
@@ -113,0 +136,0 @@ } |
@@ -46,2 +46,19 @@ jest.unmock('/shared/eventsHub'); | ||
it('should allow the same subscriber for multiple events at once', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
let unsubscribe = null; | ||
const subscriber = jest.fn(); | ||
// When | ||
const sut = new EventsHub(); | ||
unsubscribe = sut.on(eventNames, subscriber); | ||
sut.emit(eventNames); | ||
unsubscribe(); | ||
// Then | ||
expect(unsubscribe).toBeFunction(); | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
}); | ||
it('shouldn\'t allow the same subscriber multiple times for the same event', () => { | ||
@@ -82,3 +99,3 @@ // Given | ||
it('should allow a subscribers that once executed get unsubscribed (`once`)', () => { | ||
it('should allow a subscriber that once executed get unsubscribed (`once`)', () => { | ||
// Given | ||
@@ -96,2 +113,58 @@ const eventName = 'THE EVENT'; | ||
it('should allow a subscriber to get unsubscribed after executed on multiple events', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const subscriber = jest.fn(); | ||
// When | ||
const sut = new EventsHub(); | ||
sut.once(eventNames, subscriber); | ||
sut.emit(eventNames); | ||
sut.emit(eventNames); | ||
// Then | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
}); | ||
it('should allow a subscriber to get unsubscribed after executed on separated events', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const subscriber = jest.fn(); | ||
// When | ||
const sut = new EventsHub(); | ||
sut.once(eventNames, subscriber); | ||
eventNames.forEach((eventName) => sut.emit(eventName)); | ||
eventNames.forEach((eventName) => sut.emit(eventName)); | ||
// Then | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
}); | ||
it('shouldn\'t unsubscribe a subscriber until it gets executed on all the events', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const subscriber = jest.fn(); | ||
// When | ||
const sut = new EventsHub(); | ||
sut.once(eventNames, subscriber); | ||
sut.emit(eventOneName); | ||
sut.emit(eventOneName); | ||
sut.emit(eventOneName); | ||
sut.emit(eventOneName); | ||
sut.emit(eventOneName); | ||
sut.emit(eventOneName); | ||
sut.emit(eventTwoName); | ||
sut.emit(eventNames); | ||
sut.emit(eventTwoName); | ||
sut.emit(eventTwoName); | ||
sut.emit(eventTwoName); | ||
sut.emit(eventOneName); | ||
// Then | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
}); | ||
it('should allow new subscribers for reduced events (number)', () => { | ||
@@ -162,3 +235,3 @@ // Given | ||
it('should allow a subscribers to unsubscribe after reducing an event once', () => { | ||
it('should allow a subscriber to unsubscribe after reducing an event once', () => { | ||
// Given | ||
@@ -184,2 +257,102 @@ const eventName = 'THE EVENT'; | ||
it('should allow a subscriber to reduce multiple events (number)', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const targetInitialValue = 0; | ||
const target = targetInitialValue; | ||
let result = null; | ||
let unsubscribe = null; | ||
const subscriber = jest.fn((toReduce) => (toReduce + 1)); | ||
// When | ||
const sut = new EventsHub(); | ||
unsubscribe = sut.on(eventNames, subscriber); | ||
result = sut.reduce(eventNames, target); | ||
unsubscribe(); | ||
// Then | ||
expect(unsubscribe).toBeFunction(); | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
expect(result).toBe(targetInitialValue + eventNames.length); | ||
expect(target).toBe(targetInitialValue); | ||
}); | ||
it('should allow a subscriber to reduce multiple events (array)', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const targetInitialValue = ['one', 'two']; | ||
const target = targetInitialValue.slice(); | ||
let result = null; | ||
let unsubscribe = null; | ||
let counter = -1; | ||
const newValues = ['three', 'four']; | ||
const subscriber = jest.fn((toReduce) => { | ||
counter++; | ||
toReduce.push(newValues[counter]); | ||
return toReduce; | ||
}); | ||
// When | ||
const sut = new EventsHub(); | ||
unsubscribe = sut.on(eventNames, subscriber); | ||
result = sut.reduce(eventNames, target); | ||
unsubscribe(); | ||
// Then | ||
expect(unsubscribe).toBeFunction(); | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
expect(result).toEqual([...targetInitialValue, ...newValues]); | ||
expect(target).toEqual(targetInitialValue); | ||
}); | ||
it('should allow a subscriber to reduce multiple events (object)', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const targetInitialValue = { one: 1, two: 2 }; | ||
const target = Object.assign({}, targetInitialValue); | ||
let result = null; | ||
let unsubscribe = null; | ||
let counter = -1; | ||
const newValues = [{ three: 3 }, { four: 4 }]; | ||
const subscriber = jest.fn((toReduce) => { | ||
counter++; | ||
return Object.assign({}, toReduce, newValues[counter]); | ||
}); | ||
// When | ||
const sut = new EventsHub(); | ||
unsubscribe = sut.on(eventNames, subscriber); | ||
result = sut.reduce(eventNames, target); | ||
unsubscribe(); | ||
// Then | ||
expect(unsubscribe).toBeFunction(); | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
expect(result).toEqual(Object.assign({}, targetInitialValue, ...newValues)); | ||
expect(target).toEqual(targetInitialValue); | ||
}); | ||
it('should allow a subscriber to unsubscribe after reducing multiple events once', () => { | ||
// Given | ||
const eventOneName = 'FIRST EVENT'; | ||
const eventTwoName = 'SECOND EVENT'; | ||
const eventNames = [eventOneName, eventTwoName]; | ||
const targetInitialValue = 0; | ||
const target = targetInitialValue; | ||
let result = null; | ||
let unsubscribe = null; | ||
const subscriber = jest.fn((toReduce) => (toReduce + 1)); | ||
// When | ||
const sut = new EventsHub(); | ||
unsubscribe = sut.once(eventNames, subscriber); | ||
result = sut.reduce(eventNames, target); | ||
result = sut.reduce(eventNames, result); | ||
unsubscribe(); | ||
// Then | ||
expect(unsubscribe).toBeFunction(); | ||
expect(subscriber).toHaveBeenCalledTimes(eventNames.length); | ||
expect(result).toBe(targetInitialValue + eventNames.length); | ||
expect(target).toBe(targetInitialValue); | ||
}); | ||
it('should return the original target of a reduced event if there are no subscribers', () => { | ||
@@ -186,0 +359,0 @@ // Given |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
341083
3930