తెలుగు

ఈ పూర్తి గైడ్‌తో రియాక్ట్ టెస్టింగ్ లైబ్రరీ (RTL)లో నైపుణ్యం సాధించండి. మీ రియాక్ట్ అప్లికేషన్‌ల కోసం ప్రభావవంతమైన, సులభంగా నిర్వహించగల, వినియోగదారు-కేంద్రీకృత టెస్ట్‌లు ఎలా రాయాలో ఉత్తమ పద్ధతులు, వాస్తవ-ప్రపంచ ఉదాహరణలతో నేర్చుకోండి.

రియాక్ట్ టెస్టింగ్ లైబ్రరీ: ఒక సమగ్ర గైడ్

నేటి వేగవంతమైన వెబ్ డెవలప్‌మెంట్ ప్రపంచంలో, మీ రియాక్ట్ అప్లికేషన్‌ల నాణ్యత మరియు విశ్వసనీయతను నిర్ధారించడం చాలా ముఖ్యం. వినియోగదారు కోణంపై దృష్టి సారించే టెస్ట్‌లు రాయడానికి రియాక్ట్ టెస్టింగ్ లైబ్రరీ (RTL) ఒక ప్రసిద్ధ మరియు ప్రభావవంతమైన పరిష్కారంగా ఉద్భవించింది. ఈ గైడ్ RTL యొక్క పూర్తి అవలోకనాన్ని అందిస్తుంది, ప్రాథమిక భావనల నుండి అధునాతన టెక్నిక్‌ల వరకు ప్రతిదీ కవర్ చేస్తుంది, దృఢమైన మరియు నిర్వహించదగిన రియాక్ట్ అప్లికేషన్‌లను రూపొందించడంలో మీకు శక్తినిస్తుంది.

రియాక్ట్ టెస్టింగ్ లైబ్రరీని ఎందుకు ఎంచుకోవాలి?

సాంప్రదాయ టెస్టింగ్ పద్ధతులు తరచుగా ఇంప్లిమెంటేషన్ వివరాలపై ఆధారపడతాయి, దీని వలన చిన్న కోడ్ మార్పులతో టెస్ట్‌లు పెళుసుగా మరియు విఫలమయ్యే అవకాశం ఉంది. మరోవైపు, RTL, వినియోగదారు మీ కాంపోనెంట్‌లతో ఎలా సంకర్షిస్తారో అలాగే పరీక్షించమని మిమ్మల్ని ప్రోత్సహిస్తుంది, వినియోగదారు చూసే మరియు అనుభవించే దానిపై దృష్టి పెడుతుంది. ఈ విధానం అనేక ముఖ్య ప్రయోజనాలను అందిస్తుంది:

మీ టెస్టింగ్ ఎన్విరాన్మెంట్‌ను సెటప్ చేయడం

మీరు RTL ఉపయోగించడం ప్రారంభించడానికి ముందు, మీరు మీ టెస్టింగ్ ఎన్విరాన్మెంట్‌ను సెటప్ చేయాలి. దీనిలో సాధారణంగా అవసరమైన డిపెండెన్సీలను ఇన్‌స్టాల్ చేయడం మరియు మీ టెస్టింగ్ ఫ్రేమ్‌వర్క్‌ను కాన్ఫిగర్ చేయడం ఉంటాయి.

అవసరమైనవి

ఇన్‌స్టాలేషన్

npm లేదా yarn ఉపయోగించి క్రింది ప్యాకేజీలను ఇన్‌స్టాల్ చేయండి:

npm install --save-dev @testing-library/react @testing-library/jest-dom jest babel-jest @babel/preset-env @babel/preset-react

లేదా, yarn ఉపయోగించి:

yarn add --dev @testing-library/react @testing-library/jest-dom jest babel-jest @babel/preset-env @babel/preset-react

ప్యాకేజీల వివరణ:

కాన్ఫిగరేషన్

