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

ref(js): Rewrite alert rules tests in RTL (#29729)

Evan Purkhiser 3 лет назад
Родитель
Сommit
e5b56fe3a6

+ 1 - 1
static/app/views/alerts/alertBadge.tsx

@@ -32,7 +32,7 @@ function AlertBadge({status, hideText = false, isIssue}: Props) {
   }
 
   return (
-    <Wrapper displayFlex={!hideText}>
+    <Wrapper data-test-id="alert-badge" displayFlex={!hideText}>
       <AlertIconWrapper color={color} icon={Icon}>
         <Icon color="white" />
       </AlertIconWrapper>

+ 93 - 91
tests/js/spec/views/alerts/rules/index.spec.jsx

@@ -1,7 +1,7 @@
-import {mountWithTheme} from 'sentry-test/enzyme';
 import {initializeOrg} from 'sentry-test/initializeOrg';
-import {act} from 'sentry-test/reactTestingLibrary';
+import {act, fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
 
+import OrganizationStore from 'app/stores/organizationStore';
 import ProjectsStore from 'app/stores/projectsStore';
 import {trackAnalyticsEvent} from 'app/utils/analytics';
 import AlertRulesList from 'app/views/alerts/rules';
@@ -13,22 +13,19 @@ describe('OrganizationRuleList', () => {
   const {routerContext, organization, router} = initializeOrg();
   let rulesMock;
   let projectMock;
-  let wrapper;
-
-  const createWrapper = async props => {
-    wrapper = mountWithTheme(
-      <AlertRulesList
-        organization={organization}
-        params={{orgId: organization.slug}}
-        location={{query: {}, search: ''}}
-        router={router}
-        {...props}
-      />,
-      routerContext
-    );
-    await tick();
-    wrapper.update();
-  };
+
+  const getComponent = props => (
+    <AlertRulesList
+      organization={organization}
+      params={{orgId: organization.slug}}
+      location={{query: {}, search: ''}}
+      router={router}
+      {...props}
+    />
+  );
+
+  const createWrapper = props =>
+    mountWithTheme(getComponent(props), {context: routerContext});
 
   beforeEach(() => {
     rulesMock = MockApiClient.addMockResponse({
@@ -59,25 +56,20 @@ describe('OrganizationRuleList', () => {
       body: [TestStubs.Project({slug: 'earth', platform: 'javascript'})],
     });
 
+    act(() => OrganizationStore.onUpdate(organization, {replace: true}));
     act(() => ProjectsStore.loadInitialData([]));
   });
 
   afterEach(() => {
-    wrapper.unmount();
     act(() => ProjectsStore.reset());
     MockApiClient.clearMockResponses();
     trackAnalyticsEvent.mockClear();
   });
 
   it('displays list', async () => {
-    await createWrapper();
+    createWrapper();
 
-    const row = wrapper.find('RuleListRow').at(0);
-    expect(row.find('AlertName').text()).toBe('First Issue Alert');
-
-    // GlobalSelectionHeader loads projects + the Projects render-prop
-    // component to load projects for all rows.
-    expect(projectMock).toHaveBeenCalledTimes(2);
+    expect(await screen.findByText('First Issue Alert')).toBeInTheDocument();
 
     expect(projectMock).toHaveBeenLastCalledWith(
       expect.anything(),
@@ -85,9 +77,9 @@ describe('OrganizationRuleList', () => {
         query: expect.objectContaining({query: 'slug:earth'}),
       })
     );
-    expect(wrapper.find('IdBadge').at(0).prop('project')).toMatchObject({
-      slug: 'earth',
-    });
+
+    expect(screen.getAllByTestId('badge-display-name')[0]).toHaveTextContent('earth');
+
     expect(trackAnalyticsEvent).toHaveBeenCalledWith({
       eventKey: 'alert_rules.viewed',
       eventName: 'Alert Rules: Viewed',
@@ -102,59 +94,70 @@ describe('OrganizationRuleList', () => {
       body: [],
     });
 
-    await createWrapper();
+    createWrapper();
 
-    expect(rulesMock).toHaveBeenCalledTimes(0);
+    expect(
+      await screen.findByText('No alert rules found for the current query.')
+    ).toBeInTheDocument();
 
-    expect(wrapper.find('PanelItem')).toHaveLength(0);
-    expect(wrapper.text()).toContain('No alert rules found for the current query');
+    expect(rulesMock).toHaveBeenCalledTimes(0);
   });
 
   it('sorts by date created', async () => {
-    await createWrapper();
+    const {rerender} = createWrapper();
 
-    expect(wrapper.find('IconArrow').at(0).prop('direction')).toBe('down');
+    // The created column is not used for sorting
+    expect(await screen.findByText('Created')).toHaveAttribute('aria-sort', 'none');
 
-    wrapper.setProps({
-      location: {query: {asc: '1'}, search: '?asc=1`'},
-    });
+    // Sort by created (date_added)
+    rerender(
+      getComponent({
+        location: {
+          query: {asc: '1', sort: 'date_added'},
+          search: '?asc=1&sort=date_added`',
+        },
+      })
+    );
 
-    expect(wrapper.find('IconArrow').at(0).prop('direction')).toBe('up');
+    expect(await screen.findByText('Created')).toHaveAttribute('aria-sort', 'ascending');
 
     expect(rulesMock).toHaveBeenCalledTimes(2);
 
     expect(rulesMock).toHaveBeenCalledWith(
       '/organizations/org-slug/combined-rules/',
-      expect.objectContaining({query: expect.objectContaining({asc: '1'})})
+      expect.objectContaining({
+        query: expect.objectContaining({asc: '1'}),
+      })
     );
   });
 
   it('sorts by name', async () => {
-    await createWrapper();
+    const {rerender} = createWrapper();
 
-    const nameHeader = wrapper.find('StyledSortLink').first();
-    expect(nameHeader.text()).toContain('Alert Rule');
-    expect(nameHeader.props().to).toEqual(
-      expect.objectContaining({
-        query: {
-          sort: 'name',
-          asc: '1',
-          team: ['myteams', 'unassigned'],
-          expand: ['latestIncident'],
+    // The name column is not used for sorting
+    expect(await screen.findByText('Alert Rule')).toHaveAttribute('aria-sort', 'none');
+
+    // Sort by the name column
+    rerender(
+      getComponent({
+        location: {
+          query: {asc: '1', sort: 'name'},
+          search: '?asc=1&sort=name`',
         },
       })
     );
 
-    wrapper.setProps({
-      location: {query: {sort: 'name'}, search: '?asc=1&sort=name`'},
-    });
+    expect(await screen.findByText('Alert Rule')).toHaveAttribute(
+      'aria-sort',
+      'ascending'
+    );
+
+    expect(rulesMock).toHaveBeenCalledTimes(2);
 
-    expect(wrapper.find('StyledSortLink').first().props().to).toEqual(
+    expect(rulesMock).toHaveBeenCalledWith(
+      '/organizations/org-slug/combined-rules/',
       expect.objectContaining({
-        query: {
-          sort: 'name',
-          asc: '1',
-        },
+        query: expect.objectContaining({sort: 'name', asc: '1'}),
       })
     );
   });
@@ -165,29 +168,24 @@ describe('OrganizationRuleList', () => {
       access: [],
     };
 
-    await createWrapper({organization: noAccessOrg});
+    const {rerender} = createWrapper({organization: noAccessOrg});
 
-    const addButton = wrapper.find('button[aria-label="Create Alert Rule"]');
-    expect(addButton.props()['aria-disabled']).toBe(true);
-    wrapper.unmount();
+    expect(await screen.findByLabelText('Create Alert Rule')).toBeDisabled();
 
     // Enabled with access
-    await createWrapper();
-
-    const addLink = wrapper.find('button[aria-label="Create Alert Rule"]');
-    expect(addLink.props()['aria-disabled']).toBe(false);
+    rerender(getComponent());
+    expect(await screen.findByLabelText('Create Alert Rule')).toBeEnabled();
   });
 
   it('searches by name', async () => {
-    await createWrapper();
-    expect(wrapper.find('StyledSearchBar').exists()).toBe(true);
+    createWrapper();
+
+    const search = await screen.findByPlaceholderText('Search by name');
+    expect(search).toBeInTheDocument();
 
     const testQuery = 'test name';
-    wrapper
-      .find('StyledSearchBar')
-      .find('input')
-      .simulate('change', {target: {value: testQuery}})
-      .simulate('submit', {preventDefault() {}});
+    fireEvent.change(search, {target: {value: testQuery}});
+    fireEvent.submit(search);
 
     expect(router.push).toHaveBeenCalledWith(
       expect.objectContaining({
@@ -202,16 +200,18 @@ describe('OrganizationRuleList', () => {
   });
 
   it('uses empty team query parameter when removing all teams', async () => {
-    await createWrapper();
+    const {rerender} = createWrapper();
+
+    expect(await screen.findByText('First Issue Alert')).toBeInTheDocument();
+
+    rerender(
+      getComponent({location: {query: {team: 'myteams'}, search: '?team=myteams`'}})
+    );
+
+    fireEvent.click(await screen.findByTestId('filter-button'));
 
-    wrapper.setProps({
-      location: {query: {team: 'myteams'}, search: '?team=myteams`'},
-    });
-    wrapper.find('Button[data-test-id="filter-button"]').simulate('click');
     // Uncheck myteams
-    const myTeamsItem = wrapper.find('Filter').find('ListItem').at(0);
-    expect(myTeamsItem.text()).toBe('My Teams');
-    myTeamsItem.simulate('click');
+    fireEvent.click(await screen.findByText('My Teams'));
 
     expect(router.push).toHaveBeenCalledWith(
       expect.objectContaining({
@@ -225,19 +225,21 @@ describe('OrganizationRuleList', () => {
   });
 
   it('displays alert status', async () => {
-    await createWrapper({organization});
-    let row = wrapper.find('RuleListRow').at(1);
-    expect(row.find('AlertNameAndStatus').text()).toContain('My Incident Rule');
-    expect(row.find('AlertNameAndStatus').text()).toContain('Triggered');
-    expect(row.find('TriggerText').text()).toBe('Above 70');
-
-    row = wrapper.find('RuleListRow').at(2);
-    expect(row.find('TriggerText').text()).toBe('Below 36');
-    expect(wrapper.find('AlertIconWrapper').exists()).toBe(true);
+    createWrapper();
+    const rules = await screen.findAllByText('My Incident Rule');
+
+    expect(rules[0]).toBeInTheDocument();
+
+    expect(screen.getByText('Triggered')).toBeInTheDocument();
+    expect(screen.getByText('Above 70')).toBeInTheDocument();
+    expect(screen.getByText('Below 36')).toBeInTheDocument();
+    expect(screen.getAllByTestId('alert-badge')[0]).toBeInTheDocument();
   });
 
   it('sorts by alert rule', async () => {
-    await createWrapper({organization});
+    createWrapper({organization});
+
+    expect(await screen.findByText('First Issue Alert')).toBeInTheDocument();
 
     expect(rulesMock).toHaveBeenCalledWith(
       '/organizations/org-slug/combined-rules/',