hook.spec.jsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {render, screen} from 'sentry-test/reactTestingLibrary';
  2. import Hook from 'sentry/components/hook';
  3. import HookStore from 'sentry/stores/hookStore';
  4. const HookWrapper = props => (
  5. <div data-test-id="hook-wrapper">
  6. {props.children}
  7. <span>{JSON.stringify(props?.organization ?? {}, null, 2)}</span>
  8. </div>
  9. );
  10. describe('Hook', function () {
  11. afterEach(function () {
  12. HookStore.init();
  13. });
  14. it('renders component from a hook', function () {
  15. HookStore.add('footer', ({organization} = {}) => (
  16. <HookWrapper key={0} organization={organization}>
  17. {organization.slug}
  18. </HookWrapper>
  19. ));
  20. render(
  21. <div>
  22. <Hook name="footer" organization={TestStubs.Organization()} />
  23. </div>
  24. );
  25. expect(HookStore.hooks.footer).toHaveLength(1);
  26. expect(screen.getByTestId('hook-wrapper')).toBeInTheDocument();
  27. expect(screen.getByTestId('hook-wrapper')).toHaveTextContent('org-slug');
  28. });
  29. it('renders an invalid hook', function () {
  30. HookStore.add('footer', ({organization} = {}) => (
  31. <HookWrapper key={0} organization={organization}>
  32. {organization.slug}
  33. </HookWrapper>
  34. ));
  35. render(
  36. <div>
  37. <Hook name="invalid-hook" organization={TestStubs.Organization()} />
  38. invalid
  39. </div>
  40. );
  41. expect(screen.queryByText('org-slug')).not.toBeInTheDocument();
  42. expect(screen.getByText('invalid')).toBeInTheDocument();
  43. });
  44. it('can re-render when hooks get after initial render', function () {
  45. HookStore.add('footer', ({organization} = {}) => (
  46. <HookWrapper key={0} organization={organization}>
  47. Old Hook
  48. </HookWrapper>
  49. ));
  50. const {rerender} = render(
  51. <Hook name="footer" organization={TestStubs.Organization()} />
  52. );
  53. expect(screen.getByTestId('hook-wrapper')).toBeInTheDocument();
  54. HookStore.add('footer', () => (
  55. <HookWrapper key="new" organization={null}>
  56. New Hook
  57. </HookWrapper>
  58. ));
  59. rerender(<Hook name="footer" organization={TestStubs.Organization()} />);
  60. expect(screen.getAllByTestId('hook-wrapper')).toHaveLength(2);
  61. expect(screen.getByText(/New Hook/)).toBeInTheDocument();
  62. expect(screen.getByText(/Old Hook/)).toBeInTheDocument();
  63. });
  64. it('can use children as a render prop', function () {
  65. let idx = 0;
  66. render(
  67. <Hook name="footer" organization={TestStubs.Organization()}>
  68. {({hooks}) =>
  69. hooks.map((hook, i) => (
  70. <HookWrapper key={i}>
  71. {hook} {`hook: ${++idx}`}
  72. </HookWrapper>
  73. ))
  74. }
  75. </Hook>
  76. );
  77. HookStore.add('footer', () => (
  78. <HookWrapper key="new" organization={null}>
  79. First Hook
  80. </HookWrapper>
  81. ));
  82. HookStore.add('footer', () => (
  83. <HookWrapper key="new" organization={null}>
  84. Second Hook
  85. </HookWrapper>
  86. ));
  87. for (let i = 0; i < idx; i++) {
  88. expect(screen.getByText(`hook: ${idx}`)).toBeInTheDocument();
  89. }
  90. // Has 2 Wrappers from store, and each is wrapped by another Wrapper
  91. expect(screen.getAllByTestId('hook-wrapper')).toHaveLength(4);
  92. });
  93. });