1

I have a unit test in StencilJS in which I am using a jest matcher from jest-dom. When I run the test it throws an error:

TypeError: Right-hand side of 'instanceof' is not an object
      at checkHtmlElement (node_modules/@testing-library/jest-dom/dist/utils.js:61:69)
      at Object.toHaveFormValues (node_modules/@testing-library/jest-dom/dist/to-have-form-values.js:75:31)
      at __EXTERNAL_MATCHER_TRAP__ (node_modules/expect/build/index.js:342:30)
      at Object.throwingMatcher [as toHaveFormValues] (node_modules/expect/build/index.js:343:15)

The unit test is:

import '@testing-library/jest-dom';
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { AgForm, FormRenderProps } from '../ag-form';
import {getByTestId} from "@testing-library/dom";

describe('ag-form', () => {
  it('sets initial string value', async () => {
    type TestFormValues = {
      stringValue: string;
    };

    const initialValues: TestFormValues = {
      stringValue: 'foo',
    };

    const page = await newSpecPage({
      components: [AgForm],
      template: () => (
        <ag-form
          initialValues={initialValues}
          renderer={(props: FormRenderProps<TestFormValues>) => {
            const { inputProps } = props;
            return (
              <form data-testid="test-form">
                <input {...inputProps('stringValue')} />
              </form>
            );
          }}
        />
      ),
    });

    const formElement = getByTestId(page.body, 'test-form')
    expect(formElement).toHaveFormValues(initialValues);
  });
});

The error is getting thrown from this function in jest-dom, which is checking whether a valid HTMLElement is being passed into the matcher:

function checkHtmlElement(htmlElement, ...args) {
  checkHasWindow(htmlElement, ...args);
  const window = htmlElement.ownerDocument.defaultView;

  if (!(htmlElement instanceof window.HTMLElement) && !(htmlElement instanceof window.SVGElement)) {
    throw new HtmlElementTypeError(htmlElement, ...args);
  }
}

What's interesting is the error is coming from the right hand side of the if statement (as window.SVGElement is undefined), however I believe the actual problem is it shouldn't be getting to that part of the code. On the left hand side of that if statement the check of htmlElement instanceof window.HTMLElement is coming back as false, as htmlElement is of type HTMLFormElement whereas window.HTMLElement appears to be a MockHtmlElement.

So my question is - is there a way to get jest-dom to work with StencilJS unit tests, as it appears that the environment that stencil sets up isn't what jest-dom is expecting?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Ric
  • 405
  • 3
  • 12

1 Answers1

1

I'm going to answer my own question after digging into it some more and I think the answer is just that jest-dom is not going to work with Stencil.

Jest's default environment is jsdom, which it uses to create a browser-like environment within the tests. However Stencil creates its own environment that Jest uses instead, including its own mocked DOM. This mock DOM implementation is not (yet) fully featured, so libraries that have been written with jsdom in mind, like jest-dom and DOM-testing-library are failing.

Ric
  • 405
  • 3
  • 12