К основному содержанию
правило

detox — правило для Cursor: что делает и как установить

Задаёт стандарты E2E-тестирования на Detox в React Native: требует паттерн Page Object Model и селекторы по testID без произвольных пауз через sleep.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/detox.mdc
Открыть на GitHub

Что делает detox

Правило настраивает генерацию и рефакторинг сквозных тестов для мобильных приложений на React Native. Оно привязывается к файлам по маске **/*.{js,jsx}. Вся логика тестов делится через классы Page Object Model, изолируя селекторы интерфейса от самих сценариев.

Код тестов строится на стабильных селекторах by.id, а не на хрупких by.type или by.label. Любые вызовы sleep() запрещены. Для ожидания асинхронных состояний применяется метод waitFor с ограничением времени withTimeout. Состояние приложения сбрасывается перед каждым тестом вызовом device.reloadReactNative(), а для полной переустановки в хуке beforeAll используется device.launchApp({ delete: true }).

Для внешних API-запросов правило предписывает изоляцию через msw или nock, чтобы исключить сбои из-за сети. Без расставленных testID в компонентах JSX ассистент будет скатываться к ненадёжному поиску по тексту.

Какие задачи решает

  • переписать сквозные тесты Detox на паттерн Page Object Model
  • заменить произвольные паузы sleep() на waitFor с таймаутом
  • настроить сброс состояния React Native между тестовыми сценариями
  • изолировать внешние сетевые запросы с помощью msw или nock

Примеры запросов агенту

  • Создай Page Object и тест авторизации для экрана Login на Detox
  • Замени ненадёжные селекторы и вызовы sleep в тестах на waitFor с таймаутом
  • Настрой мокирование сетевых запросов через msw для сквозного теста профиля

Как установить detox

Вручную: положить файлы

.cursor/rules/detox.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о detox

Как установить detox в Cursor?

Добавьте файл правила по пути .cursor/rules/detox.mdc. Cursor будет учитывать эти инструкции при редактировании файлов с расширениями .js и .jsx.

Что делает правило detox?

Оно задаёт стандарты написания E2E-тестов на Detox: структуру Page Object Model, выбор селекторов через by.id, синхронизацию через waitFor и изоляцию API.

Как правило предлагает бороться с нестабильными тестами?

Правило полностью запрещает произвольные вызовы sleep() в пользу waitFor, требует сброса состояния через device.reloadReactNative() перед тестами и перехода на testID.

Исходный текст

detox.mdc · CC0-1.0
---
description: This guide provides definitive, opinionated best practices for writing reliable, maintainable, and performant end-to-end tests with Detox in React Native applications.
globs: **/*.{js,jsx}
---
# detox Best Practices

Detox is the definitive choice for E2E testing in React Native. These rules ensure your tests are fast, stable, and easy to maintain, leveraging modern JavaScript and Detox's gray-box capabilities.

## 1. Test Organization with Page Object Model (POM)

Always structure your tests using the Page Object Model. This abstracts UI interactions and selectors, making tests readable and resilient to UI changes.

❌ **BAD: Direct selectors and repeated logic**
```javascript
// login.e2e.js
describe('Login Flow', () => {
  it('should log in successfully', async () => {
    await element(by.id('emailInput')).typeText('[email protected]');
    await element(by.id('passwordInput')).typeText('password123');
    await element(by.id('loginButton')).tap();
    await expect(element(by.id('homeScreen'))).toBeVisible();
  });
});
```

✅ **GOOD: Page Object Model**
```javascript
// pages/LoginPage.js
class LoginPage {
  constructor() {
    this.emailInput = element(by.id('emailInput'));
    this.passwordInput = element(by.id('passwordInput'));
    this.loginButton = element(by.id('loginButton'));
  }

  async login(email, password) {
    await this.emailInput.typeText(email);
    await this.passwordInput.typeText(password);
    await this.loginButton.tap();
  }

  async isVisible() {
    await expect(this.emailInput).toBeVisible();
  }
}
export default new LoginPage();

// tests/login.e2e.js
import LoginPage from '../pages/LoginPage';
import HomeScreen from '../pages/HomeScreen';

describe('Login Flow', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('should log in successfully', async () => {
    await LoginPage.login('[email protected]', 'password123');
    await HomeScreen.isVisible();
  });
});
```

## 2. Stable Selectors are Paramount

Prioritize `by.id` for all interactive elements. Fallback to `by.text` only when `by.id` is not feasible (e.g., dynamic content). Avoid fragile selectors like `by.type` or `by.label` if a more stable alternative exists.

❌ **BAD: Fragile selector**
```javascript
// Relies on element type, which can change
await element(by.type('RCTTextView').withAncestor(by.id('welcomeMessage'))).toBeVisible();
```

✅ **GOOD: Stable selector with `testID`**
```javascript
// In your React Native component: <Text testID="welcomeMessageText">Welcome!</Text>
await expect(element(by.id('welcomeMessageText'))).toBeVisible();
```

## 3. Explicit Waits and Assertions

Never use arbitrary `sleep()` calls. Detox's gray-box synchronization handles most async operations, but for complex UI states or specific data loads, use `waitFor` with `expect` conditions.

❌ **BAD: Arbitrary `sleep`**
```javascript
await element(by.id('submitButton')).tap();
await sleep(2000); // 🚨 Flaky!
await expect(element(by.id('successMessage'))).toBeVisible();
```

