Skip to content

Commit

Permalink
test(Lit): Add tests for extractEventHandler utility
Browse files Browse the repository at this point in the history
  • Loading branch information
a11delavar committed Mar 30, 2024
1 parent bc2efb2 commit 298718c
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions packages/Lit/eventListener/extractEventHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Component, component, html } from '../Component'
import { ComponentTestFixture } from '@a11d/lit-testing'
import { extractEventHandler } from './extractEventHandler'

describe('extractEventHandler', () => {
@component('test-extract-event-handler')
class TestExtractEventHandlerComponent extends Component {
readonly eventListeners = new Map<string, Set<EventListenerOrEventListenerObject>>()

addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void {
const listeners = this.eventListeners.get(type) ?? new Set()
listeners.add(listener)
this.eventListeners.set(type, listeners)
super.addEventListener(type, listener, options)
}

removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void {
this.eventListeners.get(type)?.delete(listener)
super.removeEventListener(type, listener, options)
}
}

describe('when event listener is a lit event-part function', () => {
const clickHandler = jasmine.createSpy('clickHandler') as (e: Event) => void

const fixture = new ComponentTestFixture<TestExtractEventHandlerComponent>(html`
<test-extract-event-handler @click=${clickHandler}></test-extract-event-handler>
`)

it('should extract function handler', () => {
const eventListener = fixture.component.eventListeners.get('click')?.values().next().value

const handler = extractEventHandler(eventListener)

expect(handler).not.toBe(clickHandler) // Because the handler is bound to the element
handler(new MouseEvent('click'))

expect(clickHandler).toHaveBeenCalledOnceWith(jasmine.any(MouseEvent))
})
})

describe('when event listener is an object with handleEvent method', () => {
const clickHandler = { handleEvent: jasmine.createSpy('clickHandler') }

const fixture = new ComponentTestFixture<TestExtractEventHandlerComponent>(html`
<test-extract-event-handler></test-extract-event-handler>
`)

it('should extract handleEvent method', () => {
fixture.component.addEventListener('click', clickHandler)
const eventListener = fixture.component.eventListeners.get('click')?.values().next().value

const handler = extractEventHandler(eventListener)

expect(handler).toBe(clickHandler.handleEvent)
})
})

describe('when event listener is a function', () => {
const clickHandler = jasmine.createSpy('clickHandler') as (e: Event) => void

const fixture = new ComponentTestFixture<TestExtractEventHandlerComponent>(html`
<test-extract-event-handler></test-extract-event-handler>
`)

it('should extract function handler', () => {
fixture.component.addEventListener('click', clickHandler)
const eventListener = fixture.component.eventListeners.get('click')?.values().next().value

const handler = extractEventHandler(eventListener)

expect(handler).toBe(clickHandler)
})
})
})
20 changes: 15 additions & 5 deletions packages/Lit/eventListener/extractEventHandler.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import type { Part } from 'lit'
import { _$LH as LitInternals } from 'lit'

const EventPart = LitInternals._EventPart ?? (LitInternals as any)['I']

Object.defineProperty(EventPart.prototype, 'handler', {
get(this) {
return '_$committedValue' in this
? this._$committedValue
: '_$AH' in this
? this._$AH
: undefined
}
})

export const extractEventHandler = <TEvent extends Event = Event>(eventListener: EventListenerOrEventListenerObject): (event: TEvent) => void => {
return (eventListener as Part).type === 5
// @ts-expect-error - _$committedValue does actually exist on EventPart
// eslint-disable-next-line no-restricted-syntax
? eventListener._$committedValue.bind(eventListener.element)
return eventListener instanceof EventPart
? (eventListener as any).handler?.bind(eventListener.element) ?? (() => { })
: typeof eventListener === 'function'
? eventListener
: eventListener.handleEvent
Expand Down
2 changes: 1 addition & 1 deletion packages/Lit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@a11d/lit",
"version": "0.9.1",
"version": "0.9.2",
"description": "A thin wrapper around the Lit library",
"repository": {
"type": "git",
Expand Down

0 comments on commit 298718c

Please sign in to comment.