useCreatableSelectPersistedBehaviour.test.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { render, screen } from '@testing-library/react';
  2. import userEvent from '@testing-library/user-event';
  3. import React from 'react';
  4. import { Select, InlineField } from '@grafana/ui';
  5. import { useCreatableSelectPersistedBehaviour } from './useCreatableSelectPersistedBehaviour';
  6. describe('useCreatableSelectPersistedBehaviour', () => {
  7. it('Should make a Select accept custom values', async () => {
  8. const MyComp = (_: { force?: boolean }) => (
  9. <InlineField label="label">
  10. <Select
  11. inputId="select"
  12. {...useCreatableSelectPersistedBehaviour({
  13. options: [{ label: 'Option 1', value: 'Option 1' }],
  14. onChange() {},
  15. })}
  16. />
  17. </InlineField>
  18. );
  19. const { rerender } = render(<MyComp />);
  20. const input = screen.getByLabelText('label') as HTMLInputElement;
  21. expect(input).toBeInTheDocument();
  22. // we open the menu
  23. await userEvent.click(input);
  24. expect(screen.getByText('Option 1')).toBeInTheDocument();
  25. // we type in the input 'Option 2', which should prompt an option creation
  26. await userEvent.type(input, 'Option 2');
  27. const creatableOption = screen.getByLabelText('Select option');
  28. expect(creatableOption).toHaveTextContent('Option 2');
  29. // we click on the creatable option to trigger its creation
  30. await userEvent.click(creatableOption);
  31. // Forcing a rerender
  32. rerender(<MyComp force={true} />);
  33. // we open the menu again
  34. await userEvent.click(input);
  35. // the created option should be available
  36. expect(screen.getByText('Option 2')).toBeInTheDocument();
  37. });
  38. it('Should handle onChange properly', async () => {
  39. const onChange = jest.fn();
  40. const MyComp = () => (
  41. <InlineField label="label">
  42. <Select
  43. inputId="select"
  44. {...useCreatableSelectPersistedBehaviour({
  45. options: [{ label: 'Option 1', value: 'Option 1' }],
  46. onChange,
  47. })}
  48. />
  49. </InlineField>
  50. );
  51. render(<MyComp />);
  52. const input = screen.getByLabelText('label') as HTMLInputElement;
  53. expect(input).toBeInTheDocument();
  54. // we open the menu
  55. await userEvent.click(input);
  56. const option1 = screen.getByText('Option 1');
  57. expect(option1).toBeInTheDocument();
  58. // Should call onChange when selecting an already existing option
  59. await userEvent.click(option1);
  60. expect(onChange).toHaveBeenLastCalledWith(
  61. { value: 'Option 1', label: 'Option 1' },
  62. { action: 'select-option', name: undefined, option: undefined }
  63. );
  64. await userEvent.click(input);
  65. // we type in the input 'Option 2', which should prompt an option creation
  66. await userEvent.type(input, 'Option 2');
  67. await userEvent.click(screen.getByLabelText('Select option'));
  68. expect(onChange).toHaveBeenLastCalledWith({ value: 'Option 2' });
  69. });
  70. it('Should create an option for value if value is not in options', async () => {
  71. const MyComp = (_: { force?: boolean }) => (
  72. <InlineField label="label">
  73. <Select
  74. inputId="select"
  75. {...useCreatableSelectPersistedBehaviour({
  76. options: [{ label: 'Option 1', value: 'Option 1' }],
  77. value: 'Option 2',
  78. onChange() {},
  79. })}
  80. />
  81. </InlineField>
  82. );
  83. render(<MyComp />);
  84. const input = screen.getByLabelText('label') as HTMLInputElement;
  85. expect(input).toBeInTheDocument();
  86. // we open the menu
  87. await userEvent.click(input);
  88. // we expect 2 elemnts having "Option 2": the input itself and the option.
  89. expect(screen.getAllByText('Option 2')).toHaveLength(2);
  90. });
  91. });