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

[DataGrid] All JSDOM tests fail with v6.2.1 #8697

Closed
2 tasks done
ddolcimascolo opened this issue Apr 21, 2023 · 29 comments · Fixed by #8968
Closed
2 tasks done

[DataGrid] All JSDOM tests fail with v6.2.1 #8697

ddolcimascolo opened this issue Apr 21, 2023 · 29 comments · Fixed by #8968
Labels
component: data grid This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation plan: Premium Impact at least one Premium user test

Comments

@ddolcimascolo
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Steps to reproduce 🕹

Not required

Current behavior 😯

All tests fail.

Expected behavior 🤔

All tests pass, or @mui explain what needs to be changed

Context 🔦

In JSDOM, we historically need to mock stuff to make the grid render (see #2945 for instance).
Starting with v6.2.1 grids do not render the "virtual scroller" area anymore, and having a look at the code does not tell me why. I need your help in fixing this and I'm totally open to mocking more stuff, it's just unclear what :)

Premium customer here

Your environment 🌎

npx @mui/envinfo
  System:
    OS: Linux 5.19 Linux Mint 21.1 (Vera)
  Binaries:
    Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
    Yarn: Not Found
    npm: 8.19.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
  Browsers:
    Chrome: 112.0.5615.165
    Firefox: 112.0.1

Order ID or Support key 💳 (optional)

31461

@ddolcimascolo ddolcimascolo added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Apr 21, 2023
@zannager zannager added component: data grid This is the name of the generic UI component, not the React module! plan: Premium Impact at least one Premium user labels Apr 21, 2023
@ddolcimascolo
Copy link
Author

Adding Mocks for ResizeObsever that was added in this version did not help. I understand that it's used for resize detection but it's non availability should not prevent the virtual scroller from rendering

@ddolcimascolo
Copy link
Author

OK, finally it did help to add mocks for ResizeObserver. Here's how I got my tests back

beforeEach(mockResizeObserver);

function mockResizeObserver() {
  window.ResizeObserver = class ResizeObserver {
    constructor(callback) {
      this.callback = callback;
    }

    observe(target) {
      setTimeout(() => this.callback([{ target }]), 0);
    }

    unobserve() {}

    disconnect() {}
  };
}

You'll notice the ugly setTimeout in the observe method to call the listener. My initial tentative was calling the listener directly, and apparently the main div of the grid is not rendered yet at that time, or any other side-effect I'm not aware of was preventing the grid from rendering 😓 Calling the listener in the next tick works.

I hope it helps other JSDOM users out there.

Cheers,
David

@dnikhila
Copy link

dnikhila commented Apr 24, 2023

Still I do face same issue suddently test cases wer failing -> previously I sorted out using disableVirtualization,autoHeight using datagridpro - ^6.1.0, rows and columns were not rendering in test cases - using jest with react testing.

Tried using window.ResizeObserver (above solution), still the issue persists.

@p-m-p
Copy link

p-m-p commented Apr 24, 2023

I'm also seeing this but mocking ResizeObserver has no effect. From what little I can see hasDimensions in GridBody is not set and the body of the grid is not rendered. Works fine in v6.2.0.

In my tests I have a div with set dimensions around the grid, autoHeight is set true and virtualization is disabled.

@dnikhila
Copy link

This is how snapshot renders it includes col and row count but it was not rendering ->

  <div
            aria-colcount="4"
            aria-multiselectable="true"
            aria-rowcount="3"
            class="MuiDataGrid-root-czaLuz bmEiLl MuiDataGrid-root MuiDataGrid-autoHeight MuiDataGrid-root--densityStandard MuiDataGrid-withBorderColor"
            role="grid"
          >
            <div
              class="MuiDataGrid-main-gYeYdy hGlvJW MuiDataGrid-main"
            >
              <div
                class="MuiDataGrid-columnHeaders-hmyAqf joUSja MuiDataGrid-columnHeaders MuiDataGrid-withBorderColor"
                style="min-height: 56px; max-height: 56px; line-height: 56px;"
              >
                <div
                  class="MuiDataGrid-columnHeadersInner-dYCRFF gMqqpv MuiDataGrid-columnHeadersInner"
                  role="rowgroup"
                />
              </div>
            </div>
            <div
              class="MuiDataGrid-footerContainer-PALYL hAmnMh MuiDataGrid-footerContainer MuiDataGrid-withBorderColor"
            >
              <div />
            </div>

@cherniavskii
Copy link
Member

Hi everyone,
We use this mock for ResizeObserver in our test environment:

