Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to inject the document for a render() #4500

Open
alshdavid opened this issue Sep 16, 2024 · 2 comments
Open

Add an option to inject the document for a render() #4500

alshdavid opened this issue Sep 16, 2024 · 2 comments

Comments

@alshdavid
Copy link

alshdavid commented Sep 16, 2024

The Problem

I'd like to be able to inject the document to use for my render() to allow me to use happy-dom or JSDOM to test my Preact components without assigning a global document.

Currently you must assign it to the globalThis object like so:

import { h, render } from 'preact'

// Imagine this is a mock Window
const browser = new Browser(`<body></body>`)

// Assign itto the global context so Preact can use them
globalThis.document = browser.document

// Run the preact render
render(<div>Hi</div>, browser.document.body)

However this prevents me from being able to run the tests concurrently

setTimeout(() => {
  const browser = new Browser(`<body></body>`)
  globalThis.document = browser.document
  render(<div>Hi</div>, browser.document.body)
})

setTimeout(() => {
  const browser = new Browser(`<body></body>`)
  globalThis.document = browser.document
  render(<div>Hi</div>, browser.document.body)
})

What I've Tried

I have tried to use Node's node:vm module to alter the globalThis context, however this does not work as it doesn't have access to imports.

I have tried bundling the import and using that as a script evaluation in the mock browser, however this is slow and cumbersome, negating the benefits of making tests concurrent.

Request

From what I can tell, the globalThis.document is used in the diff function: https://github.com/preactjs/preact/blob/main/src/diff/index.js#L414

  1. Use element.ownerDocument

This would allow preact to use the document object associated with the current HTMLElement

  1. Add a new function, something like renderToDom(component, target, globalContext).

This would allow me to inject the specific DOM into the render pipeline. This might cause issues with iframes though

const browser = new Browser(`<body></body>`)
renderToDom(
  <div>Hi</div>, 
  browser.document.body,
  browser.document, // <- here
)

I can raise a PR for this, is that okay?

@alshdavid alshdavid changed the title Add an option to inject the window/document context for a render() Add an option to inject the document for a render() Sep 16, 2024
@JoviDeCroock
Copy link
Member

Hey it might be worth revisiting #3042 for this

@alshdavid
Copy link
Author

Rebased it: #4501

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants