Under Review
Last Updated: 20 May 2022 08:33 by ADMIN
Kyle
Created on: 02 May 2022 22:50
Type: Bug Report
4
Some components ignore html data attributes

In our unit tests, we sometimes want to be able to use the ByTestId methods of the React Testing Library to find bits of DOM created by a Kendo component.  However, setting a data-testid attribute (or really any data- attribute) on a Kendo component does not always result in the attribute appearing anywhere in the final DOM.

To demonstrate, below is a test suite (also included in the zip) where I tried putting a data-testid attribute on the Kendo components Input, TextArea, Checkbox, Slider, SliderLabel, MultiSelect, and DatePicker, then checked if the attribute appeared in the rendered DOM.  The tests for Input, TextArea, and Checkbox are successful.  The ones for Slider, SliderLabel, MultiSelect, and DatePicker are not.

import { render, screen } from '@testing-library/react';
import { Input, TextArea, Checkbox, Slider, SliderLabel } from '@progress/kendo-react-inputs';
import { MultiSelect } from '@progress/kendo-react-dropdowns';
import { DatePicker } from '@progress/kendo-react-dateinputs';

// SUCCEEDS
describe('Kendo Input', () => {
    it('supports data attributes', () => {
        render(
            <Input data-testid="the-input" />
        );

        const input = screen.queryByTestId('the-input');
        expect(input).toBeTruthy();
    });
});

// SUCCEEDS
describe('Kendo TextArea', () => {
    it('supports data attributes', () => {
        render(
            <TextArea data-testid="the-text-area" />
        );

        const textarea = screen.queryByTestId('the-text-area');
        expect(textarea).toBeTruthy();
    });
});

// SUCCEEDS
describe('Kendo Checkbox', () => {
    it('supports data attributes', () => {
        render(
            <Checkbox label={"Chad"} data-testid="the-checkbox" />
        );

        const checkbox = screen.queryByTestId('the-checkbox');
        expect(checkbox).toBeTruthy();
    });
});

// FAILS
describe('Kendo Slider & SliderLabel', () => {
    it('supports data attributes', () => {
        render(
            <Slider min={1} max={2} data-testid="slider-root">
                <SliderLabel position={1} data-testid="slider-label-1">One Fish</SliderLabel>
                <SliderLabel position={2} data-testid="slider-label-2">Two Fish</SliderLabel>
            </Slider>
        );

        const sliderRoot = screen.queryByTestId('slider-root');
        const sliderLabel1 = screen.queryByTestId('slider-label-1');
        const sliderLabel2 = screen.queryByTestId('slider-label-2');

        // test them all at once so we can know the full scope of our failure/success
        expect({
            sliderRoot,
            sliderLabel1,
            sliderLabel2
        }).toMatchObject({
            sliderRoot:   expect.anything(), // don't be null or undefined
            sliderLabel1: expect.anything(), // don't be null or undefined
            sliderLabel2: expect.anything()  // don't be null or undefined
        });
    });
});

// FAILS
describe('Kendo MultiSelect', () => {
    it('supports data attributes', () => {
        render(
            <MultiSelect data-testid="the-multi-select" />
        );

        const multiselect = screen.queryByTestId('the-multi-select');
        expect(multiselect).toBeTruthy();
    });
});

// FAILS
describe('Kendo DatePicker', () => {
    it('supports data attributes', () => {
        render(
            <DatePicker data-testid="the-date-picker" />
        );

        const datepicker = screen.queryByTestId('the-date-picker');
        expect(datepicker).toBeTruthy();
    });
});
While it is theoretically possible the problem is limited to just Slider, SliderLabel, MultiSelect, and DatePicker, I highly doubt it.
3 comments
ADMIN
Konstantin Dikov
Posted on: 20 May 2022 08:33

Hi Kyle,

I brought this topic to the teams attention and we have agreed that adding an "attribute" property for all components will be extremely beneficial for many use cases and we are going to plan its implementation. The idea would be to have "attribute" property that will accept an object with all custom attributes. It will also allow the developers to override some of the default attributes.

 

Regards,
Konstantin Dikov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Kyle
Posted on: 19 May 2022 22:23

The Hint and Error components are also ignoring any data attributes set on them, without the excuse of being "complex"; they're about as simple as it gets.  Furthermore, neither of them have a ref prop, so setting the attributes the already-hard-way inside a useEffect now has the added step of setting a ref on an ancestor element and then querying down from it to the .k-form-hint or .k-form-error.  And that defeats the whole point of setting data-testid in the first place, which is to avoid having tests depend on CSS classes.

Even if the ref props were there, though, there is still an exponential difference between putting data-testid="field-error" directly on the component, vs. creating a whole ref and useEffect callback to do the same via JavaScript.  Not just in the doing, but in the consuming later as well.  A month later when we're adding new tests, will we know to look in a useEffect of all things to find this component's data-testid, even though that component and that component have their data-testids clearly specified right in the JSX?  I'm doubtful.

ADMIN
Konstantin Dikov
Posted on: 03 May 2022 15:08

Hello Kyle,

Thank you for posting the request.

Each component from the KendoReact suite has a set of available properties that can be set and custom attributes could be set for simple components that render input element. More complex components do not support such custom attributes. Nevertheless, for input elements it is possible to add custom attributes as shown in the following help article:

Usually, the DOM element of each component can be accessed with the approach demonstrated in the above article, which allows the developers to add custom attributes to the DOM elements as per the exact requirements. This also allows adding attributes to nested elements. 

Nevertheless, we will leave the feature request open and we will keep an eye on it. If there is a huge demand for it, we might consider adding more straightforward approach that would allow adding custom attributes for all components in the suite. However, have in mind that each component have different structure and if such feature is implemented, those custom attributes would be added to the wrapping element.

 

Regards,
Konstantin Dikov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.