React Native Academy · Pelajaran

Mencetuskan Peristiwa dan Menguji Interaksi Pengguna

Gunakan fireEvent.press dan fireEvent.changeText untuk mensimulasikan tindakan pengguna, kemudian tegaskan bahawa kemas kini keadaan dan fungsi panggilan balik dipanggil dengan betul.

Pelajaran 3 daripada 413 langkah

Mencetuskan Peristiwa dan Menguji Interaksi Pengguna ialah pelajaran React Native Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran React Native Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus React Native Academy merangkumi sejumlah 4 pelajaran.

Mensimulasikan Peristiwa Pengguna dalam Ujian

Ujian komponen menjadi bernilai apabila mengesahkan cara komponen bertindak balas terhadap interaksi pengguna — tekanan butang, input teks dan penghantaran borang. Pustaka Pengujian React Native menyediakan utiliti fireEvent untuk mensimulasikan interaksi ini dalam persekitaran ujian tanpa peranti sebenar.

Mensimulasikan peristiwa tidak sama dengan input pengguna sebenar — tindakan ini memanggil prop pengendali peristiwa elemen secara terus. Namun, bagi kebanyakan ujian unit dan integrasi, cara ini mencukupi untuk mengesahkan bahawa logik komponen bertindak balas dengan betul terhadap interaksi.

fireEvent.press untuk Ketikan Butang

fireEvent.press(element) mensimulasikan ketikan pada elemen TouchableOpacity, Pressable atau Button. Selepas menekannya, buat penegasan terhadap kesan sampingan yang dijangka — kemas kini keadaan, panggilan navigasi atau pemanggilan callback.

Cari butang terlebih dahulu dengan pertanyaan seperti getByText atau getByRole('button'), kemudian cetuskan peristiwa tekanan. Gabungan pertanyaan dan peristiwa ini mensimulasikan keseluruhan perjalanan pengguna: cari butang, ketik butang itu dan sahkan hasilnya.

import { render, fireEvent } from '@testing-library/react-native';
import { Counter } from '../src/components/Counter';

it('increments the count when the plus button is pressed', () => {
  const { getByText } = render(<Counter />);

  // Assert initial state
  expect(getByText('Count: 0')).toBeTruthy();

  // Simulate button press
  fireEvent.press(getByText('+'));

  // Assert state changed
  expect(getByText('Count: 1')).toBeTruthy();

  // Press again
  fireEvent.press(getByText('+'));
  expect(getByText('Count: 2')).toBeTruthy();
});

fireEvent.changeText untuk TextInput

fireEvent.changeText(element, text) mensimulasikan penaipan dalam TextInput. Ia memanggil prop onChangeText dengan rentetan yang diberikan, yang sepatutnya mengemas kini keadaan komponen.

Inilah cara yang betul untuk mensimulasikan penaipan dalam ujian. Jangan cuba memanipulasi keadaan komponen secara langsung — sentiasa gunakan pengendali acara untuk menguji aliran data sebenar.

import { render, fireEvent } from '@testing-library/react-native';
import { SearchBar } from '../src/components/SearchBar';

it('calls onSearch with the typed query when submit is pressed', () => {
  const mockSearch = jest.fn();
  const { getByPlaceholderText, getByText } = render(
    <SearchBar onSearch={mockSearch} />
  );

  const input = getByPlaceholderText('Search...');

  // Simulate typing
  fireEvent.changeText(input, 'react native');

  // Simulate pressing the search button
  fireEvent.press(getByText('Search'));

  expect(mockSearch).toHaveBeenCalledWith('react native');
});

Menguji Ralat Pengesahan Borang

Satu senario ujian penting untuk borang ialah mengesahkan bahawa ralat pengesahan dipaparkan apabila pengguna menghantar data yang tidak sah. Simulasikan penghantaran borang tanpa mengisi medan yang diperlukan, kemudian tegaskan bahawa mesej ralat muncul dalam output yang dirender.

Ujian ini mengesahkan logik pengesahan dan pemaparan UI bagi mesej ralat — dua perkara yang mudah rosak semasa pemfaktoran semula. Ini ialah antara ujian paling bernilai yang boleh anda tulis untuk komponen borang.

it('shows an error when email is empty and form is submitted', () => {
  const { getByText, getByRole, queryByText } = render(<LoginForm />);

  // Initially no error
  expect(queryByText('Email is required')).toBeNull();

  // Submit without filling in the email field
  fireEvent.press(getByRole('button', { name: 'Sign In' }));

  // Error message should now appear
  expect(getByText('Email is required')).toBeTruthy();
  expect(queryByText('Password is required')).toBeTruthy();
});

Menguji Panggilan Navigasi

Apabila butang sepatutnya menavigasi ke skrin lain, mock objek navigation dan tegaskan bahawa navigate dipanggil dengan nama skrin serta parameter yang betul. Ini mengesahkan logik navigasi tanpa memerlukan NavigationContainer penuh dalam ujian.

