Files
signoz/frontend/src/tests
Vinicius Lourenço bd526df11d feat(roles): rework the create/update pages (#11815)
* fix(styles): little fix for callout

I will upstream this fix eventually

* fix(settings): ensure tab content can use height: 100%

We will need this fix for the create/edit role page later during json mode

* refactor(authz): define the verbs that supports selectorId

* refactor(roles): drop old components

We will rewrite them

* refactor(roles): use css modules on role settings

* refactor(roles): rewrite delete role modal to use dialog component

* feat(roles): add initial type files

* feat(error-in-place): add testId to allow assert on future tests

* refactor(permission-denied-full-page): change the wording a little bit to match the API

This change was requested by Vikrant

* feat(service-account-drawer): add copy button for ID

Suggested by https://github.com/SigNoz/platform-pod/issues/2529#issuecomment-4776975323

* fix(service-account-drawer): not validating the permissions correctly for read/update

Found at https://github.com/SigNoz/platform-pod/issues/2529#issuecomment-4776975323

* feat(timezone): add little helper to allow format optional dates

* refactor(authz): export parse permission to get objectId when needed

* test(authz): add helper to grant by prefix

* test(test-utils): include tooltip provider

* feat(hooks): add hook to block navigation via history

* feat(roles): add hook to map API interface to own interface for easier integration

* feat(roles): add hook to fetch role permissions

* feat(roles): add config object around how to define each section for each resource

* feat(roles): add config for monaco when showing json

* feat(view-roles): add selected ids component

* feat(view-roles): add component row to render selected roles

* feat(view-roles): add card component to render each resource selected

* feat(view-roles): add overview component to view roles

* feat(view-roles): add readonly json viewer

* feat(view-roles): add view role page

* test(view-roles): add tests for view roles

* feat(create-edit-roles): add hook for form validation

* feat(create-edit-roles): add hook for unsaved changes

* feat(create-edit-roles): add hook for generic logic for create-edit

* feat(create-edit-roles): add component to render json

* feat(create-edit-roles): add component to add new selectors for a permission

* feat(create-edit-roles): add component to select scopes of a permission

* feat(create-edit-roles): add component render resources to be selected

* feat(create-edit-roles): add component render permission editor

* feat(create-edit-roles): add page to create/edit roles

* test(create-edit-roles): add tests for page and subcomponents

* feat(list-roles): refactor to css modules & add row click to open view role page

* fix(list-roles): change description when feature gate is disabled

* refactor(roles): removed action labels and use function instead

* refactor(authz): add todo about permission.config

* feat(roles): add routes for create/edit/view

* test(service-account): update missing tests

* fix(pr): address comments

* fix(pr): rename suffix of hooks from callbacks to actions

* fix(pr): remove all usages of getByText

* test(use-navigation-blocker): fix test
2026-06-25 17:24:16 +00:00
..

Testing Guide

Tech Stack

  • React Testing Library (RTL)
  • Jest (runner, assertions, mocking)
  • MSW (Mock Service Worker) for HTTP
  • TypeScript (type-safe tests)
  • JSDOM (browser-like env)

Unit Testing: What, Why, How

  • What: Small, isolated tests for components, hooks, and utilities to verify behavior and edge cases.
  • Why: Confidence to refactor, faster feedback than E2E, catches regressions early, documents intended behavior.
  • How: Use our test harness with providers, mock external boundaries (APIs, router), assert on visible behavior and accessible roles, not implementation details.

Basic Template

import { render, screen, userEvent, waitFor } from 'tests/test-utils';
import { server, rest } from 'mocks-server/server';
import MyComponent from '../MyComponent';

describe('MyComponent', () => {
  it('renders and interacts', async () => {
    const user = userEvent.setup({ pointerEventsCheck: 0 });

    server.use(
      rest.get('*/api/v1/example', (_req, res, ctx) => res(ctx.status(200), ctx.json({ value: 42 })))
    );

    render(<MyComponent />, undefined, { initialRoute: '/foo' });

    expect(await screen.findByText(/value: 42/i)).toBeInTheDocument();
    await user.click(screen.getByRole('button', { name: /refresh/i }));
    await waitFor(() => expect(screen.getByText(/loading/i)).toBeInTheDocument());
  });
});

.cursorrules (Highlights)

  • Import from tests/test-utils only.
  • Prefer userEvent for real interactions; use fireEvent only for low-level events (scroll/resize/setting scrollTop).
  • Use MSW to mock network calls; large JSON goes in mocks-server/__mockdata__.
  • Keep tests type-safe (jest.MockedFunction<T>, avoid any).
  • Prefer accessible queries (getByRole, findByRole) before text and data-testid.
  • Pin time only when asserting relative dates; avoid global fake timers otherwise.

Repo-specific reasons:

  • The harness wires Redux, React Query, i18n, timezone, preferences, so importing from RTL directly bypasses critical providers.
  • Some infra deps are globally mocked (e.g., uplot) to keep tests fast and stable.
  • For virtualization (react-virtuoso), there is no userEvent scroll helper; use fireEvent.scroll after setting element.scrollTop.

Example patterns (from components/QuickFilters/tests/QuickFilters.test.tsx)

MSW overrides per test:

server.use(
  rest.get(`${ENVIRONMENT.baseURL}/api/v1/orgs/me/filters/logs`, (_req, res, ctx) =>
    res(ctx.status(200), ctx.json(quickFiltersListResponse)),
  ),
  rest.put(`${ENVIRONMENT.baseURL}/api/v1/orgs/me/filters`, async (req, res, ctx) => {
    // capture payload if needed
    return res(ctx.status(200), ctx.json({}));
  }),
);

Mock hooks minimally at module level:

jest.mock('hooks/queryBuilder/useQueryBuilder', () => ({
  useQueryBuilder: jest.fn(),
}));

Interact via accessible roles:

const user = userEvent.setup({ pointerEventsCheck: 0 });
await user.click(screen.getByRole('button', { name: /save changes/i }));
expect(screen.getByText(/ADDED FILTERS/i)).toBeInTheDocument();

Virtualized scroll:

const scroller = container.querySelector('[data-test-id="virtuoso-scroller"]') as HTMLElement;
scroller.scrollTop = 500;
fireEvent.scroll(scroller);

Routing-dependent behavior:

render(<Page />, undefined, { initialRoute: '/logs-explorer?panelType=list' });

Notes

  • Global mocks configured in Jest: uplot__mocks__/uplotMock.ts.
  • If a test needs custom behavior (e.g., different API response), override with server.use(...) locally.