Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 5 additions & 0 deletions .changeset/friendly-cycles-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-signals': patch
---

Fix bug where in vanilla React environments, the onChange events would error due to circular references.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { createInteractionSignal } from '../../../../types/factories'
import { SignalEmitter } from '../../../emitter'
import { OnChangeGenerator } from '../change-gen'

describe('OnChangeGenerator', () => {
let onChangeGenerator: OnChangeGenerator
let emitter: SignalEmitter
let unregister: () => void
beforeEach(() => {
onChangeGenerator = new OnChangeGenerator()
emitter = new SignalEmitter()
})

afterEach(() => {
unregister()
})

it('should emit a signal on change event', async () => {
const emitSpy = jest.spyOn(emitter, 'emit')
const target = document.createElement('input')
target.type = 'text'
target.value = 'new value'

const event = new Event('change', { bubbles: true })
Object.defineProperty(event, 'target', { value: target })

unregister = onChangeGenerator.register(emitter)
document.dispatchEvent(event)

expect(emitSpy).toHaveBeenCalledWith(
createInteractionSignal({
eventType: 'change',
listener: 'onchange',
target: expect.any(Object),
change: { value: 'new value' },
})
)
})

it('should not emit a signal for ignored elements', () => {
const emitSpy = jest.spyOn(emitter, 'emit')
const target = document.createElement('input')
target.type = 'password'

const event = new Event('change', { bubbles: true })
Object.defineProperty(event, 'target', { value: target })

unregister = onChangeGenerator.register(emitter)
document.dispatchEvent(event)

expect(emitSpy).not.toHaveBeenCalled()
})

it('should not emit a signal for elements handled by mutation observer', () => {
const emitSpy = jest.spyOn(emitter, 'emit')
const target = document.createElement('input')
target.type = 'text'
target.setAttribute('value', 'initial value')

const event = new Event('change', { bubbles: true })
Object.defineProperty(event, 'target', { value: target })

unregister = onChangeGenerator.register(emitter)
document.dispatchEvent(event)

expect(emitSpy).not.toHaveBeenCalled()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@
const parseChange = (target: HTMLElement): ChangedEvent | undefined => {
if (target instanceof HTMLSelectElement) {
return {
selectedOptions: Array.from(target.selectedOptions),
selectedOptions: Array.from(target.selectedOptions).map((option) => ({

Check warning on line 70 in packages/signals/signals/src/core/signal-generators/dom-gen/change-gen.ts

View check run for this annotation

Codecov / codecov/patch

packages/signals/signals/src/core/signal-generators/dom-gen/change-gen.ts#L70

Added line #L70 was not covered by tests
value: option.value,
label: option.label,
})),
}
}
if (target instanceof HTMLTextAreaElement) {
Expand Down
Loading