Skip to content

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

Open
@alshdavid

Description

@alshdavid

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?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions