Blueprint: DocumentFragment is not defined in jsdom + dom4

Created on 3 Jan 2017  路  17Comments  路  Source: palantir/blueprint

Bug report

I have a high order component that uses some Components from Blueprint/core and I've been trying to test it using Mocha and Enzyme. But, for some reason, when I try running my tests, they break and say I don't have DocumentFragment from dom4.max.js.

Package version: 1.4.0
OS versions: Ubuntu 16.04

Steps to reproduce

  1. Have a high order React Component that calls Blueprint
  2. Write a test for it with Enzyme + Mocha
  3. Run the tests

Actual behavior

/node_modules/dom4/build/dom4.max.js:141 -> DocumentFragmentPrototype = window.DocumentFragment && DocumentFragment.prototype

DocumentFragment is not defined

testing P1 core bug help wanted

Most helpful comment

This worked for me:

const keys = [
  'DocumentFragment',
  'Event',
  'KeyboardEvent',
  'MouseEvent'
]
keys.forEach((key) => {
  global[key] = document.defaultView[key]
})
global.self = document.defaultView

All 17 comments

@lucantini you must include typings for dom4, it's a core dependency of the library.

@blueprintjs/core v1.4.0 actually includes an NPM dependency on @types/dom4: https://github.com/palantir/blueprint/blob/master/packages/core/package.json#L9

@giladgray I'm using the 1.4.0 version of @blueprint/core and this problem still occurs.

the fix is to include @types/dom4 in your TypeScript compilation context, whatever that means for your project.

  1. is @types/dom4 installed?
  2. is it included in tsconfig.json?

sorry hold up, if this is a _runtime_ error then you need to import "dom4" directly in your application so the polyfills will be included.

final clarification:

if you import { X } from "@blueprintjs/core" (root import) then dom4 will be included automatically. if instead you import { X } from "@blueprintjs/core/dist/components/..." (relative import) then dom4 is _not_ included automatically and __you must do so yourself__.

Classic NPM.

We do not use TypeScript in our project :(

We are importing from root, as you said above:
import { Spinner } from '@blueprint/core'

In that case we don't need to import dom4 directly, right? It comes as a devDependency from blueprint itself - I tried importing dom4 anyway and it didn't worked either.

It's worth mentioning that this problem only occurs when we run our tests. The component works perfectly otherwise.

are you doing something special in your test setup that might exclude dom4? or perhaps you're running code before dom4 has loaded? or not running in a real browser environment? which file produces the error above?

this issue is beginning to seem very specific to your project setup and there's little I can do beyond telling you that this is a dom4 issue.

global.document = jsdom(''); global.window = document.defaultView; Object.keys(document.defaultView).forEach((property) => { if (typeof global[property] === 'undefined') { global[property] = document.defaultView[property]; } });
This is our test configuration with jsdom. Do you think this can be the problem by any means?

ah yes JSDom... this is why we don't use it internally yet. i tried setting up jsdom + dom4 and had some serious trouble because dom4 expects a "real browser" which jsdom just barely isn't.

sorry, i can't offer any more support for this 馃槩 . but i would love to hear if you're successful making dom4 work with JSDom, because we'd like to migrate to it too.

You could try shimming DocumentFragment, here's an example: https://github.com/barberboy/dom-elements/blob/d12ce3dd2e49e3e928e1501f6b9cbaa82385c217/src/index.js#L24

dom4 should also handle this more nicely -- let's file an issue / send a PR to add better support for jsdom

Can you show me an example of using dom4 instead of jsdom to configure both window and document? I ain't able to find it.

sorry, i haven't done it either. i suggest prodigious googling to understand how the two can play together.

Same issue, a lot of people use that kind of config: jsdom + enzyme + mocha/jest, it could be called a standard.

We've hit this same issue while attempting to integrate blueprint into our app this week. Our setup is the standard jsdom + enzyme + mocha.

This worked for me:

const keys = [
  'DocumentFragment',
  'Event',
  'KeyboardEvent',
  'MouseEvent'
]
keys.forEach((key) => {
  global[key] = document.defaultView[key]
})
global.self = document.defaultView

Good job @gimenete, thanks a lot .
Your solution saved my life :)

@lucantini It seems that not all properties in document.defaultView are enumerable. So some properties like DocumentFragment are missing because are not returned by Object.keys or a for-in loop. Check my previous comment.

Was this page helpful?
0 / 5 - 0 ratings