function ResizeObserverMock(
callback: (entries: { borderBoxSize: [{ blockSize: number }] }[]) => void,
) {
let timeout: NodeJS.Timeout;
return {
observe: (element: HTMLElement) => {
// Simulates the async behavior of the native ResizeObserver
timeout = setTimeout(() => {
callback([{ borderBoxSize: [{ blockSize: element.clientHeight }] }]);
});
},
disconnect: () => {
clearTimeout(timeout);
},
};
}

If this doesn't help, please provide a minimal reproduction example (could be a repo on GitHub) and we will look into it.

@cherniavskii cherniavskii added test 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 Apr 24, 2023
@p-m-p
Copy link

p-m-p commented Apr 24, 2023

Hi everyone, We use this mock for ResizeObserver in our test environment:

function ResizeObserverMock(
callback: (entries: { borderBoxSize: [{ blockSize: number }] }[]) => void,
) {
let timeout: NodeJS.Timeout;
return {
observe: (element: HTMLElement) => {
// Simulates the async behavior of the native ResizeObserver
timeout = setTimeout(() => {
callback([{ borderBoxSize: [{ blockSize: element.clientHeight }] }]);
});
},
disconnect: () => {
clearTimeout(timeout);
},
};
}

If this doesn't help, please provide a minimal reproduction example (could be a repo on GitHub) and we will look into it.

Thanks, I can confirm this does work but does require you use findBy or waitFor in testing library where before getBy was working. I also had to mock unobserve as this gets called from the effect callback.

@dnikhila
Copy link

dnikhila commented Apr 24, 2023

@cherniavskii @p-m-p I tried above solution, still same can you please see this comment #1151 (comment)

import React from "react";
import { renderWithProviders } from "src/utils/utils-for-jest";
import { setupStore } from "src/redux/store";
import { BrowserRouter } from "react-router-dom";
import UserManagement from "src/pages/user-management";
import { mockNetWorkResponse } from "src/mocks/userManagement/api-mock";
import { screen, fireEvent, waitFor } from "@testing-library/react";

jest.mock("@mui/x-data-grid-pro", () => ({
  ...jest.requireActual("@mui/x-data-grid-pro"),
}));

function resizeObserverMock(
  callback: (entries: { borderBoxSize: [{ blockSize: number }] }[]) => void
) {
  let timeout: NodeJS.Timeout;

  return {
    observe: (element: HTMLElement) => {
      // Simulates the async behavior of the native ResizeObserver
      timeout = setTimeout(() => {
        callback([{ borderBoxSize: [{ blockSize: element.clientHeight }] }]);
      });
    },
    disconnect: () => {
      clearTimeout(timeout);
    },
  };
}

describe("UserManagement Component", () => {
  beforeEach(() => {
    resizeObserverMock(jest.fn());
    mockNetWorkResponse();
  });
  const store = setupStore();
  test("Edit row user management", async () => {
    const tree = renderWithProviders(
      <BrowserRouter>
        <UserManagement />
      </BrowserRouter>,
      { store }
    );
    expect(tree).toMatchSnapshot();

    const handleSearch = screen.getByTestId("content-input");
    fireEvent.change(handleSearch, {
      target: { value: "testing" },
    });
    await waitFor(async () => {
      expect(fireEvent.keyPress(handleSearch, { key: "Ent", code: 13, charCode: 13 })).toBe(true);
    });
    await waitFor(async () => {
      const handleEdit = screen.getAllByTestId("editRow");
      expect(fireEvent.click(handleEdit[0])).toBe(true);
    });
  });
})

@p-m-p
Copy link

p-m-p commented Apr 25, 2023

@dnikhila by looks of the code you pasted you're not setting window.ResizeObserver to the mocked function as per the linked code. Example below

import { render, screen } from '@testing-library/react'
import App from "./App"

function ResizeObserverMock(callback: () => void) {
  let timeout: NodeJS.Timeout

  return {
    disconnect: () => clearTimeout(timeout),
    observe: () => {
      timeout = setTimeout(callback)
    },
    unobserve: () => clearTimeout(timeout),
  }
}

describe('App', () => {
  it('renders grid', async () => {
    const originalObserver = window.ResizeObserver
    window.ResizeObserver = ResizeObserverMock as any
    render(<App />)
    await screen.findAllByRole('row')
    window.ResizeObserver = originalObserver
  })
})

