#document is not defined error while testing preact hooks

6 messages · Page 1 of 1 (latest)

tight jolt
#

Currently I'm developing a preact hooks library. When I try to run a simple test using deno test, it throws me the next error:

error: ReferenceError: document is not defined

Here is the code of the test I'm doing and the deno.json at root and workspace

Code:

import { renderHook } from "@testing-library/preact";
import { useFetch } from "@/hooks/use-fetch.ts";
import { expect } from "@std/expect";

Deno.test("Use fetch", () => {
    const { result } = renderHook(()=> useFetch("https://jsonplaceholder.typicode.com/todos/1"))
    expect(result.current.data).not.toEqual(null);
});

deno.json (root)

{
  "workspace": [
    "./packages/pretch-core",
    "./packages/pretch-preact",
    "./packages/pretch-react"
  ],
  "compilerOptions": {
    "lib": [
      "dom",
      "dom.iterable",
      "dom.asynciterable",
      "deno.ns"
    ],
    "jsx": "react-jsx",
    "jsxImportSource": "preact"
  },
  "lint": {
    "rules": {
      "include": [
        "no-console",
        "ban-types",
        "camelcase",
        "verbatim-module-syntax"
      ]
    }
  },
  "exclude": [
    ".git",
    ".vscode"
  ],
  "imports": {
    "@std/expect": "jsr:@std/expect@^1.0.5",
    "@testing-library/dom": "npm:@testing-library/dom@^10.4.0"
  }
}

deno.json (workspace)

{
  "name": "@prefetch/preact",
  "version": "0.1.2",
  "tasks": {
    "doc": "deno doc --html --name='Pretch' src"
  },
  "imports": {
    "@preact/signals": "npm:@preact/signals@^1.3.0",
    "@std/assert": "jsr:@std/assert@1",
    "preact": "npm:preact@^10.24.1",
    "@/": "./",
    "@std/expect": "jsr:@std/expect@^1.0.5",
    "@testing-library/preact": "npm:@testing-library/preact@^3.2.4"
  },
  "exports": {
    ".": "./mod.ts"
  }
}
meager cobalt
#

@livid geyser can you please take a look?

livid geyser
#

The way the @testing-library/preact works is that it expects to be run inside an environment where a subset of the DOM APIs are available. The idea behind it is that you're asserting against the rendered result.

By default, server runtimes don't ship with the DOM API as it's something mostly for users. This means you need to include a library like happy-dom, deno_dom, linkedom or JSDom to polyfill that.

Adding any of these libraries and setting up the document global according to their documentation will resolve the issue.

meager cobalt
tight jolt
livid geyser
#

Sure, copy & pasting the example on how to use JSDOM straight out of the readme gives you this:

  import { renderHook } from "@testing-library/preact";
  import { useFetch } from "@/hooks/use-fetch.ts";
  import { expect } from "@std/expect";
  
+ import { JSDOM } from "npm:jsdom";
+ const { document } = (new JSDOM("")).window;
+ (globalThis as any).document = document;
  
  Deno.test("Use fetch", () => {
      const { result } = renderHook(()=> useFetch("https://jsonplaceholder.typicode.com/todos/1"))
      expect(result.current.data).not.toEqual(null);
  });