మీ ప్రాజెక్ట్ యొక్క రూట్‌లో `babel.config.js` ఫైల్‌ను ఈ క్రింది కంటెంట్‌తో సృష్టించండి:

module.exports = {
  presets: ['@babel/preset-env', '@babel/preset-react'],
};

టెస్ట్ స్క్రిప్ట్‌ను చేర్చడానికి మీ `package.json` ఫైల్‌ను నవీకరించండి:

{
  "scripts": {
    "test": "jest"
  }
}

Jestను కాన్ఫిగర్ చేయడానికి మీ ప్రాజెక్ట్ యొక్క రూట్‌లో `jest.config.js` ఫైల్‌ను సృష్టించండి. ఒక కనీస కాన్ఫిగరేషన్ ఇలా ఉండవచ్చు:

module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['/src/setupTests.js'],
};

ఈ క్రింది కంటెంట్‌తో `src/setupTests.js` ఫైల్‌ను సృష్టించండి. ఇది Jest DOM మ్యాచర్‌లు మీ అన్ని టెస్ట్‌లలో అందుబాటులో ఉండేలా చేస్తుంది:

import '@testing-library/jest-dom/extend-expect';

మీ మొదటి టెస్ట్ రాయడం

ఒక సాధారణ ఉదాహరణతో ప్రారంభిద్దాం. మీకు గ్రీటింగ్ సందేశాన్ని ప్రదర్శించే రియాక్ట్ కాంపోనెంట్ ఉందని అనుకుందాం:

// src/components/Greeting.js
import React from 'react';

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

export default Greeting;

ఇప్పుడు, ఈ కాంపోనెంట్ కోసం ఒక టెస్ట్ రాద్దాం:

// src/components/Greeting.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders a greeting message', () => {
  render(<Greeting name="World" />);
  const greetingElement = screen.getByText(/Hello, World!/i);
  expect(greetingElement).toBeInTheDocument();
});

వివరణ:

టెస్ట్ రన్ చేయడానికి, మీ టెర్మినల్‌లో ఈ క్రింది కమాండ్‌ను అమలు చేయండి:

npm test

అన్నీ సరిగ్గా కాన్ఫిగర్ చేయబడితే, టెస్ట్ పాస్ అవుతుంది.

సాధారణ RTL క్వెరీలు

RTL DOMలో ఎలిమెంట్లను కనుగొనడానికి వివిధ క్వెరీ మెథడ్స్‌ను అందిస్తుంది. ఈ క్వెరీలు వినియోగదారులు మీ అప్లికేషన్‌తో ఎలా సంకర్షిస్తారో అనుకరించేలా రూపొందించబడ్డాయి.

`getByRole`

ఈ క్వెరీ ఒక ఎలిమెంట్‌ను దాని ARIA రోల్ ద్వారా కనుగొంటుంది. సాధ్యమైనప్పుడల్లా `getByRole` ఉపయోగించడం మంచి పద్ధతి, ఎందుకంటే ఇది యాక్సెసిబిలిటీని ప్రోత్సహిస్తుంది మరియు మీ టెస్ట్‌లు అంతర్లీన DOM నిర్మాణంలో మార్పులకు నిరోధకంగా ఉండేలా చేస్తుంది.

<button role="button">Click me</button>
const buttonElement = screen.getByRole('button');
expect(buttonElement).toBeInTheDocument();

`getByLabelText`

ఈ క్వెరీ ఒక ఎలిమెంట్‌ను దాని అనుబంధ లేబుల్ యొక్క టెక్స్ట్ ద్వారా కనుగొంటుంది. ఫారమ్ ఎలిమెంట్లను పరీక్షించడానికి ఇది ఉపయోగకరంగా ఉంటుంది.

<label htmlFor="name">Name:</label>
<input type="text" id="name" />
const nameInputElement = screen.getByLabelText('Name:');
expect(nameInputElement).toBeInTheDocument();

