Browse Source

feat: add biome rules for strict tests (#69528)

Adds biome rules specifically for Jest.
Yagiz Nizipli 10 months ago
parent
commit
66c45a6181

+ 2 - 0
.eslintrc.js

@@ -27,6 +27,7 @@ module.exports = {
     'array-bracket-spacing': 'off',
     'computed-property-spacing': 'off',
     'react/no-danger-with-children': 'off',
+    'jest/no-disabled-tests': 'off',
   },
   // JSON file formatting is handled by Biome. ESLint should not be linting
   // and formatting these files.
@@ -47,6 +48,7 @@ module.exports = {
         'array-bracket-spacing': 'off',
         'computed-property-spacing': 'off',
         'react/no-danger-with-children': 'off',
+        'jest/no-disabled-tests': 'off',
       },
     },
     {

+ 6 - 2
biome.json

@@ -31,7 +31,8 @@
         "noUselessLoneBlockStatements": "error",
         "noUselessEmptyExport": "error",
         "noUselessConstructor": "error",
-        "noUselessTypeConstraint": "error"
+        "noUselessTypeConstraint": "error",
+        "noExcessiveNestedTestSuites": "error"
       },
       "nursery": {
         "noDuplicateJsonKeys": "error",
@@ -59,7 +60,10 @@
         "noApproximativeNumericConstant": "error",
         "noMisrefactoredShorthandAssign": "error",
         "useAwait": "error",
-        "useNamespaceKeyword": "error"
+        "useNamespaceKeyword": "error",
+        "noSkippedTests": "error",
+        "noFocusedTests": "error",
+        "noDuplicateTestHooks": "error"
       },
       "style": {
         "noCommaOperator": "error",

+ 0 - 2
static/app/components/assigneeSelectorDropdown.spec.tsx

@@ -94,9 +94,7 @@ describe('AssigneeSelectorDropdown', () => {
     jest.spyOn(GroupStore, 'get').mockImplementation(() => GROUP_1);
 
     MemberListStore.reset();
-  });
 
-  beforeEach(() => {
     ProjectsStore.loadInitialData([PROJECT_1]);
   });
 

+ 1 - 4
static/app/components/deprecatedAssigneeSelector.spec.tsx

@@ -105,6 +105,7 @@ describe('DeprecatedAssigneeSelector', () => {
     });
 
     MemberListStore.reset();
+    ProjectsStore.loadInitialData([PROJECT_1]);
   });
 
   // Doesn't need to always be async, but it was easier to prevent flakes this way
