edit.spec.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import sortBy from 'lodash/sortBy';
  2. import {mountGlobalModal} from 'sentry-test/modal';
  3. import {openModal} from 'sentry/actionCreators/modal';
  4. import {convertRelayPiiConfig} from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
  5. import Edit from 'sentry/views/settings/components/dataScrubbing/modals/edit';
  6. import submitRules from 'sentry/views/settings/components/dataScrubbing/submitRules';
  7. import {MethodType, RuleType} from 'sentry/views/settings/components/dataScrubbing/types';
  8. import {
  9. getMethodLabel,
  10. getRuleLabel,
  11. valueSuggestions,
  12. } from 'sentry/views/settings/components/dataScrubbing/utils';
  13. const relayPiiConfig = TestStubs.DataScrubbingRelayPiiConfig();
  14. const stringRelayPiiConfig = JSON.stringify(relayPiiConfig);
  15. const organizationSlug = 'sentry';
  16. const convertedRules = convertRelayPiiConfig(stringRelayPiiConfig);
  17. const rules = convertedRules;
  18. const rule = rules[2];
  19. const successfullySaved = jest.fn();
  20. const projectId = 'foo';
  21. const endpoint = `/projects/${organizationSlug}/${projectId}/`;
  22. const api = new MockApiClient();
  23. jest.mock('sentry/views/settings/components/dataScrubbing/submitRules');
  24. async function renderComponent() {
  25. const modal = await mountGlobalModal();
  26. openModal(modalProps => (
  27. <Edit
  28. {...modalProps}
  29. projectId={projectId}
  30. savedRules={rules}
  31. api={api}
  32. endpoint={endpoint}
  33. orgSlug={organizationSlug}
  34. onSubmitSuccess={successfullySaved}
  35. rule={rule}
  36. />
  37. ));
  38. await tick();
  39. modal.update();
  40. return modal;
  41. }
  42. describe('Edit Modal', () => {
  43. it('open Edit Rule Modal', async () => {
  44. const wrapper = await renderComponent();
  45. expect(wrapper.find('Header').text()).toEqual('Edit an advanced data scrubbing rule');
  46. const fieldGroup = wrapper.find('FieldGroup');
  47. expect(fieldGroup).toHaveLength(2);
  48. // Method Field
  49. const methodGroup = fieldGroup.at(0).find('Field');
  50. const methodField = methodGroup.at(0);
  51. expect(methodField.find('FieldLabel').text()).toEqual('Method');
  52. const methodFieldHelp = 'What to do';
  53. expect(methodField.find('QuestionTooltip').prop('title')).toEqual(methodFieldHelp);
  54. expect(methodField.find('Tooltip').prop('title')).toEqual(methodFieldHelp);
  55. const methodFieldSelect = methodField.find('SelectField');
  56. expect(methodFieldSelect.exists()).toBe(true);
  57. const methodFieldSelectProps = methodFieldSelect.props();
  58. expect(methodFieldSelectProps.value).toEqual(MethodType.REPLACE);
  59. const methodFieldSelectOptions = sortBy(Object.values(MethodType)).map(value => ({
  60. ...getMethodLabel(value),
  61. value,
  62. }));
  63. expect(methodFieldSelectProps.options).toEqual(methodFieldSelectOptions);
  64. // Placeholder Field
  65. const placeholderField = methodGroup.at(1);
  66. expect(placeholderField.find('FieldLabel').text()).toEqual(
  67. 'Custom Placeholder (Optional)'
  68. );
  69. const placeholderFieldHelp = 'It will replace the default placeholder [Filtered]';
  70. expect(placeholderField.find('QuestionTooltip').prop('title')).toEqual(
  71. placeholderFieldHelp
  72. );
  73. expect(placeholderField.find('Tooltip').prop('title')).toEqual(placeholderFieldHelp);
  74. if (rule.method === MethodType.REPLACE) {
  75. const placeholderInput = placeholderField.find('input');
  76. expect(placeholderInput.prop('value')).toEqual(rule.placeholder);
  77. }
  78. // Type Field
  79. const typeGroup = fieldGroup.at(1).find('Field');
  80. const typeField = typeGroup.at(0);
  81. expect(typeField.find('FieldLabel').text()).toEqual('Data Type');
  82. const typeFieldHelp =
  83. 'What to look for. Use an existing pattern or define your own using regular expressions.';
  84. expect(typeField.find('QuestionTooltip').prop('title')).toEqual(typeFieldHelp);
  85. expect(typeField.find('Tooltip').prop('title')).toEqual(typeFieldHelp);
  86. const typeFieldSelect = typeField.find('SelectField');
  87. expect(typeFieldSelect.exists()).toBe(true);
  88. const typeFieldSelectProps = typeFieldSelect.props();
  89. expect(typeFieldSelectProps.value).toEqual(RuleType.PATTERN);
  90. const typeFieldSelectOptions = sortBy(Object.values(RuleType)).map(value => ({
  91. label: getRuleLabel(value),
  92. value,
  93. }));
  94. expect(typeFieldSelectProps.options).toEqual(typeFieldSelectOptions);
  95. // Regex matches Field
  96. const regexField = typeGroup.at(1);
  97. expect(regexField.find('FieldLabel').text()).toEqual('Regex matches');
  98. const regexFieldHelp = 'Custom regular expression (see documentation)';
  99. expect(regexField.find('QuestionTooltip').prop('title')).toEqual(regexFieldHelp);
  100. expect(regexField.find('Tooltip').prop('title')).toEqual(regexFieldHelp);
  101. if (rule.type === RuleType.PATTERN) {
  102. const regexFieldInput = regexField.find('input');
  103. expect(regexFieldInput.prop('value')).toEqual(rule.pattern);
  104. }
  105. // Event ID
  106. expect(wrapper.find('Toggle').text()).toEqual('Use event ID for auto-completion');
  107. // Source Field
  108. const sourceGroup = wrapper.find('SourceGroup');
  109. expect(sourceGroup.exists()).toBe(true);
  110. expect(sourceGroup.find('EventIdField')).toHaveLength(0);
  111. const sourceField = sourceGroup.find('Field');
  112. expect(sourceField.find('FieldLabel').text()).toEqual('Source');
  113. const sourceFieldHelp =
  114. 'Where to look. In the simplest case this can be an attribute name.';
  115. expect(sourceField.find('QuestionTooltip').prop('title')).toEqual(sourceFieldHelp);
  116. expect(sourceField.find('Tooltip').prop('title')).toEqual(sourceFieldHelp);
  117. const sourceFieldInput = sourceField.find('input');
  118. expect(sourceFieldInput.prop('value')).toEqual(rule.source);
  119. // Close Modal
  120. const cancelButton = wrapper.find('[aria-label="Cancel"]').hostNodes();
  121. expect(cancelButton.exists()).toBe(true);
  122. cancelButton.simulate('click');
  123. await tick();
  124. wrapper.update();
  125. expect(wrapper.find('GlobalModal[visible=true]').exists()).toBe(false);
  126. });
  127. it('edit Rule Modal', async () => {
  128. const wrapper = await renderComponent();
  129. // Method Field
  130. const methodField = wrapper.find('[data-test-id="method-field"]');
  131. const methodFieldInput = methodField.find('input').at(0);
  132. methodFieldInput.simulate('keyDown', {key: 'ArrowDown'});
  133. const methodFieldMenuOptions = wrapper.find(
  134. '[data-test-id="method-field"] MenuList Option'
  135. );
  136. const maskOption = methodFieldMenuOptions.at(1);
  137. maskOption.simulate('click');
  138. // Placeholder Field should be now hidden
  139. const placeholderField = wrapper.find('[data-test-id="placeholder-field"]');
  140. expect(placeholderField).toHaveLength(0);
  141. // Type Field
  142. const typeField = wrapper.find('[data-test-id="type-field"]');
  143. const typeFieldInput = typeField.find('input').at(0);
  144. typeFieldInput.simulate('keyDown', {key: 'ArrowDown'});
  145. const typeFieldMenuOptions = wrapper.find(
  146. '[data-test-id="type-field"] MenuList Option'
  147. );
  148. const anythingOption = typeFieldMenuOptions.at(0);
  149. anythingOption.simulate('click');
  150. // Regex Field should be now hidden
  151. const regexField = wrapper.find('[data-test-id="regex-field"]');
  152. expect(regexField).toHaveLength(0);
  153. // Source Field
  154. const sourceField = wrapper.find('[data-test-id="source-field"]');
  155. const sourceFieldInput = sourceField.find('input');
  156. sourceFieldInput.simulate('change', {target: {value: valueSuggestions[2].value}});
  157. // Save rule
  158. const saveButton = wrapper.find('[aria-label="Save Rule"]').hostNodes();
  159. expect(saveButton.exists()).toBe(true);
  160. saveButton.simulate('click');
  161. expect(submitRules).toHaveBeenCalled();
  162. expect(submitRules).toHaveBeenCalledWith(api, endpoint, [
  163. {
  164. id: 0,
  165. method: 'replace',
  166. type: 'password',
  167. source: 'password',
  168. placeholder: 'Scrubbed',
  169. },
  170. {id: 1, method: 'mask', type: 'creditcard', source: '$message'},
  171. {
  172. id: 2,
  173. method: 'mask',
  174. pattern: '',
  175. placeholder: '',
  176. type: 'anything',
  177. source: '$error.value',
  178. },
  179. ]);
  180. });
  181. });