Просмотр исходного кода

test(ui): RTL create alert test, add react-select-event (#27304)

Scott Cooper 3 лет назад
Родитель
Сommit
5c7afb40e3

+ 1 - 0
package.json

@@ -173,6 +173,7 @@
     "mockdate": "3.0.5",
     "prettier": "2.3.2",
     "react-refresh": "^0.8.3",
+    "react-select-event": "5.3.0",
     "react-test-renderer": "17.0.2",
     "size-limit": "^4.5.6",
     "speed-measure-webpack-plugin": "^1.5.0",

+ 1 - 1
tests/fixtures/js-stubs/projectAlertRuleConfiguration.js

@@ -225,7 +225,7 @@ export function ProjectAlertRuleConfiguration(params = {}) {
         },
         enabled: true,
         id: 'sentry.rules.filters.age_comparison.AgeComparisonFilter',
-        label: 'An issue is {comparison_type} than {value} {time}',
+        label: 'The issue is {comparison_type} than {value} {time}',
       },
       {
         formFields: {

+ 111 - 125
tests/js/spec/views/alerts/create.spec.jsx

@@ -1,7 +1,13 @@
-import {mountWithTheme} from 'sentry-test/enzyme';
+import selectEvent from 'react-select-event';
+
 import {initializeOrg} from 'sentry-test/initializeOrg';
 import {mockRouterPush} from 'sentry-test/mockRouterPush';
-import {selectByValue} from 'sentry-test/select-new';
+import {
+  cleanup,
+  fireEvent,
+  mountWithTheme,
+  waitFor,
+} from 'sentry-test/reactTestingLibrary';
 
 import * as memberActionCreators from 'app/actionCreators/members';
 import ProjectsStore from 'app/stores/projectsStore';
@@ -83,7 +89,7 @@ describe('ProjectAlertsCreate', function () {
     },
   ];
 
-  beforeEach(async function () {
+  beforeEach(function () {
     memberActionCreators.fetchOrgMembers = jest.fn();
     MockApiClient.addMockResponse({
       url: '/projects/org-slug/project-slug/rules/configuration/',
@@ -105,6 +111,7 @@ describe('ProjectAlertsCreate', function () {
   });
 
   afterEach(function () {
+    cleanup();
     MockApiClient.clearMockResponses();
   });
 
@@ -125,7 +132,7 @@ describe('ProjectAlertsCreate', function () {
           />
         </AlertBuilderProjectProvider>
       </AlertsContainer>,
-      routerContext
+      {context: routerContext}
     );
     mockRouterPush(wrapper, router);
 
@@ -139,19 +146,28 @@ describe('ProjectAlertsCreate', function () {
 
   describe('Issue Alert', function () {
     it('loads default values', async function () {
-      const {wrapper} = createWrapper();
-      await tick();
-      wrapper.update();
-      expect(memberActionCreators.fetchOrgMembers).toHaveBeenCalled();
-      expect(wrapper.find('SelectControl[name="environment"]').prop('value')).toBe(
-        '__all_environments__'
-      );
-      expect(wrapper.find('SelectControl[name="actionMatch"]').prop('value')).toBe('all');
-      expect(wrapper.find('SelectControl[name="frequency"]').prop('value')).toBe('30');
+      const {
+        wrapper: {getByDisplayValue},
+      } = createWrapper();
+
+      await waitFor(() => {
+        expect(getByDisplayValue('__all_environments__')).toBeInTheDocument();
+      });
+      expect(getByDisplayValue('all')).toBeInTheDocument();
+      expect(getByDisplayValue('30')).toBeInTheDocument();
     });
 
     it('updates values and saves', async function () {
-      const {wrapper, router} = createWrapper({
+      const {
+        wrapper: {
+          getAllByLabelText,
+          getAllByText,
+          getByLabelText,
+          getByPlaceholderText,
+          getByText,
+        },
+        router,
+      } = createWrapper({
         organization: {
           features: ['alert-filters'],
         },
@@ -161,140 +177,110 @@ describe('ProjectAlertsCreate', function () {
         method: 'POST',
         body: TestStubs.ProjectAlertRule(),
       });
-      await tick();
-      wrapper.update();
 
-      expect(memberActionCreators.fetchOrgMembers).toHaveBeenCalled();
-      // Change target environment
+      await waitFor(() => {
+        expect(memberActionCreators.fetchOrgMembers).toHaveBeenCalled();
+      });
 
-      selectByValue(wrapper, 'production', {control: true, name: 'environment'});
+      // Change target environment
+      await selectEvent.select(getByText('All Environments'), ['production']);
       // Change actionMatch and filterMatch dropdown
-      selectByValue(wrapper, 'any', {name: 'actionMatch'});
-      selectByValue(wrapper, 'any', {name: 'filterMatch'});
+      await selectEvent.select(getAllByText('all')[0], ['any']);
+      await selectEvent.select(getAllByText('all')[0], ['any']);
 
       // Change name of alert rule
-      wrapper
-        .find('input[name="name"]')
-        .simulate('change', {target: {value: 'My Rule Name'}});
-      // Add a condition and remove it
-      selectByValue(
-        wrapper,
-        'sentry.rules.conditions.first_seen_event.FirstSeenEventCondition',
-        {selector: 'Select[placeholder="Add optional condition..."]'}
-      );
+      fireEvent.change(getByPlaceholderText('My Rule Name'), {
+        target: {value: 'My Rule Name'},
+      });
 
-      wrapper
-        .find('RuleNode')
-        .at(0)
-        .find('button[aria-label="Delete Node"]')
-        .simulate('click');
+      // Add a condition and remove it
+      await selectEvent.select(getByText('Add optional condition...'), [
+        'A new issue is created',
+      ]);
+      fireEvent.click(getByLabelText('Delete Node'));
 
       // Add another condition
-      selectByValue(
-        wrapper,
-        'sentry.rules.conditions.tagged_event.TaggedEventCondition',
-        {selector: 'Select[placeholder="Add optional condition..."]'}
-      );
-
+      await selectEvent.select(getByText('Add optional condition...'), [
+        "An event's tags match {key} {match} {value}",
+      ]);
       // Edit new Condition
-      const ruleNode = wrapper.find('RuleNode').at(0);
-
-      ruleNode
-        .find('input[name="key"]')
-        .simulate('change', {target: {value: 'conditionKey'}});
-
-      ruleNode
-        .find('input[name="value"]')
-        .simulate('change', {target: {value: 'conditionValue'}});
-
-      selectByValue(wrapper, 'ne', {name: 'match', control: true});
-
-      // Add a filter and remove it
-      selectByValue(wrapper, 'sentry.rules.filters.age_comparison.AgeComparisonFilter', {
-        selector: 'Select[placeholder="Add optional filter..."]',
+      fireEvent.change(getByPlaceholderText('key'), {
+        target: {value: 'conditionKey'},
       });
+      fireEvent.change(getByPlaceholderText('value'), {
+        target: {value: 'conditionValue'},
+      });
+      await selectEvent.select(getByText('equals'), ['does not equal']);
 
-      wrapper
-        .find('RuleNode')
-        .at(1)
-        .find('button[aria-label="Delete Node"]')
-        .simulate('click');
+      // Add a filter and remove it
+      await selectEvent.select(getByText('Add optional filter...'), [
+        'The issue is {comparison_type} than {value} {time}',
+      ]);
+      fireEvent.click(getAllByLabelText('Delete Node')[1]);
 
       // Add a new filter
-      selectByValue(wrapper, 'sentry.rules.filters.age_comparison.AgeComparisonFilter', {
-        selector: 'Select[placeholder="Add optional filter..."]',
+      await selectEvent.select(getByText('Add optional filter...'), [
+        'The issue is {comparison_type} than {value} {time}',
+      ]);
+      fireEvent.change(getByPlaceholderText('10'), {
+        target: {value: '12'},
       });
 
-      const filterRuleNode = wrapper.find('RuleNode').at(1);
-
-      filterRuleNode
-        .find('input[type="number"]')
-        .simulate('change', {target: {value: '12'}});
-
       // Add an action and remove it
-      selectByValue(wrapper, 'sentry.rules.actions.notify_event.NotifyEventAction', {
-        selector: 'Select[placeholder="Add action..."]',
-      });
-
-      wrapper
-        .find('RuleNodeList')
-        .at(2)
-        .find('button[aria-label="Delete Node"]')
-        .simulate('click');
+      await selectEvent.select(getByText('Add action...'), [
+        'Send a notification (for all legacy integrations)',
+      ]);
+      fireEvent.click(getAllByLabelText('Delete Node')[2]);
 
       // Add a new action
-      selectByValue(
-        wrapper,
-        'sentry.rules.actions.notify_event_service.NotifyEventServiceAction',
-        {
-          selector: 'Select[placeholder="Add action..."]',
-        }
-      );
+      await selectEvent.select(getByText('Add action...'), [
+        'Send a notification via {service}',
+      ]);
 
-      selectByValue(wrapper, '60', {
-        name: 'frequency',
-      });
+      // Update action interval
+      await selectEvent.select(getByText('30 minutes'), ['60 minutes']);
 
-      wrapper.find('form').simulate('submit');
+      fireEvent.click(getByText('Save Rule'));
 
-      expect(mock).toHaveBeenCalledWith(
-        expect.any(String),
-        expect.objectContaining({
-          data: {
-            actionMatch: 'any',
-            filterMatch: 'any',
-            actions: [
-              {
-                id: 'sentry.rules.actions.notify_event_service.NotifyEventServiceAction',
-                service: 'mail',
-              },
-            ],
-            conditions: [
-              {
-                id: 'sentry.rules.conditions.tagged_event.TaggedEventCondition',
-                key: 'conditionKey',
-                match: 'ne',
-                value: 'conditionValue',
-              },
-            ],
-            filters: [
-              {
-                id: 'sentry.rules.filters.age_comparison.AgeComparisonFilter',
-                comparison_type: 'older',
-                time: 'minute',
-                value: '12',
-              },
-            ],
-            environment: 'production',
-            frequency: '60',
-            name: 'My Rule Name',
-            owner: null,
-          },
-        })
-      );
+      await waitFor(() => {
+        expect(mock).toHaveBeenCalledWith(
+          expect.any(String),
+          expect.objectContaining({
+            data: {
+              actionMatch: 'any',
+              filterMatch: 'any',
+              actions: [
+                {
+                  id: 'sentry.rules.actions.notify_event_service.NotifyEventServiceAction',
+                  service: 'mail',
+                },
+              ],
+              conditions: [
+                {
+                  id: 'sentry.rules.conditions.tagged_event.TaggedEventCondition',
+                  key: 'conditionKey',
+                  match: 'ne',
+                  value: 'conditionValue',
+                },
+              ],
+              filters: [
+                {
+                  id: 'sentry.rules.filters.age_comparison.AgeComparisonFilter',
+                  comparison_type: 'older',
+                  time: 'minute',
+                  value: '12',
+                },
+              ],
+              environment: 'production',
+              frequency: '60',
+              name: 'My Rule Name',
+              owner: null,
+            },
+          })
+        );
+      });
       expect(metric.startTransaction).toHaveBeenCalledWith({name: 'saveAlertRule'});
 
-      await tick();
       expect(router.push).toHaveBeenCalledWith('/organizations/org-slug/alerts/rules/');
     });
   });

+ 21 - 0
yarn.lock

@@ -2958,6 +2958,20 @@
     remark "^13.0.0"
     unist-util-find-all-after "^3.0.2"
 
+"@testing-library/dom@>=7":
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d"
+  integrity sha512-kmW9alndr19qd6DABzQ978zKQ+J65gU2Rzkl8hriIetPnwpesRaK4//jEQyYh8fEALmGhomD/LBQqt+o+DL95Q==
+  dependencies:
+    "@babel/code-frame" "^7.10.4"
+    "@babel/runtime" "^7.12.5"
+    "@types/aria-query" "^4.2.0"
+    aria-query "^4.2.2"
+    chalk "^4.1.0"
+    dom-accessibility-api "^0.5.6"
+    lz-string "^1.4.4"
+    pretty-format "^27.0.2"
+
 "@testing-library/dom@^8.0.0":
   version "8.0.0"
   resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.0.0.tgz#2bb994393c566aae021db86dd263ba06e8b71b38"
@@ -12986,6 +13000,13 @@ react-router@3.2.0:
     prop-types "^15.5.6"
     warning "^3.0.0"
 
+react-select-event@5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/react-select-event/-/react-select-event-5.3.0.tgz#4548fffd615a47176951cbb301ee21a0c60b582a"
+  integrity sha512-Novkl7X9JJKmDV5LyYaKwl0vffWtqPrBa1vuI0v43P/f87mSA7JfdYxU93SFb99RssphVzBSIAbcnbX1w21QIQ==
+  dependencies:
+    "@testing-library/dom" ">=7"
+
 react-select@^3.0.8:
   version "3.0.8"
   resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.8.tgz#06ff764e29db843bcec439ef13e196865242e0c1"