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

feat: Make screen compatible with document.body.replaceWith() #1311

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jdufresne
Copy link
Contributor

@jdufresne jdufresne commented Apr 28, 2024

What:

The screen utility no longer caches the body element at import time. When the body or entire HTML document changes with replaceWith(), the screen utility continues to operate on the global value.

Why:

Closes #1310

My integration testing environment strives to creates testing scenarios that are as realistic to production as possible. This aligns with the library's guiding principles:

We try to only expose methods and utilities that encourage you to
write tests that closely resemble how your web pages are used.

To assist with this, parts of my integration testing environment involve a 2-step process:

  1. Run a command to dump the HTML documents rendered by the backend.
  2. Load those dumps into a Jest test environment to assert JavaScript behavior.

Loading the HTML document in Jest is a challenge as the global HTML document is setup by jest-environment-jsdom ahead of the test running. To make this work well, the environment "replaces" the jsdom HTML document like:

const content = loadHTML(...);
const tmpDom = new jsdom.JSDOM(content);
const tmpDocument = tmpDom.window.document;
// Replace the global document with the one from the backend.
document.documentElement.replaceWith(document.adoptNode(tmpDocument.documentElement));

This works out great in practice for me. The JavaScript is tested against real HTML documents rather than fabricated ones for the test. In the event that the backend changes how elements are rendered that, the integration tests will expose this and force a fix to make the two compatible.

With this change, the screen utility is now usable as a convenience.

How:

Rather than caching the document.body at import time, screen now dynamically uses the most up date value on the global document.

Checklist:

  • Documentation added to the
    docs site N/A
  • Tests
  • TypeScript definitions updated
  • Ready to be merged

Copy link

codesandbox-ci bot commented Apr 28, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 430e952:

Sandbox Source
react-testing-library-examples Configuration

@jdufresne
Copy link
Contributor Author

Right now this fails type checks with the errors:

Error: [typecheck] src/screen.ts(54,19): error TS7019: Rest parameter 'args' implicitly has an 'any[]' type.
Error: [typecheck] src/screen.ts(61,30): error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.

I'm uncertain how to best resolve this.

What:

The screen utility no longer caches the body element at import time.
When the body or entire HTML document changes with replaceWith(), the
screen utility continues to operate on the global value.

Why:

My integration testing environment strives to creates testing scenarios
that are as realistic to production as possible. This aligns with the
library's guiding principles:

> We try to only expose methods and utilities that encourage you to
> write tests that closely resemble how your web pages are used.

To assist with this, parts of my integration testing environment involve
a 2-step process:

1. Run a command to dump the HTML documents rendered by the backend.
2. Load those dumps into a Jest test environment to assert JavaScript
behavior.

Loading the HTML document in Jest is a challenge as the global HTML
document is setup by jest-environment-jsdom ahead of the test running.
To make this work well, the environment "replaces" the jsdom HTML
document like:

```
const content = loadHTML(...);
const tmpDom = new jsdom.JSDOM(content);
const tmpDocument = tmpDom.window.document;
// Replace the global document with the one from the backend.
document.documentElement.replaceWith(document.adoptNode(tmpDocument.documentElement));
```

This works out great in practice for me. The JavaScript is tested
against real HTML documents rather than fabricated ones for the test. In
the event that the backend changes how elements are rendered that, the
integration tests will expose this and force a fix to make the two
compatible.

With this change, the screen utility is now usable as a convenience.

How:

Rather than caching the document.body at import time, screen now
dynamically uses the most up date value on the global document.
@jdufresne jdufresne changed the title Make screen compatible with document.body.replaceWith() feat: Make screen compatible with document.body.replaceWith() Apr 28, 2024
@jdufresne jdufresne closed this May 4, 2024
@jdufresne jdufresne deleted the replacewith branch May 4, 2024 14:52
@jdufresne jdufresne restored the replacewith branch May 6, 2024 22:06
@jdufresne jdufresne reopened this May 6, 2024
@jdufresne jdufresne marked this pull request as draft May 6, 2024 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

screen incompatible with document.body.replaceWith()
1 participant