123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- import sortBy from 'lodash/sortBy';
- import {mountWithTheme} from 'sentry-test/enzyme';
- import {openModal} from 'sentry/actionCreators/modal';
- import GlobalModal from 'sentry/components/globalModal';
- import convertRelayPiiConfig from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
- import Add from 'sentry/views/settings/components/dataScrubbing/modals/add';
- import {MethodType, RuleType} from 'sentry/views/settings/components/dataScrubbing/types';
- import {
- getMethodLabel,
- getRuleLabel,
- } from 'sentry/views/settings/components/dataScrubbing/utils';
- const relayPiiConfig = TestStubs.DataScrubbingRelayPiiConfig();
- const stringRelayPiiConfig = JSON.stringify(relayPiiConfig);
- const organizationSlug = 'sentry';
- const convertedRules = convertRelayPiiConfig(stringRelayPiiConfig);
- const rules = convertedRules;
- const successfullySaved = jest.fn();
- const projectId = 'foo';
- const endpoint = `/projects/${organizationSlug}/${projectId}/`;
- const api = new MockApiClient();
- async function renderComponent() {
- const wrapper = mountWithTheme(<GlobalModal />);
- openModal(modalProps => (
- <Add
- {...modalProps}
- projectId={projectId}
- savedRules={rules}
- api={api}
- endpoint={endpoint}
- orgSlug={organizationSlug}
- onSubmitSuccess={successfullySaved}
- />
- ));
- await tick();
- wrapper.update();
- return wrapper;
- }
- describe('Add Modal', () => {
- it('open Add Rule Modal', async () => {
- const wrapper = await renderComponent();
- expect(wrapper.find('Header').text()).toEqual('Add an advanced data scrubbing rule');
- const fieldGroup = wrapper.find('FieldGroup');
- expect(fieldGroup).toHaveLength(2);
- // Method Field
- const methodGroup = fieldGroup.at(0).find('Field');
- expect(methodGroup.find('FieldLabel').text()).toEqual('Method');
- const methodFieldHelp = 'What to do';
- expect(methodGroup.find('QuestionTooltip').prop('title')).toEqual(methodFieldHelp);
- expect(methodGroup.find('Tooltip').prop('title')).toEqual(methodFieldHelp);
- const methodField = methodGroup.find('SelectField');
- expect(methodField.exists()).toBe(true);
- const methodFieldProps = methodField.props();
- expect(methodFieldProps.value).toEqual(MethodType.MASK);
- const methodFieldOptions = sortBy(Object.values(MethodType)).map(value => ({
- ...getMethodLabel(value),
- value,
- }));
- expect(methodFieldProps.options).toEqual(methodFieldOptions);
- // Type Field
- const typeGroup = fieldGroup.at(1).find('Field');
- expect(typeGroup.find('FieldLabel').text()).toEqual('Data Type');
- const typeFieldHelp =
- 'What to look for. Use an existing pattern or define your own using regular expressions.';
- expect(typeGroup.find('QuestionTooltip').prop('title')).toEqual(typeFieldHelp);
- expect(typeGroup.find('Tooltip').prop('title')).toEqual(typeFieldHelp);
- const typeField = typeGroup.find('SelectField');
- expect(typeField.exists()).toBe(true);
- const typeFieldProps = typeField.props();
- expect(typeFieldProps.value).toEqual(RuleType.CREDITCARD);
- const typeFieldOptions = sortBy(Object.values(RuleType)).map(value => ({
- label: getRuleLabel(value),
- value,
- }));
- expect(typeFieldProps.options).toEqual(typeFieldOptions);
- // Event ID
- expect(wrapper.find('Toggle').text()).toEqual('Use event ID for auto-completion');
- // Source Field
- const sourceGroup = wrapper.find('SourceGroup');
- expect(sourceGroup.exists()).toBe(true);
- expect(sourceGroup.find('EventIdField')).toHaveLength(0);
- const sourceField = sourceGroup.find('Field');
- expect(sourceField.find('FieldLabel').text()).toEqual('Source');
- const sourceFieldHelp =
- 'Where to look. In the simplest case this can be an attribute name.';
- expect(sourceField.find('QuestionTooltip').prop('title')).toEqual(sourceFieldHelp);
- expect(sourceField.find('Tooltip').prop('title')).toEqual(sourceFieldHelp);
- // Close Modal
- const cancelButton = wrapper.find('[aria-label="Cancel"]').hostNodes();
- expect(cancelButton.exists()).toBe(true);
- cancelButton.simulate('click');
- await tick();
- wrapper.update();
- expect(wrapper.find('GlobalModal[visible=true]').exists()).toBe(false);
- });
- it('Display placeholder field', async () => {
- const wrapper = await renderComponent();
- const fieldGroup = wrapper.find('FieldGroup');
- expect(fieldGroup).toHaveLength(2);
- // Method Field
- const methodGroup = fieldGroup.at(0).find('Field');
- expect(methodGroup).toHaveLength(1);
- const methodField = methodGroup.find('[data-test-id="method-field"]');
- const methodFieldInput = methodField.find('input').at(1);
- methodFieldInput.simulate('keyDown', {key: 'ArrowDown'});
- const methodFieldMenuOptions = wrapper.find(
- '[data-test-id="method-field"] MenuList Option'
- );
- expect(methodFieldMenuOptions).toHaveLength(4);
- const replaceOption = methodFieldMenuOptions.at(3);
- expect(replaceOption.find('Label').text()).toEqual('Replace');
- expect(replaceOption.find('Details').text()).toEqual('(Replace with Placeholder)');
- // After the click the placeholder field MUST be in the DOM
- replaceOption.simulate('click');
- wrapper.update();
- expect(
- wrapper.find('[data-test-id="method-field"] input').at(1).prop('value')
- ).toEqual(MethodType.REPLACE);
- const updatedMethodGroup = wrapper.find('FieldGroup').at(0).find('Field');
- expect(updatedMethodGroup).toHaveLength(2);
- const placeholderField = updatedMethodGroup.at(1);
- expect(placeholderField.find('FieldLabel').text()).toEqual(
- 'Custom Placeholder (Optional)'
- );
- const placeholderFieldHelp = 'It will replace the default placeholder [Filtered]';
- expect(placeholderField.find('QuestionTooltip').prop('title')).toEqual(
- placeholderFieldHelp
- );
- expect(placeholderField.find('Tooltip').prop('title')).toEqual(placeholderFieldHelp);
- // After the click, the placeholder field MUST NOT be in the DOM
- wrapper
- .find('[data-test-id="method-field"]')
- .find('input')
- .at(1)
- .simulate('keyDown', {key: 'ArrowDown'});
- const hashOption = wrapper
- .find('[data-test-id="method-field"] MenuList Option')
- .at(0);
- hashOption.simulate('click');
- expect(wrapper.find('[data-test-id="method-field"] input').at(1).prop('value')).toBe(
- MethodType.HASH
- );
- expect(wrapper.find('FieldGroup').at(0).find('Field')).toHaveLength(1);
- });
- it('Display regex field', async () => {
- const wrapper = await renderComponent();
- const fieldGroup = wrapper.find('FieldGroup');
- expect(fieldGroup).toHaveLength(2);
- // Type Field
- const typeGroup = fieldGroup.at(1).find('Field');
- expect(typeGroup).toHaveLength(1);
- const typeField = typeGroup.find('[data-test-id="type-field"]');
- const typeFieldInput = typeField.find('input').at(1);
- typeFieldInput.simulate('keyDown', {key: 'ArrowDown'});
- const typeFieldMenuOptions = wrapper.find(
- '[data-test-id="type-field"] MenuList Option'
- );
- expect(typeFieldMenuOptions).toHaveLength(13);
- const regexOption = typeFieldMenuOptions.at(7);
- expect(regexOption.find('Label').text()).toEqual('Regex matches');
- // After the click, the regex matches field MUST be in the DOM
- regexOption.simulate('click');
- wrapper.update();
- expect(wrapper.find('[data-test-id="type-field"] input').at(1).prop('value')).toEqual(
- RuleType.PATTERN
- );
- const updatedTypeGroup = wrapper.find('FieldGroup').at(1).find('Field');
- expect(updatedTypeGroup).toHaveLength(2);
- const regexField = updatedTypeGroup.at(1);
- expect(regexField.find('FieldLabel').text()).toEqual('Regex matches');
- const regexFieldHelp = 'Custom regular expression (see documentation)';
- expect(regexField.find('QuestionTooltip').prop('title')).toEqual(regexFieldHelp);
- expect(regexField.find('Tooltip').prop('title')).toEqual(regexFieldHelp);
- // After the click, the regex matches field MUST NOT be in the DOM
- wrapper
- .find('[data-test-id="type-field"]')
- .find('input')
- .at(1)
- .simulate('keyDown', {key: 'ArrowDown'});
- const creditCardOption = wrapper
- .find('[data-test-id="type-field"] MenuList Option')
- .at(1);
- creditCardOption.simulate('click');
- expect(wrapper.find('[data-test-id="type-field"] input').at(1).prop('value')).toBe(
- RuleType.CREDITCARD
- );
- expect(wrapper.find('FieldGroup').at(1).find('Field')).toHaveLength(1);
- });
- it('Display Event Id', async () => {
- const eventId = '12345678901234567890123456789012';
- MockApiClient.addMockResponse({
- url: `/organizations/${organizationSlug}/data-scrubbing-selector-suggestions/`,
- body: {
- suggestions: [
- {type: 'value', examples: ['34359738368'], value: "extra.'system.cpu.memory'"},
- {type: 'value', value: '$frame.abs_path'},
- ],
- },
- });
- const wrapper = await renderComponent();
- const eventIdToggle = wrapper.find('Toggle');
- eventIdToggle.simulate('click');
- const eventIdFieldInput = wrapper.find('[data-test-id="event-id-field"] input');
- eventIdFieldInput.simulate('change', {
- target: {value: eventId},
- });
- eventIdFieldInput.simulate('blur');
- await tick();
- // Loading
- expect(wrapper.find('[data-test-id="event-id-field"] FormSpinner')).toHaveLength(1);
- wrapper.update();
- // Fetched new suggestions successfully through the informed event ID
- expect(wrapper.find('[data-test-id="event-id-field"] IconCheckmark')).toHaveLength(1);
- });
- });
|