✅ **GOOD: Explicit `waitFor` and `expect`**
```javascript
await element(by.id('submitButton')).tap();
await waitFor(element(by.id('successMessage')))
  .toBeVisible()
  .withTimeout(5000); // Max wait time
```

## 4. Reset App State Before Each Test

Ensure test isolation by resetting the app state before every `it` block. `device.reloadReactNative()` is the standard for a quick, clean slate. For a full app re-installation, use `device.launchApp({ delete: true })` in `beforeAll`.

```javascript
describe('User Profile', () => {
  beforeEach(async () => {
    // Resets React Native state, including navigation and Redux store
    await device.reloadReactNative();
    // Perform login or other common setup here
    await LoginPage.login('[email protected]', 'password123');
  });

  it('should display user details', async () => {
    // ... test logic
  });
});
```

## 5. Embrace `async/await` Everywhere

All Detox interactions and assertions are asynchronous. Use `async/await` consistently for clear, sequential test logic.

❌ **BAD: Mixing Promises and `async/await` inconsistently**
```javascript
it('should navigate', () => { // Missing async
  element(by.id('navButton')).tap().then(() => {
    return expect(element(by.id('nextScreen'))).toBeVisible();
  });
});
```

✅ **GOOD: Consistent `async/await`**
```javascript
it('should navigate', async () => {
  await element(by.id('navButton')).tap();
  await expect(element(by.id('nextScreen'))).toBeVisible();
});
```

## 6. Mocking Strategies for External Dependencies

For true E2E tests, mock external APIs or services to control test data and eliminate flakiness from network instability. Use tools like `msw` (Mock Service Worker) for client-side mocking or `nock` for Node.js-based API mocks.

```javascript
// setup.js (run before tests)
import { setupServer } from 'msw/node';
import { rest } from 'msw';

const server = setupServer(
  rest.post('https://api.example.com/login', (req, res, ctx) => {
    return res(ctx.json({ token: 'mock-token', user: { id: '123' } }));
  }),
  rest.get('https://api.example.com/profile', (req, res, ctx) => {
    return res(ctx.json({ name: 'Test User', email: '[email protected]' }));
  })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

// tests/profile.e2e.js
describe('User Profile', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
    // Login will now use the mocked API response
    await LoginPage.login('[email protected]', 'password');
  });

  it('should display mocked user profile data', async () => {
    await expect(element(by.id('userName'))).toHaveText('Test User');
    await expect(element(by.id('userEmail'))).toHaveText('[email protected]');
  });
});
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Мобильная разработка» →
typescript-expo-jest-detox-cursorrules-prompt-file PatrickJS Правило для Cursor, которое настраивает ассистента на TypeScript, React Native, Expo и мобильный UI. Пригодится, если пишете приложение на Expo и тестируете его через Jest и Detox. ★ 41 028звёзд репо limrun-detox-testing limrun-inc Помогает настроить, запустить и отладить тесты Detox на удалённых симуляторах Limrun iOS. Пригодится при пробросе туннелей к медиатору и инжекции рантайма в приложение. CX Codex +1 43 100установок mobile-app-testing aj-geddes Задаёт правила тестирования приложений для iOS и Android. Помогает писать юнит-, UI- и интеграционные тесты с Jest, Detox, Espresso и XCTest. CX Codex +1 823установок gem-mobile-tester официальный github Субагент гоняет E2E-тесты на симуляторах и эмуляторах iOS и Android через Detox и Maestro. Код он не пишет — только запускает проверки и отдаёт отчёт. ★ 40 478звёзд репо frontend-testing-best-practices sergiodxa Набор из 6 правил тестирования фронтенда: заставляет писать сквозные E2E-тесты в Playwright вместо изолированных юнит-тестов компонентов. CX Codex +1 2 200установок maestro-e2e raphaelbarbosaqwerty Скилл для написания и отладки E2E-тестов на Maestro: логины, регистрация, навигация, диалоги разрешений. Работает с iOS, Android, Flutter, React Native и вебом. CX Codex +1 533установок

Из того же набора240

django-rest-framework Правило Cursor, которое задаёт агенту единый стиль разработки API на Django REST Framework: структура проекта, сериализаторы, ViewSets. ★ 3 580звёзд репо django-orm Набор инструкций для Cursor по работе с Django ORM. Помогает структурировать модели и убирать проблему N+1 в запросах к базе. ★ 3 580звёзд репо discord-api Правило помогает писать Discord-приложения с REST-запросами, типами API и обработкой интеракций. Пригодится при разработке бота на TypeScript. ★ 3 580звёзд репо digitalocean Правило для Cursor задаёт, как строить и разворачивать приложения в DigitalOcean: VPC, managed-сервисы, контейнеры. ★ 3 580звёзд репо deno Правило задаёт рекомендации для проектов на Deno: от настройки deno.json до разрешений, типов и тестов. Пригодится, когда агент пишет или проверяет код на JavaScript и TypeScript. ★ 3 580звёзд репо datadog Правило для Cursor задаёт стандарты Datadog: обязательные теги service, env и version, структурные логи и порядок в именах метрик. ★ 3 580звёзд репо databricks Задаёт стандарты разработки на Databricks: вынос кода из блокнотов в модули, настройку бандлов и перенос тяжёлых вычислений с мощностей Databricks Apps. ★ 3 580звёзд репо dask Правило помогает писать код на Dask с учётом ленивых вычислений, памяти и работы кластера. Подключите его, когда Cursor редактирует Python-проект с Dask. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой