جاوااسکریپت - چرا useState در یک تست واحد (Jest، Enzyme) باعث باز-render شدن کامپوننت نمیشود؟


من در رندر دوبارهٔ یک کامپوننت که با Enzyme پیچیده شده است در Jest به مشکل برخوردهام. مدتی طول کشید تا مشکل را مشخص کنم، اما به نظر میرسد که مشکل مربوط به useState و Enzyme است.

من یک کامپوننت دارم که یک دکمه در آن است. کلیک کردن روی دکمه باعث فراخوانی تابع setState() میشود تا وضعیت کامپوننت را بهروزرسانی کرده و دوباره رندر شود. برای مثال:

// ...
<Drawer
  classes={{ paper: classes.drawer }}
  anchor="right"
  open={showInfoDrawer}
  variant={mobile() ? 'temporary' : 'persistent'}
  onClose={() => {
    console.log('closing'); // to check onClose simulation works
    setShowInfoDrawer(false);
  }}
  >
  // rest of component...
</Drawer>
// ...

در این مثال، setShowInfoDrawer() بخشی از یک هوک useState() است که به عنوان یک prop از یک کامپوننت والد منتقل شده است.

وقتی یک تست اجرا میکنم (نمونه زیر را ببینید)، شبیهسازی کلیک به نظر میرسد که کار میکند، اما کامپوننت دوباره رندر نمیشود.

test('should close ActivityInfoDrawer', () => {
  expect(wrappedActivityInfoDrawer.find(Drawer)).toHaveLength(1);
  const wrappedDrawer = wrappedActivityInfoDrawer.find(Drawer);
  // @ts-ignore
  act(() => wrappedDrawer.props().onClose()); // Logs "Clicked..."
  wrappedActivityInfoDrawer.update();
  expect(wrappedActivityInfoDrawer.find(Drawer)).toHaveLength(0); // Fails
  });

من کمی تحقیق کردم و به نظر میرسد که برای مدتی Enzyme از useState پشتیبانی نمیکرد، اما این موضوع در این PR حل شد، که به نظر میرسد با نسخه ۳.۱۱.۰ منتشر شده است، یا شاید حتی ۳.۱۰.۰ (من از ۳.۱۱.۰، آخرین نسخه، استفاده میکنم).

من دارم چه کار اشتباهی انجام میدهم؟ آیا به این دلیل است که setShowInfoDrawer() از یک کامپوننت والد میآید؟ اگر چنین است، چگونه میتوانم آن را درست کار کنم؟

پاسخ شماره ۱

باشه، فهمیدم. با نگاه به گذشته کاملاً واضح است. من نیاز داشتم این تست را بهصورت تستی برای کامپوننت والد (یعنی کامپوننتی که دراور را باز میکند و هوک useState() را دارد) اجرا کنم، نه بهصورت تست واحد برای خود کامپوننت Drawer.