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

Allow click, doubleClick, and triggerEvent to trigger events on window. #943

Merged
merged 5 commits into from
Nov 12, 2020
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import getElement from './-get-element';
import Target, { isWindow } from './-target';

/**
Used internally by the DOM interaction helpers to find either window or an element.

@private
@param {string|Element} target the window, an element or selector to retrieve
@returns {Element|Window} the target or selector
*/
export function getWindowOrElement(target: Target): Element | Document | Window | null {
if (isWindow(target)) {
return target as Window;
}

return getElement(target);
}
8 changes: 6 additions & 2 deletions addon-test-support/@ember/test-helpers/dom/-is-focusable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import isFormControl from './-is-form-control';
import { isDocument, isContentEditable } from './-target';
import { isDocument, isContentEditable, isWindow } from './-target';

const FOCUSABLE_TAGS = ['A'];

Expand All @@ -16,8 +16,12 @@ function isFocusableElement(element: Element): element is FocusableElement {
@returns {boolean} `true` when the element is focusable, `false` otherwise
*/
export default function isFocusable(
element: HTMLElement | SVGElement | Element | Document
element: HTMLElement | SVGElement | Element | Document | Window
): element is HTMLElement | SVGElement {
if (isWindow(element)) {
return false;
}

if (isDocument(element)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isDocument } from './-target';
import { isDocument, isWindow } from './-target';

const FORM_CONTROL_TAGS = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'];

Expand All @@ -13,8 +13,11 @@ export type FormControl =
@param {Element} element the element to check
@returns {boolean} `true` when the element is a form control, `false` otherwise
*/
export default function isFormControl(element: Element | Document): element is FormControl {
export default function isFormControl(
element: Element | Document | Window
): element is FormControl {
return (
!isWindow(element) &&
!isDocument(element) &&
FORM_CONTROL_TAGS.indexOf(element.tagName) > -1 &&
(element as HTMLInputElement).type !== 'hidden'
Expand Down
5 changes: 5 additions & 0 deletions addon-test-support/@ember/test-helpers/dom/-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export function isElement(target: any): target is Element {
return target.nodeType === Node.ELEMENT_NODE;
}

// eslint-disable-next-line require-jsdoc
export function isWindow(target: Target): target is Window {
return target instanceof Window;
}

// eslint-disable-next-line require-jsdoc
export function isDocument(target: any): target is Document {
return target.nodeType === Node.DOCUMENT_NODE;
Expand Down
6 changes: 3 additions & 3 deletions addon-test-support/@ember/test-helpers/dom/click.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assign } from '@ember/polyfills';
import getElement from './-get-element';
import { getWindowOrElement } from './-get-window-or-element';
import fireEvent from './fire-event';
import { __focus__ } from './focus';
import settled from '../settled';
Expand Down Expand Up @@ -31,7 +31,7 @@ export const DEFAULT_CLICK_OPTIONS = {
@param {Element} element the element to click on
@param {MouseEventInit} options the options to be merged into the mouse events
*/
export function __click__(element: Element | Document, options: MouseEventInit): void {
export function __click__(element: Element | Document | Window, options: MouseEventInit): void {
fireEvent(element, 'mousedown', options);

if (isFocusable(element)) {
Expand Down Expand Up @@ -97,7 +97,7 @@ export default function click(target: Target, _options: MouseEventInit = {}): Pr
throw new Error('Must pass an element or selector to `click`.');
}

let element = getElement(target);
let element = getWindowOrElement(target);
if (!element) {
throw new Error(`Element not found when calling \`click('${target}')\`.`);
}
Expand Down
9 changes: 6 additions & 3 deletions addon-test-support/@ember/test-helpers/dom/double-click.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assign } from '@ember/polyfills';
import getElement from './-get-element';
import { getWindowOrElement } from './-get-window-or-element';
import fireEvent from './fire-event';
import { __focus__ } from './focus';
import settled from '../settled';
Expand All @@ -20,7 +20,10 @@ registerHook('doubleClick', 'start', (target: Target) => {
@param {Element} element the element to double-click on
@param {MouseEventInit} options the options to be merged into the mouse events
*/
export function __doubleClick__(element: Element | Document, options: MouseEventInit): void {
export function __doubleClick__(
element: Element | Document | Window,
options: MouseEventInit
): void {
fireEvent(element, 'mousedown', options);

if (isFocusable(element)) {
Expand Down Expand Up @@ -98,7 +101,7 @@ export default function doubleClick(target: Target, _options: MouseEventInit = {
throw new Error('Must pass an element or selector to `doubleClick`.');
}

let element = getElement(target);
let element = getWindowOrElement(target);
if (!element) {
throw new Error(`Element not found when calling \`doubleClick('${target}')\`.`);
}
Expand Down
4 changes: 2 additions & 2 deletions addon-test-support/@ember/test-helpers/dom/trigger-event.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import getElement from './-get-element';
import { getWindowOrElement } from './-get-window-or-element';
import fireEvent from './fire-event';
import settled from '../settled';
import { nextTickPromise } from '../-utils';
Expand Down Expand Up @@ -72,7 +72,7 @@ export default function triggerEvent(
throw new Error(`Must provide an \`eventType\` to \`triggerEvent\``);
}

let element = getElement(target);
let element = getWindowOrElement(target);
if (!element) {
throw new Error(`Element not found when calling \`triggerEvent('${target}', ...)\`.`);
}
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/dom/click-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,19 @@ module('DOM Helper: click', function (hooks) {
});
});
});

module('DOM Helper: click with window', function () {
test('clicking window without context set fires the given event type', async function (assert) {
let listener = e => {
assert.step('click');
assert.ok(e instanceof Event, `click listener receives a native event`);
};
window.addEventListener('click', listener);

await click(window, 'click');

assert.verifySteps(['click']);

window.removeEventListener('click', listener);
});
});
16 changes: 16 additions & 0 deletions tests/unit/dom/double-click-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,19 @@ module('DOM Helper: doubleClick', function (hooks) {
});
});
});

module('DOM Helper: doubleClick with window', function () {
test('double clicking window without context set fires the given event type', async function (assert) {
let listener = e => {
assert.step('click');
assert.ok(e instanceof Event, `click listener receives a native event`);
};
window.addEventListener('click', listener);

await doubleClick(window, 'click');

assert.verifySteps(['click', 'click']);

window.removeEventListener('click', listener);
});
});
16 changes: 16 additions & 0 deletions tests/unit/dom/trigger-event-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,19 @@ module('DOM Helper: triggerEvent', function (hooks) {
assert.verifySteps(['inner: mouseenter', 'outer: mouseenter', 'mouseenter']);
});
});

module('DOM Helper: triggerEvent with window', function () {
test('triggering event via window without context set fires the given event type', async function (assert) {
let listener = e => {
assert.step('resize');
assert.ok(e instanceof Event, `resize listener receives a native event`);
};
window.addEventListener('resize', listener);

await triggerEvent(window, 'resize');

assert.verifySteps(['resize']);

window.removeEventListener('resize', listener);
});
});