Skip to content

Commit bccac9c

Browse files
authored
Merge pull request #22 from cibernox/add_tap_helper
Added `tap` helper
2 parents 476a415 + 8b51cd1 commit bccac9c

File tree

8 files changed

+178
-6
lines changed

8 files changed

+178
-6
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,17 @@ assert.equal($(find('.my-class')).attr('aria-owns'), '#id123')
104104
## Helpers
105105

106106
- `click(selector, eventOptions)`
107+
- `tap(selector, eventOptions)`
107108
- `fillIn(selector, text)`
108109
- `find(selector, contextHTMLElement)` (query for an element in test DOM, `#ember-testing`)
109110
- `findAll(selector, contextHTMLElement)` (query for elements in test DOM, `#ember-testing`)
110111
- `findWithAssert(selector, contextHTMLElement)` (same as `find`, but raises Error if no result)
111112
- `keyEvent(selector, type, keyCode)` (type being `keydown`, `keyup` or `keypress`)
112113
- `triggerEvent(selector, type, options)`
114+
115+
## Notes of `tap`
116+
117+
In order for `tap` to work, your browser has to support touch events. Desktop Chrome and Firefox
118+
have touch events disabled unless the device emulation mode is on.
119+
In order to enable touch events in your CI, you need to configure testem like the `testem.js`
120+
file on this repo.

addon-test-support/click.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ import wait from 'ember-test-helpers/wait';
66

77
const { run } = Ember;
88

9+
/*
10+
@method clickEventSequence
11+
@private
12+
*/
13+
export function clickEventSequence(el, options) {
14+
run(() => fireEvent(el, 'mousedown', options));
15+
focus(el);
16+
run(() => fireEvent(el, 'mouseup', options));
17+
run(() => fireEvent(el, 'click', options));
18+
}
919

1020
/*
1121
@method click
@@ -16,9 +26,6 @@ const { run } = Ember;
1626
*/
1727
export function click(selector, options = {}) {
1828
let el = findWithAssert(selector);
19-
run(() => fireEvent(el, 'mousedown', options));
20-
focus(el);
21-
run(() => fireEvent(el, 'mouseup', options));
22-
run(() => fireEvent(el, 'click', options));
29+
clickEventSequence(el, options);
2330
return wait();
2431
}

