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.
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.
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
- Menyediakan Jest dalam Projek React Native
- Memaparkan Komponen dengan React Native Testing Library
- Mencetuskan Peristiwa dan Menguji Interaksi Pengguna
- Memalsukan Modul Natif dan Kod Tak Segerak