Access native html dialogs show/close methods in clickHandler

Hey folks, I am currently using native html dialogs inside my app and am accessing their show/close methods by using them from window (e.g. window.myModal.show()). However this is pretty error prone and also doesn't play well with testing. Is there a recommended way on how to use these without accessing the window? I thought of using refs but apparently these refs are not set, when my handler functions are created, so they stay undefined. 🤔 Ideally I would export show/close functions from my component file that could be used everywhere througout the app. Any idea what would be a good way to solve this?
11 Replies
oneiro
oneiroOP2y ago
ah, It seems to work if I just use as signal setter inside the ref and access the signal. Is this the recommended approach, or does this have any downsides, I am not aware of, yet? for example:
const [myRef, setMyRef] = createSignal<HTMLDialogElement>()

export const showMyDialog = () => {
myRef()?.show()
}

function MyDialog() {
return (
<dialog ref={setMyRef}>Something</dialog>
)
}
const [myRef, setMyRef] = createSignal<HTMLDialogElement>()

export const showMyDialog = () => {
myRef()?.show()
}

function MyDialog() {
return (
<dialog ref={setMyRef}>Something</dialog>
)
}
hm, this still doesn't seem to play well with tests 🤔
Alex Lohr
Alex Lohr2y ago
I guess jsdom does not support the dialog tag's extensions.
oneiro
oneiroOP2y ago
ah damn 😦
Alex Lohr
Alex Lohr2y ago
It should be possible to patch this on the prototype. I'm currently not on my PC, so I cannot easily test it myself, though.
oneiro
oneiroOP2y ago
ah, thanks. Hm - how would I mock the functionality attached to buttons on a dialog, though 🤔
Alex Lohr
Alex Lohr2y ago
Give me a moment...
oneiro
oneiroOP2y ago
(another small issue i noticed with my approach above is, that apparently refs can break on HMR-updates 😬 ) - so they no longer work after making changes to our codebase
Alex Lohr
Alex Lohr2y ago
I'm not too deep in the whole HMR stuff, so I cannot answer this one. HMR + testing is still mostly broken. You can attach a click listener to the dialog tag on calling open and remove it on close().
oneiro
oneiroOP2y ago
I still wouldn't have access to the markup inside the dialog, though, right? So I would need a different testing-lib query? Or am I mssing something?
Alex Lohr
Alex Lohr2y ago
You can use the event.target. at least inside the test, dialog is just another HTML element.
oneiro
oneiroOP2y ago
@lexlohr Ah nice I just realised, that it seems to be easier, than I thought. I got the following code, from this issue: https://github.com/jsdom/jsdom/issues/3294
beforeEach(() => {
resetGlobalStores()

HTMLDialogElement.prototype.show = vi.fn(function mock(this: HTMLDialogElement) {
this.open = true
})

HTMLDialogElement.prototype.showModal = vi.fn(function mock(this: HTMLDialogElement) {
this.open = true
})

HTMLDialogElement.prototype.close = vi.fn(function mock(this: HTMLDialogElement) {
this.open = false
})
})
beforeEach(() => {
resetGlobalStores()

HTMLDialogElement.prototype.show = vi.fn(function mock(this: HTMLDialogElement) {
this.open = true
})

HTMLDialogElement.prototype.showModal = vi.fn(function mock(this: HTMLDialogElement) {
this.open = true
})

HTMLDialogElement.prototype.close = vi.fn(function mock(this: HTMLDialogElement) {
this.open = false
})
})
Now the dialog will actually be shown, and can be queried with testing-library 👍
GitHub
Any plans to add support for the HTMLDialogElement? · Issue #3294 ·...
Basic info: Node.js version: v16.13.0 jsdom version: 18.1.0 Minimal reproduction case /** * show and showModal don't exist (jsdom + HTMLDialogElement) */ // Suite('can have state toggled...
Want results from more Discord servers?
Add your server