-
-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TASK: Refactor the executeCallback abstract and add unit tests. #18
- Loading branch information
1 parent
552716e
commit 06f6bfa
Showing
12 changed files
with
176 additions
and
34 deletions.
There are no files selected for viewing
50 changes: 35 additions & 15 deletions
50
Resources/Private/JavaScript/Host/Abstracts/ExecuteCallback.js
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,44 @@ | ||
import isObject from 'lodash.isobject'; | ||
import isFunction from 'lodash.isfunction'; | ||
|
||
export const ERROR_INVALID_EVENT = 'Please supply a valid native or Synthetic Event to the executeCallback function.'; | ||
|
||
/** | ||
* Abstracts the prevent of a DOM event and the existence check for a callback function. | ||
* @param {Event} e The event object to handle. | ||
* @param {Function} cb The callback to call after the event was handled. | ||
* @param {Boolean} preventDefault Should the function call e.preventDefault();? (Defaults to `true`) | ||
* @param {Boolean} stopImmediatePropagation Should the function call e.stopImmediatePropagation();? (Defaults to `false`) | ||
* | ||
* @param {Array} ...args All arguments which are passed to the function. | ||
* @return {Null} | ||
* @example <a onClick={e => executeCallback(e, this.props.onClick)}>Click me</a> | ||
*/ | ||
const executeCallback = (...args) => { | ||
let e; | ||
export default ({e, cb, preventDefault = true, stopImmediatePropagation = false} = {}) => { | ||
// | ||
// Check for the validaty of the event object, if one was passed. | ||
// | ||
if (e && !e.preventDefault) { | ||
throw new Error(ERROR_INVALID_EVENT); | ||
} | ||
|
||
args.forEach(arg => { | ||
if (isObject(arg) && isFunction(arg.preventDefault)) { | ||
e = arg; | ||
e.preventDefault(); | ||
} else if (isFunction(arg)) { | ||
arg(e); | ||
} | ||
}); | ||
}; | ||
if (e && preventDefault) { | ||
e.preventDefault(); | ||
} | ||
|
||
export default executeCallback; | ||
if (e && stopImmediatePropagation) { | ||
// | ||
// Since react bubbles SyntheticEvents instead of native DOM events, | ||
// we need to handle both cases appropriately. | ||
// | ||
// @see https://facebook.github.io/react/docs/events.html#syntheticevent | ||
// | ||
try { | ||
e.stopImmediatePropagation(); | ||
} catch(e) {} | ||
try { | ||
e.stopPropagation(); | ||
} catch(e) {} | ||
} | ||
|
||
if (cb && isFunction(cb)) { | ||
cb(e); | ||
} | ||
}; |
90 changes: 90 additions & 0 deletions
90
Resources/Private/JavaScript/Host/Abstracts/ExecuteCallback.spec.js
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import chai from 'chai'; | ||
import sinon from 'sinon'; | ||
import sinonMiddleware from 'sinon-chai'; | ||
import executeCallback, {ERROR_INVALID_EVENT} from './ExecuteCallback.js'; | ||
|
||
const expect = chai.expect; | ||
|
||
chai.should(); | ||
chai.use(sinonMiddleware); | ||
|
||
describe('"ExecuteCallback" abstract', () => { | ||
let eventMock = null; | ||
|
||
beforeEach(done => { | ||
eventMock = { | ||
preventDefault: sinon.spy(), | ||
stopImmediatePropagation: sinon.spy(), | ||
stopPropagation: sinon.spy() | ||
}; | ||
|
||
done(); | ||
}); | ||
|
||
afterEach(done => { | ||
eventMock = null; | ||
|
||
done(); | ||
}); | ||
|
||
it('should call the `cb` property if it was passed to the function.', () => { | ||
const spy = sinon.spy(); | ||
|
||
executeCallback({ | ||
cb: spy | ||
}); | ||
|
||
spy.should.have.callCount(1); | ||
}); | ||
|
||
it('should throw an error if an invalid event object was passed to the function.', () => { | ||
const spy = sinon.spy(); | ||
|
||
const fn = () => executeCallback({ | ||
cb: spy, | ||
e: { | ||
nope: true | ||
} | ||
});; | ||
|
||
expect(fn).to.throw(ERROR_INVALID_EVENT); | ||
}); | ||
|
||
it('should propagate the event object to the `cb` function.', () => { | ||
const spy = sinon.spy(); | ||
|
||
executeCallback({ | ||
cb: spy, | ||
e: eventMock | ||
}); | ||
|
||
spy.should.have.been.calledWith(eventMock); | ||
}); | ||
|
||
it('should call the preventDefault() method if not otherwise configured.', () => { | ||
executeCallback({ | ||
e: eventMock | ||
}); | ||
|
||
eventMock.preventDefault.should.have.callCount(1); | ||
}); | ||
|
||
it('should not call the preventDefault() method if properly configured.', () => { | ||
executeCallback({ | ||
e: eventMock, | ||
preventDefault: false | ||
}); | ||
|
||
eventMock.preventDefault.should.have.callCount(0); | ||
}); | ||
|
||
it('should call either the stopPropagation() method if properly configured.', () => { | ||
executeCallback({ | ||
e: eventMock, | ||
stopImmediatePropagation: true | ||
}); | ||
|
||
eventMock.stopPropagation.should.have.callCount(1); | ||
eventMock.stopImmediatePropagation.should.have.callCount(1); | ||
}); | ||
}); |
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
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
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
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
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
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
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
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
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
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