@@ -112,10 +113,6 @@ describe('DeprecatedAssigneeSelector', () => {
     await userEvent.click(await screen.findByTestId('assignee-selector'), undefined);
   };
 
-  beforeEach(() => {
-    ProjectsStore.loadInitialData([PROJECT_1]);
-  });
-
   afterEach(() => {
     ProjectsStore.reset();
     MockApiClient.clearMockResponses();

+ 1 - 1
static/app/components/events/contexts/gpu/index.spec.tsx

@@ -43,7 +43,7 @@ const event = EventFixture({
 });
 
 // Flaky test https://github.com/getsentry/sentry/actions/runs/4465585304/jobs/7842795315?pr=45984
-// eslint-disable-next-line
+// biome-ignore lint/suspicious/noSkippedTests: Flaky test
 describe.skip('gpu event context', function () {
   it('display redacted data', async function () {
     render(<GPUEventContext event={event} data={gpuMockData} />, {

+ 0 - 7
static/app/plugins/components/pluginIcon.spec.tsx

@@ -1,5 +1,3 @@
-/* eslint-disable jest/no-disabled-tests */
-
 import {render} from 'sentry-test/reactTestingLibrary';
 
 import PluginIcon from 'sentry/plugins/components/pluginIcon';
@@ -13,9 +11,4 @@ describe('PluginIcon', function () {
   it('renders', function () {
     render(<PluginIcon pluginId="github" size={20} />);
   });
-
-  // doesn't work because of the above comment
-  it.skip('renders with default icon with invalid plugin id', function () {
-    render(<PluginIcon pluginId="invalid" size={20} />);
-  });
 });

+ 0 - 104
static/app/views/dashboards/create.spec.tsx

@@ -1,104 +0,0 @@
-import {DashboardFixture} from 'sentry-fixture/dashboard';
-import {OrganizationFixture} from 'sentry-fixture/organization';
-import {ProjectFixture} from 'sentry-fixture/project';
-
-import {initializeOrg} from 'sentry-test/initializeOrg';
-import {
-  render,
-  renderGlobalModal,
-  screen,
-  userEvent,
-} from 'sentry-test/reactTestingLibrary';
-
-import ProjectsStore from 'sentry/stores/projectsStore';
-import CreateDashboard from 'sentry/views/dashboards/create';
-
-describe('Dashboards > Create', function () {
-  const organization = OrganizationFixture({
-    features: ['dashboards-basic', 'dashboards-edit', 'discover-query'],
-  });
-
-  describe('new dashboards', function () {
-    let initialData;
-    const projects = [ProjectFixture()];
-
-    beforeEach(function () {
-      ProjectsStore.init();
-      ProjectsStore.loadInitialData(projects);
-
-      initialData = initializeOrg({
-        organization,
-        project: undefined,
-        projects: [],
-        router: {},
-      });
-
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/tags/',
-        body: [],
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/projects/',
-        body: [ProjectFixture()],
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/dashboards/',
-        body: [DashboardFixture([], {id: 'default-overview', title: 'Default'})],
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/events-stats/',
-        body: {data: []},
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/dashboards/widgets/',
-        method: 'POST',
-        body: [],
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/users/',
-        method: 'GET',
-        body: [],
-      });
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/eventsv2/',
-        body: {data: []},
-      });
-    });
-
-    afterEach(function () {
-      MockApiClient.clearMockResponses();
-    });
-
-    // eslint-disable-next-line
-    it.skip('can create with new widget', async function () {
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/dashboards/',
-        method: 'POST',
-        body: DashboardFixture([], {id: '1', title: 'Custom Errors'}),
-      });
-
-      render(
-        <CreateDashboard
-          organization={initialData.organization}
-          params={{orgId: 'org-slug'}}
-          router={initialData.router}
-          location={initialData.router.location}
-          {...initialData.router}
-        />,
-        {context: initialData.routerContext}
-      );
-      renderGlobalModal({context: initialData.routerContext});
-
-      await userEvent.click(await screen.findByTestId('widget-add'));
-
-      // Add a custom widget to the dashboard
-      await userEvent.click(await screen.findByText('Custom Widget'));
-      await userEvent.click(screen.getByTestId('widget-title-input'));
-      await userEvent.paste('Widget Title');
-      await userEvent.click(screen.getByText('Save'));
-
-      // Committing dashboard should complete without throwing error
-      await userEvent.click(screen.getByText('Save and Finish'));
-    });
-  });
-});

+ 0 - 2
static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx

@@ -525,8 +525,6 @@ describe('GroupReplays', () => {
       );
     });
 
-    // Test seems to be flaky
-    // eslint-disable-next-line jest/no-disabled-tests
     it('Should switch replays when clicking and replay-play-from-replay-tab is enabled', async () => {
       ({router, organization, routerContext} = init({
         organizationProps: {features: ['session-replay']},

+ 3 - 8
static/app/views/issueList/overview.polling.spec.tsx

@@ -32,12 +32,9 @@ describe('IssueList -> Polling', function () {
   let issuesRequest: jest.Mock;
   let pollRequest: jest.Mock;
 
-  beforeEach(() => {
-    jest.useFakeTimers();
-  });
-
   afterEach(() => {
     jest.useRealTimers();
+    MockApiClient.clearMockResponses();
   });
 
   const {organization, project, routerProps, routerContext} = initializeOrg({
@@ -74,6 +71,8 @@ describe('IssueList -> Polling', function () {
   };
 
   beforeEach(function () {
+    jest.useFakeTimers();
+
     // The tests fail because we have a "component update was not wrapped in act" error.
     // It should be safe to ignore this error, but we should remove the mock once we move to react testing library
     // eslint-disable-next-line no-console
@@ -151,10 +150,6 @@ describe('IssueList -> Polling', function () {
     TagStore.init();
   });
 
-  afterEach(function () {
-    MockApiClient.clearMockResponses();
-  });
-
   it('toggles polling for new issues', async function () {
     await renderComponent();
 

+ 1 - 40
static/app/views/issueList/searchBar.spec.tsx

@@ -1,7 +1,7 @@
 import {TagsFixture} from 'sentry-fixture/tags';
 
 import {initializeOrg} from 'sentry-test/initializeOrg';
-import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
+import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
 
 import TagStore from 'sentry/stores/tagStore';
 import IssueListSearchBar from 'sentry/views/issueList/searchBar';
@@ -164,44 +164,5 @@ describe('IssueListSearchBar', function () {
         })
       );
     });
-
-    // Flaky due to timeouts, see https://github.com/getsentry/sentry/issues/42898
-    // eslint-disable-next-line jest/no-disabled-tests
-    it.skip('cycles through keyboard navigation for selection', async function () {
-      MockApiClient.addMockResponse({
-        url: '/organizations/org-slug/tags/device.orientation/values/',
-        method: 'GET',
-        body: [],
-      });
-
-      render(<IssueListSearchBar {...defaultProps} />, {context: routerContext});
-
-      const textarea = screen.getByRole('textbox');
-
-      // Keyboard navigate to first item and select
-      await userEvent.type(textarea, 't');
-      await waitFor(() =>
-        expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
-      );
-      await userEvent.keyboard('{ArrowDown}{Tab}');
-      expect(textarea).not.toHaveValue('t');
-      const firstItemValue = textarea.textContent;
-
-      // Keyboard navigate to second item and select
-      await userEvent.keyboard('{selectall}{backspace}t');
-      await waitFor(() =>
-        expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
-      );
-      await userEvent.keyboard('{ArrowDown}{ArrowDown}{Tab}');
-      expect(textarea).not.toHaveValue(firstItemValue);
-
-      // Keyboard navigate to second item, then back to first item and select
-      await userEvent.keyboard('{selectall}{backspace}t');
-      await waitFor(() =>
-        expect(screen.getAllByTestId('search-autocomplete-item')[0]).toBeInTheDocument()
-      );
-      await userEvent.keyboard('{ArrowDown}{ArrowDown}{ArrowUp}{Tab}');
-      expect(textarea).toHaveValue(firstItemValue);
-    });
   });
 });

Some files were not shown because too many files changed in this diff