test-guidelines
SkillMonitoring & opsLets your agent write Jest tests for Sentry React Native following the project's naming, structure, and mocking conventions.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the test-guidelines skill
About this capability
Enforce Sentry React Native SDK test conventions for naming, structure, mocking, and fixtures with Jest. Use when writing tests, adding tests, modifying tests, reviewing test code, fixing failing tests, adding coverage, TDD, test-first / red-green, reproducing bugs with tests, regression tests, or t
What this skill tells your AI
The instructions your AI receives, as published by getsentry/sentry-react-native in .agents/skills/test-guidelines/SKILL.md and read by ahel’s review.
Apply these conventions to all new and modified tests in packages/core. Existing tests may not follow them — do not refactor them unless asked. Tests run on Jest (yarn test, yarn test:watch, yarn test:sdk, yarn test:tools).
Tests are easiest to write against code designed to accept its dependencies — when implementing the code under test, load design-first (where the seams go) and code-guidelines (the rules).
Test-first loop
Work in vertical slices. One failing test → the minimal code that makes it pass → repeat. Each test proves one thin path end-to-end, and what it teaches shapes the next.
Do not write all the tests first and then all the implementation. That horizontal slicing produces tests of imagined behavior — they assert the shape you guessed at and pass when the real behavior breaks. Write one test at a time, against behavior you can already reason about.
Fixing a bug? Reproduce it with a failing test first — see diagnosing-bugs.
File structure
- One test file per source file. Mirror the path:
src/js/client.ts→test/client.test.ts;src/js/integrations/release.ts→test/integrations/release.test.ts. - React component tests use
.test.tsxand@testing-library/react-native. - A single top-level
describenaming the unit under test, with nesteddescribe/itinside it.
Naming
Follow the convention in packages/core/AGENTS.md: describe/it blocks (preferred), with the it describing the expected behavior for a given input.
- The top-level
describenames the unit under test — the exported name (myFeatureIntegration,NATIVE, the class). - Nested
describegroups a method or a scenario;itstates the behavior being verified. - Write
itas a clear behavior description, e.g.returns expected value when input is valid.
describe('nativeLinkedErrorsIntegration', () => {
describe('when the native module is unavailable', () => {
it('returns the event unchanged', () => { /* ... */ });
});
describe('processEvent', () => {
it('appends linked errors up to the configured limit', () => { /* ... */ });
});
});
Style — Arrange / Act / Assert
Structure every test in three clear sections; a blank line between them is enough.
it('returns expected value when input is valid', () => {
// Arrange
const input = 'test';
// Act
const result = functionName(input);
// Assert
expect(result).toBe('expected');
});
Use specific matchers — they produce better failure messages:
expect(array).toHaveLength(3); // not expect(array.length).toBe(3)
expect(obj).toMatchObject({ a: 1 }); // partial structural match
expect(fn).toThrow(Error);
await expect(promise).resolves.toBe('ok');
await expect(promise).rejects.toThrow();
Assert the exact symptom, not "didn't crash". A test that only checks a call didn't throw catches almost nothing.
Mocking
- Reset between tests. Use
afterEach(() => { jest.clearAllMocks(); })(orresetAllMockswhen you also stub implementations). A leaked mock is the most common flaky-test cause here. - Mock the native module, not the whole SDK. Prefer the shared helpers (
test/mockWrapper.ts,test/mocks/) over re-mockingreact-nativead hoc. When you must, mock the bridge surface only:
jest.mock('react-native', () => ({
NativeModules: { RNSentry: { fetchNativeSdkInfo: jest.fn(() => Promise.resolve({})) } },
Platform: { OS: 'ios', select: (o: any) => o.ios ?? o.default },
}));
- Test both architectures / platforms when the code branches on them. Drive
Platform.OS,isTurboModuleEnabled(),isFabricEnabled()from the test rather than assuming one. - Prefer injecting a fake at a seam over
jest.mockof a deep import — a test that mocks internals breaks on refactors even when behavior is unchanged (see design-first: the interface is the test surface). - Don't mock the thing under test. Don't assert on private internals; assert on observable output (the event, the envelope, the resolved value).
Async & timers
- Always
awaitasync assertions; return or await the promise so Jest sees failures. - For timing-dependent code (flush timers, debounces, retries) use fake timers (
jest.useFakeTimers()+jest.advanceTimersByTime(...)), not realsetTimeout— real delays make tests slow and flaky. Restore withjest.useRealTimers()inafterEach. - No real network or filesystem. Stub the transport / bridge.
What to test
- The behavior at the seam a caller depends on — inputs → observable outputs.
- Edge cases the code guidelines call out: native module missing,
enableNativefalse, PII gating on/off, serialization round-trips across the bridge, both architectures. - Every bug fix carries a regression test that goes red before the fix and green after.
Signals
- GitHub stars
- 2k
- Forks
- 367
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
test-guidelines- Source
- github.com/getsentry/sentry-react-native