Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Select] Targeting dropdown items with Cypress using data-testid when closed #44939

Open
NhutMinhIT opened this issue Jan 4, 2025 · 7 comments
Assignees
Labels
component: select This is the name of the generic UI component, not the React module! package: material-ui Specific to @mui/material status: waiting for author Issue with insufficient information test

Comments

@NhutMinhIT
Copy link

NhutMinhIT commented Jan 4, 2025

Steps to reproduce

Steps to reproduce the issue

  1. Open a live example:
    Go to the Material-UI docs page with a live example of the Select component:
    Material-UI Select Component

  2. Inspect the DOM structure:

  • Open the browser's Developer Tools (F12 or Ctrl+Shift+I).

  • Locate the <Select /> dropdown in the DOM. You'll notice that the dropdown items (<MenuItem />) are not displayed inside the same parent as the <Select /> component when the dropdown is closed.

  1. Open the dropdown:
  • Click the dropdown to open it.

  • Observe that the dropdown is displayed in a different part of the DOM, usually a sibling element to the root element (<body>), due to the use of portal.

  1. Test the data-testid attribute:
  • Use Cypress or another testing tool to target the dropdown items with data-testid.

  • If the dropdown item is not open, the items will be inaccessible, meaning that cypess has not yet recognized the data-testid for the Select element.

Current behavior

Dropdown <Select /> Behavior in Testing

The <Select /> dropdown component includes both an id and a data-testid, allowing you to use either for testing. However, there are cases where data-testid may not work as expected. Below are some common scenarios to consider:

Issues with data-testid

  1. Dropdown Not Rendered Yet
    If the dropdown has not been rendered or if there are changes in the DOM structure, the data-testid attribute might not be accessible.

  2. UI Libraries and DOM Structure
    Some UI libraries (e.g., Material-UI) render the dropdown menu in a different location in the DOM when the dropdown is opened. As a result:

    • Even if you use data-testid="role", the dropdown items (<MenuItem />) will not be accessible unless the dropdown is opened.
    • This behavior occurs because these libraries often use portals or dynamically modify the DOM structure.

Expected behavior

Recommendations for Testing

To handle these scenarios effectively when using Cypress or other testing tools:

  • Ensure Dropdown Is Open
    Before interacting with dropdown items, make sure the dropdown is opened using a method like .click() or .focus() on the trigger element.

  • Use Stable Selectors (using id)
    Prefer id attributes if they remain static across renders. While data-testid is convenient, it might not always work as intended in dynamic UI libraries.

  • Inspect DOM Behavior
    Check the DOM structure when the dropdown is open to ensure you are targeting the correct elements.

Context

Component with MUI <Select> Integration

This component demonstrates the usage of Material UI's <Select> component for selecting a role in a form. It is designed to handle form validation and updates based on user interactions.

Component Code Example

<FormControl fullWidth required>
    <InputLabel id="role-label">Select Role</InputLabel>
    <Select
        id="role"
        data-testid="role"
        labelId="role-label"
        label="Select Role"
        name="role"
        value={formData.role}
        onChange={(e) => handleSelectChange('role', e.target.value)}
        onBlur={() => handleBlur('role')}
        error={touched.role && Boolean(errors.role)}
    >
        {ROLE_OPTIONS.map((option) => (
            <MenuItem key={option.value} value={option.value} data-testid={option.value}>
                {option.label}
            </MenuItem>
        ))}
    </Select>
</FormControl>

                    
 ####This is test case
