-
-
Notifications
You must be signed in to change notification settings - Fork 260
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
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
77 changes: 77 additions & 0 deletions
77
addon-test-support/@ember/test-helpers/dom/double-click.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,77 @@ | ||
import getElement from './-get-element'; | ||
import fireEvent from './fire-event'; | ||
import { __focus__ } from './focus'; | ||
import settled from '../settled'; | ||
import isFocusable from './-is-focusable'; | ||
import { nextTickPromise } from '../-utils'; | ||
|
||
/** | ||
@private | ||
@param {Element} element the element to double-click on | ||
*/ | ||
export function __doubleClick__(element) { | ||
fireEvent(element, 'mousedown'); | ||
|
||
if (isFocusable(element)) { | ||
__focus__(element); | ||
} | ||
|
||
fireEvent(element, 'mouseup'); | ||
fireEvent(element, 'click'); | ||
fireEvent(element, 'mousedown'); | ||
fireEvent(element, 'mouseup'); | ||
fireEvent(element, 'click'); | ||
fireEvent(element, 'dblclick'); | ||
} | ||
|
||
/** | ||
Double-clicks on the specified target. | ||
Sends a number of events intending to simulate a "real" user clicking on an | ||
element. | ||
For non-focusable elements the following events are triggered (in order): | ||
- `mousedown` | ||
- `mouseup` | ||
- `click` | ||
- `mousedown` | ||
- `mouseup` | ||
- `click` | ||
- `dblclick` | ||
For focusable (e.g. form control) elements the following events are triggered | ||
(in order): | ||
- `mousedown` | ||
- `focus` | ||
- `focusin` | ||
- `mouseup` | ||
- `click` | ||
- `mousedown` | ||
- `mouseup` | ||
- `click` | ||
- `dblclick` | ||
The exact listing of events that are triggered may change over time as needed | ||
to continue to emulate how actual browsers handle clicking a given element. | ||
@public | ||
@param {string|Element} target the element or selector to double-click on | ||
@return {Promise<void>} resolves when settled | ||
*/ | ||
export default function doubleClick(target) { | ||
return nextTickPromise().then(() => { | ||
if (!target) { | ||
throw new Error('Must pass an element or selector to `doubleClick`.'); | ||
} | ||
|
||
let element = getElement(target); | ||
if (!element) { | ||
throw new Error(`Element not found when calling \`doubleClick('${target}')\`.`); | ||
} | ||
|
||
__doubleClick__(element); | ||
return settled(); | ||
}); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ toc: | |
- name: DOM Interaction Helpers | ||
children: | ||
- click | ||
- doubleClick | ||
- tap | ||
- focus | ||
- blur | ||
|
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,213 @@ | ||
import { module, test } from 'qunit'; | ||
import { doubleClick, setupContext, teardownContext } from '@ember/test-helpers'; | ||
import { buildInstrumentedElement, instrumentElement, insertElement } from '../../helpers/events'; | ||
import { isIE11 } from '../../helpers/browser-detect'; | ||
import hasEmberVersion from 'ember-test-helpers/has-ember-version'; | ||
|
||
module('DOM Helper: doubleClick', function(hooks) { | ||
if (!hasEmberVersion(2, 4)) { | ||
return; | ||
} | ||
|
||
let context, element; | ||
|
||
hooks.beforeEach(function() { | ||
context = {}; | ||
}); | ||
|
||
hooks.afterEach(async function() { | ||
element.setAttribute('data-skip-steps', true); | ||
|
||
if (element) { | ||
element.parentNode.removeChild(element); | ||
} | ||
if (context.owner) { | ||
await teardownContext(context); | ||
} | ||
|
||
document.getElementById('ember-testing').innerHTML = ''; | ||
}); | ||
|
||
module('non-focusable element types', function() { | ||
test('double-clicking a div via selector with context set', async function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
await setupContext(context); | ||
await doubleClick(`#${element.id}`); | ||
|
||
assert.verifySteps([ | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]); | ||
}); | ||
|
||
test('double-clicking a div via element with context set', async function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
await setupContext(context); | ||
await doubleClick(element); | ||
|
||
assert.verifySteps([ | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]); | ||
}); | ||
|
||
test('double-clicking a div via element without context set', async function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
await doubleClick(element); | ||
|
||
assert.verifySteps([ | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]); | ||
}); | ||
|
||
test('does not run sync', async function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
let promise = doubleClick(element); | ||
|
||
assert.verifySteps([]); | ||
|
||
await promise; | ||
|
||
assert.verifySteps([ | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]); | ||
}); | ||
|
||
test('rejects if selector is not found', async function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
await setupContext(context); | ||
|
||
assert.rejects( | ||
doubleClick(`#foo-bar-baz-not-here-ever-bye-bye`), | ||
/Element not found when calling `doubleClick\('#foo-bar-baz-not-here-ever-bye-bye'\)`/ | ||
); | ||
}); | ||
|
||
test('double-clicking a div via selector without context set', function(assert) { | ||
element = buildInstrumentedElement('div'); | ||
|
||
assert.rejects( | ||
doubleClick(`#${element.id}`), | ||
/Must setup rendering context before attempting to interact with elements/ | ||
); | ||
}); | ||
}); | ||
|
||
module('focusable element types', function() { | ||
let clickSteps = [ | ||
'mousedown', | ||
'focus', | ||
'focusin', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]; | ||
|
||
if (isIE11) { | ||
clickSteps = [ | ||
'mousedown', | ||
'focusin', | ||
'mouseup', | ||
'click', | ||
'focus', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]; | ||
} | ||
|
||
test('double-clicking a input via selector with context set', async function(assert) { | ||
element = buildInstrumentedElement('input'); | ||
|
||
await setupContext(context); | ||
await doubleClick(`#${element.id}`); | ||
|
||
assert.verifySteps(clickSteps); | ||
assert.strictEqual(document.activeElement, element, 'activeElement updated'); | ||
}); | ||
|
||
test('double-clicking a input via element with context set', async function(assert) { | ||
element = buildInstrumentedElement('input'); | ||
|
||
await setupContext(context); | ||
await doubleClick(element); | ||
|
||
assert.verifySteps(clickSteps); | ||
assert.strictEqual(document.activeElement, element, 'activeElement updated'); | ||
}); | ||
|
||
test('double-clicking a input via element without context set', async function(assert) { | ||
element = buildInstrumentedElement('input'); | ||
|
||
await doubleClick(element); | ||
|
||
assert.verifySteps(clickSteps); | ||
assert.strictEqual(document.activeElement, element, 'activeElement updated'); | ||
}); | ||
|
||
test('double-clicking a input via selector without context set', function(assert) { | ||
element = buildInstrumentedElement('input'); | ||
|
||
assert.rejects( | ||
doubleClick(`#${element.id}`), | ||
/Must setup rendering context before attempting to interact with elements/ | ||
); | ||
}); | ||
}); | ||
|
||
module('elements in different realms', function() { | ||
test('double-clicking an element in a different realm', async function(assert) { | ||
element = document.createElement('iframe'); | ||
|
||
insertElement(element); | ||
|
||
let iframeDocument = element.contentDocument; | ||
let iframeElement = iframeDocument.createElement('div'); | ||
|
||
instrumentElement(iframeElement); | ||
|
||
await doubleClick(iframeElement); | ||
|
||
assert.verifySteps([ | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'mousedown', | ||
'mouseup', | ||
'click', | ||
'dblclick', | ||
]); | ||
}); | ||
}); | ||
}); |