jest-dom icon indicating copy to clipboard operation
jest-dom copied to clipboard

toHaveFormValues is not working on fieldsets

Open alfechner opened this issue 6 years ago • 10 comments

  • jest-dom version: 3.1.2
  • node version: v8.11.4
  • npm version: 5.6.0

Relevant code or config:

test('toHaveFormValues', () => {
  const { getByTestId } = render(
    <form data-testid="login-form">
      <fieldset data-testid="login-fieldset">
        <input type="text" name="username" value="jane.doe" />
        <input type="password" name="password" value="12345678" />
        <input type="checkbox" name="rememberMe" checked />
        <button type="submit">Sign in</button>
      </fieldset>
    </form>
  );

  const form = getByTestId('login-form') as HTMLFormElement;
  const fieldset = getByTestId('login-fieldset') as HTMLFieldSetElement;

  // passes
  expect(form).toHaveFormValues({
    username: 'jane.doe'
  });

  // fails with "toHaveFormValues must be called on a form or a fieldset"
  expect(fieldset).toHaveFormValues({
    username: 'jane.doe'
  });
});

What you did:

I tried to check form values with toHaveFormValues on a fieldset.

What happened:

The test fails "toHaveFormValues must be called on a form or a fieldset". It works well when running the assertions on the form element, though.

Reproduction:

Run the test.

alfechner avatar Mar 14 '19 14:03 alfechner