it('checks response when submitting form with valid data', () => {
    mountCreateUserDialog({
        formData: {
            username: "manager1",
            password: "Manager@123",
            email: "[email protected]",
            fullName: "Management",
            role: "manager"
        }
    });

    // Fill in the form fields
    cy.get('[data-testid="username"]').type("manager1");
    cy.get('[data-testid="password"]').type("Manager@123");
    cy.get('[data-testid="email"]').type("[email protected]");
    cy.get('[data-testid="fullName"]').type("Management");
    
    // Select the role
    cy.get('[data-testid="role"]').click({ force: true });
    cy.get('[data-testid="manager"]').click({ force: true });
    
    // Submit the form
    cy.get('[data-testid="submit-create-user-form"]').click();

    // Verify the API response
    cy.wait("@createUserRequest")
        .its("response.statusCode")
        .should("eq", 201);
});

It only works when I change `data-testid` with id` in this line:
`cy.get('[data-testid="role"]').click({ force: true })`



### Your environment

_No response_

**Search keywords**: cypress, select, mui, material ui, data-testid
@NhutMinhIT NhutMinhIT added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jan 4, 2025
@mj12albert
Copy link
Member

@NhutMinhIT Have you tried this? https://stackoverflow.com/a/70958592

@mj12albert mj12albert added component: select This is the name of the generic UI component, not the React module! package: material-ui Specific to @mui/material test labels Jan 6, 2025
@mj12albert mj12albert changed the title Select doesn't work when using Cypress, please help fix the issue [Select] Targeting dropdown items with Cypress using data-testid when closed Jan 6, 2025
@mj12albert mj12albert added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 6, 2025
@NhutMinhIT
Copy link
Author

NhutMinhIT commented Jan 6, 2025

@mj12albert Components like <TextField />, radio buttons, and checkbox work fine. However, the <Select /> component does not receive the data-testid attribute when the component is mounted, causing the use of data-testid for the <Select /> component to be missing. The data-testid is only recognized when the dropdown of the <Select /> is opened. This is because the element is stored in a different part of the DOM (maybe the virtual DOM) during the initial render before it is clicked.

I think, this problem need improve. I dont't confirm it's bug. Thanks you very much !

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jan 6, 2025
@mj12albert
Copy link
Member

The data-testid is only recognized when the dropdown of the <Select /> is opened.

Yes - this is expected, because the select menu is not rendered to the DOM at all before it's opened

I dont't confirm it's bug

Does the SO suggestion of cy.get('[data-testid="abc"]',{withinSubject:null}).should('exist'); work for you?

@mj12albert mj12albert removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jan 6, 2025
@mj12albert mj12albert self-assigned this Jan 6, 2025
@mj12albert mj12albert added the status: waiting for author Issue with insufficient information label Jan 6, 2025
@NhutMinhIT
Copy link
Author

NhutMinhIT commented Jan 7, 2025

@mj12albert
image

image
image

The Select element is not open, so the option in Select is not selected

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jan 7, 2025
@mj12albert
Copy link
Member

The Select element is not open, so the option in Select is not selected

I think you need to add an extra step to explicitly open the select menu before selecting an item

@NhutMinhIT
Copy link
Author

@mj12albert
I have this problem, i suggest note at document of Material UI.
This is my request:
#44958

THANK YOU !

@mj12albert
Copy link
Member

mj12albert commented Jan 8, 2025

@NhutMinhIT Are you able to share a minimal repro (e.g. a repo, or CodeSandbox, though separate repo is probably easier)? It's hard to go by just screenshots

In your screenshot, I think this line is wrong, [data-testid="role"] appears to be the select, not one of the options.

cy.get('[data-testid="role"]', { withinSubject: null }).should('exist');

I think what needs to be done is something like:

  1. cy.get('[data-testid="role"]').click() click the unopened component
  2. cy.get('[data-testid="manager"]', { withinSubject: null }).should('exist') assert that the menu item you are looking for exists, maybe the function form of should is needed (I'm not sure)
  3. cy.get('[data-testid="manager"]').click() lastly click the option you want

@mj12albert mj12albert added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: select This is the name of the generic UI component, not the React module! package: material-ui Specific to @mui/material status: waiting for author Issue with insufficient information test
Projects
None yet
Development

No branches or pull requests

2 participants