Skip to content

Commit 78d8914

Browse files
authored
fix: [#1603] HTMLSelectElement should not dispatch "change" event when changing value or index
* fix: [#1603] HTMLSelectElement should not dispatch "change" event when changing value or index * chore: [#1603] Tries to fix integration test * chore: [#1603] Fixes failing integration test
1 parent 23f8673 commit 78d8914

File tree

4 files changed

+8
-49
lines changed

4 files changed

+8
-49
lines changed

packages/happy-dom/src/ClassMethodBinder.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export default class ClassMethodBinder {
2323
* @param name Method name.
2424
*/
2525
public bind(name: string | symbol): void {
26-
if (this.cache.has(name)) {
26+
// We should never bind the Symbol.iterator method as it can cause problems with Array.from()
27+
if (this.cache.has(name) || name === Symbol.iterator) {
2728
return;
2829
}
2930

packages/happy-dom/src/nodes/html-select-element/HTMLSelectElement.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,6 @@ export default class HTMLSelectElement extends HTMLElement {
385385
*/
386386
public set value(value: string) {
387387
const options = QuerySelector.querySelectorAll(this, 'option')[PropertySymbol.items];
388-
const previousSelectedIndex = this[PropertySymbol.selectedIndex];
389388

390389
this[PropertySymbol.selectedIndex] = -1;
391390

@@ -399,10 +398,6 @@ export default class HTMLSelectElement extends HTMLElement {
399398
option[PropertySymbol.selectedness] = false;
400399
}
401400
}
402-
403-
if (previousSelectedIndex !== this[PropertySymbol.selectedIndex]) {
404-
this.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
405-
}
406401
}
407402

408403
/**
@@ -427,7 +422,6 @@ export default class HTMLSelectElement extends HTMLElement {
427422
}
428423

429424
const options = QuerySelector.querySelectorAll(this, 'option')[PropertySymbol.items];
430-
const previousSelectedIndex = this[PropertySymbol.selectedIndex];
431425

432426
this[PropertySymbol.selectedIndex] = -1;
433427

@@ -443,10 +437,6 @@ export default class HTMLSelectElement extends HTMLElement {
443437
this[PropertySymbol.selectedIndex] = selectedIndex;
444438
}
445439
}
446-
447-
if (previousSelectedIndex !== this[PropertySymbol.selectedIndex]) {
448-
this.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
449-
}
450440
}
451441

452442
/**
@@ -669,7 +659,6 @@ export default class HTMLSelectElement extends HTMLElement {
669659
const isMultiple = this.hasAttribute('multiple');
670660
const options = QuerySelector.querySelectorAll(this, 'option')[PropertySymbol.items];
671661
const selected: HTMLOptionElement[] = [];
672-
const previousSelectedIndex = this[PropertySymbol.selectedIndex];
673662

674663
if (selectedOption) {
675664
this[PropertySymbol.selectedIndex] = -1;
@@ -728,10 +717,6 @@ export default class HTMLSelectElement extends HTMLElement {
728717
}
729718
}
730719
}
731-
732-
if (previousSelectedIndex !== this[PropertySymbol.selectedIndex]) {
733-
this.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
734-
}
735720
}
736721

737722
/**

packages/happy-dom/test/nodes/html-select-element/HTMLSelectElement.test.ts

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe('HTMLSelectElement', () => {
9595
expect(element.options.selectedIndex).toBe(0);
9696
});
9797

98-
it('Dispatches "change" event.', () => {
98+
it('Should not dispatch "change" event', () => {
9999
const option1 = <HTMLOptionElement>document.createElement('option');
100100
const option2 = <HTMLOptionElement>document.createElement('option');
101101
option1.value = 'option1';
@@ -106,13 +106,7 @@ describe('HTMLSelectElement', () => {
106106
let dispatchedEvent: Event | null = null;
107107
element.addEventListener('change', (event: Event) => (dispatchedEvent = event));
108108

109-
element.value = 'option2';
110-
111-
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
112-
113-
dispatchedEvent = null;
114-
115-
element.value = 'option2';
109+
element.value = 'option1';
116110

117111
expect(dispatchedEvent).toBeNull();
118112
});
@@ -282,7 +276,7 @@ describe('HTMLSelectElement', () => {
282276
expect(element.options.selectedIndex).toBe(-1);
283277
});
284278

285-
it('Dispatched "change" event.', () => {
279+
it('Should not dispatch "change" event', () => {
286280
const option1 = document.createElement('option');
287281
const option2 = document.createElement('option');
288282

@@ -294,12 +288,6 @@ describe('HTMLSelectElement', () => {
294288

295289
element.selectedIndex = 1;
296290

297-
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
298-
299-
dispatchedEvent = null;
300-
301-
element.selectedIndex = 1;
302-
303291
expect(dispatchedEvent).toBeNull();
304292
});
305293
});
@@ -485,7 +473,7 @@ describe('HTMLSelectElement', () => {
485473
expect(element.item(2) === option3).toBe(true);
486474
});
487475

488-
it('Dispatches "change" event.', () => {
476+
it('Should not dispatch "change" event', () => {
489477
const option1 = <HTMLOptionElement>document.createElement('option');
490478
const option2 = <HTMLOptionElement>document.createElement('option');
491479
const option3 = <HTMLOptionElement>document.createElement('option');
@@ -498,22 +486,7 @@ describe('HTMLSelectElement', () => {
498486
element.appendChild(option2);
499487
element.appendChild(option3);
500488

501-
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
502-
expect(element.selectedIndex).toBe(0);
503-
504-
dispatchedEvent = null;
505-
506-
option3.selected = true;
507-
508-
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
509-
expect(element.selectedIndex).toBe(2);
510-
511-
dispatchedEvent = null;
512-
513-
option3.remove();
514-
515-
expect((<Event>(<unknown>dispatchedEvent)).type).toBe('change');
516-
expect(element.selectedIndex).toBe(0);
489+
expect(dispatchedEvent).toBeNull();
517490
});
518491

519492
it('Sets "parentNode" of child elements to the proxy and not the original element.', () => {

packages/integration-test/test/utilities/TestFunctions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function run(description, callback) {
4343
hasError = true;
4444
hasTimedout = true;
4545
resolve();
46-
}, 60000);
46+
}, 90000);
4747
result
4848
.then(() => {
4949
if (!hasTimedout) {

0 commit comments

Comments
 (0)