edit.spec.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import selectEvent from 'react-select-event';
  2. import {DataScrubbingRelayPiiConfig} from 'sentry-fixture/dataScrubbingRelayPiiConfig';
  3. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  4. import {
  5. makeClosableHeader,
  6. makeCloseButton,
  7. ModalBody,
  8. ModalFooter,
  9. } from 'sentry/components/globalModal/components';
  10. import {convertRelayPiiConfig} from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
  11. import Edit from 'sentry/views/settings/components/dataScrubbing/modals/edit';
  12. import submitRules from 'sentry/views/settings/components/dataScrubbing/submitRules';
  13. import {MethodType, RuleType} from 'sentry/views/settings/components/dataScrubbing/types';
  14. import {
  15. getMethodLabel,
  16. getRuleLabel,
  17. valueSuggestions,
  18. } from 'sentry/views/settings/components/dataScrubbing/utils';
  19. const relayPiiConfig = DataScrubbingRelayPiiConfig();
  20. const stringRelayPiiConfig = JSON.stringify(relayPiiConfig);
  21. const organizationSlug = 'sentry';
  22. const convertedRules = convertRelayPiiConfig(stringRelayPiiConfig);
  23. const rules = convertedRules;
  24. const rule = rules[2];
  25. const projectId = 'foo';
  26. const endpoint = `/projects/${organizationSlug}/${projectId}/`;
  27. const api = new MockApiClient();
  28. jest.mock('sentry/views/settings/components/dataScrubbing/submitRules');
  29. describe('Edit Modal', function () {
  30. it('open Edit Rule Modal', async function () {
  31. const handleCloseModal = jest.fn();
  32. render(
  33. <Edit
  34. Body={ModalBody}
  35. closeModal={handleCloseModal}
  36. CloseButton={makeCloseButton(jest.fn())}
  37. Header={makeClosableHeader(jest.fn())}
  38. Footer={ModalFooter}
  39. projectId={projectId}
  40. savedRules={rules}
  41. api={api}
  42. endpoint={endpoint}
  43. orgSlug={organizationSlug}
  44. onSubmitSuccess={jest.fn()}
  45. rule={rule}
  46. />
  47. );
  48. expect(
  49. screen.getByRole('heading', {name: 'Edit an advanced data scrubbing rule'})
  50. ).toBeInTheDocument();
  51. // Method Field
  52. expect(screen.getByText('Method')).toBeInTheDocument();
  53. await userEvent.hover(screen.getAllByTestId('more-information')[0]);
  54. expect(await screen.findByText('What to do')).toBeInTheDocument();
  55. await userEvent.click(screen.getByText('Replace'));
  56. Object.values(MethodType)
  57. .filter(method => method !== MethodType.REPLACE)
  58. .forEach(method => {
  59. expect(screen.getByText(getMethodLabel(method).label)).toBeInTheDocument();
  60. });
  61. // Placeholder Field
  62. expect(screen.getByText('Custom Placeholder (Optional)')).toBeInTheDocument();
  63. await userEvent.hover(screen.getAllByTestId('more-information')[1]);
  64. expect(
  65. await screen.findByText('It will replace the default placeholder [Filtered]')
  66. ).toBeInTheDocument();
  67. expect(screen.getByPlaceholderText('[Filtered]')).toBeInTheDocument();
  68. // Type Field
  69. expect(screen.getByText('Data Type')).toBeInTheDocument();
  70. await userEvent.hover(screen.getAllByTestId('more-information')[2]);
  71. expect(
  72. await screen.findByText(
  73. 'What to look for. Use an existing pattern or define your own using regular expressions.'
  74. )
  75. ).toBeInTheDocument();
  76. await userEvent.click(screen.getAllByText('Regex matches')[0]);
  77. Object.values(RuleType)
  78. .filter(ruleType => ruleType !== RuleType.PATTERN)
  79. .forEach(ruleType => {
  80. expect(screen.getByText(getRuleLabel(ruleType))).toBeInTheDocument();
  81. });
  82. await userEvent.click(screen.getAllByText('Regex matches')[0]);
  83. // Regex matches Field
  84. expect(screen.getAllByText('Regex matches')).toHaveLength(2);
  85. await userEvent.hover(screen.getAllByTestId('more-information')[3]);
  86. expect(
  87. await screen.findByText('Custom regular expression (see documentation)')
  88. ).toBeInTheDocument();
  89. expect(screen.getByRole('textbox', {name: 'Regex matches'})).toHaveAttribute(
  90. 'placeholder',
  91. '[a-zA-Z0-9]+'
  92. );
  93. // Event ID
  94. expect(
  95. screen.getByRole('button', {name: 'Use event ID for auto-completion'})
  96. ).toBeInTheDocument();
  97. // Source Field
  98. expect(screen.getByText('Source')).toBeInTheDocument();
  99. await userEvent.hover(screen.getAllByTestId('more-information')[4]);
  100. expect(
  101. await screen.findByText(
  102. 'Where to look. In the simplest case this can be an attribute name.'
  103. )
  104. ).toBeInTheDocument();
  105. expect(screen.getByRole('textbox', {name: 'Source'})).toHaveAttribute(
  106. 'placeholder',
  107. 'Enter a custom attribute, variable or header name'
  108. );
  109. // Close Modal
  110. await userEvent.click(screen.getByRole('button', {name: 'Cancel'}));
  111. expect(handleCloseModal).toHaveBeenCalled();
  112. });
  113. it('edit Rule Modal', async function () {
  114. render(
  115. <Edit
  116. Body={ModalBody}
  117. closeModal={jest.fn()}
  118. CloseButton={makeCloseButton(jest.fn())}
  119. Header={makeClosableHeader(jest.fn())}
  120. Footer={ModalFooter}
  121. projectId={projectId}
  122. savedRules={rules}
  123. api={api}
  124. endpoint={endpoint}
  125. orgSlug={organizationSlug}
  126. onSubmitSuccess={jest.fn()}
  127. rule={rule}
  128. />
  129. );
  130. // Method Field
  131. await selectEvent.select(screen.getByText('Replace'), 'Mask');
  132. // Placeholder Field should be now hidden
  133. expect(screen.queryByText('Custom Placeholder (Optional)')).not.toBeInTheDocument();
  134. // Type Field
  135. await selectEvent.select(screen.getAllByText('Regex matches')[0], 'Anything');
  136. // Regex Field should be now hidden
  137. expect(screen.queryByText('Regex matches')).not.toBeInTheDocument();
  138. // Source Field
  139. await userEvent.clear(screen.getByRole('textbox', {name: 'Source'}));
  140. await userEvent.type(
  141. screen.getByRole('textbox', {name: 'Source'}),
  142. valueSuggestions[2].value
  143. );
  144. // Save rule
  145. await userEvent.click(screen.getByRole('button', {name: 'Save Rule'}));
  146. expect(submitRules).toHaveBeenCalledWith(api, endpoint, [
  147. {
  148. id: 0,
  149. method: 'replace',
  150. type: 'password',
  151. source: 'password',
  152. placeholder: 'Scrubbed',
  153. },
  154. {id: 1, method: 'mask', type: 'creditcard', source: '$message'},
  155. {
  156. id: 2,
  157. method: 'mask',
  158. pattern: '',
  159. placeholder: '',
  160. type: 'anything',
  161. source: valueSuggestions[2].value,
  162. },
  163. ]);
  164. });
  165. });