`getByPlaceholderText`

ఈ క్వెరీ ఒక ఎలిమెంట్‌ను దాని ప్లేస్‌హోల్డర్ టెక్స్ట్ ద్వారా కనుగొంటుంది.

<input type="text" placeholder="Enter your email" />
const emailInputElement = screen.getByPlaceholderText('Enter your email');
expect(emailInputElement).toBeInTheDocument();

`getByAltText`

ఈ క్వెరీ ఒక ఇమేజ్ ఎలిమెంట్‌ను దాని ఆల్ట్ టెక్స్ట్ ద్వారా కనుగొంటుంది. యాక్సెసిబిలిటీని నిర్ధారించడానికి అన్ని ఇమేజ్‌లకు అర్థవంతమైన ఆల్ట్ టెక్స్ట్ అందించడం ముఖ్యం.

<img src="logo.png" alt="Company Logo" />
const logoImageElement = screen.getByAltText('Company Logo');
expect(logoImageElement).toBeInTheDocument();

`getByTitle`

ఈ క్వెరీ ఒక ఎలిమెంట్‌ను దాని టైటిల్ అట్రిబ్యూట్ ద్వారా కనుగొంటుంది.

<span title="Close">X</span>
const closeElement = screen.getByTitle('Close');
expect(closeElement).toBeInTheDocument();

`getByDisplayValue`

ఈ క్వెరీ ఒక ఎలిమెంట్‌ను దాని డిస్ప్లే విలువ ద్వారా కనుగొంటుంది. ముందుగా నింపిన విలువలతో ఫారమ్ ఇన్‌పుట్‌లను పరీక్షించడానికి ఇది ఉపయోగకరంగా ఉంటుంది.

<input type="text" value="Initial Value" />
const inputElement = screen.getByDisplayValue('Initial Value');
expect(inputElement).toBeInTheDocument();

`getAllBy*` క్వెరీలు

`getBy*` క్వెరీలతో పాటు, RTL `getAllBy*` క్వెరీలను కూడా అందిస్తుంది, ఇవి సరిపోలిన ఎలిమెంట్ల శ్రేణిని తిరిగి ఇస్తాయి. ఒకే లక్షణాలు గల బహుళ ఎలిమెంట్లు DOMలో ఉన్నాయని నిర్ధారించవలసినప్పుడు ఇవి ఉపయోగపడతాయి.

<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
const listItems = screen.getAllByRole('listitem');
expect(listItems).toHaveLength(3);

`queryBy*` క్వెరీలు

`queryBy*` క్వెరీలు `getBy*` క్వెరీల మాదిరిగానే ఉంటాయి, కానీ సరిపోలిన ఎలిమెంట్ కనుగొనబడకపోతే అవి `null` తిరిగి ఇస్తాయి, ఎర్రర్ త్రో చేయకుండా. DOMలో ఒక ఎలిమెంట్ *లేదని* నిర్ధారించాలనుకున్నప్పుడు ఇది ఉపయోగపడుతుంది.

const missingElement = screen.queryByText('Non-existent text');
expect(missingElement).toBeNull();

`findBy*` క్వెరీలు

`findBy*` క్వెరీలు `getBy*` క్వెరీల యొక్క అసింక్రోనస్ వెర్షన్‌లు. అవి సరిపోలిన ఎలిమెంట్ కనుగొనబడినప్పుడు రిసాల్వ్ అయ్యే ప్రామిస్‌ను తిరిగి ఇస్తాయి. API నుండి డేటాను ఫెచ్ చేయడం వంటి అసింక్రోనస్ ఆపరేషన్లను పరీక్షించడానికి ఇవి ఉపయోగపడతాయి.

// Simulating an asynchronous data fetch
const fetchData = () => new Promise(resolve => {
  setTimeout(() => resolve('Data Loaded!'), 1000);
});

