Skip to content

Commit

Permalink
fix: [#1534] Toggle open attribute on HTMLDetailsElement when dispatc…
Browse files Browse the repository at this point in the history
…hing a click event on a summary element which is a child of the details element (#1534)

* fix: [#1534] Fix click event not removing open attribute

* chore: [#1534] Adds unit tests and adds some additional logic according to the spec

---------

Co-authored-by: David Ortner <david@ortner.se>
  • Loading branch information
mikedidomizio and capricorn86 authored Nov 4, 2024
1 parent 7f57469 commit 8f74989
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Event from '../../event/Event.js';
import HTMLElement from '../html-element/HTMLElement.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import Attr from '../attr/Attr.js';
import EventPhaseEnum from '../../event/EventPhaseEnum.js';
import MouseEvent from '../../event/events/MouseEvent.js';

/**
* HTMLDetailsElement
Expand Down Expand Up @@ -56,4 +58,23 @@ export default class HTMLDetailsElement extends HTMLElement {
this.dispatchEvent(new Event('toggle'));
}
}

/**
* @override
*/
public override dispatchEvent(event: Event): boolean {
const returnValue = super.dispatchEvent(event);

if (
!event[PropertySymbol.defaultPrevented] &&
event[PropertySymbol.target]?.[PropertySymbol.localName] === 'summary' &&
event.type === 'click' &&
event.eventPhase === EventPhaseEnum.bubbling &&
event instanceof MouseEvent
) {
this.open = !this.open;
}

return returnValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Window from '../../../src/window/Window.js';
import Document from '../../../src/nodes/document/Document.js';
import { beforeEach, describe, it, expect, vi } from 'vitest';
import Event from '../../../src/event/Event.js';
import MouseEvent from '../../../src/event/events/MouseEvent.js';

describe('HTMLDetailsElement', () => {
let window: Window;
Expand Down Expand Up @@ -51,5 +52,21 @@ describe('HTMLDetailsElement', () => {
element.open = false;
expect((<Event>(<unknown>triggeredEvent)).type).toBe('toggle');
});

it('Should not toggle the open state when a click event is dispatched directly on the details element', () => {
element.dispatchEvent(new MouseEvent('click'));
expect(element.open).toBe(false);
});

it('Should toggle the "open" attribute when a click event is dispatched on a summary element, which is a child of the details element', () => {
const summary = document.createElement('summary');
element.appendChild(summary);

summary.click();
expect(element.open).toBe(true);

summary.click();
expect(element.open).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,34 @@ describe('TestingLibrary', () => {
expect(attribute).toMatch('test');
expect(attribute).not.toMatch('hello');
});

it('Removes and adds `open` attribute for `<details>` element on click event.', async () => {
const user = UserEvent.setup();
const handleToggle = jest.fn();

render(
<details open={true} onToggle={handleToggle}>
<summary>summary</summary>details
</details>
);

expect(document.body.innerHTML).toBe(
'<div><details open=""><summary>summary</summary>details</details></div>'
);
expect(handleToggle).toHaveBeenCalledTimes(0);

await user.click(screen.getByText('summary'));

expect(document.body.innerHTML).toBe(
'<div><details><summary>summary</summary>details</details></div>'
);
expect(handleToggle).toHaveBeenCalledTimes(1);

await user.click(screen.getByText('summary'));

expect(document.body.innerHTML).toBe(
'<div><details open=""><summary>summary</summary>details</details></div>'
);
expect(handleToggle).toHaveBeenCalledTimes(2);
});
});

0 comments on commit 8f74989

Please sign in to comment.