modelscope.cn

react-native-web-testing

Use when testing React Native Web applications. Provides patterns for Jest, React Native Testing Library, component testing, and web-specific testing strategies.

Installation

$ npx skills add https://modelscope.cn

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from modelscope.cn · top by installs.

npx skills add https://modelscope.cn

Browse all from modelscope.cn

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Write, Edit, Bash, Grep, Glob

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,343 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

React Native Web - Testing

Comprehensive testing patterns for React Native Web applications using Jest and React Native Testing Library.

Key Concepts

React Native Testing Library

The standard testing library for React Native components:

import { render, screen, fireEvent } from '@testing-library/react-native';
import { Button } from './Button';

describe('Button', () => {
  it('calls onPress when pressed', () => {
    const onPress = jest.fn();
    render(<Button title="Click me" onPress={onPress} />);

    const button = screen.getByText('Click me');
    fireEvent.press(button);

    expect(onPress).toHaveBeenCalledTimes(1);
  });
});

Jest Configuration

Configure Jest for React Native Web:

// jest.config.js
module.exports = {
  preset: 'react-native',
  moduleNameMapper: {
    '^react-native$': 'react-native-web',
  },
  transformIgnorePatterns: [
    'node_modules/(?!(react-native|@react-native|react-native-web)/)',
  ],
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};

Testing Utilities

Common testing utilities and helpers:

import { render, RenderOptions } from '@testing-library/react-native';
import { ReactElement } from 'react';
import { ThemeProvider } from './theme';

interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
  theme?: Theme;
}

export function renderWithProviders(
  ui: ReactElement,
  { theme = defaultTheme, ...options }: CustomRenderOptions = {}
) {
  return render(
    <ThemeProvider value={theme}>
      {ui}
    </ThemeProvider>,
    options
  );
}

Best Practices

Component Testing

✅ Test user interactions and behavior:

import { render, screen, fireEvent, waitFor } from '@testing-library/react-native';
import { LoginForm } from './LoginForm';

describe('LoginForm', () => {
  it('submits form with valid credentials', async () => {
    const onSubmit = jest.fn();
    render(<LoginForm onSubmit={onSubmit} />);

    const emailInput = screen.getByPlaceholderText('Email');
    const passwordInput = screen.getByPlaceholderText('Password');
    const submitButton = screen.getByText('Login');

    fireEvent.changeText(emailInput, '[email protected]');
    fireEvent.changeText(passwordInput, 'password123');
    fireEvent.press(submitButton);

    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledWith({
        email: '[email protected]',
        password: 'password123',
      });
    });
  });

  it('shows error for invalid email', async () => {
    render(<LoginForm onSubmit={jest.fn()} />);

    const emailInput = screen.getByPlaceholderText('Email');
    const submitButton = screen.getByText('Login');

    fireEvent.changeText(emailInput, 'invalid-email');
    fireEvent.press(submitButton);

    await waitFor(() => {
      expect(screen.getByText('Invalid email address')).toBeTruthy();
    });
  });
});

Async Testing

✅ Use waitFor for async operations:

import { render, screen, waitFor } from '@testing-library/react-native';
import { UserProfile } from './UserProfile';

describe('UserProfile', () => {
  it('loads and displays user data', async () => {
    const mockUser = { id: '1', name: 'John Doe', email: '[email protected]' };

    global.fetch = jest.fn(() =>
      Promise.resolve({
        json: () => Promise.resolve(mockUser),
      })
    ) as jest.Mock;

    render(<UserProfile userId="1" />);

    // Check loading state
    expect(screen.getByTestId('loading-indicator')).toBeTruthy();

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('John Doe')).toBeTruthy();
      expect(screen.getByText('[email protected]')).toBeTruthy();
    });

    expect(screen.queryByTestId('loading-indicator')).toBeNull();
  });
});

Mocking Modules

✅ Mock navigation and other dependencies:

import { render, screen, fireEvent } from '@testing-library/react-native';

// Mock navigation
const mockNavigate = jest.fn();
jest.mock('@react-navigation/native', () => ({
  useNavigation: () => ({
    navigate: mockNavigate,
  }),
}));

describe('HomeScreen', () => {
  it('navigates to details on item press', () => {
    render(<HomeScreen />);

    const item = screen.getByText('Item 1');
    fireEvent.press(item);

    expect(mockNavigate).toHaveBeenCalledWith('Details', { id: '1' });
  });
});

Examples

Testing Custom Hooks

import { renderHook, act } from '@testing-library/react-hooks';
import { useCounter } from './useCounter';