function MyComponent() {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    fetchData().then(setData);
  }, []);

  return <div>{data}</div>;
}
test('loads data asynchronously', async () => {
  render(<MyComponent />);
  const dataElement = await screen.findByText('Data Loaded!');
  expect(dataElement).toBeInTheDocument();
});

వినియోగదారు చర్యలను అనుకరించడం

RTL బటన్లను క్లిక్ చేయడం, ఇన్‌పుట్ ఫీల్డ్‌లలో టైప్ చేయడం, మరియు ఫారమ్‌లను సమర్పించడం వంటి వినియోగదారు చర్యలను అనుకరించడానికి `fireEvent` మరియు `userEvent` APIలను అందిస్తుంది.

`fireEvent`

`fireEvent` మిమ్మల్ని ప్రోగ్రామాటిక్‌గా DOM ఈవెంట్‌లను ట్రిగ్గర్ చేయడానికి అనుమతిస్తుంది. ఇది ఒక తక్కువ-స్థాయి API, ఇది ఫైర్ అయ్యే ఈవెంట్‌లపై మీకు చక్కటి నియంత్రణను ఇస్తుంది.

<button onClick={() => alert('Button clicked!')}>Click me</button>
import { fireEvent } from '@testing-library/react';

test('simulates a button click', () => {
  const alertMock = jest.spyOn(window, 'alert').mockImplementation(() => {});
  render(<button onClick={() => alert('Button clicked!')}>Click me</button>);
  const buttonElement = screen.getByRole('button');
  fireEvent.click(buttonElement);
  expect(alertMock).toHaveBeenCalledTimes(1);
  alertMock.mockRestore();
});

`userEvent`

`userEvent` ఒక ఉన్నత-స్థాయి API, ఇది వినియోగదారు చర్యలను మరింత వాస్తవికంగా అనుకరిస్తుంది. ఇది ఫోకస్ మేనేజ్‌మెంట్ మరియు ఈవెంట్ ఆర్డరింగ్ వంటి వివరాలను నిర్వహిస్తుంది, మీ టెస్ట్‌లను మరింత దృఢంగా మరియు తక్కువ పెళుసుగా చేస్తుంది.

<input type="text" onChange={e => console.log(e.target.value)} />
import userEvent from '@testing-library/user-event';

test('simulates typing in an input field', () => {
  const inputElement = screen.getByRole('textbox');
  userEvent.type(inputElement, 'Hello, world!');
  expect(inputElement).toHaveValue('Hello, world!');
});

అసింక్రోనస్ కోడ్‌ను టెస్ట్ చేయడం

అనేక రియాక్ట్ అప్లికేషన్‌లు API నుండి డేటాను ఫెచ్ చేయడం వంటి అసింక్రోనస్ ఆపరేషన్లను కలిగి ఉంటాయి. RTL అసింక్రోనస్ కోడ్‌ను పరీక్షించడానికి అనేక సాధనాలను అందిస్తుంది.

`waitFor`

`waitFor` ఒక నిర్ధారణ చేయడానికి ముందు ఒక షరతు నిజం కావడానికి వేచి ఉండటానికి మిమ్మల్ని అనుమతిస్తుంది. పూర్తి కావడానికి కొంత సమయం తీసుకునే అసింక్రోనస్ ఆపరేషన్లను పరీక్షించడానికి ఇది ఉపయోగపడుతుంది.

function MyComponent() {
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    setTimeout(() => {
      setData('Data loaded!');
    }, 1000);
  }, []);

  return <div>{data}</div>;
}
import { waitFor } from '@testing-library/react';

test('waits for data to load', async () => {
  render(<MyComponent />);
  await waitFor(() => screen.getByText('Data loaded!'));
  const dataElement = screen.getByText('Data loaded!');
  expect(dataElement).toBeInTheDocument();
});

`findBy*` క్వెరీలు

