From 06a9a6ef1dfcdf35f4b7a570279c52046be36a11 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Sat, 15 Oct 2022 14:14:27 +0200 Subject: [PATCH 1/2] Add support for passing event options --- src/diff/props.js | 9 +- src/jsx.d.ts | 368 +++++++++++++++++++++++++++--------- test/browser/events.test.js | 92 +++++++++ 3 files changed, 373 insertions(+), 96 deletions(-) diff --git a/src/diff/props.js b/src/diff/props.js index df5710925a..a0c94cd7c6 100644 --- a/src/diff/props.js +++ b/src/diff/props.js @@ -54,7 +54,7 @@ function setStyle(style, key, value) { * @param {boolean} isSvg Whether or not this DOM node is an SVG node or not */ export function setProperty(dom, name, value, oldValue, isSvg) { - let useCapture; + let useCapture, eventOptions; o: if (name === 'style') { if (typeof value == 'string') { @@ -90,12 +90,17 @@ export function setProperty(dom, name, value, oldValue, isSvg) { else name = name.slice(2); if (!dom._listeners) dom._listeners = {}; + if (!useCapture && Array.isArray(value)) { + eventOptions = value[1]; + value = value[0]; + useCapture = eventOptions.capture || useCapture; + } dom._listeners[name + useCapture] = value; if (value) { if (!oldValue) { const handler = useCapture ? eventProxyCapture : eventProxy; - dom.addEventListener(name, handler, useCapture); + dom.addEventListener(name, handler, eventOptions || useCapture); } } else { const handler = useCapture ? eventProxyCapture : eventProxy; diff --git a/src/jsx.d.ts b/src/jsx.d.ts index 2fb6813776..425bf31935 100644 --- a/src/jsx.d.ts +++ b/src/jsx.d.ts @@ -376,12 +376,15 @@ export namespace JSXInternal { readonly currentTarget: Target; }; - export type TargetedAnimationEvent = - TargetedEvent; - export type TargetedClipboardEvent = - TargetedEvent; - export type TargetedCompositionEvent = - TargetedEvent; + export type TargetedAnimationEvent< + Target extends EventTarget + > = TargetedEvent; + export type TargetedClipboardEvent< + Target extends EventTarget + > = TargetedEvent; + export type TargetedCompositionEvent< + Target extends EventTarget + > = TargetedEvent; export type TargetedDragEvent = TargetedEvent< Target, DragEvent @@ -406,8 +409,9 @@ export namespace JSXInternal { Target, TouchEvent >; - export type TargetedTransitionEvent = - TargetedEvent; + export type TargetedTransitionEvent< + Target extends EventTarget + > = TargetedEvent; export type TargetedUIEvent = TargetedEvent< Target, UIEvent @@ -425,14 +429,22 @@ export namespace JSXInternal { (this: never, event: E): void; } + export interface EventHandlerOptions { + capture?: boolean; + once?: boolean; + passive?: boolean; + signal?: AbortSignal; + } + export type AnimationEventHandler = EventHandler< TargetedAnimationEvent >; export type ClipboardEventHandler = EventHandler< TargetedClipboardEvent >; - export type CompositionEventHandler = - EventHandler>; + export type CompositionEventHandler< + Target extends EventTarget + > = EventHandler>; export type DragEventHandler = EventHandler< TargetedDragEvent >; @@ -467,148 +479,276 @@ export namespace JSXInternal { export interface DOMAttributes extends PreactDOMAttributes { // Image Events - onLoad?: GenericEventHandler; + onLoad?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onLoadCapture?: GenericEventHandler; - onError?: GenericEventHandler; + onError?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onErrorCapture?: GenericEventHandler; // Clipboard Events - onCopy?: ClipboardEventHandler; + onCopy?: + | ClipboardEventHandler + | [ClipboardEventHandler, EventHandlerOptions]; onCopyCapture?: ClipboardEventHandler; - onCut?: ClipboardEventHandler; + onCut?: + | ClipboardEventHandler + | [ClipboardEventHandler, EventHandlerOptions]; onCutCapture?: ClipboardEventHandler; - onPaste?: ClipboardEventHandler; + onPaste?: + | ClipboardEventHandler + | [ClipboardEventHandler, EventHandlerOptions]; onPasteCapture?: ClipboardEventHandler; // Composition Events - onCompositionEnd?: CompositionEventHandler; + onCompositionEnd?: + | CompositionEventHandler + | [CompositionEventHandler, EventHandlerOptions]; onCompositionEndCapture?: CompositionEventHandler; - onCompositionStart?: CompositionEventHandler; + onCompositionStart?: + | CompositionEventHandler + | [CompositionEventHandler, EventHandlerOptions]; onCompositionStartCapture?: CompositionEventHandler; - onCompositionUpdate?: CompositionEventHandler; + onCompositionUpdate?: + | CompositionEventHandler + | [CompositionEventHandler, EventHandlerOptions]; onCompositionUpdateCapture?: CompositionEventHandler; // Details Events - onToggle?: GenericEventHandler; + onToggle?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; // Focus Events - onFocus?: FocusEventHandler; + onFocus?: + | FocusEventHandler + | [FocusEventHandler, EventHandlerOptions]; onFocusCapture?: FocusEventHandler; - onfocusin?: FocusEventHandler; + onfocusin?: + | FocusEventHandler + | [FocusEventHandler, EventHandlerOptions]; onfocusinCapture?: FocusEventHandler; - onfocusout?: FocusEventHandler; + onfocusout?: + | FocusEventHandler + | [FocusEventHandler, EventHandlerOptions]; onfocusoutCapture?: FocusEventHandler; - onBlur?: FocusEventHandler; + onBlur?: + | FocusEventHandler + | [FocusEventHandler, EventHandlerOptions]; onBlurCapture?: FocusEventHandler; // Form Events - onChange?: GenericEventHandler; + onChange?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onChangeCapture?: GenericEventHandler; - onInput?: GenericEventHandler; + onInput?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onInputCapture?: GenericEventHandler; - onBeforeInput?: GenericEventHandler; + onBeforeInput?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onBeforeInputCapture?: GenericEventHandler; - onSearch?: GenericEventHandler; + onSearch?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onSearchCapture?: GenericEventHandler; - onSubmit?: GenericEventHandler; + onSubmit?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onSubmitCapture?: GenericEventHandler; - onInvalid?: GenericEventHandler; + onInvalid?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onInvalidCapture?: GenericEventHandler; - onReset?: GenericEventHandler; + onReset?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onResetCapture?: GenericEventHandler; - onFormData?: GenericEventHandler; + onFormData?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onFormDataCapture?: GenericEventHandler; // Keyboard Events - onKeyDown?: KeyboardEventHandler; + onKeyDown?: + | KeyboardEventHandler + | [KeyboardEventHandler, EventHandlerOptions]; onKeyDownCapture?: KeyboardEventHandler; - onKeyPress?: KeyboardEventHandler; + onKeyPress?: + | KeyboardEventHandler + | [KeyboardEventHandler, EventHandlerOptions]; onKeyPressCapture?: KeyboardEventHandler; - onKeyUp?: KeyboardEventHandler; + onKeyUp?: + | KeyboardEventHandler + | [KeyboardEventHandler, EventHandlerOptions]; onKeyUpCapture?: KeyboardEventHandler; // Media Events - onAbort?: GenericEventHandler; + onAbort?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onAbortCapture?: GenericEventHandler; - onCanPlay?: GenericEventHandler; + onCanPlay?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onCanPlayCapture?: GenericEventHandler; - onCanPlayThrough?: GenericEventHandler; + onCanPlayThrough?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onCanPlayThroughCapture?: GenericEventHandler; - onDurationChange?: GenericEventHandler; + onDurationChange?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onDurationChangeCapture?: GenericEventHandler; - onEmptied?: GenericEventHandler; + onEmptied?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onEmptiedCapture?: GenericEventHandler; - onEncrypted?: GenericEventHandler; + onEncrypted?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onEncryptedCapture?: GenericEventHandler; - onEnded?: GenericEventHandler; + onEnded?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onEndedCapture?: GenericEventHandler; - onLoadedData?: GenericEventHandler; + onLoadedData?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onLoadedDataCapture?: GenericEventHandler; - onLoadedMetadata?: GenericEventHandler; + onLoadedMetadata?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onLoadedMetadataCapture?: GenericEventHandler; - onLoadStart?: GenericEventHandler; + onLoadStart?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onLoadStartCapture?: GenericEventHandler; - onPause?: GenericEventHandler; + onPause?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onPauseCapture?: GenericEventHandler; - onPlay?: GenericEventHandler; + onPlay?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onPlayCapture?: GenericEventHandler; - onPlaying?: GenericEventHandler; + onPlaying?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onPlayingCapture?: GenericEventHandler; - onProgress?: GenericEventHandler; + onProgress?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onProgressCapture?: GenericEventHandler; - onRateChange?: GenericEventHandler; + onRateChange?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onRateChangeCapture?: GenericEventHandler; - onSeeked?: GenericEventHandler; + onSeeked?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onSeekedCapture?: GenericEventHandler; - onSeeking?: GenericEventHandler; + onSeeking?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onSeekingCapture?: GenericEventHandler; - onStalled?: GenericEventHandler; + onStalled?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onStalledCapture?: GenericEventHandler; - onSuspend?: GenericEventHandler; + onSuspend?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onSuspendCapture?: GenericEventHandler; - onTimeUpdate?: GenericEventHandler; + onTimeUpdate?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onTimeUpdateCapture?: GenericEventHandler; - onVolumeChange?: GenericEventHandler; + onVolumeChange?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onVolumeChangeCapture?: GenericEventHandler; - onWaiting?: GenericEventHandler; + onWaiting?: + | GenericEventHandler + | [GenericEventHandler, EventHandlerOptions]; onWaitingCapture?: GenericEventHandler; // MouseEvents - onClick?: MouseEventHandler; + onClick?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onClickCapture?: MouseEventHandler; - onContextMenu?: MouseEventHandler; + onContextMenu?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onContextMenuCapture?: MouseEventHandler; - onDblClick?: MouseEventHandler; + onDblClick?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onDblClickCapture?: MouseEventHandler; - onDrag?: DragEventHandler; + onDrag?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragCapture?: DragEventHandler; - onDragEnd?: DragEventHandler; + onDragEnd?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragEndCapture?: DragEventHandler; - onDragEnter?: DragEventHandler; + onDragEnter?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragEnterCapture?: DragEventHandler; - onDragExit?: DragEventHandler; + onDragExit?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragExitCapture?: DragEventHandler; - onDragLeave?: DragEventHandler; + onDragLeave?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragLeaveCapture?: DragEventHandler; - onDragOver?: DragEventHandler; + onDragOver?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragOverCapture?: DragEventHandler; - onDragStart?: DragEventHandler; + onDragStart?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDragStartCapture?: DragEventHandler; - onDrop?: DragEventHandler; + onDrop?: + | DragEventHandler + | [DragEventHandler, EventHandlerOptions]; onDropCapture?: DragEventHandler; - onMouseDown?: MouseEventHandler; + onMouseDown?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseDownCapture?: MouseEventHandler; - onMouseEnter?: MouseEventHandler; + onMouseEnter?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseEnterCapture?: MouseEventHandler; - onMouseLeave?: MouseEventHandler; + onMouseLeave?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseLeaveCapture?: MouseEventHandler; - onMouseMove?: MouseEventHandler; + onMouseMove?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseMoveCapture?: MouseEventHandler; - onMouseOut?: MouseEventHandler; + onMouseOut?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseOutCapture?: MouseEventHandler; - onMouseOver?: MouseEventHandler; + onMouseOver?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseOverCapture?: MouseEventHandler; - onMouseUp?: MouseEventHandler; + onMouseUp?: + | MouseEventHandler + | [MouseEventHandler, EventHandlerOptions]; onMouseUpCapture?: MouseEventHandler; // Selection Events @@ -616,55 +756,95 @@ export namespace JSXInternal { onSelectCapture?: GenericEventHandler; // Touch Events - onTouchCancel?: TouchEventHandler; + onTouchCancel?: + | TouchEventHandler + | [TouchEventHandler, EventHandlerOptions]; onTouchCancelCapture?: TouchEventHandler; - onTouchEnd?: TouchEventHandler; + onTouchEnd?: + | TouchEventHandler + | [TouchEventHandler, EventHandlerOptions]; onTouchEndCapture?: TouchEventHandler; - onTouchMove?: TouchEventHandler; + onTouchMove?: + | TouchEventHandler + | [TouchEventHandler, EventHandlerOptions]; onTouchMoveCapture?: TouchEventHandler; - onTouchStart?: TouchEventHandler; + onTouchStart?: + | TouchEventHandler + | [TouchEventHandler, EventHandlerOptions]; onTouchStartCapture?: TouchEventHandler; // Pointer Events - onPointerOver?: PointerEventHandler; + onPointerOver?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerOverCapture?: PointerEventHandler; - onPointerEnter?: PointerEventHandler; + onPointerEnter?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerEnterCapture?: PointerEventHandler; - onPointerDown?: PointerEventHandler; + onPointerDown?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerDownCapture?: PointerEventHandler; - onPointerMove?: PointerEventHandler; + onPointerMove?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerMoveCapture?: PointerEventHandler; - onPointerUp?: PointerEventHandler; + onPointerUp?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerUpCapture?: PointerEventHandler; - onPointerCancel?: PointerEventHandler; + onPointerCancel?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerCancelCapture?: PointerEventHandler; - onPointerOut?: PointerEventHandler; + onPointerOut?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerOutCapture?: PointerEventHandler; - onPointerLeave?: PointerEventHandler; + onPointerLeave?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onPointerLeaveCapture?: PointerEventHandler; - onGotPointerCapture?: PointerEventHandler; + onGotPointerCapture?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onGotPointerCaptureCapture?: PointerEventHandler; - onLostPointerCapture?: PointerEventHandler; + onLostPointerCapture?: + | PointerEventHandler + | [PointerEventHandler, EventHandlerOptions]; onLostPointerCaptureCapture?: PointerEventHandler; // UI Events - onScroll?: UIEventHandler; + onScroll?: + | UIEventHandler + | [UIEventHandler, EventHandlerOptions]; onScrollCapture?: UIEventHandler; // Wheel Events - onWheel?: WheelEventHandler; + onWheel?: + | WheelEventHandler + | [WheelEventHandler, EventHandlerOptions]; onWheelCapture?: WheelEventHandler; // Animation Events - onAnimationStart?: AnimationEventHandler; + onAnimationStart?: + | AnimationEventHandler + | [AnimationEventHandler, EventHandlerOptions]; onAnimationStartCapture?: AnimationEventHandler; - onAnimationEnd?: AnimationEventHandler; + onAnimationEnd?: + | AnimationEventHandler + | [AnimationEventHandler, EventHandlerOptions]; onAnimationEndCapture?: AnimationEventHandler; - onAnimationIteration?: AnimationEventHandler; + onAnimationIteration?: + | AnimationEventHandler + | [AnimationEventHandler, EventHandlerOptions]; onAnimationIterationCapture?: AnimationEventHandler; // Transition Events - onTransitionEnd?: TransitionEventHandler; + onTransitionEnd?: + | TransitionEventHandler + | [TransitionEventHandler, EventHandlerOptions]; onTransitionEndCapture?: TransitionEventHandler; } diff --git a/test/browser/events.test.js b/test/browser/events.test.js index 2e43cba73a..db60636c3c 100644 --- a/test/browser/events.test.js +++ b/test/browser/events.test.js @@ -198,5 +198,97 @@ describe('event handling', () => { expect(clickCapture, 'click').to.have.been.calledOnce; expect(click, 'click').to.have.been.calledOnce; }); + + describe('options', () => { + it('supports capture option', () => { + let click = sinon.spy(); + + render( +
+
, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + + expect(click, 'click').to.have.been.calledOnce; + + // IE doesn't set it + if (!/Edge/.test(navigator.userAgent)) { + expect(click).to.have.been.calledWithMatch({ eventPhase: 0 }); // capturing + } + }); + + if (supportsPassiveEvents()) { + it('supports passive option', () => { + let isPassive = false; + let click = sinon.spy(e => { + e.preventDefault(); + isPassive = !e.defaultPrevented; + }); + + render( +
+
, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + + expect(click, 'click').to.have.been.calledOnce; + expect(isPassive).to.equal(true); + }); + } + + if (supportsPassiveEvents()) { + it('supports once option', () => { + let click = sinon.spy(); + + render( +
+
, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + + expect(click, 'click').to.have.been.calledOnce; + + root.firstElementChild.click(); + expect(click, 'click').to.have.been.calledOnce; + }); + } + + // IE doesn't support AbortSignal + if (typeof AbortController !== 'undefined') { + it('supports signal option', () => { + let click = sinon.spy(); + let controller = new AbortController(); + + render( +
+
, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + + expect(click, 'click').to.have.been.calledOnce; + + controller.abort(); + root.firstElementChild.click(); + + expect(click, 'click').to.have.been.calledOnce; + }); + } + }); } }); From 0be145c640d2326c992cbb8ad5357440d5143bbd Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Sat, 15 Oct 2022 14:25:36 +0200 Subject: [PATCH 2/2] Compat: Make `touchstart`, `touchmove` and `wheel` event passive by default --- compat/src/render.js | 5 ++++ compat/test/browser/events.test.js | 45 ++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/compat/src/render.js b/compat/src/render.js index 5e923667fd..a4f7972bb8 100644 --- a/compat/src/render.js +++ b/compat/src/render.js @@ -153,6 +153,11 @@ options.vnode = vnode => { i = 'onfocusin'; } else if (/^onblur$/i.test(i)) { i = 'onfocusout'; + } + // See: https://github.com/facebook/react/blob/54f0e0f7308b4d0d51e52e149d3f7e5a207991ee/packages/react-dom-bindings/src/events/DOMPluginEventSystem.js#L432-L447 + else if (/^on(Touch[MS]|Wh)/.test(i)) { + i = i.toLowerCase(); + value = [value, { passive: true, capture: /Capture$/.test(i) }]; } else if (/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)) { i = i.toLowerCase(); } else if (nonCustomElement && CAMEL_PROPS.test(i)) { diff --git a/compat/test/browser/events.test.js b/compat/test/browser/events.test.js index fa725e138d..a4bf83bec5 100644 --- a/compat/test/browser/events.test.js +++ b/compat/test/browser/events.test.js @@ -175,13 +175,19 @@ describe('preact/compat events', () => { expect(proto.addEventListener.args.length).to.eql(4); expect(proto.addEventListener.args[0].length).to.eql(3); expect(proto.addEventListener.args[0][0]).to.eql('touchstart'); - expect(proto.addEventListener.args[0][2]).to.eql(false); + expect(proto.addEventListener.args[0][2]).to.eql({ + passive: true, + capture: false + }); expect(proto.addEventListener.args[1].length).to.eql(3); expect(proto.addEventListener.args[1][0]).to.eql('touchend'); expect(proto.addEventListener.args[1][2]).to.eql(false); expect(proto.addEventListener.args[2].length).to.eql(3); expect(proto.addEventListener.args[2][0]).to.eql('touchmove'); - expect(proto.addEventListener.args[2][2]).to.eql(false); + expect(proto.addEventListener.args[2][2]).to.eql({ + passive: true, + capture: false + }); expect(proto.addEventListener.args[3].length).to.eql(3); expect(proto.addEventListener.args[3][0]).to.eql('touchcancel'); expect(proto.addEventListener.args[3][2]).to.eql(false); @@ -215,6 +221,41 @@ describe('preact/compat events', () => { expect(proto.removeEventListener.args[3][2]).to.eql(false); }); + it('should makie touchstart, touchemove and wheel events passive', () => { + const onTouchStart = sinon.spy(); + const onTouchMove = sinon.spy(); + const onWheel = sinon.spy(); + + render( +
, + scratch + ); + + scratch.firstChild.dispatchEvent(createEvent('touchstart')); + scratch.firstChild.dispatchEvent(createEvent('touchmove')); + scratch.firstChild.dispatchEvent(createEvent('wheel')); + + expect(proto.addEventListener.args[0][0]).to.eql('touchstart'); + expect(proto.addEventListener.args[0][2]).to.eql({ + passive: true, + capture: false + }); + expect(proto.addEventListener.args[1][0]).to.eql('touchmove'); + expect(proto.addEventListener.args[1][2]).to.eql({ + passive: true, + capture: false + }); + expect(proto.addEventListener.args[2][0]).to.eql('wheel'); + expect(proto.addEventListener.args[2][2]).to.eql({ + passive: true, + capture: false + }); + }); + it('should support onTransitionEnd', () => { const func = sinon.spy(() => {}); render(
, scratch);