describe('useCounter', () => {
  it('increments counter', () => {
    const { result } = renderHook(() => useCounter());

    expect(result.current.count).toBe(0);

    act(() => {
      result.current.increment();
    });

    expect(result.current.count).toBe(1);
  });

  it('decrements counter', () => {
    const { result } = renderHook(() => useCounter(5));

    act(() => {
      result.current.decrement();
    });

    expect(result.current.count).toBe(4);
  });
});

Testing with Context

import { render, screen } from '@testing-library/react-native';
import { AuthProvider } from './auth-context';
import { ProtectedScreen } from './ProtectedScreen';

describe('ProtectedScreen', () => {
  it('shows content when authenticated', () => {
    const mockUser = { id: '1', name: 'John' };

    render(
      <AuthProvider initialUser={mockUser}>
        <ProtectedScreen />
      </AuthProvider>
    );

    expect(screen.getByText('Welcome, John')).toBeTruthy();
  });

  it('shows login prompt when not authenticated', () => {
    render(
      <AuthProvider initialUser={null}>
        <ProtectedScreen />
      </AuthProvider>
    );

    expect(screen.getByText('Please log in')).toBeTruthy();
  });
});

Snapshot Testing

import { render } from '@testing-library/react-native';
import { Card } from './Card';

describe('Card', () => {
  it('matches snapshot', () => {
    const { toJSON } = render(
      <Card title="Test Card" description="Test description" />
    );

    expect(toJSON()).toMatchSnapshot();
  });
});

Integration Testing

import { render, screen, fireEvent, waitFor } from '@testing-library/react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { HomeScreen } from './HomeScreen';
import { DetailsScreen } from './DetailsScreen';

const Stack = createNativeStackNavigator();

function TestApp() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

describe('Navigation Flow', () => {
  it('navigates from home to details', async () => {
    render(<TestApp />);

    // On Home screen
    expect(screen.getByText('Home Screen')).toBeTruthy();

    // Navigate to Details
    const item = screen.getByText('View Details');
    fireEvent.press(item);

    // Wait for Details screen
    await waitFor(() => {
      expect(screen.getByText('Details Screen')).toBeTruthy();
    });
  });
});

Common Patterns

Testing Forms

describe('ContactForm', () => {
  it('validates all fields before submit', async () => {
    const onSubmit = jest.fn();
    render(<ContactForm onSubmit={onSubmit} />);

    const submitButton = screen.getByText('Submit');
    fireEvent.press(submitButton);

    await waitFor(() => {
      expect(screen.getByText('Name is required')).toBeTruthy();
      expect(screen.getByText('Email is required')).toBeTruthy();
      expect(onSubmit).not.toHaveBeenCalled();
    });
  });
});

Testing Lists

describe('ItemsList', () => {
  it('renders all items', () => {
    const items = [
      { id: '1', title: 'Item 1' },
      { id: '2', title: 'Item 2' },
      { id: '3', title: 'Item 3' },
    ];

    render(<ItemsList items={items} />);

    items.forEach(item => {
      expect(screen.getByText(item.title)).toBeTruthy();
    });
  });

  it('handles empty state', () => {
    render(<ItemsList items={[]} />);
    expect(screen.getByText('No items found')).toBeTruthy();
  });
});

Testing Accessibility

describe('Button accessibility', () => {
  it('has correct accessibility props', () => {
    render(<Button title="Submit" onPress={jest.fn()} />);

    const button = screen.getByRole('button');
    expect(button).toHaveAccessibilityState({ disabled: false });
    expect(button).toHaveAccessibilityHint('Submits the form');
  });

  it('is disabled when loading', () => {
    render(<Button title="Submit" onPress={jest.fn()} loading />);

    const button = screen.getByRole('button');
    expect(button).toHaveAccessibilityState({ disabled: true, busy: true });
  });
});

Anti-Patterns

❌ Don't test implementation details:

// Bad - testing internal state
expect(component.state.count).toBe(5);

// Good - test observable behavior
expect(screen.getByText('Count: 5')).toBeTruthy();

❌ Don't use querySelector or DOM methods:

// Bad
const element = container.querySelector('.button');

// Good
const button = screen.getByRole('button');

❌ Don't create overly coupled tests:

// Bad - too specific
expect(screen.getByText('Submit')).toHaveStyle({
  backgroundColor: '#007AFF',
  paddingHorizontal: 16
});

// Good - test behavior
const button = screen.getByText('Submit');
expect(button).toBeTruthy();
fireEvent.press(button);
expect(mockSubmit).toHaveBeenCalled();

❌ Don't forget to clean up:

// Bad
afterEach(() => {
  // No cleanup
});

// Good
afterEach(() => {
  jest.clearAllMocks();
  cleanup();
});

Related Skills

  • react-native-web-core: Core React Native Web concepts
  • react-native-web-navigation: Testing navigation flows
  • react-native-web-performance: Performance testing