ముందు చెప్పినట్లుగా, `findBy*` క్వెరీలు అసింక్రోనస్ మరియు సరిపోలిన ఎలిమెంట్ కనుగొనబడినప్పుడు రిసాల్వ్ అయ్యే ప్రామిస్‌ను తిరిగి ఇస్తాయి. DOMలో మార్పులకు దారితీసే అసింక్రోనస్ ఆపరేషన్లను పరీక్షించడానికి ఇవి ఉపయోగపడతాయి.

హుక్స్ టెస్ట్ చేయడం

రియాక్ట్ హుక్స్ స్టేట్‌ఫుల్ లాజిక్‌ను పొందుపరిచే పునర్వినియోగ ఫంక్షన్లు. RTL కస్టమ్ హుక్స్‌ను ఒంటరిగా పరీక్షించడానికి `@testing-library/react-hooks` నుండి `renderHook` యుటిలిటీని అందిస్తుంది (ఇది v17 నాటికి `@testing-library/react` లో నేరుగా చేర్చబడినందున వాడుకలో లేదు).

// src/hooks/useCounter.js
import { useState } from 'react';

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  const decrement = () => {
    setCount(prevCount => prevCount - 1);
  };

  return { count, increment, decrement };
}

export default useCounter;
// src/hooks/useCounter.test.js
import { renderHook, act } from '@testing-library/react';
import useCounter from './useCounter';

test('increments the counter', () => {
  const { result } = renderHook(() => useCounter());

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

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

వివరణ:

అధునాతన టెస్టింగ్ టెక్నిక్‌లు

మీరు RTL యొక్క ప్రాథమికాలను నేర్చుకున్న తర్వాత, మీ టెస్ట్‌ల నాణ్యత మరియు నిర్వహణను మెరుగుపరచడానికి మీరు మరింత అధునాతన టెస్టింగ్ టెక్నిక్‌లను అన్వేషించవచ్చు.

మాడ్యూల్స్‌ను మాక్ చేయడం

కొన్నిసార్లు, మీ కాంపోనెంట్‌లను వేరుచేయడానికి మరియు టెస్టింగ్ సమయంలో వాటి ప్రవర్తనను నియంత్రించడానికి మీరు బాహ్య మాడ్యూల్స్ లేదా డిపెండెన్సీలను మాక్ చేయవలసి రావచ్చు. Jest దీని కోసం ఒక శక్తివంతమైన మాకింగ్ APIని అందిస్తుంది.

// src/api/dataService.js
export const fetchData = async () => {
  const response = await fetch('/api/data');
  const data = await response.json();
  return data;
};
// src/components/MyComponent.js
import React, { useState, useEffect } from 'react';
import { fetchData } from '../api/dataService';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then(setData);
  }, []);

  return <div>{data}</div>;
}
// src/components/MyComponent.test.js
import { render, screen, waitFor } from '@testing-library/react';
import MyComponent from './MyComponent';
import * as dataService from '../api/dataService';

jest.mock('../api/dataService');

test('fetches data from the API', async () => {
  dataService.fetchData.mockResolvedValue({ message: 'Mocked data!' });

  render(<MyComponent />);

  await waitFor(() => screen.getByText('Mocked data!'));

  expect(screen.getByText('Mocked data!')).toBeInTheDocument();
  expect(dataService.fetchData).toHaveBeenCalledTimes(1);
});

వివరణ:

కాంటెక్స్ట్ ప్రొవైడర్లు

మీ కాంపోనెంట్ కాంటెక్స్ట్ ప్రొవైడర్‌పై ఆధారపడితే, మీరు టెస్టింగ్ సమయంలో మీ కాంపోనెంట్‌ను ప్రొవైడర్‌లో చుట్టాలి. ఇది కాంపోనెంట్‌కు కాంటెక్స్ట్ విలువలకు యాక్సెస్ ఉందని నిర్ధారిస్తుంది.

