timofeysie / dynamic-forms

A React app implementing a dynamic forms framework
2 stars 0 forks source link

test id doesn't get projected into the react-datepicker component #2

Closed timofeysie closed 4 years ago

timofeysie commented 4 years ago

Datepicker creates react-datepicker-wrapper and react-datepicker__input-container, but the test id doesn't get projected into the component so we get the error: Unable to find an element by: [data-testid="datepickerid"]

timofeysie commented 4 years ago

There is an open issue for this on the datepicker GitHub.

timofeysie commented 4 years ago

Trying to use className, or even id on the element results in this error:

(JSX attribute) id: string
Type '{ id: string; name: any; required: any; key: any; handleChange: (e: FormEvent<HTMLInputElement>) => void; }' is not assignable to type 'IntrinsicAttributes & IProps'.
  Property 'id' does not exist on type 'IntrinsicAttributes & IProps'.ts(2322)
timofeysie commented 4 years ago

Until that issue linked above is resolved, what are the options here? The DOM snapshot looks like this currently:

         <div>
            <div class="react-datepicker-wrapper">
              <div class="react-datepicker__input-container">
                <input
                  autocomplete="off"
                  class=""
                  name="dob"
                  required=""
                  type="text"
                  value="02/15/2020"
                />
              </div>
            </div>
  1. put a test id on a surrounding div.
  2. use a different way to target the input, such as getByName (doesn't exists) or getByDisplayValue
  3. use the workaround from the linked issue: customInput={<input data-testid="some-test-id" type="text" />}
  4. use the react-datepicker__input-container and something like container.firstChild.className

One well known issue with snapshot testing is components that have changing values such as, you guessed it, the date. I would be good to pass only static dates into the input in the unit tests and make sure the format is respected.

So that's an issue with option 2, but worth the effort given our limited options. Option 4 actually looks like the easiest way to start for now.

timofeysie commented 4 years ago

Going with option one, we get this back now as the container:

 <div data-testid="datepickerid">
  <div class="react-datepicker-wrapper">
    <div class="react-datepicker__input-container">
      <input autocomplete="off" class="" name="dob" required="" type="text" value="02/16/2020" />
    </div>
  </div>
</div>

Would like to do something like this:

getAllByTestId("datepickerid").getElementsByTagName("input")

But the result for that is:

 TypeError: getAllByTestId(...).getElementsByTagName is not a function

So more work needs to be done to target the input for the unit tests on this component.

timofeysie commented 4 years ago

One way that works is to manually drill down to get the grandchild inut element:

    const { getByTestId } = testing_lib_render(<DynamicForm fields={fields}/>);
    const elem = getByTestId("datepickerid");
    expect(elem.children[0].children[0].children[0]).toHaveAttribute('value', '02/15/2020');

There we can test attributes.