
Setelah musim dingin yang sangat sibuk dengan penanaman pohon dan pekerjaan klien yang tak terhitung jumlahnya yang berusaha melepaskan petugas pajak Belanda, saya berkesempatan untuk beristirahat sejenak dan menulis tentang beberapa hal keren yang sedang saya kerjakan. Beberapa artikel singkat akan muncul tanpa urutan atau topik tertentu, tetapi yang pertama adalah: Bagaimana cara menulis tes otomatis untuk Laravel Nova Actions tanpa membuat pusing seluruh browser yang mengejek? Mengapa Anda perlu melakukan ini?
Salah satu proyek yang saya kerjakan bersama sekelompok relawan dan pekerja lepas adalah Tree Tracker, yang awalnya dibangun untuk “Menyelamatkan Bumi” namun akhirnya diperluas hingga mencakup lebih banyak organisasi penanaman pohon. Kami membutuhkan banyak fungsi dan harus dapat berkembang dengan cepat. Sebagian besar “generator backend yang melakukan semuanya” memungkinkan Anda melakukan 80% pekerjaan dan menendang wajah Anda jika Anda mencoba melangkah lebih jauh, tetapi Laravel Nova selalu memenuhi kebutuhan kami dengan baik, tetapi cakupan pengujian backend logikanya tidak lengkap, Operasi Nova menjadi semakin penting, namun jarang diuji.
Jadi mari kita lihat cara mengganti operasi melalui pengujian. Pertama, sebuah tindakan.
status === OrderStatus::Incomplete) {
++$numOrdersSkipped;
continue;
}
dispatch(new SendFulfilled($order))->onQueue(Queue::emails->value);
++$numOrdersSent;
}
return Action::message(sprintf('Sent %s certificate emails, and skipped %s.', $numOrdersSent, $numOrdersSkipped));
}
}
Operasi Laravel Nova yang disebut SendCertificate yang akan memberi tahu klien pohon apa, restorasi hutan, padang rumput bunga liar, dll. yang telah mereka tanam/pulihkan/dll.
Berdebatlah sebanyak yang Anda inginkan tentang kode tersebut, tetapi itulah yang dilakukan tindakan ini.
Sekarang, bagaimana saya bisa 100% yakin bahwa ini berfungsi tanpa harus mengunjungi semua situs klien dan benar-benar mengirim beberapa email?
Uji langsung fungsionalitas Nova API
Saya tidak tahu apakah ini gila, tapi saya melihat sepotong kode yang dihasilkan di Laracasts yang kurang tepat, tapi samar-samar mengarahkan saya ke arah ini.
Bus::fake());
it('will email a single order', function () {
$user = User::factory()->create();
$order = Order::factory()->fulfilled()->create();
$response = $this->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => $order->id,
]);
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
$response
->assertStatus(200)
->assertJson([
'message' => 'Sent 1 order completion emails, and skipped 0.',
]);
});
Jelaskan Pengujian sintaksis dipersembahkan kepada Anda melalui Pest, yang paling mirip dengan RSpec/Jest di PHP, dan saya menyukainya.
itu berhasil.
Ini adalah bagian yang melakukan semua pekerjaan berat.
$response = $this
->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => $order->id,
]);
Ini pada dasarnya sama dengan respons forum Laracast yang dihasilkan AI, tetapi kebutuhannya telah diantisipasi postJson()
Saat melihat panel halaman Web, saya melihat bahwa panel ini lebih tertarik pada data formulir.

Bot juga menyarankan agar URL-nya seperti itu /nova-api/orders/send-certificate
Tapi Laravel meneriaki saya bahwa ia tidak bisa POST ke titik akhir itu. Melihat panel “Jaringan” lagi, saya menemukannya /nova-api/{nova-object}/action?action={action-name}
adalah metode yang disukai.

