organizationSampleRateInput.spec.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  3. import {OrganizationSampleRateInput} from './organizationSampleRateInput';
  4. describe('OrganizationSampleRateInput', () => {
  5. const organization = OrganizationFixture({
  6. access: ['org:write'],
  7. });
  8. const defaultProps = {
  9. value: '10',
  10. onChange: jest.fn(),
  11. label: 'Sample Rate',
  12. help: 'Help text',
  13. previousValue: '20',
  14. showPreviousValue: false,
  15. };
  16. beforeEach(() => {
  17. jest.clearAllMocks();
  18. });
  19. it('renders with basic props', () => {
  20. render(<OrganizationSampleRateInput {...defaultProps} />, {
  21. organization,
  22. });
  23. expect(screen.getByRole('spinbutton')).toHaveValue(10);
  24. expect(screen.getByText('Sample Rate')).toBeInTheDocument();
  25. expect(screen.getByText('Help text')).toBeInTheDocument();
  26. });
  27. it('shows previous value when showPreviousValue is true', () => {
  28. render(<OrganizationSampleRateInput {...defaultProps} showPreviousValue />, {
  29. organization,
  30. });
  31. expect(screen.getByText('previous: 20%')).toBeInTheDocument();
  32. });
  33. it('shows "All spans are stored" message when value is 100', () => {
  34. render(<OrganizationSampleRateInput {...defaultProps} value="100" />, {
  35. organization,
  36. });
  37. expect(screen.getByText('All spans are stored')).toBeInTheDocument();
  38. });
  39. it('shows error message when error prop is provided', () => {
  40. render(<OrganizationSampleRateInput {...defaultProps} error="Invalid value" />, {
  41. organization,
  42. });
  43. expect(screen.getByText('Invalid value')).toBeInTheDocument();
  44. });
  45. describe('Access Control', () => {
  46. it('disables input when user does not have access', () => {
  47. const orgWithoutAccess = OrganizationFixture({
  48. access: [], // No org:write access
  49. });
  50. render(<OrganizationSampleRateInput {...defaultProps} />, {
  51. organization: orgWithoutAccess,
  52. });
  53. expect(screen.getByRole('spinbutton')).toBeDisabled();
  54. });
  55. it('enables input when user has access', () => {
  56. render(<OrganizationSampleRateInput {...defaultProps} />, {
  57. organization,
  58. });
  59. expect(screen.getByRole('spinbutton')).toBeEnabled();
  60. });
  61. });
  62. describe('Bulk Edit Mode', () => {
  63. it('shows bulk edit button when enabled and user has access', () => {
  64. const {rerender} = render(
  65. <OrganizationSampleRateInput
  66. {...defaultProps}
  67. isBulkEditEnabled
  68. isBulkEditActive={false}
  69. onBulkEditChange={jest.fn()}
  70. />,
  71. {organization}
  72. );
  73. expect(
  74. screen.getByRole('button', {name: 'Proportionally scale project rates'})
  75. ).toBeInTheDocument();
  76. // In active state, the button should not be shown
  77. rerender(
  78. <OrganizationSampleRateInput
  79. {...defaultProps}
  80. isBulkEditEnabled
  81. isBulkEditActive
  82. onBulkEditChange={jest.fn()}
  83. />
  84. );
  85. expect(
  86. screen.queryByRole('button', {name: 'Proportionally scale project rates'})
  87. ).not.toBeInTheDocument();
  88. });
  89. it('hides bulk edit button when user does not have access', () => {
  90. const orgWithoutAccess = OrganizationFixture({
  91. access: [], // No org:write access
  92. });
  93. render(
  94. <OrganizationSampleRateInput
  95. {...defaultProps}
  96. isBulkEditEnabled
  97. isBulkEditActive={false}
  98. onBulkEditChange={jest.fn()}
  99. />,
  100. {organization: orgWithoutAccess}
  101. );
  102. expect(
  103. screen.queryByRole('button', {name: 'Proportionally scale project rates'})
  104. ).not.toBeInTheDocument();
  105. });
  106. it('autofocuses input after bulk edit becomes active', async () => {
  107. const onBulkEditChange = jest.fn();
  108. const {rerender} = render(
  109. <OrganizationSampleRateInput
  110. {...defaultProps}
  111. isBulkEditEnabled
  112. isBulkEditActive={false}
  113. onBulkEditChange={onBulkEditChange}
  114. />,
  115. {organization}
  116. );
  117. const input = screen.getByRole('spinbutton');
  118. expect(input).not.toHaveFocus();
  119. await userEvent.click(
  120. screen.getByRole('button', {name: 'Proportionally scale project rates'})
  121. );
  122. expect(onBulkEditChange).toHaveBeenCalledWith(true);
  123. // Simulate the parent component updating the active state
  124. rerender(
  125. <OrganizationSampleRateInput
  126. {...defaultProps}
  127. isBulkEditEnabled
  128. isBulkEditActive
  129. onBulkEditChange={onBulkEditChange}
  130. />
  131. );
  132. expect(input).toHaveFocus();
  133. });
  134. });
  135. });