// src/contexts/ThemeContext.js
import React, { createContext, useState } from 'react';

export const ThemeContext = createContext();

export function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}
// src/components/MyComponent.js
import React, { useContext } from 'react';
import { ThemeContext } from '../contexts/ThemeContext';

function MyComponent() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div style={{ backgroundColor: theme === 'light' ? '#fff' : '#000', color: theme === 'light' ? '#000' : '#fff' }}>
      <p>Current theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}
// src/components/MyComponent.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
import { ThemeProvider } from '../contexts/ThemeContext';

test('toggles the theme', () => {
  render(
    <ThemeProvider>
      <MyComponent />
    </ThemeProvider>
  );

  const themeParagraph = screen.getByText(/Current theme: light/i);
  const toggleButton = screen.getByRole('button', { name: /Toggle Theme/i });

  expect(themeParagraph).toBeInTheDocument();

  fireEvent.click(toggleButton);

  expect(screen.getByText(/Current theme: dark/i)).toBeInTheDocument();
});

వివరణ:

రౌటర్‌తో టెస్టింగ్

రియాక్ట్ రౌటర్‌ను ఉపయోగించే కాంపోనెంట్లను పరీక్షించేటప్పుడు, మీరు ఒక మాక్ రౌటర్ కాంటెక్స్ట్‌ను అందించాలి. మీరు `react-router-dom` నుండి `MemoryRouter` కాంపోనెంట్‌ను ఉపయోగించి దీనిని సాధించవచ్చు.

// src/components/MyComponent.js
import React from 'react';
import { Link } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <Link to="/about">Go to About Page</Link>
    </div>
  );
}
// src/components/MyComponent.test.js
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import MyComponent from './MyComponent';

test('renders a link to the about page', () => {
  render(
    <MemoryRouter>
      <MyComponent />
    </MemoryRouter>
  );

  const linkElement = screen.getByRole('link', { name: /Go to About Page/i });
  expect(linkElement).toBeInTheDocument();
  expect(linkElement).toHaveAttribute('href', '/about');
});

వివరణ:

ప్రభావవంతమైన టెస్ట్‌లు రాయడానికి ఉత్తమ పద్ధతులు

RTLతో టెస్ట్‌లు రాసేటప్పుడు అనుసరించాల్సిన కొన్ని ఉత్తమ పద్ధతులు ఇక్కడ ఉన్నాయి:

ముగింపు

రియాక్ట్ టెస్టింగ్ లైబ్రరీ మీ రియాక్ట్ అప్లికేషన్‌ల కోసం ప్రభావవంతమైన, నిర్వహించదగిన మరియు వినియోగదారు-కేంద్రీకృత టెస్ట్‌లను రాయడానికి ఒక శక్తివంతమైన సాధనం. ఈ గైడ్‌లో వివరించిన సూత్రాలు మరియు టెక్నిక్‌లను అనుసరించడం ద్వారా, మీరు మీ వినియోగదారుల అవసరాలను తీర్చే దృఢమైన మరియు విశ్వసనీయమైన అప్లికేషన్‌లను రూపొందించవచ్చు. వినియోగదారు కోణం నుండి పరీక్షించడం, ఇంప్లిమెంటేషన్ వివరాలను పరీక్షించడం మానుకోవడం, మరియు స్పష్టమైన, సంక్షిప్త టెస్ట్‌లు రాయడంపై దృష్టి పెట్టాలని గుర్తుంచుకోండి. RTLను స్వీకరించడం మరియు ఉత్తమ పద్ధతులను అవలంబించడం ద్వారా, మీరు మీ స్థానం లేదా మీ గ్లోబల్ ప్రేక్షకుల నిర్దిష్ట అవసరాలతో సంబంధం లేకుండా మీ రియాక్ట్ ప్రాజెక్ట్‌ల నాణ్యత మరియు నిర్వహణను గణనీయంగా మెరుగుపరచవచ్చు.