Di sini, kami mengirimkan permintaan HTTP palsu namun cukup nyata ke API Laravel Nova, tempat ia melakukan semua pemikiran. Agar tidak terpental karena tidak login, kita bisa memanfaatkan actingAs($user)
ini mungkin berguna bagi Anda.
Jika Anda menerima panggilan 403 app/Providers/NovaServiceProvider.php
dan lihat apakah pengguna Anda memenuhi kriteria di penjaga.
/**
* Register the Nova gate.
*
* This gate determines who can access Nova in non-local environments.
*/
protected function gate(): void
{
Gate::define('viewNova', fn ($user) => true);
}
Jika disetel ke true, ini akan mengizinkan pengguna mana pun untuk masuk, melewati pemeriksaan saat APP_ENV=pengujian
Dengan penjelasan ini, berikut adalah keseluruhan pengujian dengan semua kasus pengujian.
Bus::fake());
it('will email a single order', function ($user) {
$order = Order::factory()
->fulfilled()
->create();
$response = $this->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => $order->id,
]);
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
$response
->assertStatus(200)
->assertJson([
'message' => 'Sent 1 order completion emails, and skipped 0.',
]);
})->with('user');
it('will handle multiple orders', function ($user) {
$orders = Order::factory(3)
->fulfilled()
->create();
$orderIds = $orders->pluck('id')
->toArray();
$response = $this->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => implode(',', $orderIds),
]);
foreach ($orders as $order) {
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
}
$response
->assertStatus(200)
->assertJson([
'message' => 'Sent 3 order completion emails, and skipped 0.',
]);
})->with('user');
it('will skip incomplete orders', function ($user) {
$incompleteOrders = Order::factory(2)
->incomplete()
->create();
$completeOrders = Order::factory(3)
->fulfilled()
->create();
$orderIds = array_merge(
$incompleteOrders->pluck('id')->toArray(),
$completeOrders->pluck('id')->toArray(),
);
$response = $this->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => implode(',', $orderIds),
]);
foreach ($completeOrders as $order) {
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
}
foreach ($incompleteOrders as $order) {
Bus::assertNotDispatched(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
});
}
$response
->assertStatus(200)
->assertJson([
'message' => 'Sent 3 order completion emails, and skipped 2.',
]);
})->with('user');
});
# This is actually in tests/Datasets/User.php but can be here too.
dataset('user', [
fn() => User::factory()->create()
]);
Mari kita perbesar sedikit kalau-kalau itu tidak masuk akal.
meningkatkan…meningkatkan
Pertama, yang mendeskripsikannya adalah Hama, dan Anda dapat mempelajarinya lebih lanjut di sana. Ini relatif baru, tetapi banyak dari kami yang memintanya dan itu ada di sini.
describe(SendCertificate::class, function() {
beforeEach(fn() => Bus::fake());
it('will email a single order', function () {
Anda dapat melakukan hal yang sama di PHPUnit, tapi saya akan memberi tahu Anda caranya.
bus palsu
Untungnya, hal ini tidak ada hubungannya dengan Brexit. Jika Anda menggunakan Nova Actions, bus mungkin penting bagi Anda karena Anda mungkin menggunakan Actions untuk mengantri. Mengapa? Sebuah operasi dapat dijalankan sekali atau untuk setiap record dalam database, dan kecuali host Anda dikonfigurasi untuk membiarkan thread web berjalan dalam jangka waktu yang tidak terbatas (seharusnya tidak demikian!), maka Anda akan memerlukan hampir semua yang mereka lakukan. harus mengantri. Ini melibatkan bus.
Ditangguhkan karena kinerja buruk
Dalam arsitektur berorientasi sistem, komunikasi dengan sistem lain sangatlah penting. Dalam dunia yang ideal, setiap layanan akan mengetahui informasi yang cukup untuk memuaskan kliennya, namun sayangnya, sering kali ada persyaratan yang memerlukan pengambilan informasi secara dinamis. Mode proxy, proxy, dll, atau bahkan hanya proses jarak jauh

Mari kita memalsukan busnya sehingga kita tidak benar-benar mulai menjadwalkan pekerjaan ini dan memasukkannya ke dalam a beforeEach
Jadi kita bisa meresetnya setiap saat sehingga bisa dihitung sudah berapa kali terkirim.
beforeEach(fn() => Bus::fake());
Kita hanya bisa memalsukan pekerjaan yang kita pedulikan Bus::fake(SendFulfilled::class)
Namun, jika ada beberapa kemungkinan kejadian yang dapat dipicu tergantung pada bagaimana pengoperasiannya berjalan, memarkir seluruh bus mungkin merupakan pilihan yang lebih baik.
Pada tes pertama saya ingin mengetahui apakah sudah terkirim, dan saya ingin dikirim hanya sekali.
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
Dalam pengujian lain, saya memeriksa apakah beberapa pesanan terkirim dan ada pula yang tidak.
$response = $this->actingAs($user)
->post('/nova-api/orders/action?action=send-certificate', [
'resources' => implode(',', $orderIds),
]);
foreach ($completeOrders as $order) {
Bus::assertDispatchedTimes(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
}, 1);
}
foreach ($incompleteOrders as $order) {
Bus::assertNotDispatched(function (SendFulfilled $job) use ($order) {
return $job->order->id === $order->id;
});
}
Callback ini memastikan bahwa pekerjaan memiliki ID tertentu, yang berguna jika Anda mengirim 6 pesanan ke sana dan melihat mana yang terkirim atau tidak.
Saya memang harus membuat properti pribadi menjadi publik agar ini berfungsi, tetapi ini hanya dapat dibaca dan saya tidak peduli.
Kemudian, setiap pengujian juga memiliki pernyataan untuk memastikan bahwa respon HTTP dari nova API terlihat normal.
$response
->assertStatus(200)
->assertJson([
'message' => 'Sent 3 order completion emails, and skipped 2.',
]);
200 OK dan sebuah pesan memberi tahu saya berapa banyak orang yang mengirim atau tidak mengirim.
Luar biasa.
Saya perlu mulai menguji Laravel Nova lebih banyak karena semua pengontrol, model, layanan, repositori, perintah, pendengar, pekerjaan, dan antrian kami memiliki cakupan pengujian yang sangat baik, tetapi konsumen menghadapi hal-hal Nova Sangat kurang.
Sekarang saya dapat melakukan kepanduan netral gender melalui basis kode, dan setiap kali saya menyentuh Nova Action, saya dapat menulis tes terlebih dahulu dan kemudian mengubahnya dengan tes baru sehingga saya dapat lebih percaya diri dan tidak merasa tidak nyaman. Organisasi sangat sibuk menanam ratusan ribu pohon dan merestorasi rawa gambut, mereka sebenarnya tidak perlu melakukan kesalahan konyol untuk mengumpulkan bukti dan pendanaan.
Jika Anda memiliki masukan, perbaikan, atau komentar yang penuh kebencian dan tidak berguna, Anda tahu di mana harus meninggalkannya!
Tentu saja, lima menit setelah menekan tombol kirim, saya mengetahuinya joshgaber/NovaUnittetapi jika itu tidak berhasil bagi Anda, setidaknya sekarang Anda punya pilihan.