Mock useNavigation daripada @react-navigation/native dalam fail ujian dan sediakan fungsi navigate mock. Selepas menekan butang, tegaskan bahawa navigate dipanggil dengan betul.

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

it('navigates to PostDetail when a post is pressed', () => {
  const { getByText } = render(<PostList posts={[
    { id: '1', title: 'Hello World' }
  ]} />);

  fireEvent.press(getByText('Hello World'));

  expect(mockNavigate).toHaveBeenCalledWith('PostDetail', { postId: '1' });
});

Menguji dengan userEvent untuk Interaksi yang Lebih Realistik

RNTL v12+ menyertakan API userEvent yang mensimulasikan interaksi pengguna dengan lebih realistik berbanding fireEvent. Contohnya, userEvent.type(element, 'text') mensimulasikan penekanan setiap aksara satu demi satu, yang turut mencetuskan acara fokus, blur dan penekanan kekunci mengikut susunan yang betul.

Gunakan userEvent untuk senario yang bergantung pada susunan acara — seperti pengesahan borang yang dicetuskan semasa blur dan bukannya semasa perubahan. userEvent bersifat tak segerak dan memerlukan await.

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

it('shows inline error after leaving the email field empty', async () => {
  const user = userEvent.setup();
  const { getByPlaceholderText, findByText } = render(<RegistrationForm />);

  const emailInput = getByPlaceholderText('Email');

  // Focus the field, then leave it (triggers onBlur validation)
  await user.type(emailInput, '');
  await user.press(getByPlaceholderText('Password')); // Focus next field

  // Error appears after blur
  expect(await findByText('Email is required')).toBeTruthy();
});

Menguji Komponen Togol dan Suis

Untuk komponen Switch dan komponen togol tersuai, cetuskan acara valueChange untuk mensimulasikan pengguna menogol suis. Tegaskan bahawa keadaan dikemas kini dengan betul dan sebarang kesan sampingan (seperti menyimpan ke storan) dicetuskan.

Utiliti fireEvent juga menyokong fireEvent.scroll untuk acara tatal dan fireEvent(element, 'press') untuk nama acara tersuai generik jika komponen menggunakan nama prop yang berbeza daripada onPress.

import { render, fireEvent } from '@testing-library/react-native';
import { NotificationsSettings } from '../src/screens/NotificationsSettings';

it('toggles notifications when the switch is pressed', () => {
  const mockSave = jest.fn();
  const { getByTestId } = render(
    <NotificationsSettings onSave={mockSave} />
  );

  const toggle = getByTestId('notifications-toggle');

  // Simulate toggling the switch to true
  fireEvent(toggle, 'valueChange', true);

  expect(mockSave).toHaveBeenCalledWith({ notifications: true });

  // Toggle back to false
  fireEvent(toggle, 'valueChange', false);
  expect(mockSave).toHaveBeenCalledWith({ notifications: false });
});

Menguji Perubahan Keadaan Tak Segerak dengan act

Apabila interaksi mencetuskan kemas kini keadaan melalui Promise (seperti panggilan API), anda mesti membungkus interaksi dalam act() supaya React dapat melaksanakan semua kemas kini sebelum anda membuat penegasan. fireEvent RNTL membungkus kemas kini segerak dalam act secara automatik, tetapi kemas kini keadaan tak segerak memerlukan pengendalian yang jelas.

Gunakan await act(async () => { ... }) apabila komponen membuat panggilan tak segerak sebagai tindak balas kepada acara, atau gunakan pertanyaan findBy yang secara tersirat menunggu DOM dikemas kini.

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

it('shows success message after form submission', async () => {
  const { getByRole, findByText } = render(<ContactForm />);

  fireEvent.press(getByRole('button', { name: 'Submit' }));

  // findByText waits for the element to appear (async)
  const successMsg = await findByText('Message sent successfully!');
  expect(successMsg).toBeTruthy();

  // Alternative: use waitFor with getByText
  await waitFor(() => {
    expect(getByText('Message sent successfully!')).toBeTruthy();
  });
});

Menguji Keadaan Dilumpuhkan

Butang dan input sering dilumpuhkan semasa pemuatan atau apabila pengesahan belum berjaya. Uji bahawa keadaan dilumpuhkan digunakan dengan betul dengan membuat penegasan menggunakan toBeDisabled() daripada jest-native, dan sahkan bahawa menekan butang yang dilumpuhkan tidak memanggil pengendali.

Ini mengesan pepijat apabila pembangun terlupa melumpuhkan butang hantar semasa panggilan API, lalu membenarkan pengguna menghantar beberapa kali dan menghasilkan data pendua.