Hmmm, I just tried extending the toHaveFormValues tests on this repo (so far only locally in my computer, I haven't pushed anything), adding a test that specifically asserts the expected values inside a fieldset element, and it passed.

Can you please provide a minimal repo reproducing the issue as it is happening to you? Maybe it will shed some light on the conditions under which it's failing in your case.

gnapse avatar Mar 18 '19 18:03 gnapse

I'm also seeing this but haven't been able to repro it on Codesandbox. I'll try to get an example repo instead.

In the meanwhile, here's what I see when I inspect the fieldset matched in jsdom, which indeed does not have an elements property.

HTMLFieldSetElement {
  '__reactInternalInstance$j29t8gct7vn':
    FiberNode {
      tag: 5,
      key: null,
      elementType: 'fieldset',
      type: 'fieldset',
      stateNode: [Circular],
      return:
      FiberNode {
        tag: 9,
        key: null,
        elementType: [Object],
        type: [Object],
        stateNode: null,
        return: [FiberNode],
        child: [Circular],
        sibling: null,
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: [Object],
        mode: 0,
        effectTag: 1,
        nextEffect: null,
        firstEffect: [FiberNode],
        lastEffect: [FiberNode],
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [FiberNode],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 29,
        _debugSource: null,
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      child:
      FiberNode {
        tag: 0,
        key: '.$on_event',
        elementType: [Function: MultilineFormRadio],
        type: [Function: MultilineFormRadio],
        stateNode: null,
        return: [Circular],
        child: [FiberNode],
        sibling: [FiberNode],
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: null,
        mode: 0,
        effectTag: 1,
        nextEffect: null,
        firstEffect: [FiberNode],
        lastEffect: [FiberNode],
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [FiberNode],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 31,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      sibling: null,
      index: 0,
      ref: null,
      pendingProps:
      { style: {}, children: [Array], className: 'sc-elNKlv eBpbxN' },
      memoizedProps:
      { style: {}, children: [Array], className: 'sc-elNKlv eBpbxN' },
      updateQueue: null,
      memoizedState: null,
      contextDependencies: null,
      mode: 0,
      effectTag: 0,
      nextEffect: null,
      firstEffect:
      FiberNode {
        tag: 0,
        key: '.1',
        elementType: [Function],
        type: [Function],
        stateNode: null,
        return: null,
        child: null,
        sibling: [FiberNode],
        index: 1,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: null,
        mode: 0,
        effectTag: 8,
        nextEffect: [FiberNode],
        firstEffect: null,
        lastEffect: null,
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: null,
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 361,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      lastEffect:
      FiberNode {
        tag: 11,
        key: '.5',
        elementType: [Object],
        type: [Object],
        stateNode: null,
        return: [Circular],
        child: [FiberNode],
        sibling: null,
        index: 3,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: null,
        mode: 0,
        effectTag: 1,
        nextEffect: [FiberNode],
        firstEffect: [FiberNode],
        lastEffect: [FiberNode],
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: null,
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 380,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      expirationTime: 0,
      childExpirationTime: 0,
      alternate:
      FiberNode {
        tag: 5,
        key: null,
        elementType: 'fieldset',
        type: 'fieldset',
        stateNode: [Circular],
        return: [FiberNode],
        child: [FiberNode],
        sibling: null,
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: null,
        mode: 0,
        effectTag: 0,
        nextEffect: null,
        firstEffect: [FiberNode],
        lastEffect: [FiberNode],
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [Circular],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 30,
        _debugSource: null,
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      actualDuration: 0,
      actualStartTime: -1,
      selfBaseDuration: 0,
      treeBaseDuration: 0,
      _debugID: 30,
      _debugSource: null,
      _debugOwner:
      FiberNode {
        tag: 9,
        key: null,
        elementType: [Object],
        type: [Object],
        stateNode: null,
        return: [FiberNode],
        child: [Circular],
        sibling: null,
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: null,
        contextDependencies: [Object],
        mode: 0,
        effectTag: 1,
        nextEffect: null,
        firstEffect: [FiberNode],
        lastEffect: [FiberNode],
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [FiberNode],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 29,
        _debugSource: null,
        _debugOwner: [FiberNode],
        _debugIsCurrentlyTiming: false,
        _debugHookTypes: null },
      _debugIsCurrentlyTiming: false,
      _debugHookTypes: null },
  '__reactEventHandlers$j29t8gct7vn':
    { style: {},
      children: [ [Object], [Object], [Object], [Object] ],
      className: 'sc-elNKlv eBpbxN' },
  [Symbol(SameObject caches)]:
    { style:
      CSSStyleDeclaration {
        _values: {},
        _importants: {},
        _length: 0,
        _onChange: [Function] },
      childNodes:
      NodeList {
        '0': [HTMLInputElement],
        '1': [HTMLLabelElement],
        '2': [HTMLInputElement],
        '3': [HTMLLabelElement],
        '4': [HTMLInputElement],
        '5': [HTMLLabelElement],
        '6': [HTMLDivElement] } } }

filoxo avatar Aug 12 '19 22:08 filoxo

Thanks for taking the time to report more details. Looking forward to the reproducible example.

gnapse avatar Aug 12 '19 23:08 gnapse

OK so I have this codesandbox https://codesandbox.io/s/react-testing-library-demo-wydte that is returning the correct elements in the browser; but when I download the repo, yarn install locally, and run the test, it is returning the entire current jsdom (suggesting that it is returning the default of "everything" because elements does not exist on the fieldset).

Here's some additional details:

  • react-testing-library: 6.1.2
  • jest-dom: 3.1.4
  • node version: v11.6.0
  • yarn version: 1.17.0

filoxo avatar Aug 13 '19 15:08 filoxo

I just got the same issue in a personal project. It should be reproducible with this (using react-testing-library):

it('should get fieldset value', () => {
  const { queryByRole, getByText } = render(
    <fieldset>
      <label>
        <input type="radio" name="foo" value="a" />
        option A
      </label>
      <label>
        <input type="radio" name="foo" value="b" />
        option B
      </label>
    </fieldset>
  );

  fireEvent.click(getByText('option B'));

  expect(queryByRole('group')).toHaveFormValues({ foo: 'b' });
});

Editing to add info about the env:

Belco90 avatar Sep 24 '19 14:09 Belco90

I ran into this today. Used @Belco90's test and it failed with toHaveFormValues must be called on a form or a fieldset. Try to recreate it on codesandbox and it passes every time. If it helps at all, I recreated it in a Create React App. I wonder if this is some kind of transpiling problem?

"dependencies": {
    "@material-ui/core": "4.5.1",
    "@material-ui/icons": "4.5.1",
    "@material-ui/styles": "4.5.0",
    "@testing-library/jest-dom": "5.1.1",
    "@testing-library/react": "9.4.0",
    "@testing-library/user-event": "10.0.0",
    "fast-json-patch": "^3.0.0-1",
    "react": "^16.12.0",
    "react-async": "^10.0.0",
    "react-dom": "^16.12.0",
    "react-ga": "^2.7.0",
    "react-gtm-module": "^2.0.8",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.3.0",
    "typeface-roboto": "0.0.75"
  },
  • node - 12.14.1
  • npm - 6.13.4

williamscs avatar Feb 20 '20 05:02 williamscs

Can't we just replace the method with this?

const formData = new FormData(form);
return Object.fromEntries(formData.entries());

Not sure if it would cause compatibility issues or whatnot. But it did work in my instance, where I had (don't ask why) several fieldsets nested in a single form.

<form>
  <fieldset>...</fieldset>
  <fieldset>...</fieldset>
  <fieldset>...</fieldset>
  <fieldset>...</fieldset>
</form

davidanitoiu avatar Dec 18 '20 21:12 davidanitoiu

@davidanitoiu I'm not sure I understand your suggestion. Replace what method with what you suggest?

As for the original report, I still cannot reproduce in the very tests of this library. I stand by my comment above (https://github.com/testing-library/jest-dom/issues/87#issuecomment-474055218).

Can someone provide a small minimal repo that reproduces the issue? It would go a long way in helping us identify the problem and fix it.

gnapse avatar Dec 29 '20 13:12 gnapse

Is there a reason to ignore the repro I shared in 2019? Its right after your comment asking for a repro, and there was no feedback.

filoxo avatar Dec 29 '20 15:12 filoxo

Sorry, I never gave my feedback on it at the time, and I tried it again now. I don't see any use of toHaveFormValues in the couple of tests file in that repo. I also make a project-wide search for that name with no luck.

Also, both test files pass for me, in Codesandbox running in the browser and when run locally using jsdom. Maybe I am missing something?

gnapse avatar Dec 30 '20 01:12 gnapse