@cherniavskii it feels like this might be better handled internally somehow. I can resolve failing tests on a component that wraps the grid but for a more complex component that includes the wrapped grid component among other components it seems to still be an issue. Perhaps due to different uses of observers, I'll try to reproduce that and share.

@ddolcimascolo
Copy link
Author

Yeah, testing the grid in JSDOM has always been a pain, see my OP

@github-actions github-actions bot removed the status: waiting for author Issue with insufficient information label Apr 25, 2023
@Lori-Becker
Copy link

We are also using react-testing-library and JSDOM. Tests verifying the content inside the Data Grid were passing for me in 6.0.4, but I was having issues testing a column with type="actions". The actions buttons were not rendering in my tests, even though the row data was there. I thought if I upgraded to 6.3.0, that might fix it, but now all tests fail.

@sanderkoenders
Copy link

I am facing the same issues when testing DataGrid. The issues have appeared in version 6.2.0 for me.

@Nic-S
Copy link

Nic-S commented May 2, 2023

Also the same in DataGridPro from version 6.2.1 .
Moreover, I don't think it's a good thing that a minor one creates these compatibility problems with tests.

@brunomendola
Copy link

Hi all. Here is a minimal example of this bug (there's a failing test):
https://codesandbox.io/s/react-ts-mui-x-data-grid-9rojxn
Works with "@mui/x-data-grid": "6.2.0" but stops working from "@mui/x-data-grid": "6.2.1" (also 6.3.0).

@m4theushw
Copy link
Member

m4theushw commented May 3, 2023

@brunomendola You need to mock ResizeObserver before the JSDOM instance is created. In CodeSandbox this can't be done.

Moreover, I don't think it's a good thing that a minor one creates these compatibility problems with tests.

@Nic-S We recommend using a real browser to run tests, otherwise, problems like these may happen. We can't guarantee that a change we release won't break tests. We aim to guarantee that the APIs will be compatible, but tests are a different world.

@Nic-S
Copy link

Nic-S commented May 4, 2023

@brunomendola You need to mock ResizeObserver before the JSDOM instance is created. In CodeSandbox this can't be done.

Moreover, I don't think it's a good thing that a minor one creates these compatibility problems with tests.

@Nic-S We recommend using a real browser to run tests, otherwise, problems like these may happen. We can't guarantee that a change we release won't break tests. We aim to guarantee that the APIs will be compatible, but tests is a different world.

Within the MUI documentation we have this:
Testing

Instead in the MUI-X package, we only have within virtualization a paragraph about testing.
Nowhere in the documentation is it recommended to use a real browser for testing.

@fjohnson-eab
Copy link

@Nic-S We recommend using a real browser to run tests, otherwise, problems like these may happen. We can't guarantee that a change we release won't break tests. We aim to guarantee that the APIs will be compatible, but tests are a different world.

Are you suggesting that developers forego unit testing components that use Material UI? I am shocked to read this.

@DavidArmendariz
Copy link

None of the solutions worked for me.

@joaosousafranco
Copy link

joaosousafranco commented May 10, 2023

Same issue but with version 6.3.1

the only thing that gets rendered is the following:

<div
                  class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-2 css-1o7apob-MuiGrid-root"
                >
                  <button
                    class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-sizeMedium css-zylse7-MuiButtonBase-root-MuiIconButton-root"
                    tabindex="0"
                    type="button"
                  >
                    <div
                      class="MuiStack-root css-1q36rmd-MuiStack-root"
                    >
                      <div
                        class="MuiAvatar-root MuiAvatar-circular MuiAvatar-colorDefault css-2s90m6-MuiAvatar-root"
                      >
                        <svg
                          aria-hidden="true"
                          class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiAvatar-fallback css-10mi8st-MuiSvgIcon-root-MuiAvatar-fallback"
                          data-testid="PersonIcon"
                          focusable="false"
                          viewBox="0 0 24 24"
                        >
                          <path
                            d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
                          />
                        </svg>
                      </div>
                      <h6
                        class="MuiTypography-root MuiTypography-h6 MuiTypography-noWrap css-8u39c-MuiTypography-root"
                      />
                    </div>
                    <span
                      class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
                    />
                  </button>
                </div>
              </div>

I have 3 rows taht should be rendered, which happens when using version 6.1.0

@m4theushw you might not have responsability if u are breaking the tests when you are changing the API, i completely agree on that, but in my case at least im just rendering a simple grid and writing a test to check if the text is displayed, my test doesnt access any Grid API, so i am expecting it will render the Grid just like it does when testing manually. I would say that the product you produce, specially being a commercial product should be test compatible.

@cherniavskii
Copy link
Member

I created this repo with a basic DataGrid test using React Testing Library and JSDOM: https://github.com/cherniavskii/data-grid-testing
Adding ResizeObserver makes the test pass: cherniavskii/data-grid-testing@0da89b5
Can you try using this mock?

@joaosousafranco
Copy link

@cherniavskii it works but forces some dirty type cast when using typescript, anyway is better then nothing, thank you

@rafaelcmm
Copy link

rafaelcmm commented May 11, 2023

I created this repo with a basic DataGrid test using React Testing Library and JSDOM: https://github.com/cherniavskii/data-grid-testing Adding ResizeObserver makes the test pass: cherniavskii/data-grid-testing@0da89b5 Can you try using this mock?

In our case the solution was pretty inconsistent. Making it work at some test cases, but not in others, so I don't see this as a permanent solution, specially for bigger projects.

UPDATE

I've identified two PR's that changed things related to what is probably causing the issue, that were added after the last known working version v6.1.0 to the latest one v6.3.1

I will continue to investigate to see if I get more information related to it.

@cherniavskii
Copy link
Member

In our case the solution was pretty inconsistent. Making it work at some test cases, but not in others, so I don't see this as a permanent solution, specially for bigger projects.

Could you provide a test case where it's not working? I will look into it.

I've identified two PR's that changed things related to what is probably causing the issue, that were added after the last known working version v6.1.0 to the latest one v6.3.1

Yes, we changed the implementation of the internal auto sizer in #8091
While it's not a breaking change in terms of API or behavior in the browser (it actually fixed a few bugs), this caused the tests to fail in non-browser environments that do not have ResizeObserver available.

@Lori-Becker
Copy link

I created this repo with a basic DataGrid test using React Testing Library and JSDOM: https://github.com/cherniavskii/data-grid-testing Adding ResizeObserver makes the test pass: cherniavskii/data-grid-testing@0da89b5 Can you try using this mock?

I tried using the ResizeObserver mock (converted to TS - see this gist for a TS version) and it generally worked! 2 out of 3 of my tests passed. The third test that did not pass is trying to target an Actions button when a column is type: actions. This still does not reveal that column in JSDOM for some reason.

@ddolcimascolo
Copy link
Author

About that, keep in mind that by default the grid uses virtualization for rows AND columns, and you have to make it think there's more space available so that all your columns are rendered. From the top of my head, the usual defaults you get in JSDOM are 15-ish rows and 3 columns.

I linked an issue in my OP, and especially this note #2945 (comment) might be helpful.

I have tens of tests rendering grids in various conditions in our main project, using extra features like aggregations and grouping, and they all pass fine using the ResizeObsever mock I posted above.

Cheers,
David

@cherniavskii
Copy link
Member

Hey everyone,
I had an idea that could make the ResizeObserver mock unnecessary in JSDOM and opened a draft PR: #8961

I tested a build from that PR in https://github.com/cherniavskii/data-grid-testing/tree/without-mock
And the test passes without a mock.

Does this build fix failing tests in your testing env?
https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid
https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-pro
https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-premium

@rafaelcmm
Copy link

Hey everyone, I had an idea that could make the ResizeObserver mock unnecessary in JSDOM and opened a draft PR: #8961

I tested a build from that PR in https://github.com/cherniavskii/data-grid-testing/tree/without-mock And the test passes without a mock.

Does this build fix failing tests in your testing env? https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-pro https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-premium

@cherniavskii in the project that I work on, this build made all tests pass 🥳

900+ test cases.

@cherniavskii
Copy link
Member

@rafaelcmm Thanks for your feedback!
We will address this issue, so that the ResizeObserver mock will not be required in JSDOM 👍

@emildudnyk
Copy link

Hey everyone, I had an idea that could make the ResizeObserver mock unnecessary in JSDOM and opened a draft PR: #8961

I tested a build from that PR in https://github.com/cherniavskii/data-grid-testing/tree/without-mock And the test passes without a mock.

Does this build fix failing tests in your testing env? https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-pro https://pkg.csb.dev/mui/mui-x/commit/8695c6af/@mui/x-data-grid-premium

@cherniavskii all failure tests passed. Thank you, it's awesome 😃

@oliviertassinari oliviertassinari changed the title [DataGridPremium] All JSDOM tests fail with v6.2.1 [DataGrid] All JSDOM tests fail with v6.2.1 Oct 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation plan: Premium Impact at least one Premium user test
Projects
None yet
Development

Successfully merging a pull request may close this issue.