it('disables the submit button while loading', async () => {
  const mockSubmit = jest.fn().mockReturnValue(new Promise(() => {})); // Never resolves
  const { getByRole } = render(<LoginForm onSubmit={mockSubmit} />);

  const emailInput = getByPlaceholderText('Email');
  const passwordInput = getByPlaceholderText('Password');
  fireEvent.changeText(emailInput, 'user@test.com');
  fireEvent.changeText(passwordInput, 'password123');

  const submitBtn = getByRole('button', { name: 'Sign In' });
  fireEvent.press(submitBtn);

  // Button should be disabled while the submit Promise is pending
  expect(submitBtn).toBeDisabled();
  expect(mockSubmit).toHaveBeenCalledTimes(1); // Not called again
});

Menguji Acara Tatal

Uji tingkah laku yang didorong oleh tatal seperti fungsi load-more menggunakan fireEvent.scroll. Hantar objek acara mock yang sepadan dengan struktur yang dijangkakan oleh komponen React Native daripada acara tatal.

Ini berguna untuk menguji onEndReached pada FlatList, tingkah laku tarik untuk segar semula dan sebarang komponen yang bertindak balas terhadap kedudukan tatal. Objek acara memerlukan nativeEvent.contentOffset dan nativeEvent.contentSize.

it('loads more posts when scrolling to the bottom', () => {
  const mockLoadMore = jest.fn();
  const { getByTestId } = render(
    <PostList posts={mockPosts} onLoadMore={mockLoadMore} />
  );

  const list = getByTestId('posts-list');

  // Simulate scrolling to near the bottom
  fireEvent.scroll(list, {
    nativeEvent: {
      contentOffset: { y: 900 },
      contentSize: { height: 1000, width: 400 },
      layoutMeasurement: { height: 100, width: 400 },
    },
  });

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

Menyusun Ujian dengan Corak Perjalanan Pengguna

Ujian yang paling bernilai ialah ujian yang mengesahkan keseluruhan aliran pengguna dalam satu komponen atau skrin — corak perjalanan pengguna. Daripada menguji setiap acara secara berasingan, tulis satu ujian yang merangkaikan beberapa interaksi: isi borang, tekan hantar dan buat penegasan terhadap keadaan akhir.

Ujian komponen bergaya integrasi ini lebih perlahan berbanding ujian unit tetapi mengesan lebih banyak pepijat sebenar kerana menguji interaksi antara bahagian komponen yang berbeza.

it('completes the login flow: type credentials, submit, show home', async () => {
  const { getByPlaceholderText, getByRole, findByText } = render(
    <LoginScreen />, { wrapper: NavigationWrapper }
  );

  // Step 1: Type email
  fireEvent.changeText(getByPlaceholderText('Email'), 'alice@test.com');

  // Step 2: Type password
  fireEvent.changeText(getByPlaceholderText('Password'), 'secret123');

  // Step 3: Submit
  fireEvent.press(getByRole('button', { name: 'Sign In' }));

  // Step 4: Assert navigation to home screen
  expect(await findByText('Welcome, Alice!')).toBeTruthy();
});

Semakan Pantas

Uji pemahaman anda tentang konsep Pembangunan Mudah Alih React Native daripada pelajaran ini.

Imbas Kembali Pelajaran

Dalam pelajaran ini, anda mempelajari: cara menggunakan fireEvent.press dan fireEvent.changeText untuk mensimulasikan interaksi pengguna dalam ujian komponen, cara menguji ralat pengesahan borang, panggilan navigasi dan perubahan keadaan tak segerak, serta cara corak perjalanan pengguna merangkaikan beberapa interaksi untuk menghasilkan ujian bergaya integrasi yang lebih bernilai. Seterusnya, kita akan melakukan mock modul natif dan menguji aliran kod tak segerak dalam React Native.

Percuma untuk bermula

Pelajari JavaScript dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
30
Pelajaran
120

Soalan Lazim

Adakah pelajaran “Mencetuskan Peristiwa dan Menguji Interaksi Pengguna” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran React Native Academy, termasuk “Mencetuskan Peristiwa dan Menguji Interaksi Pengguna”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus React Native Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Mencetuskan Peristiwa dan Menguji Interaksi Pengguna”?

Gunakan fireEvent.press dan fireEvent.changeText untuk mensimulasikan tindakan pengguna, kemudian tegaskan bahawa kemas kini keadaan dan fungsi panggilan balik dipanggil dengan betul. Anda berlatih React Native Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan React Native Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran React Native Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Mencetuskan Peristiwa dan Menguji Interaksi Pengguna” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran React Native Academy ini?

Ya. Setiap pelajaran React Native Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Menyediakan Jest dalam Projek React Native
  2. Memaparkan Komponen dengan React Native Testing Library
  3. Mencetuskan Peristiwa dan Menguji Interaksi Pengguna
  4. Memalsukan Modul Natif dan Kod Tak Segerak
← Kembali ke React Native Academy