Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map lowercase mouse events in #simulate #77

Merged
merged 1 commit into from
Jan 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Map lowercase native events to React camelcase
React camelcases a bunch of events that JS has in all lower case. This
PR adds a map of them so people can call `simulate` with either the
React version or the native event version.

Fixes #29.
  • Loading branch information
jackfranklin committed Jan 14, 2016
commit 2f303b261c83077c115e822d56063bd6efe4daf6
4 changes: 3 additions & 1 deletion src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Simulate,
findDOMNode,
} from './react-compat';
import { mapNativeEventNames } from './Utils';

/**
* Finds all nodes in the current wrapper nodes' render trees that match the provided predicate
Expand Down Expand Up @@ -306,7 +307,8 @@ export default class ReactWrapper {
*/
simulate(event, ...args) {
this.single(n => {
const eventFn = Simulate[event];
const mappedEvent = mapNativeEventNames(event);
const eventFn = Simulate[mappedEvent];
if (!eventFn) {
throw new TypeError(`ReactWrapper::simulate() event '${event}' does not exist`);
}
Expand Down
51 changes: 50 additions & 1 deletion src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
isDOMComponent,
findDOMNode,
} from './react-compat';
import { REACT013 } from './version';
import {
REACT013,
REACT014,
} from './version';

export function propsOfNode(node) {
if (REACT013) {
Expand Down Expand Up @@ -168,3 +171,49 @@ export function coercePropValue(propValue) {
// coerce to boolean
return propValue === 'true' ? true : false;
}

export function mapNativeEventNames(event) {
const nativeToReactEventMap = {
compositionend: 'compositionEnd',
compositionstart: 'compositionStart',
compositionupdate: 'compositionUpdate',
keydown: 'keyDown',
keyup: 'keyUp',
keypress: 'keyPress',
contextmenu: 'contextMenu',
doubleclick: 'doubleClick',
dragend: 'dragEnd',
dragenter: 'dragEnter',
dragexist: 'dragExit',
dragleave: 'dragLeave',
dragover: 'dragOver',
dragstart: 'dragStart',
mousedown: 'mouseDown',
mousemove: 'mouseMove',
mouseout: 'mouseOut',
mouseover: 'mouseOver',
mouseup: 'mouseUp',
touchcancel: 'touchCancel',
touchend: 'touchEnd',
touchmove: 'touchMove',
touchstart: 'touchStart',
canplay: 'canPlay',
canplaythrough: 'canPlayThrough',
durationchange: 'durationChange',
loadeddata: 'loadedData',
loadedmetadata: 'loadedMetadata',
loadstart: 'loadStart',
ratechange: 'rateChange',
timeupdate: 'timeUpdate',
volumechange: 'volumeChange',
};

if (REACT014) {
// these could not be simulated in React 0.13:
// https://github.com/facebook/react/issues/1297
nativeToReactEventMap.mouseenter = 'mouseEnter';
nativeToReactEventMap.mouseleave = 'mouseLeave';
}

return nativeToReactEventMap[event] || event;
}
36 changes: 36 additions & 0 deletions src/__tests__/ReactWrapper-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,42 @@ describeWithDOM('mount', () => {
expect(wrapper.simulate.bind(wrapper, 'invalidEvent'))
.to.throw(TypeError, "ReactWrapper::simulate() event 'invalidEvent' does not exist");
});

describe('Normalizing JS event names', () => {
it('should convert lowercase events to React camelcase', () => {
const spy = sinon.spy();
class Foo extends React.Component {
render() {
return (
<a onDoubleClick={spy}>foo</a>
);
}
}

const wrapper = mount(<Foo />);

wrapper.simulate('doubleclick');
expect(spy.calledOnce).to.equal(true);
});

describeIf(!REACT013, 'normalizing mouseenter', () => {
it('should convert lowercase events to React camelcase', () => {
const spy = sinon.spy();
class Foo extends React.Component {
render() {
return (
<a onMouseEnter={spy}>foo</a>
);
}
}

const wrapper = mount(<Foo />);

wrapper.simulate('mouseenter');
expect(spy.calledOnce).to.equal(true);
});
});
});
});

describe('.setState(newState)', () => {
Expand Down
24 changes: 24 additions & 0 deletions src/__tests__/Utils-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
propFromEvent,
SELECTOR,
selectorType,
mapNativeEventNames,
} from '../Utils';
import {
describeWithDOM,
Expand Down Expand Up @@ -240,7 +241,30 @@ describe('Utils', () => {
expect(coercePropValue('true')).to.equal(true);
expect(coercePropValue('false')).to.equal(false);
});
});

describe('mapNativeEventNames', () => {
describe('given an event that isn\'t a mapped', () => {
it('returns the original event', () => {
const result = mapNativeEventNames('click');
expect(result).to.equal('click');
});

});

describe('given a React capitalised mouse event', () => {
it('returns the original event', () => {
const result = mapNativeEventNames('mouseEnter');
expect(result).to.equal('mouseEnter');
});
});

describe('given a native lowercase event', () => {
it('transforms it into the React capitalised event', () => {
const result = mapNativeEventNames('dragenter');
expect(result).to.equal('dragEnter');
});
});
});

});