reactjsseleniumtestingnightwatch

Selenium Nightwatch setValue on input only showing last character


With the following code, I am trying to test a react input passing in the value "My test", but on the screen (and in the component value) only the last "t" appears

this.useXpath()
    .waitForElementVisible('@subsetDialogNameInput')
    .clearValue('@subsetDialogNameInput')
    .setValue('@subsetDialogNameInput', name)
    .pause(500)
    .expect.element('@subsetDialogNameInput').to.have.value.that.equals(name)

The test output then becomes:

Expected element @subsetDialogNameInput <.//*[local-name()="input" and @id="Subset-name"]> to have value that equals: "My test" - expected "equals 'My test'" but got: "t"

I am running chromedriver on version 100.0.0

edit: Adding the jsx for the input field as requested

import { TextField as MuiTextField } from '@mui/material';
import clsx from 'clsx';
import type { ChangeEvent } from 'react';
import { memo } from 'react';

import { formStyle } from '@/style';

import { asteriskStyle, controlStyle, inputReadOnlyStyle, inputStyle, labelReadOnlyStyle, labelStyle, nativeInputStyle } from './style';


interface Props {
    readonly borderless: boolean;
    readonly className: string | undefined;
    readonly dark: boolean;
    readonly id: string;
    readonly label: string | undefined;
    readonly onChange: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
    readonly readOnly: boolean;
    readonly required: boolean;
    readonly type: 'text' | 'number';
    readonly value: string;
    readonly max?: number | undefined;
    readonly min?: number | undefined;
}

const TextField = ({ borderless, className, dark, onChange, id, label, max, min, readOnly, required, type, value }: Props) => (
    <MuiTextField
        autoComplete="off"
        fullWidth
        id={id}
        InputLabelProps={{
            classes: { root: clsx(labelStyle, dark ? formStyle.labelDark : formStyle.labelLight, readOnly && labelReadOnlyStyle), asterisk: asteriskStyle }
        }}
        inputProps={{ className: nativeInputStyle, max, min, tabIndex: readOnly ? -1 : 0 }}
        InputProps={{
            readOnly,
            className: clsx(
                inputStyle,
                dark ? formStyle.inputDark : formStyle.inputLight,
                borderless && formStyle.inputBorderless,
                readOnly && inputReadOnlyStyle
            )
        }}
        label={label}
        onChange={onChange}
        required={required}
        type={type}
        value={value}
        variant="filled"
        className={clsx(controlStyle, className)}
    />
);

export default memo(TextField);

Solution

  • Adding a useState hook on the parent component of the TextField, and using the callback function inside the setInputValue solves this issue. It seems that some sort of race condition is created when typing via the selenium setValue function, and using the setState callback solves it.