addon-test-support/fire-event.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ const DEFAULT_EVENT_OPTIONS = { canBubble: true, cancelable: true };
55
const KEYBOARD_EVENT_TYPES = ['keydown', 'keypress', 'keyup'];
66
const MOUSE_EVENT_TYPES = ['click', 'mousedown', 'mouseup', 'dblclick', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover'];
77

8-
98
/*
109
@method fireEvent
1110
@param {HTMLElement} element
1211
@param {String} type
1312
@param {Object} (optional) options
13+
@return {Event} The dispatched event
1414
@private
1515
*/
1616
export function fireEvent(element, type, options = {}) {
@@ -35,6 +35,7 @@ export function fireEvent(element, type, options = {}) {
3535
event = buildBasicEvent(type, options);
3636
}
3737
element.dispatchEvent(event);
38+
return event;
3839
}
3940

4041
/*

addon-test-support/helpers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { find } from './find';
22
export { findAll } from './find-all';
33
export { findWithAssert } from './find-with-assert';
44
export { click } from './click';
5+
export { tap } from './tap';
56
export { fillIn } from './fill-in';
67
export { keyEvent } from './key-event';
78
export { triggerEvent } from './trigger-event';

addon-test-support/tap.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Ember from 'ember';
2+
import { findWithAssert } from './find-with-assert';
3+
import { fireEvent } from './fire-event';
4+
import { clickEventSequence } from './click';
5+
import wait from 'ember-test-helpers/wait';
6+
7+
const { run } = Ember;
8+
9+
/*
10+
@method tap
11+
@param {String} selector
12+
@param {Object} options
13+
@return {RSVP.Promise}
14+
@public
15+
*/
16+
export function tap(selector, options = {}) {
17+
let el = findWithAssert(selector);
18+
let touchstartEv;
19+
let touchendEv;
20+
run(() => touchstartEv = fireEvent(el, 'touchstart', options));
21+
run(() => touchendEv = fireEvent(el, 'touchend', options));
22+
if (!touchstartEv.defaultPrevented && !touchendEv.defaultPrevented) {
23+
clickEventSequence(el);
24+
}
25+
return wait();
26+
}

firefox_config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
user_pref("dom.w3c_touch_events.enabled", 1);

testem.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
module.exports = {
33
"test_page": "tests/index.html?hidepassed",
44
"disable_watching": true,
5+
"firefox_user_js": "./firefox_config.js",
56
"launch_in_ci": [
67
"PhantomJS",
78
"Firefox",
@@ -10,5 +11,10 @@ module.exports = {
1011
"launch_in_dev": [
1112
"Firefox",
1213
"Chrome"
13-
]
14+
],
15+
"browser_args": {
16+
"Chrome": [
17+
"--touch-events"
18+
]
19+
}
1420
};

tests/integration/tap-test.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { moduleForComponent, test } from 'ember-qunit';
2+
import hbs from 'htmlbars-inline-precompile';
3+
import { tap } from 'ember-native-dom-helpers/test-support/helpers';
4+
5+
6+
moduleForComponent('tap', 'Integration | Test Helper | tap', {
7+
integration: true
8+
});
9+
10+
// Note: This test will fail in desktop browsers as it doesn't fire
11+
// touch events unless device emulation mode is enabled.
12+
test('It fires touchstart, touchend, and then the click sequence(mousedown -> focus -> mouseup -> click) events on the element with the given selector (in that order)', function(assert) {
13+
assert.expect(18);
14+
let index = 0;
15+
this.onTouchStart = (e) => {
16+
assert.equal(++index, 1, 'touchstart is fired first');
17+
assert.ok(true, 'a touchstart event is fired');
18+
assert.ok(e instanceof window.Event, 'It receives a native event');
19+
}
20+
this.onTouchEnd = (e) => {
21+
assert.equal(++index, 2, 'touchend is fired second');
22+
assert.ok(true, 'a touchend event is fired');
23+
assert.ok(e instanceof window.Event, 'It receives a native event');
24+
}
25+
this.onMouseDown = (e) => {
26+
assert.equal(++index, 3, 'mousedown is fired third');
27+
assert.ok(true, 'a mousedown event is fired');
28+
assert.ok(e instanceof window.Event, 'It receives a native event');
29+
}
30+
this.onFocus = (e) => {
31+
assert.equal(++index, 4, 'focus is fired forth');
32+
assert.ok(true, 'a focus event is fired');
33+
assert.ok(e instanceof window.Event, 'It receives a native event');
34+
}
35+
this.onMouseUp = (e) => {
36+
assert.equal(++index, 5, 'mouseup is fired fifth');
37+
assert.ok(true, 'a mouseup event is fired');
38+
assert.ok(e instanceof window.Event, 'It receives a native event');
39+
}
40+
this.onClick = (e) => {
41+
assert.equal(++index, 6, 'click is fired sixth');
42+
assert.ok(true, 'a click event is fired');
43+
assert.ok(e instanceof window.Event, 'It receives a native event');
44+
}
45+
46+
this.render(hbs`
47+
<input class="target-element"
48+
ontouchstart={{onTouchStart}}
49+
ontouchend={{onTouchEnd}}
50+
onmouseup={{onMouseUp}}
51+
onfocus={{onFocus}}
52+
onclick={{onClick}}
53+
onmousedown={{onMouseDown}} />
54+
`);
55+
56+
tap('.target-element');
57+
});
58+
59+
test('It the touchstart event is defaultPrevented, the focus and mouse events are not fired', function(assert) {
60+
assert.expect(6);
61+
let index = 0;
62+
this.onTouchStart = (e) => {
63+
assert.equal(++index, 1, 'touchstart is fired first');
64+
assert.ok(true, 'a touchstart event is fired');
65+
assert.ok(e instanceof window.Event, 'It receives a native event');
66+
e.preventDefault();
67+
}
68+
this.onTouchEnd = (e) => {
69+
assert.equal(++index, 2, 'touchend is fired second');
70+
assert.ok(true, 'a touchend event is fired');
71+
assert.ok(e instanceof window.Event, 'It receives a native event');
72+
}
73+
this.onMouseDown = () => assert.ok(false, 'mousedown should not be fired');
74+
this.onFocus = () => assert.ok(false, 'focus should not be fired');
75+
this.onMouseUp = () => assert.ok(false, 'mouseup should not be fired');
76+
this.onClick = () => assert.ok(false, 'click should not be fired');
77+
78+
this.render(hbs`
79+
<input class="target-element"
80+
ontouchstart={{onTouchStart}}
81+
ontouchend={{onTouchEnd}}
82+
onmouseup={{onMouseUp}}
83+
onfocus={{onFocus}}
84+
onclick={{onClick}}
85+
onmousedown={{onMouseDown}} />
86+
`);
87+
88+
tap('.target-element');
89+
});
90+
91+
92+
test('It the touchend event is defaultPrevented, the focus and mouse events are not fired', function(assert) {
93+
assert.expect(6);
94+
let index = 0;
95+
this.onTouchStart = (e) => {
96+
assert.equal(++index, 1, 'touchstart is fired first');
97+
assert.ok(true, 'a touchstart event is fired');
98+
assert.ok(e instanceof window.Event, 'It receives a native event');
99+
}
100+
this.onTouchEnd = (e) => {
101+
assert.equal(++index, 2, 'touchend is fired second');
102+
assert.ok(true, 'a touchend event is fired');
103+
assert.ok(e instanceof window.Event, 'It receives a native event');
104+
e.preventDefault();
105+
}
106+
this.onMouseDown = () => assert.ok(false, 'mousedown should not be fired');
107+
this.onFocus = () => assert.ok(false, 'focus should not be fired');
108+
this.onMouseUp = () => assert.ok(false, 'mouseup should not be fired');
109+
this.onClick = () => assert.ok(false, 'click should not be fired');
110+
111+
this.render(hbs`
112+
<input class="target-element"
113+
ontouchstart={{onTouchStart}}
114+
ontouchend={{onTouchEnd}}
115+
onmouseup={{onMouseUp}}
116+
onfocus={{onFocus}}
117+
onclick={{onClick}}
118+
onmousedown={{onMouseDown}} />
119+
`);
120+
121+
tap('.target-element');
122+
});

0 commit comments

Comments
 (0)