“react-admin”,List页面的单元测试无法看到模拟数据。

huangapple go评论93阅读模式
英文:

react-admin, the unit-test of a List-page can't see the mock data

问题

我正在尝试对典型的基于列表的react-admin组件进行单元测试。所以我添加了一个带有仅getList()方法(被调用)的模拟dataProvider到AdminContext中。

const BookList = (props:any) => {
  return (
      <List {...props}  >
        <Datagrid >
          <TextField source='title'/>
        </Datagrid>
      </List>
  )
}
describe('list test', () => {
  it('list test', async () => {
    let dataProvider:DataProvider = testDataProvider({
        getList: function <RecordType extends RaRecord<Identifier> = any>(resource: string, params: GetListParams): Promise<GetListResult<RecordType>> {
            let record:RecordType = {
                id:"1",
                title:'myTitle'
            }as unknown as RecordType;
            return Promise.resolve({data:[record],total:1});
        }      
    });

    render(
        <AdminContext dataProvider={dataProvider} >
                <BookList resource='books'/>   
        </AdminContext>
    );
    expect(await screen.getByText('myTitle')).toBeInTheDocument();
  });
})

然而,似乎没有起作用。输出的HTML DOM中列表中没有行,因此测试失败。

还有这个act警告,但将渲染调用包装在act()中并没有改变任何事情,甚至警告仍然存在。

警告:在测试中,没有在act(...)中包装的ListBase内部的更新。

在测试时,导致React状态更新的代码应该包装在act(...)中:

act(() => {
  /* 触发更新状态的事件 */
});
/* 对输出进行断言 */
英文:

I’m trying to unit-test a typical List-based react-admin component. So i have a mock dataProvider added to the AdminContext with just the getList() method (which is called).

const BookList = (props:any) => {
  return (
      <List {...props}  >
        <Datagrid >
          <TextField source='title'/>
        </Datagrid>
      </List>
  )
}
describe('list test', () => {
  it('list test', async () => {
    let dataProvider:DataProvider = testDataProvider({
        getList: function <RecordType extends RaRecord<Identifier> = any>(resource: string, params: GetListParams): Promise<GetListResult<RecordType>> {
            let record:RecordType = {
                id:"1",
                title:'myTitle'
            }as unknown as RecordType;
            return Promise.resolve({data:[record],total:1});
        }      
    });

    render(
        <AdminContext dataProvider={dataProvider} >
                <BookList resource='books'/>   
        </AdminContext>
    );
    expect(await screen.getByText('myTitle')).toBeInTheDocument();
  });
})

Yet, it doesn’t seem to work. The outputted html dom has 0 rows in the list and therefore the test fails.

There is also this act warning, but wrapping the render call in act() doesn’t change anything, even the warning remains.

Warning: An update to ListBase inside a test was not wrapped in act(...).

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

答案1

得分: 0

感谢 @slax57

解决方法是将 await screen.getByText() 替换为 await screen.findByText()

基本上,当使用 screen.debug(); 记录 HTML 输出时,可以看到屏幕没有填充 API 响应内容(列表没有行),因此等待未激活。一个方法返回一个 promise,而另一个方法则不返回。

英文:

Thanks to @slax57

The solution was to replace await screen.getByText() by await screen.findByText()

Basically, when logging the html output with screen.debug();, it can be seen that the screen was not filled with the API response content (list with no rows) so the await was not active. One method returns a promise when the other does not.

huangapple
  • 本文由 发表于 2023年6月2日 05:08:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定