Skip to content

Commit

Permalink
fix: return original event object in events to be more aligned with w…
Browse files Browse the repository at this point in the history
…eb event handling
  • Loading branch information
tujoworker committed Dec 1, 2020
1 parent 9754960 commit 1d86c85
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ describe('Dropdown component', () => {
expect(on_select.mock.calls[1][0].data).toStrictEqual(selectedItem)
expect(on_change).toHaveBeenCalledWith({
attributes: {},
isTrusted: false,
data: selectedItem,
event: new KeyboardEvent('keydown', {}),
selected_item: props.value + 1,
Expand Down Expand Up @@ -379,6 +380,7 @@ describe('Dropdown component', () => {

expect(on_change).toHaveBeenCalledWith({
attributes: {},
isTrusted: false,
data: {
__id: 0,
content: 'English',
Expand All @@ -398,6 +400,7 @@ describe('Dropdown component', () => {

expect(on_change).toHaveBeenLastCalledWith({
attributes: {},
isTrusted: false,
data: {
content: 'Norsk',
selected_key: 'nb-NO',
Expand Down Expand Up @@ -465,6 +468,7 @@ describe('Dropdown component', () => {
expect(on_hide.mock.calls.length).toBe(1)
expect(on_hide.mock.calls[0][0].attributes).toMatchObject(params)
expect(on_hide).toHaveBeenCalledWith({
isTrusted: false,
attributes: params,
data: null,
event: new KeyboardEvent('keydown', {})
Expand Down Expand Up @@ -514,6 +518,7 @@ describe('Dropdown component', () => {
expect(on_hide).toBeCalledTimes(1)
expect(on_hide).toHaveBeenCalledWith({
attributes: {},
isTrusted: false,
event: new KeyboardEvent('keydown', {}),
data: null
})
Expand Down
56 changes: 50 additions & 6 deletions packages/dnb-ui-lib/src/shared/__tests__/component-helper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
dispatchCustomElementEvent,
toPascalCase,
toCamelCase,
toSnakeCase,
// pickRenderProps,
detectOutsideClick,
makeUniqueId,
Expand Down Expand Up @@ -296,7 +297,7 @@ describe('"isTrue" should', () => {
})

describe('"dispatchCustomElementEvent" should', () => {
it('call a custom event function, set as a property in props', () => {
it('emit snake case and camel case events', () => {
const my_event = jest.fn()
const myEvent = jest.fn()
const instance = {
Expand All @@ -305,10 +306,47 @@ describe('"dispatchCustomElementEvent" should', () => {
myEvent
}
}
const event = {}
dispatchCustomElementEvent(instance, 'my_event', event)
expect(my_event.mock.calls.length).toBe(1)
expect(myEvent.mock.calls.length).toBe(1)

const eventObject = {}

dispatchCustomElementEvent(instance, 'my_event', eventObject)
expect(my_event).toBeCalledTimes(1)
expect(myEvent).toBeCalledTimes(1)

// dispatchCustomElementEvent(instance, 'my_event', eventObject)
dispatchCustomElementEvent(instance, 'myEvent', eventObject)
expect(my_event).toBeCalledTimes(2)
expect(myEvent).toBeCalledTimes(2)
})

it('emit an event and return its event properties, including custom properties', () => {
const my_event = jest.fn()
const myEvent = jest.fn()
const instance = {
props: {
my_event,
myEvent
}
}

const keyCode = 13
const event = new KeyboardEvent('keydown', { keyCode })
const data = { foo: 'bar' }
const eventObject = { event, data }
dispatchCustomElementEvent(instance, 'my_event', eventObject)

expect(my_event).toBeCalledTimes(1)
expect(myEvent).toBeCalledTimes(1)

const eventResult = {
data: {
foo: 'bar'
},
event,
isTrusted: false
}
expect(my_event).toBeCalledWith(eventResult)
expect(myEvent).toBeCalledWith(eventResult)
})

it('call a custom event function, set as a property in props', () => {
Expand All @@ -322,7 +360,7 @@ describe('"dispatchCustomElementEvent" should', () => {
}
const event = {}
dispatchCustomElementEvent(instance, 'eventName', event)
expect(fireEvent.mock.calls.length).toBe(1)
expect(fireEvent).toBeCalledTimes(1)
expect(fireEvent.mock.calls[0][0]).toBe('eventName')
})

Expand Down Expand Up @@ -362,6 +400,12 @@ describe('"toCamelCase" should', () => {
})
})

describe('"toSnakeCase" should', () => {
it('transform a camel case event name to snake case', () => {
expect(toSnakeCase('myEventIsLong')).toBe('my_event_is_long')
})
})

// Removed as we now run function props from Web Components (custom-element)
// describe('"pickRenderProps" should', () => {
// it('only pass function props which dont exists in renderProps', () => {
Expand Down
58 changes: 48 additions & 10 deletions packages/dnb-ui-lib/src/shared/component-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,14 @@ export const isTrue = (value) => {
export const dispatchCustomElementEvent = (
src,
eventName,
eventObject
eventObjectOrig
) => {
let ret = null
let ret = undefined

const eventObject = {
...(eventObjectOrig.event || {}),
...eventObjectOrig
}

// distribute dataset like "data-*" to both currentTarget and target
if (eventObject && eventObject.attributes && eventObject.event) {
Expand Down Expand Up @@ -358,15 +363,38 @@ export const dispatchCustomElementEvent = (
}

// call the default snake case event
if (typeof props[eventName] === 'function') {
ret = props[eventName].apply(src, [eventObject])
}
if (eventName.includes('_')) {
if (typeof props[eventName] === 'function') {
const r = props[eventName].apply(src, [eventObject])
if (typeof r !== 'undefined') {
ret = r
}
}

// call Syntetic React event camelCase naming events
eventName = toCamelCase(eventName)
if (typeof props[eventName] === 'function') {
// TODO: we may use [eventObject.event, eventObject] in future
ret = props[eventName].apply(src, [eventObject])
// call Syntetic React event camelCase naming events
eventName = toCamelCase(eventName)
if (typeof props[eventName] === 'function') {
const r = props[eventName].apply(src, [eventObject])
if (typeof r !== 'undefined') {
ret = r
}
}
} else {
if (typeof props[eventName] === 'function') {
const r = props[eventName].apply(src, [eventObject])
if (typeof r !== 'undefined') {
ret = r
}
}

// call (in future deprecated) event snake case naming events
eventName = toSnakeCase(eventName)
if (typeof props[eventName] === 'function') {
const r = props[eventName].apply(src, [eventObject])
if (typeof r !== 'undefined') {
ret = r
}
}
}

return ret
Expand All @@ -388,6 +416,12 @@ export const toCamelCase = (s) =>
''
)

// TODO: Test if this solution is faster
// const toCamelCase = (str) =>
// str.replace(/([-_][a-z])/g, (group) =>
// group.toUpperCase().replace('-', '').replace('_', '')
// )

// transform my_component to MyComponent
export const toPascalCase = (s) =>
s
Expand All @@ -402,6 +436,10 @@ export const toPascalCase = (s) =>
''
)

// transform MyComponent to my_component
export const toSnakeCase = (str) =>
str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)

// Removed as we now run function props from Web Components (custom-element)
// export const pickRenderProps = (props, renderProps) =>
// Object.entries(props)
Expand Down

0 comments on commit 1d86c85

Please sign in to comment.