update kelompok tani
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Web\Produktivitas\SurveyKelompokTaniController;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
beforeEach(function () {
|
||||
foreach ([
|
||||
'master_kabupaten_kota' => null,
|
||||
'master_kecamatan' => 'kabupaten_kota_id',
|
||||
'master_desa_kelurahan' => 'kecamatan_id',
|
||||
'master_komoditas' => null,
|
||||
] as $name => $parent) {
|
||||
Schema::create($name, function (Blueprint $table) use ($parent) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
if ($parent) $table->integer($parent);
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
Schema::create('survey_kelompok_tani', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama_kelompok');
|
||||
$table->string('nama_responden')->nullable();
|
||||
$table->integer('desa_kelurahan_id');
|
||||
$table->string('jenis_kelompok')->nullable();
|
||||
$table->json('komoditas_id')->nullable();
|
||||
foreach (['jumlah_pengurus', 'jumlah_pengurus_aktif', 'jumlah_anggota_terdaftar', 'jumlah_anggota_aktif'] as $field) {
|
||||
$table->integer($field)->nullable();
|
||||
}
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
DB::table('master_kabupaten_kota')->insert([
|
||||
['id' => 1, 'nama' => 'Kabupaten Ngada'], ['id' => 2, 'nama' => 'Kabupaten Lain'],
|
||||
]);
|
||||
DB::table('master_kecamatan')->insert([
|
||||
['id' => 1, 'nama' => 'Kecamatan A', 'kabupaten_kota_id' => 1],
|
||||
['id' => 2, 'nama' => 'Kecamatan B', 'kabupaten_kota_id' => 1],
|
||||
['id' => 3, 'nama' => 'Kecamatan C', 'kabupaten_kota_id' => 2],
|
||||
]);
|
||||
DB::table('master_desa_kelurahan')->insert([
|
||||
['id' => 1, 'nama' => 'Desa A', 'kecamatan_id' => 1],
|
||||
['id' => 2, 'nama' => 'Desa B', 'kecamatan_id' => 1],
|
||||
['id' => 3, 'nama' => 'Desa C', 'kecamatan_id' => 2],
|
||||
['id' => 4, 'nama' => 'Desa D', 'kecamatan_id' => 3],
|
||||
]);
|
||||
DB::table('master_komoditas')->insert([
|
||||
['id' => 1, 'nama' => 'Kakao'], ['id' => 2, 'nama' => 'Kopi'], ['id' => 11, 'nama' => 'Vanili'],
|
||||
]);
|
||||
foreach ([
|
||||
[1, 'Alpha', 'Budi', 1, 'Poktan', ['1', '2'], 3, 2, 30, 25, null],
|
||||
[2, 'Beta', 'Siti', 2, 'KWT', [1], 5, 4, 40, 35, null],
|
||||
[3, 'Citra', 'Ani', 3, 'Poktan', [2, 11], null, null, 0, 0, null],
|
||||
[4, 'Diluar', 'Toni', 4, 'Poktan', [1], 99, 99, 900, 900, null],
|
||||
[5, 'Dihapus', 'Dewi', 1, 'Poktan', [1], 99, 99, 900, 900, '2026-01-01'],
|
||||
] as [$id, $nama, $responden, $desa, $jenis, $komoditas, $pengurus, $pengurusAktif, $anggota, $anggotaAktif, $deletedAt]) {
|
||||
DB::table('survey_kelompok_tani')->insert([
|
||||
'id' => $id, 'nama_kelompok' => $nama, 'nama_responden' => $responden,
|
||||
'desa_kelurahan_id' => $desa, 'jenis_kelompok' => $jenis,
|
||||
'komoditas_id' => json_encode($komoditas), 'jumlah_pengurus' => $pengurus,
|
||||
'jumlah_pengurus_aktif' => $pengurusAktif, 'jumlah_anggota_terdaftar' => $anggota,
|
||||
'jumlah_anggota_aktif' => $anggotaAktif, 'created_at' => "2026-01-0{$id}", 'deleted_at' => $deletedAt,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->listKelompok = function (array $filters = []) {
|
||||
$request = Request::create('/survey/kelompok-tani', 'GET', $filters);
|
||||
$this->app->instance('request', $request);
|
||||
|
||||
return app(SurveyKelompokTaniController::class)->index($request)->getData();
|
||||
};
|
||||
});
|
||||
|
||||
test('kelompok cards summarize the default region and exclude deleted groups', function () {
|
||||
$data = ($this->listKelompok)();
|
||||
|
||||
expect($data['kelompokTani']->pluck('id')->all())->toBe([3, 2, 1]);
|
||||
expect((int) $data['summary']->total_kelompok)->toBe(3)
|
||||
->and((int) $data['summary']->total_jenis)->toBe(2)
|
||||
->and((int) $data['summary']->total_pengurus)->toBe(8)
|
||||
->and((int) $data['summary']->pengurus_aktif)->toBe(6)
|
||||
->and((int) $data['summary']->total_anggota)->toBe(70)
|
||||
->and((int) $data['summary']->anggota_aktif)->toBe(60);
|
||||
expect($data['kecamatanOptions']->pluck('id')->all())->toBe([1, 2]);
|
||||
});
|
||||
|
||||
test('kelompok region filters constrain rows cards and dependent options', function () {
|
||||
$data = ($this->listKelompok)(['kecamatan_id' => 1, 'desa_kelurahan_id' => 2]);
|
||||
expect($data['kelompokTani']->pluck('id')->all())->toBe([2]);
|
||||
expect((int) $data['summary']->total_anggota)->toBe(40);
|
||||
expect($data['desaOptions']->pluck('id')->all())->toBe([1, 2]);
|
||||
expect(($this->listKelompok)(['kecamatan_id' => 2])['kelompokTani']->pluck('id')->all())->toBe([3]);
|
||||
expect(($this->listKelompok)(['kabupaten_kota_id' => 2])['kelompokTani']->pluck('id')->all())->toBe([4]);
|
||||
});
|
||||
|
||||
test('kelompok commodity filter matches string and numeric JSON ids exactly', function () {
|
||||
$data = ($this->listKelompok)(['komoditas_id' => '1']);
|
||||
expect($data['kelompokTani']->pluck('id')->all())->toBe([2, 1]);
|
||||
expect((int) $data['summary']->total_kelompok)->toBe(2);
|
||||
expect(($this->listKelompok)(['komoditas_id' => 2, 'jenis_kelompok' => 'Poktan'])['kelompokTani']->pluck('id')->all())->toBe([3, 1]);
|
||||
expect(($this->listKelompok)(['jenis_kelompok' => 'KWT'])['kelompokTani']->pluck('id')->all())->toBe([2]);
|
||||
});
|
||||
|
||||
test('kelompok search matches group and respondent names without escaping region filters', function () {
|
||||
expect(($this->listKelompok)(['search' => 'aLpHa'])['kelompokTani']->pluck('id')->all())->toBe([1]);
|
||||
expect(($this->listKelompok)(['search' => 'sITI'])['kelompokTani']->pluck('id')->all())->toBe([2]);
|
||||
$data = ($this->listKelompok)(['search' => 'Toni']);
|
||||
expect($data['kelompokTani']->total())->toBe(0);
|
||||
expect((int) $data['summary']->total_pengurus)->toBe(0)
|
||||
->and((int) $data['summary']->total_anggota)->toBe(0);
|
||||
});
|
||||
|
||||
test('kelompok sorting supports names membership totals and safe fallback', function () {
|
||||
foreach ([
|
||||
'nama_asc' => [1, 2, 3], 'nama_desc' => [3, 2, 1],
|
||||
'anggota_desc' => [2, 1, 3], 'anggota_asc' => [3, 1, 2], 'unknown' => [3, 2, 1],
|
||||
] as $sort => $ids) {
|
||||
expect(($this->listKelompok)(['sort_by' => $sort])['kelompokTani']->pluck('id')->all())->toBe($ids);
|
||||
}
|
||||
});
|
||||
|
||||
test('kelompok totals cover every result and pagination preserves all filters', function () {
|
||||
for ($index = 0; $index < 12; $index++) {
|
||||
DB::table('survey_kelompok_tani')->insert([
|
||||
'nama_kelompok' => 'Kelompok tambahan ' . $index, 'desa_kelurahan_id' => 1,
|
||||
'jenis_kelompok' => 'Poktan', 'komoditas_id' => '["1"]', 'jumlah_anggota_terdaftar' => 10,
|
||||
]);
|
||||
}
|
||||
$data = ($this->listKelompok)(['komoditas_id' => 1, 'sort_by' => 'nama_asc', 'page' => 2, 'per_page' => '10']);
|
||||
expect($data['kelompokTani']->count())->toBe(4);
|
||||
expect($data['kelompokTani']->perPage())->toBe(10);
|
||||
expect((int) $data['summary']->total_kelompok)->toBe(14)
|
||||
->and((int) $data['summary']->total_anggota)->toBe(190);
|
||||
parse_str(parse_url($data['kelompokTani']->url(1), PHP_URL_QUERY), $params);
|
||||
expect($params)->toMatchArray(['komoditas_id' => '1', 'sort_by' => 'nama_asc', 'per_page' => '10']);
|
||||
});
|
||||
|
||||
test('kelompok filters reject malformed ids and unsupported page sizes', function (array $filters) {
|
||||
expect(fn () => ($this->listKelompok)($filters))->toThrow(ValidationException::class);
|
||||
})->with([
|
||||
[['kecamatan_id' => 'invalid']], [['komoditas_id' => 999]], [['per_page' => 0]], [['search' => ['invalid']]],
|
||||
]);
|
||||
@@ -0,0 +1,942 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Web\Produktivitas\PengurusKelompokTaniController;
|
||||
use App\Http\Controllers\Web\Produktivitas\AsetKelompokTaniController;
|
||||
use App\Http\Controllers\Web\Produktivitas\BantuanKelompokTaniController;
|
||||
use App\Http\Controllers\Web\Produktivitas\SurveyKelompokTaniController;
|
||||
use App\Models\Pertanian\KelompokTani;
|
||||
use App\Models\Pertanian\AsetKelompokTani;
|
||||
use App\Models\Pertanian\BantuanKelompokTani;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ViewErrorBag;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
beforeEach(function () {
|
||||
foreach ([
|
||||
'master_provinsi' => null,
|
||||
'master_kabupaten_kota' => 'provinsi_id',
|
||||
'master_kecamatan' => 'kabupaten_kota_id',
|
||||
'master_desa_kelurahan' => 'kecamatan_id',
|
||||
'master_komoditas' => null,
|
||||
] as $name => $parent) {
|
||||
Schema::create($name, function (Blueprint $table) use ($parent) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->string('kode')->nullable();
|
||||
$table->boolean('is_utama')->default(true);
|
||||
if ($parent) $table->integer($parent);
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
Schema::create('survey_kelompok_tani', function (Blueprint $table) {
|
||||
$table->id();
|
||||
foreach ([
|
||||
'uid', 'nama_kelompok', 'nama_responden', 'jabatan_responden', 'kontak_responden',
|
||||
'dusun', 'jenis_kelompok', 'nama_gapoktan', 'cakupan_wilayah', 'nama_wilayah_cakupan',
|
||||
'status_legalitas', 'nomor_sk', 'tanggal_tahun_penerbitan_sk', 'frekuensi_pertemuan',
|
||||
'tanggal_pertemuan_terakhir',
|
||||
'pembukuan_kas', 'pengelola_kas', 'masalah_pengelolaan_kas_simpan_pinjam', 'deskripsi_masalah_pengelolaan_kas_simpan_pinjam',
|
||||
'potensi_kelompok', 'alasan_penilaian_potensi', 'konflik_kelompok', 'topik_konflik', 'penyelesaian_konflik', 'partisipasi_perempuan',
|
||||
] as $field) {
|
||||
$table->string($field)->nullable();
|
||||
}
|
||||
foreach ([
|
||||
'desa_kelurahan_id', 'tahun_berdiri', 'jumlah_pengurus', 'jumlah_pengurus_aktif',
|
||||
'jumlah_anggota_terdaftar', 'jumlah_anggota_aktif', 'jumlah_pengurus_laki_laki',
|
||||
'jumlah_pengurus_perempuan', 'jumlah_anggota_laki_laki', 'jumlah_anggota_perempuan',
|
||||
'jumlah_anggota_pemuda_laki_laki', 'jumlah_anggota_pemuda_perempuan',
|
||||
'created_by', 'updated_by', 'deleted_by',
|
||||
] as $field) {
|
||||
$table->integer($field)->nullable();
|
||||
}
|
||||
$table->json('komoditas_id')->nullable();
|
||||
$table->json('kegiatan_terlaksana')->nullable();
|
||||
$table->json('fungsi_kelompok_bagi_anggota')->nullable();
|
||||
$table->boolean('pernah_mendapatkan_bantuan')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
Schema::create('survey_pengurus_kelompok_tani', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid');
|
||||
$table->integer('survey_kelompok_tani_id');
|
||||
$table->string('nama_pengurus');
|
||||
$table->string('jabatan');
|
||||
$table->string('kontak');
|
||||
$table->boolean('status');
|
||||
$table->integer('created_by')->nullable();
|
||||
$table->integer('updated_by')->nullable();
|
||||
$table->integer('deleted_by')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
Schema::create('survey_aset_kelompok_tani', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid');
|
||||
$table->integer('survey_kelompok_tani_id');
|
||||
$table->string('jenis_aset');
|
||||
$table->boolean('status_aset');
|
||||
$table->string('status_pengelolaan_aset');
|
||||
$table->string('kondisi_aset');
|
||||
$table->integer('created_by')->nullable();
|
||||
$table->integer('updated_by')->nullable();
|
||||
$table->integer('deleted_by')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
Schema::create('survey_bantuan_kelompok_tani', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uid');
|
||||
$table->integer('survey_kelompok_tani_id');
|
||||
$table->string('nama_program');
|
||||
$table->string('penyelenggara');
|
||||
$table->string('bentuk_bantuan');
|
||||
$table->integer('tahun')->nullable();
|
||||
$table->integer('created_by')->nullable();
|
||||
$table->integer('updated_by')->nullable();
|
||||
$table->integer('deleted_by')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
DB::table('master_provinsi')->insert(['id' => 1, 'nama' => 'NTT']);
|
||||
DB::table('master_kabupaten_kota')->insert(['id' => 1, 'nama' => 'Ngada', 'provinsi_id' => 1]);
|
||||
DB::table('master_kecamatan')->insert(['id' => 1, 'nama' => 'Kecamatan A', 'kabupaten_kota_id' => 1]);
|
||||
DB::table('master_desa_kelurahan')->insert(['id' => 1, 'nama' => 'Desa A', 'kecamatan_id' => 1]);
|
||||
|
||||
$user = new User(['name' => 'Admin Test', 'email' => 'admin@example.test', 'role' => 'admin']);
|
||||
$user->id = 7;
|
||||
$this->be($user);
|
||||
Event::forget('composing: *');
|
||||
view()->share('errors', new ViewErrorBag());
|
||||
|
||||
$this->kelompok = fn (array $attributes = []) => KelompokTani::create([
|
||||
'nama_kelompok' => 'Kelompok A', 'nama_responden' => 'Responden A',
|
||||
'desa_kelurahan_id' => 1, 'jenis_kelompok' => 'Kelompok Tani (Poktan)', ...$attributes,
|
||||
]);
|
||||
$this->profileRequest = function (array $input = [], string $method = 'PUT') {
|
||||
$request = Request::create('/survey/kelompok-tani/1/edit', $method, $input);
|
||||
$request->setLaravelSession(app('session')->driver());
|
||||
$this->app->instance('request', $request);
|
||||
|
||||
return $request;
|
||||
};
|
||||
$this->profileDom = function ($view) {
|
||||
$dom = new DOMDocument();
|
||||
$previous = libxml_use_internal_errors(true);
|
||||
$dom->loadHTML($view->render());
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($previous);
|
||||
|
||||
return new DOMXPath($dom);
|
||||
};
|
||||
});
|
||||
|
||||
test('profile saves identity and membership together on creation and update', function () {
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
$input = [
|
||||
'nama_kelompok' => 'Kelompok Baru', 'nama_responden' => 'Budi',
|
||||
'desa_kelurahan_id' => 1, 'jenis_kelompok' => 'Kelompok Tani (Poktan)',
|
||||
'jumlah_pengurus' => 4, 'jumlah_pengurus_aktif' => 3, 'jumlah_anggota_terdaftar' => 20,
|
||||
'jumlah_anggota_aktif' => 18, 'jumlah_pengurus_laki_laki' => 2, 'jumlah_pengurus_perempuan' => 2,
|
||||
'jumlah_anggota_laki_laki' => 12, 'jumlah_anggota_perempuan' => 8,
|
||||
'jumlah_anggota_pemuda_laki_laki' => 5, 'jumlah_anggota_pemuda_perempuan' => 3,
|
||||
];
|
||||
$locations = ['provinsi_id' => 1, 'kabupaten_id' => 1, 'kecamatan_id' => 1];
|
||||
$controller->store(($this->profileRequest)([...$input, ...$locations], 'POST'));
|
||||
$group = KelompokTani::firstOrFail();
|
||||
foreach ($input as $field => $value) expect($group->{$field})->toBe($value);
|
||||
|
||||
$response = $controller->update(($this->profileRequest)([
|
||||
...$input, ...$locations, 'nama_kelompok' => 'Kelompok Diubah', 'jumlah_anggota_terdaftar' => 25,
|
||||
]), $group);
|
||||
expect($group->refresh()->nama_kelompok)->toBe('Kelompok Diubah')
|
||||
->and($group->jumlah_anggota_terdaftar)->toBe(25);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '#section-pengurus');
|
||||
});
|
||||
|
||||
test('invalid membership prevents partial profile saves', function () {
|
||||
$group = ($this->kelompok)(['jumlah_anggota_terdaftar' => 20]);
|
||||
$request = ($this->profileRequest)([
|
||||
'nama_kelompok' => 'Tidak boleh tersimpan', 'nama_responden' => 'Budi',
|
||||
'provinsi_id' => 1, 'kabupaten_id' => 1, 'kecamatan_id' => 1,
|
||||
'desa_kelurahan_id' => 1, 'jenis_kelompok' => 'Kelompok Tani (Poktan)',
|
||||
'jumlah_anggota_terdaftar' => -1,
|
||||
]);
|
||||
|
||||
expect(fn () => app(SurveyKelompokTaniController::class)->update($request, $group))
|
||||
->toThrow(ValidationException::class);
|
||||
expect($group->refresh()->nama_kelompok)->toBe('Kelompok A')
|
||||
->and($group->jumlah_anggota_terdaftar)->toBe(20);
|
||||
});
|
||||
|
||||
test('membership fields belong to the profile form on create and edit', function () {
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
($this->profileRequest)([], 'GET');
|
||||
$create = ($this->profileDom)($controller->create());
|
||||
expect($create->query('//form[@id="addKelompokTaniForm"]//input[@name="jumlah_anggota_terdaftar"]')->length)->toBe(1);
|
||||
|
||||
$group = ($this->kelompok)(['jumlah_anggota_terdaftar' => 20]);
|
||||
$group->pengurus()->create([
|
||||
'uid' => 'PKT-TEST', 'nama_pengurus' => 'Ketua A', 'jabatan' => 'Ketua', 'kontak' => '08123456789', 'status' => true,
|
||||
]);
|
||||
$edit = ($this->profileDom)($controller->edit(($this->profileRequest)([], 'GET'), $group));
|
||||
expect($edit->query('//form[@id="editKelompokTaniForm"]//input[@name="jumlah_anggota_terdaftar" and @value="20"]')->length)->toBe(1);
|
||||
expect($edit->query('//div[@id="section-pengurus"]//input[@value="Ketua A"]')->length)->toBe(1);
|
||||
expect($edit->query('//form[contains(@class,"form-repeater-pengurus")]')->length)->toBe(1);
|
||||
expect($edit->query('//ul[contains(@class,"nav-pills")]//a[normalize-space()="Keanggotaan"]')->length)->toBe(0);
|
||||
});
|
||||
|
||||
test('SK fields render enabled only for statuses with an existing SK', function (?string $status, bool $enabled) {
|
||||
$group = ($this->kelompok)(['status_legalitas' => $status]);
|
||||
$view = app(SurveyKelompokTaniController::class)->edit(
|
||||
($this->profileRequest)(['section' => 'kelembagaan'], 'GET'), $group
|
||||
);
|
||||
$dom = ($this->profileDom)($view);
|
||||
foreach (['klb-nomor-sk', 'klb-tanggal-penerbitan-sk'] as $id) {
|
||||
expect($dom->query('//input[@id="' . $id . '"]')->item(0)->hasAttribute('disabled'))->toBe(!$enabled);
|
||||
}
|
||||
expect($dom->query('//label[@for="klb-nomor-sk"]')->item(0)->textContent)->toBe('Nomor SK');
|
||||
})->with([
|
||||
[null, false], ['Belum ada SK/dokumen apa pun', false], ['Sedang proses pengajuan', false],
|
||||
['Tidak tahu', false], ['Sudah ada SK dari desa/kecamatan', true],
|
||||
['Sudah ada SK dan terdaftar di Dinas/Kabupaten', true],
|
||||
]);
|
||||
|
||||
test('inactive SK input is ignored and existing values survive status changes', function () {
|
||||
$group = ($this->kelompok)(['nomor_sk' => 'SK-LAMA', 'tanggal_tahun_penerbitan_sk' => '2020']);
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
$controller->update(($this->profileRequest)([
|
||||
'section' => 'kelembagaan', 'status_legalitas' => 'Tidak tahu',
|
||||
'nomor_sk' => ['invalid'], 'tanggal_tahun_penerbitan_sk' => str_repeat('x', 100),
|
||||
]), $group);
|
||||
expect($group->refresh()->nomor_sk)->toBe('SK-LAMA')
|
||||
->and($group->tanggal_tahun_penerbitan_sk)->toBe('2020');
|
||||
|
||||
$controller->update(($this->profileRequest)([
|
||||
'section' => 'kelembagaan', 'status_legalitas' => 'Sudah ada SK dari desa/kecamatan',
|
||||
'nomor_sk' => 'SK-BARU', 'tanggal_tahun_penerbitan_sk' => '2026',
|
||||
]), $group);
|
||||
expect($group->refresh()->nomor_sk)->toBe('SK-BARU')
|
||||
->and($group->tanggal_tahun_penerbitan_sk)->toBe('2026');
|
||||
});
|
||||
|
||||
test('pengurus actions and the former membership URL return to profile', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(PengurusKelompokTaniController::class);
|
||||
$response = $controller->index($group);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '#section-ringkasan');
|
||||
$response = $controller->store(($this->profileRequest)(['pengurus' => [[
|
||||
'nama_pengurus' => 'Ketua A', 'jabatan' => 'Ketua', 'kontak' => '08123456789', 'status' => 1,
|
||||
]]], 'POST'), $group);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '#section-pengurus');
|
||||
$pengurus = $group->pengurus()->firstOrFail();
|
||||
$response = $controller->destroy($group, $pengurus);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '#section-pengurus');
|
||||
expect($group->pengurus()->count())->toBe(0);
|
||||
});
|
||||
|
||||
test('meeting fields are shown in Kegiatan with existing values and removed from Kelembagaan', function () {
|
||||
$group = ($this->kelompok)([
|
||||
'frekuensi_pertemuan' => '1x per bulan', 'tanggal_pertemuan_terakhir' => '2026-10-20',
|
||||
]);
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
$kelembagaan = ($this->profileDom)($controller->edit(
|
||||
($this->profileRequest)(['section' => 'kelembagaan'], 'GET'), $group
|
||||
));
|
||||
expect($kelembagaan->query('//select[@name="frekuensi_pertemuan"] | //input[@name="tanggal_pertemuan_terakhir"]')->length)->toBe(0);
|
||||
|
||||
$aktivitas = ($this->profileDom)($controller->edit(
|
||||
($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET'), $group
|
||||
));
|
||||
expect($aktivitas->query('//form//select[@name="frekuensi_pertemuan"]/option[@selected]')->item(0)->getAttribute('value'))->toBe('1x per bulan');
|
||||
expect($aktivitas->query('//form//input[@name="tanggal_pertemuan_terakhir"]')->item(0)->getAttribute('value'))->toBe('20-10-2026');
|
||||
expect($aktivitas->query('//ul[contains(@class,"nav-pills")]//a[normalize-space()="Operasional"]')->length)->toBe(1);
|
||||
expect($aktivitas->query('//input[@name="tanggal_pertemuan_terakhir"]')->item(0)->hasAttribute('placeholder'))->toBeFalse();
|
||||
});
|
||||
|
||||
test('Kegiatan saves meeting details and rejects invalid dates without partial updates', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
$response = $controller->update(($this->profileRequest)([
|
||||
'section' => 'aktivitas-fungsi', 'frekuensi_pertemuan' => '1x per bulan',
|
||||
'tanggal_pertemuan_terakhir' => '20-10-2026', 'kegiatan_terlaksana' => ['Pertemuan/diskusi rutin'],
|
||||
]), $group);
|
||||
expect($group->refresh()->frekuensi_pertemuan)->toBe('1x per bulan')
|
||||
->and($group->tanggal_pertemuan_terakhir->format('Y-m-d'))->toBe('2026-10-20')
|
||||
->and($group->kegiatan_terlaksana)->toBe(['Pertemuan/diskusi rutin']);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi#section-aset-baku');
|
||||
|
||||
$invalid = ($this->profileRequest)([
|
||||
'section' => 'aktivitas-fungsi', 'frekuensi_pertemuan' => 'Tidak rutin/tidak terjadwal',
|
||||
'tanggal_pertemuan_terakhir' => 'invalid-date',
|
||||
]);
|
||||
expect(fn () => $controller->update($invalid, $group))->toThrow(ValidationException::class);
|
||||
expect($group->refresh()->frekuensi_pertemuan)->toBe('1x per bulan')
|
||||
->and($group->tanggal_pertemuan_terakhir->format('Y-m-d'))->toBe('2026-10-20');
|
||||
|
||||
$controller->update(($this->profileRequest)([
|
||||
'section' => 'kelembagaan', 'cakupan_wilayah' => 'Desa', 'frekuensi_pertemuan' => 'Diabaikan',
|
||||
'tanggal_pertemuan_terakhir' => 'invalid-date',
|
||||
]), $group);
|
||||
expect($group->refresh()->cakupan_wilayah)->toBe('Desa')
|
||||
->and($group->frekuensi_pertemuan)->toBe('1x per bulan');
|
||||
});
|
||||
|
||||
test('all group tabs show Simpan with a check and Kembali to the group list', function () {
|
||||
($this->profileRequest)([], 'GET');
|
||||
$group = ($this->kelompok)();
|
||||
foreach (['pengurus', 'aset', 'bantuan'] as $relation) $group->setRelation($relation, collect());
|
||||
|
||||
foreach (['add', 'edit', 'kelembagaan', 'aktivitas-fungsi', 'sosial-konflik'] as $template) {
|
||||
$dom = ($this->profileDom)(view('produktivitas.survey-kelompok-tani.' . $template, [
|
||||
'kelompokTani' => $template === 'add' ? null : $group,
|
||||
'provinsi' => collect(), 'komoditas' => collect(),
|
||||
]));
|
||||
$buttons = $dom->query('//div[contains(@class,"kelompok-tani-page")]//button[@type="submit" and contains(@class,"btn-success")]');
|
||||
expect($buttons->length)->toBeGreaterThan(0);
|
||||
foreach ($buttons as $button) {
|
||||
$form = $dom->query('ancestor::form', $button)->item(0);
|
||||
expect($form->hasAttribute('novalidate'))->toBeTrue();
|
||||
expect(trim($button->textContent))->toBe('Simpan');
|
||||
expect($dom->query('.//i[contains(@class,"tabler-check")]', $button)->length)->toBe(1);
|
||||
$back = $dom->query('./a[normalize-space()="Kembali"]', $button->parentNode);
|
||||
expect($back->length)->toBe(1);
|
||||
expect($back->item(0)->getAttribute('href'))->toBe(route('kelompok-tani.index'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('flash notifications appear once above the group summary regardless of section', function (string $key) {
|
||||
($this->profileRequest)([], 'GET');
|
||||
session()->flash($key, 'Pesan pemeriksaan');
|
||||
session()->flash($key . '_section', 'kas');
|
||||
$group = ($this->kelompok)();
|
||||
$group->setRelation('pengurus', collect());
|
||||
$dom = ($this->profileDom)(view('produktivitas.survey-kelompok-tani.edit', [
|
||||
'kelompokTani' => $group, 'provinsi' => collect(), 'komoditas' => collect(),
|
||||
]));
|
||||
|
||||
expect($dom->query('//div[@id="kelompok-tani-notifications"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="kelompok-tani-summary"]/preceding-sibling::div[@id="kelompok-tani-notifications"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="kelompok-tani-notifications"]//div[@role="alert"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="kelompok-tani-notifications"]')->item(0)->textContent)->toContain('Pesan pemeriksaan');
|
||||
})->with(['success', 'error', 'warning', 'info', 'status', 'message']);
|
||||
|
||||
test('validation errors are summarized above the group summary', function () {
|
||||
($this->profileRequest)([], 'GET');
|
||||
$errors = new ViewErrorBag();
|
||||
$errors->put('default', new Illuminate\Support\MessageBag(['nomor_sk' => 'Nomor SK tidak valid.']));
|
||||
view()->share('errors', $errors);
|
||||
$dom = ($this->profileDom)(view('produktivitas.survey-kelompok-tani.kelembagaan', [
|
||||
'kelompokTani' => ($this->kelompok)(),
|
||||
]));
|
||||
|
||||
expect($dom->query('//div[@id="kelompok-tani-summary"]/preceding-sibling::div[@id="kelompok-tani-notifications"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="kelompok-tani-notifications"]//li')->item(0)->textContent)->toBe('Nomor SK tidak valid.');
|
||||
});
|
||||
|
||||
test('one asset submission saves standard and additional assets and skips empty rows', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(AsetKelompokTaniController::class);
|
||||
$response = $controller->update(($this->profileRequest)([
|
||||
'aset' => [[
|
||||
'jenis_aset' => 'Timbangan', 'status_aset' => 1,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]],
|
||||
'aset_lainnya' => [
|
||||
['jenis_aset' => 'Mesin pengering', 'status_pengelolaan_aset' => 'Swadaya', 'kondisi_aset' => 'Berfungsi'],
|
||||
['jenis_aset' => '', 'status_pengelolaan_aset' => '', 'kondisi_aset' => ''],
|
||||
],
|
||||
]), $group);
|
||||
|
||||
expect($group->aset()->count())->toBe(2);
|
||||
expect($group->aset()->where('jenis_aset', 'Timbangan')->firstOrFail()->status_pengelolaan_aset)->toBe('Hibah');
|
||||
expect($group->aset()->where('jenis_aset', 'Mesin pengering')->firstOrFail()->kondisi_aset)->toBe('Berfungsi');
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi#section-status-bantuan');
|
||||
});
|
||||
|
||||
test('invalid additional assets prevent standard assets from being changed', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$existing = $group->aset()->create([
|
||||
'uid' => 'AKT-TEST', 'jenis_aset' => 'Timbangan', 'status_aset' => true,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
$request = ($this->profileRequest)([
|
||||
'aset' => [['jenis_aset' => 'Timbangan', 'status_aset' => 0]],
|
||||
'aset_lainnya' => [['jenis_aset' => 'Timbangan']],
|
||||
]);
|
||||
expect(fn () => app(AsetKelompokTaniController::class)->update($request, $group))->toThrow(ValidationException::class);
|
||||
expect($existing->fresh()->trashed())->toBeFalse();
|
||||
expect($group->aset()->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('combined asset save restores and removes standard assets while keeping additional assets', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(AsetKelompokTaniController::class);
|
||||
$existing = $group->aset()->create([
|
||||
'uid' => 'AKT-TEST', 'jenis_aset' => 'Timbangan', 'status_aset' => true,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
$existing->delete();
|
||||
$controller->update(($this->profileRequest)([
|
||||
'aset' => [[
|
||||
'jenis_aset' => 'Timbangan', 'status_aset' => 1,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]],
|
||||
'aset_lainnya' => [['jenis_aset' => 'Mesin pengering']],
|
||||
]), $group);
|
||||
expect($existing->fresh()->trashed())->toBeFalse();
|
||||
expect($group->aset()->withTrashed()->where('jenis_aset', 'Timbangan')->count())->toBe(1);
|
||||
|
||||
$controller->update(($this->profileRequest)([
|
||||
'aset' => [['jenis_aset' => 'Timbangan', 'status_aset' => 0]],
|
||||
]), $group);
|
||||
expect($existing->fresh()->trashed())->toBeTrue();
|
||||
expect($group->aset()->pluck('jenis_aset')->all())->toBe(['Mesin pengering']);
|
||||
});
|
||||
|
||||
test('asset save rolls back standard changes if additional asset creation fails', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$existing = $group->aset()->create([
|
||||
'uid' => 'AKT-TEST', 'jenis_aset' => 'Timbangan', 'status_aset' => true,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
Event::listen('eloquent.creating: ' . AsetKelompokTani::class, function ($asset) {
|
||||
if ($asset->jenis_aset === 'Mesin gagal') throw new RuntimeException('Simulated failure');
|
||||
});
|
||||
$request = ($this->profileRequest)([
|
||||
'aset' => [['jenis_aset' => 'Timbangan', 'status_aset' => 0]],
|
||||
'aset_lainnya' => [['jenis_aset' => 'Mesin gagal']],
|
||||
]);
|
||||
expect(fn () => app(AsetKelompokTaniController::class)->update($request, $group))->toThrow(RuntimeException::class);
|
||||
expect($existing->fresh()->trashed())->toBeFalse();
|
||||
expect($group->aset()->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('asset card has one shared form and preserves inputs after validation errors', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$existing = $group->aset()->create([
|
||||
'uid' => 'AKT-TEST', 'jenis_aset' => 'Mesin lama', 'status_aset' => true,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
($this->profileRequest)([], 'GET');
|
||||
session()->flashInput([
|
||||
'aset' => [['status_aset' => '1', 'status_pengelolaan_aset' => 'Pinjaman', 'kondisi_aset' => 'Mangkrak']],
|
||||
'aset_lainnya' => [['jenis_aset' => 'Mesin baru', 'status_pengelolaan_aset' => 'Sewa', 'kondisi_aset' => 'Berfungsi']],
|
||||
]);
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit(($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET'), $group));
|
||||
expect($dom->query('//div[@id="section-aset-baku"]//form[@id="aset-produktif-form"]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//div[@id="section-aset-lainnya"]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//button[contains(@class,"btn-success")]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//form')->length)->toBe(0);
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//input[@value="Mesin baru"]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//select[@name="aset[0][status_pengelolaan_aset]"]/option[@selected]')->item(0)->getAttribute('value'))->toBe('Pinjaman');
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//select[@name="status_pengelolaan_aset"]/option[@selected]')->item(0)->getAttribute('value'))->toBe('Sewa');
|
||||
expect($dom->query('//button[@form="delete-aset-' . $existing->id . '"]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="delete-aset-' . $existing->id . '"]')->length)->toBe(1);
|
||||
});
|
||||
|
||||
test('cash management is visible only when the cash asset is present or selected in old input', function (?bool $savedStatus, bool $deleted, ?string $oldStatus, bool $visible) {
|
||||
$group = ($this->kelompok)();
|
||||
if ($savedStatus !== null) {
|
||||
$asset = $group->aset()->create([
|
||||
'uid' => 'AKT-KAS', 'jenis_aset' => 'Kas/simpanan kelompok', 'status_aset' => $savedStatus,
|
||||
'status_pengelolaan_aset' => 'Swadaya', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
if ($deleted) $asset->delete();
|
||||
}
|
||||
($this->profileRequest)([], 'GET');
|
||||
if ($oldStatus !== null) {
|
||||
$cashIndex = array_search('Kas/simpanan kelompok', AsetKelompokTaniController::JENIS_ASET_BAKU, true);
|
||||
session()->flashInput(['aset' => [$cashIndex => ['status_aset' => $oldStatus]]]);
|
||||
}
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit(($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET'), $group));
|
||||
expect($dom->query('//div[@id="section-kas"]')->item(0)->hasAttribute('hidden'))->toBe(!$visible);
|
||||
expect($dom->query('//tr[@data-aset-kas]//input[@value="1"]')->item(0)->hasAttribute('checked'))->toBe($visible);
|
||||
})->with([
|
||||
[null, false, null, false],
|
||||
[true, false, null, true],
|
||||
[false, false, null, false],
|
||||
[true, true, null, false],
|
||||
[true, false, '0', false],
|
||||
[null, false, '1', true],
|
||||
]);
|
||||
|
||||
test('the combined tab contains activities assets and cash management with one header', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$group->aset()->create([
|
||||
'uid' => 'AKT-KAS', 'jenis_aset' => 'Kas/simpanan kelompok', 'status_aset' => true,
|
||||
'status_pengelolaan_aset' => 'Swadaya', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
$request = ($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET');
|
||||
$route = (new Illuminate\Routing\Route('GET', '/survey/kelompok-tani/{kelompokTani}/edit', fn () => null))->name('kelompok-tani.edit');
|
||||
$request->setRouteResolver(fn () => $route);
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit($request, $group));
|
||||
|
||||
expect($dom->query('//div[@id="kelompok-tani-summary"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="section-aktivitas-fungsi"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="section-aset-baku"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="section-kas"]')->item(0)->hasAttribute('hidden'))->toBeFalse();
|
||||
expect($dom->query('//div[@id="section-status-bantuan"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="section-penilaian"]')->length)->toBe(0);
|
||||
expect($dom->query('//ul[contains(@class,"nav-pills")]//a[normalize-space()="Bantuan & Penilaian"]')->length)->toBe(0);
|
||||
expect($dom->query('//ul[contains(@class,"nav-pills")]//a[contains(@class,"active") and normalize-space()="Operasional"]')->length)->toBe(1);
|
||||
expect($dom->query('//ul[contains(@class,"nav-pills")]//a[normalize-space()="Aset & Keuangan"]')->length)->toBe(0);
|
||||
});
|
||||
|
||||
test('asset actions and cash saves return to the combined tab', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(AsetKelompokTaniController::class);
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi';
|
||||
expect($controller->index($group)->getTargetUrl())->toBe($url . '#section-aset-baku');
|
||||
|
||||
$response = $controller->store(($this->profileRequest)([
|
||||
'aset_lainnya' => [['jenis_aset' => 'Mesin pengering']],
|
||||
], 'POST'), $group);
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-status-bantuan');
|
||||
$response = $controller->destroy($group, $group->aset()->firstOrFail());
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-aset-lainnya');
|
||||
|
||||
$response = app(SurveyKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'section' => 'kas', 'pengelola_kas' => 'Bendahara kelompok',
|
||||
]), $group);
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-status-bantuan');
|
||||
expect($group->refresh()->pengelola_kas)->toBe('Bendahara kelompok');
|
||||
});
|
||||
|
||||
test('present assets require both management status and condition before saving any assets', function ($status) {
|
||||
$group = ($this->kelompok)();
|
||||
$request = ($this->profileRequest)([
|
||||
'aset' => [['jenis_aset' => 'Timbangan', 'status_aset' => $status]],
|
||||
'aset_lainnya' => [['jenis_aset' => 'Mesin pengering']],
|
||||
]);
|
||||
try {
|
||||
app(AsetKelompokTaniController::class)->update($request, $group);
|
||||
$this->fail('An asset marked Ada must require management status and condition.');
|
||||
} catch (ValidationException $exception) {
|
||||
expect(array_keys($exception->errors()))->toBe([
|
||||
'aset.0.status_pengelolaan_aset', 'aset.0.kondisi_aset',
|
||||
]);
|
||||
expect($exception->errors()['aset.0.kondisi_aset'][0])->toBe('Kondisi wajib diisi jika aset dipilih Ada.');
|
||||
}
|
||||
expect($group->aset()->count())->toBe(0);
|
||||
})->with(['1', 1, true]);
|
||||
|
||||
test('asset requirements follow each row and reject blank values', function (array $details, string $missingField) {
|
||||
$group = ($this->kelompok)();
|
||||
$request = ($this->profileRequest)([
|
||||
'aset' => [
|
||||
['jenis_aset' => 'Timbangan', 'status_aset' => '0'],
|
||||
['jenis_aset' => 'Gudang/tempat simpan', 'status_aset' => '1', ...$details],
|
||||
],
|
||||
]);
|
||||
try {
|
||||
app(AsetKelompokTaniController::class)->update($request, $group);
|
||||
$this->fail('The selected asset has a missing detail.');
|
||||
} catch (ValidationException $exception) {
|
||||
expect(array_keys($exception->errors()))->toBe(['aset.1.' . $missingField]);
|
||||
}
|
||||
expect($group->aset()->count())->toBe(0);
|
||||
})->with([
|
||||
[['status_pengelolaan_aset' => '', 'kondisi_aset' => 'Berfungsi'], 'status_pengelolaan_aset'],
|
||||
[['status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => null], 'kondisi_aset'],
|
||||
[['status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => ' '], 'kondisi_aset'],
|
||||
]);
|
||||
|
||||
test('asset dropdowns are required only on rows selected Ada', function (bool $present) {
|
||||
$group = ($this->kelompok)();
|
||||
$group->aset()->create([
|
||||
'uid' => 'AKT-TEST', 'jenis_aset' => 'Timbangan', 'status_aset' => $present,
|
||||
'status_pengelolaan_aset' => 'Hibah', 'kondisi_aset' => 'Berfungsi',
|
||||
]);
|
||||
$request = ($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET');
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit($request, $group));
|
||||
$index = array_search('Timbangan', AsetKelompokTaniController::JENIS_ASET_BAKU, true);
|
||||
foreach (['status_pengelolaan_aset', 'kondisi_aset'] as $field) {
|
||||
$select = $dom->query('//select[@name="aset[' . $index . '][' . $field . ']"]')->item(0);
|
||||
expect($select->hasAttribute('required'))->toBe($present);
|
||||
expect($select->hasAttribute('disabled'))->toBe(!$present);
|
||||
}
|
||||
})->with([true, false]);
|
||||
|
||||
test('asset validation errors appear beside the marked required dropdowns', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$request = ($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET');
|
||||
session()->flashInput(['aset' => [['status_aset' => '1']]]);
|
||||
$messages = [
|
||||
'aset.0.status_pengelolaan_aset' => 'Status Pengelolaan wajib diisi jika aset dipilih Ada.',
|
||||
'aset.0.kondisi_aset' => 'Kondisi wajib diisi jika aset dipilih Ada.',
|
||||
];
|
||||
$errors = new ViewErrorBag();
|
||||
$errors->put('default', new Illuminate\Support\MessageBag($messages));
|
||||
view()->share('errors', $errors);
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit($request, $group));
|
||||
|
||||
expect($dom->query('//form[@id="aset-produktif-form"]//th/span[contains(@class,"text-danger")]')->length)->toBe(2);
|
||||
foreach (['status_pengelolaan_aset' => 'status-pengelolaan', 'kondisi_aset' => 'kondisi'] as $field => $idPart) {
|
||||
$id = 'aset-0-' . $idPart;
|
||||
$select = $dom->query('//select[@id="' . $id . '"]')->item(0);
|
||||
expect($select->getAttribute('class'))->toContain('is-invalid');
|
||||
expect($select->getAttribute('aria-describedby'))->toBe($id . '-error');
|
||||
expect(trim($dom->query('//div[@id="' . $id . '-error"]')->item(0)->textContent))->toBe($messages['aset.0.' . $field]);
|
||||
}
|
||||
});
|
||||
|
||||
test('saving assets advances to cash only when the cash section is available', function (bool $hasCash) {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(AsetKelompokTaniController::class);
|
||||
$input = ['aset' => [[
|
||||
'jenis_aset' => 'Kas/simpanan kelompok', 'status_aset' => $hasCash,
|
||||
'status_pengelolaan_aset' => 'Swadaya', 'kondisi_aset' => 'Berfungsi',
|
||||
]]];
|
||||
$response = $controller->update(($this->profileRequest)($input), $group);
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi';
|
||||
expect($response->getTargetUrl())->toBe($url . ($hasCash ? '#section-kas' : '#section-status-bantuan'));
|
||||
|
||||
$input['aset'][0]['status_aset'] = false;
|
||||
$response = $controller->update(($this->profileRequest)($input), $group);
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-status-bantuan');
|
||||
})->with([true, false]);
|
||||
|
||||
test('saving aid status stays on the combined aid card in Operasional', function (bool $hasAid) {
|
||||
$group = ($this->kelompok)();
|
||||
$response = app(SurveyKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'section' => 'status-bantuan', 'pernah_mendapatkan_bantuan' => $hasAid,
|
||||
'bantuan' => $hasAid ? [['nama_program' => 'Program A', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026]] : [],
|
||||
]), $group);
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi';
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-status-bantuan');
|
||||
})->with([true, false]);
|
||||
|
||||
test('legacy aid saves return to Operasional and failed saves retain the notification target', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => true]);
|
||||
$controller = app(BantuanKelompokTaniController::class);
|
||||
$response = $controller->store(($this->profileRequest)(['bantuan' => [[
|
||||
'nama_program' => 'Bibit Kakao', 'penyelenggara' => 'Dinas Pertanian', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026,
|
||||
]]], 'POST'), $group);
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi';
|
||||
expect($response->getTargetUrl())->toBe($url . '#section-status-bantuan');
|
||||
|
||||
$group->update(['pernah_mendapatkan_bantuan' => false]);
|
||||
$response = $controller->store(($this->profileRequest)([], 'POST'), $group);
|
||||
expect($response->getTargetUrl())->toBe($url . '#kelompok-tani-notifications');
|
||||
expect($group->bantuan()->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('single and final section saves stay on their own box', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$controller = app(SurveyKelompokTaniController::class);
|
||||
foreach ([
|
||||
'kelembagaan' => ['cakupan_wilayah' => 'Desa'],
|
||||
'sosial-konflik' => ['konflik_kelompok' => 'Tidak pernah'],
|
||||
] as $section => $input) {
|
||||
$response = $controller->update(($this->profileRequest)(['section' => $section, ...$input]), $group);
|
||||
expect(parse_url($response->getTargetUrl(), PHP_URL_FRAGMENT))->toBe('section-' . $section);
|
||||
}
|
||||
});
|
||||
|
||||
test('invalid required fields return Indonesian errors above the summary and beside each field', function (string $section, array $payload, array $messages) {
|
||||
$group = ($this->kelompok)();
|
||||
$url = route('kelompok-tani.edit', $group->id) . ($section === 'identitas' ? '' : '?section=' . ($section === 'status-bantuan' ? 'aktivitas-fungsi' : $section));
|
||||
$response = $this->from($url)->put(route('kelompok-tani.update', $group->id), ['section' => $section, ...$payload]);
|
||||
$response->assertRedirect($url)->assertSessionHasErrors(array_keys($messages));
|
||||
$page = $this->get($url)->assertOk();
|
||||
expect(strpos($page->getContent(), 'id="kelompok-tani-notifications"'))->toBeLessThan(strpos($page->getContent(), 'id="kelompok-tani-summary"'));
|
||||
|
||||
$dom = new DOMDocument();
|
||||
libxml_use_internal_errors(true);
|
||||
$dom->loadHTML($page->getContent());
|
||||
libxml_clear_errors();
|
||||
$xpath = new DOMXPath($dom);
|
||||
$summary = $xpath->query('//div[@id="kelompok-tani-notifications"]')->item(0)->textContent;
|
||||
$inlineMessages = collect($xpath->query('//div[contains(@class,"invalid-feedback")]'))->map(fn ($node) => trim($node->textContent))->all();
|
||||
foreach ($messages as $message) {
|
||||
expect($summary)->toContain($message);
|
||||
expect($inlineMessages)->toContain($message);
|
||||
}
|
||||
expect($xpath->query('//input[contains(@class,"is-invalid")] | //select[contains(@class,"is-invalid")]')->length)->toBeGreaterThan(0);
|
||||
expect($group->refresh()->nama_kelompok)->toBe('Kelompok A');
|
||||
})->with([
|
||||
['identitas', [], [
|
||||
'nama_responden' => 'Nama responden wajib diisi.', 'nama_kelompok' => 'Nama kelompok wajib diisi.',
|
||||
'provinsi_id' => 'Provinsi wajib diisi.', 'kabupaten_id' => 'Kabupaten/Kota wajib diisi.',
|
||||
'kecamatan_id' => 'Kecamatan wajib diisi.', 'desa_kelurahan_id' => 'Desa/Kelurahan wajib dipilih.',
|
||||
'jenis_kelompok' => 'Terdaftar/Dikenal Sebagai wajib diisi.',
|
||||
]],
|
||||
['identitas', ['jenis_kelompok' => 'Lainnya'], ['jenis_kelompok_lainnya' => 'Sebutkan Jenis Kelompok wajib diisi.']],
|
||||
['status-bantuan', [], ['pernah_mendapatkan_bantuan' => 'Pengalaman Akses Bantuan/Program wajib diisi.']],
|
||||
['status-bantuan', ['pernah_mendapatkan_bantuan' => '1', 'bantuan' => [[]]], [
|
||||
'bantuan.0.nama_program' => 'Nama Program/Bantuan pada baris pertama wajib diisi.',
|
||||
'bantuan.0.penyelenggara' => 'Penyelenggara pada baris pertama wajib diisi.',
|
||||
'bantuan.0.bentuk_bantuan' => 'Bentuk Bantuan pada baris pertama wajib diisi.',
|
||||
'bantuan.0.tahun' => 'Tahun pada baris pertama wajib diisi.',
|
||||
]],
|
||||
['sosial-konflik', ['konflik_kelompok' => 'Pernah, sudah selesai'], [
|
||||
'topik_konflik' => 'Jika Pernah, Soal Apa? wajib diisi jika pernah terjadi konflik internal.',
|
||||
]],
|
||||
]);
|
||||
|
||||
test('asset errors show together above the summary and beside both conditional dropdowns', function () {
|
||||
$group = ($this->kelompok)();
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi';
|
||||
$this->from($url)->put(route('kelompok-tani.aset-keuangan.update', $group->id), [
|
||||
'aset' => [['jenis_aset' => AsetKelompokTaniController::JENIS_ASET_BAKU[0], 'status_aset' => '1']],
|
||||
])->assertRedirect($url)->assertSessionHasErrors(['aset.0.status_pengelolaan_aset', 'aset.0.kondisi_aset']);
|
||||
$page = $this->get($url)->assertOk();
|
||||
foreach (['Status Pengelolaan wajib diisi jika aset dipilih Ada.', 'Kondisi wajib diisi jika aset dipilih Ada.'] as $message) {
|
||||
expect(substr_count($page->getContent(), $message))->toBeGreaterThanOrEqual(2);
|
||||
}
|
||||
expect($group->aset()->count())->toBe(0);
|
||||
});
|
||||
|
||||
test('profile location choices survive a failed save on both create and edit', function (bool $creating) {
|
||||
$group = ($this->kelompok)();
|
||||
$url = $creating ? route('kelompok-tani.create') : route('kelompok-tani.edit', $group->id);
|
||||
$input = ['provinsi_id' => 1, 'kabupaten_id' => 1, 'kecamatan_id' => 1, 'desa_kelurahan_id' => 1, 'jenis_kelompok' => 'Kelompok Tani (Poktan)'];
|
||||
$response = $creating
|
||||
? $this->from($url)->post(route('kelompok-tani.store'), $input)
|
||||
: $this->from($url)->put(route('kelompok-tani.update', $group->id), $input);
|
||||
$response->assertRedirect($url)->assertSessionHasErrors(['nama_responden', 'nama_kelompok']);
|
||||
$page = $this->get($url)->assertOk();
|
||||
$dom = new DOMDocument();
|
||||
libxml_use_internal_errors(true);
|
||||
$dom->loadHTML($page->getContent());
|
||||
libxml_clear_errors();
|
||||
$xpath = new DOMXPath($dom);
|
||||
foreach (array_keys($input) as $field) {
|
||||
expect($xpath->query('//select[@name="' . $field . '"]/option[@selected]')->length)->toBe(1);
|
||||
}
|
||||
expect($xpath->query('//select[@name="desa_kelurahan_id" and @disabled]')->length)->toBe(0);
|
||||
})->with([true, false]);
|
||||
|
||||
test('invalid location input returns feedback without breaking the form reload', function ($invalidId) {
|
||||
$url = route('kelompok-tani.create');
|
||||
$this->from($url)->post(route('kelompok-tani.store'), [
|
||||
'provinsi_id' => $invalidId, 'kabupaten_id' => $invalidId, 'kecamatan_id' => $invalidId, 'desa_kelurahan_id' => $invalidId,
|
||||
])->assertRedirect($url)->assertSessionHasErrors(['provinsi_id', 'kabupaten_id', 'kecamatan_id', 'desa_kelurahan_id']);
|
||||
$this->get($url)->assertOk()->assertSee('Pilihan Provinsi tidak valid.');
|
||||
})->with([[['invalid']], ['1.5'], ['invalid']]);
|
||||
|
||||
test('aid experience and program entries are saved together in Operasional', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => false]);
|
||||
$response = app(SurveyKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'section' => 'status-bantuan', 'pernah_mendapatkan_bantuan' => '1',
|
||||
'bantuan' => [
|
||||
['nama_program' => 'Bibit Kakao', 'penyelenggara' => 'Dinas Pertanian', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026],
|
||||
['nama_program' => '', 'penyelenggara' => '', 'bentuk_bantuan' => '', 'tahun' => null],
|
||||
],
|
||||
]), $group);
|
||||
expect($group->refresh()->pernah_mendapatkan_bantuan)->toBeTrue();
|
||||
expect($group->bantuan()->pluck('nama_program')->all())->toBe(['Bibit Kakao']);
|
||||
expect($response->getTargetUrl())->toBe(route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi#section-status-bantuan');
|
||||
expect(session('success'))->toBe('Data Operasional berhasil disimpan.');
|
||||
});
|
||||
|
||||
test('answering Belum Pernah ignores hidden program payloads and preserves existing history', function ($payload) {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => true]);
|
||||
$group->bantuan()->create([
|
||||
'uid' => 'BKT-TEST', 'nama_program' => 'Program Lama', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit',
|
||||
]);
|
||||
app(SurveyKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'section' => 'status-bantuan', 'pernah_mendapatkan_bantuan' => '0', 'bantuan' => $payload,
|
||||
]), $group);
|
||||
expect($group->refresh()->pernah_mendapatkan_bantuan)->toBeFalse();
|
||||
expect($group->bantuan()->pluck('nama_program')->all())->toBe(['Program Lama']);
|
||||
})->with([
|
||||
['malformed'],
|
||||
[[['nama_program' => ['invalid'], 'tahun' => 'invalid']]],
|
||||
]);
|
||||
|
||||
test('invalid aid entries cannot partially update the experience answer', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => false]);
|
||||
$request = ($this->profileRequest)([
|
||||
'section' => 'status-bantuan', 'pernah_mendapatkan_bantuan' => '1',
|
||||
'bantuan' => [['nama_program' => 'Program A', 'tahun' => date('Y') + 1]],
|
||||
]);
|
||||
expect(fn () => app(SurveyKelompokTaniController::class)->update($request, $group))->toThrow(ValidationException::class);
|
||||
expect($group->refresh()->pernah_mendapatkan_bantuan)->toBeFalse();
|
||||
expect($group->bantuan()->count())->toBe(0);
|
||||
});
|
||||
|
||||
test('aid creation failures roll back the experience answer', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => false]);
|
||||
Event::listen('eloquent.creating: ' . BantuanKelompokTani::class, function () {
|
||||
throw new RuntimeException('Simulated aid failure');
|
||||
});
|
||||
$request = ($this->profileRequest)([
|
||||
'section' => 'status-bantuan', 'pernah_mendapatkan_bantuan' => '1',
|
||||
'bantuan' => [['nama_program' => 'Program A', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026]],
|
||||
]);
|
||||
expect(fn () => app(SurveyKelompokTaniController::class)->update($request, $group))->toThrow(RuntimeException::class);
|
||||
expect($group->refresh()->pernah_mendapatkan_bantuan)->toBeFalse();
|
||||
expect($group->bantuan()->count())->toBe(0);
|
||||
});
|
||||
|
||||
test('aid list shares the experience box and is only visible for Pernah', function (?bool $savedAnswer, ?string $oldAnswer, bool $visible) {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => $savedAnswer]);
|
||||
$request = ($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET');
|
||||
if ($oldAnswer !== null) {
|
||||
session()->flashInput([
|
||||
'pernah_mendapatkan_bantuan' => $oldAnswer,
|
||||
'bantuan' => [['nama_program' => 'Program belum disimpan', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026]],
|
||||
]);
|
||||
}
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit($request, $group));
|
||||
expect($dom->query('//form[@id="pengalaman-bantuan-form"]//div[@id="section-bantuan"]')->length)->toBe(1);
|
||||
expect($dom->query('//div[@id="section-bantuan"]')->item(0)->hasAttribute('hidden'))->toBe(!$visible);
|
||||
expect($dom->query('//fieldset[@id="bantuan-fields"]')->item(0)->hasAttribute('disabled'))->toBe(!$visible);
|
||||
expect($dom->query('//form[@id="pengalaman-bantuan-form"]//button[contains(@class,"btn-success")]')->length)->toBe(1);
|
||||
expect($dom->query('//form[@id="pengalaman-bantuan-form"]//form')->length)->toBe(0);
|
||||
expect($dom->query('//div[@id="section-penilaian"] | //input[@name="potensi_kelompok"] | //textarea[@name="alasan_penilaian_potensi"]')->length)->toBe(0);
|
||||
if ($oldAnswer !== null) {
|
||||
expect($dom->query('//form[@id="pengalaman-bantuan-form"]//input[@value="Program belum disimpan"]')->length)->toBe(1);
|
||||
}
|
||||
})->with([
|
||||
[null, null, false], [false, null, false], [true, null, true], [true, '0', false], [false, '1', true],
|
||||
]);
|
||||
|
||||
test('old aid URLs redirect to Operasional and removed assessment fields cannot be saved', function () {
|
||||
$group = ($this->kelompok)(['potensi_kelompok' => 'Rendah']);
|
||||
$url = route('kelompok-tani.edit', $group->id) . '?section=aktivitas-fungsi#section-status-bantuan';
|
||||
expect(app(BantuanKelompokTaniController::class)->index($group)->getTargetUrl())->toBe($url);
|
||||
$response = app(SurveyKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'section' => 'penilaian', 'potensi_kelompok' => 'Tinggi', 'alasan_penilaian_potensi' => 'Diabaikan',
|
||||
]), $group);
|
||||
expect($response->getTargetUrl())->toBe($url);
|
||||
expect($group->refresh()->potensi_kelompok)->toBe('Rendah');
|
||||
});
|
||||
|
||||
test('Pernah requires every first-row aid field before saving', function (string $missing) {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => false]);
|
||||
$row = ['nama_program' => 'Program A', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026];
|
||||
$row[$missing] = ' ';
|
||||
$request = ($this->profileRequest)(['pernah_mendapatkan_bantuan' => '1', 'bantuan' => [$row]]);
|
||||
try {
|
||||
app(BantuanKelompokTaniController::class)->update($request, $group);
|
||||
$this->fail('An incomplete first row must be rejected.');
|
||||
} catch (ValidationException $exception) {
|
||||
expect($exception->errors())->toHaveKey('bantuan.0.' . $missing);
|
||||
}
|
||||
expect($group->refresh()->pernah_mendapatkan_bantuan)->toBeFalse();
|
||||
expect($group->bantuan()->count())->toBe(0);
|
||||
})->with(['nama_program', 'penyelenggara', 'bentuk_bantuan', 'tahun']);
|
||||
|
||||
test('Pernah rejects missing first aid rows including attempts to skip the first index', function ($rows) {
|
||||
$group = ($this->kelompok)();
|
||||
$request = ($this->profileRequest)(['pernah_mendapatkan_bantuan' => '1', 'bantuan' => $rows]);
|
||||
expect(fn () => app(BantuanKelompokTaniController::class)->update($request, $group))->toThrow(ValidationException::class);
|
||||
expect($group->bantuan()->count())->toBe(0);
|
||||
})->with([
|
||||
[null], [[]], [[[]]],
|
||||
[[1 => ['nama_program' => 'Program A', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit', 'tahun' => 2026]]],
|
||||
]);
|
||||
|
||||
test('recorded aid meets the minimum without requiring a duplicate entry', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => true]);
|
||||
$group->bantuan()->create(['uid' => 'BKT-EXISTING', 'nama_program' => 'Program Lama', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit']);
|
||||
app(BantuanKelompokTaniController::class)->update(($this->profileRequest)(['pernah_mendapatkan_bantuan' => '1']), $group);
|
||||
expect($group->bantuan()->count())->toBe(1);
|
||||
|
||||
app(BantuanKelompokTaniController::class)->update(($this->profileRequest)([
|
||||
'pernah_mendapatkan_bantuan' => '1', 'bantuan' => [['nama_program' => 'Program Tambahan'], []],
|
||||
]), $group);
|
||||
expect($group->bantuan()->count())->toBe(2);
|
||||
});
|
||||
|
||||
test('an optional aid row with details still needs a program name', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => true]);
|
||||
$group->bantuan()->create(['uid' => 'BKT-EXISTING', 'nama_program' => 'Program Lama', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit']);
|
||||
$request = ($this->profileRequest)(['pernah_mendapatkan_bantuan' => '1', 'bantuan' => [['penyelenggara' => 'Dinas']]]);
|
||||
expect(fn () => app(BantuanKelompokTaniController::class)->update($request, $group))->toThrow(ValidationException::class);
|
||||
expect($group->bantuan()->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('required aid markers only apply to the first unsaved row for Pernah', function (bool $pernah, bool $saved) {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => $pernah]);
|
||||
if ($saved) {
|
||||
$group->bantuan()->create(['uid' => 'BKT-EXISTING', 'nama_program' => 'Program Lama', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit']);
|
||||
}
|
||||
$request = ($this->profileRequest)(['section' => 'aktivitas-fungsi'], 'GET');
|
||||
session()->flashInput(['bantuan' => [[], []]]);
|
||||
$dom = ($this->profileDom)(app(SurveyKelompokTaniController::class)->edit($request, $group));
|
||||
$expected = $pernah && !$saved ? 4 : 0;
|
||||
expect($dom->query('//fieldset[@id="bantuan-fields"]//input[@required]')->length)->toBe($expected);
|
||||
expect($dom->query('//fieldset[@id="bantuan-fields"]//span[contains(@class,"bantuan-required-mark") and not(@hidden)]')->length)->toBe($expected);
|
||||
expect($dom->query('//div[@data-repeater-list="bantuan"]/div[2]//input[@required]')->length)->toBe(0);
|
||||
expect($dom->query('//div[@id="section-bantuan"]/p[normalize-space()="Minimal satu data bantuan wajib diisi."]')->length)->toBe(1);
|
||||
$firstRow = $saved
|
||||
? '//div[@id="section-bantuan"]/div[1]'
|
||||
: '//div[@data-repeater-list="bantuan"]/div[1]';
|
||||
foreach (['Nama Program/Bantuan', 'Penyelenggara', 'Bentuk Bantuan', 'Tahun'] as $label) {
|
||||
$marks = $dom->query($firstRow . '//label[starts-with(normalize-space(),"' . $label . '")]/span[contains(@class,"text-danger") and not(@hidden)]');
|
||||
expect($marks->length)->toBe($saved || $pernah ? 1 : 0);
|
||||
}
|
||||
})->with([[true, false], [false, false], [true, true]]);
|
||||
|
||||
test('conflict topics are required for both Pernah answers without partial saves', function (string $answer, $topic) {
|
||||
$group = ($this->kelompok)(['konflik_kelompok' => 'Tidak pernah', 'partisipasi_perempuan' => 'Hadir tapi pasif']);
|
||||
$request = ($this->profileRequest)([
|
||||
'section' => 'sosial-konflik', 'konflik_kelompok' => $answer,
|
||||
'topik_konflik' => $topic, 'partisipasi_perempuan' => 'Tidak terlibat',
|
||||
]);
|
||||
try {
|
||||
app(SurveyKelompokTaniController::class)->update($request, $group);
|
||||
$this->fail('A conflict topic is required.');
|
||||
} catch (ValidationException $exception) {
|
||||
expect($exception->errors())->toHaveKey('topik_konflik');
|
||||
}
|
||||
expect($group->refresh()->konflik_kelompok)->toBe('Tidak pernah');
|
||||
expect($group->partisipasi_perempuan)->toBe('Hadir tapi pasif');
|
||||
})->with(['Pernah, sudah selesai', 'Pernah, masih berlanjut/belum selesai'])->with([null, '', ' ']);
|
||||
|
||||
test('social saves accept conflict topics and require none for other answers', function ($answer, bool $required) {
|
||||
$group = ($this->kelompok)();
|
||||
$request = ($this->profileRequest)([
|
||||
'section' => 'sosial-konflik', 'konflik_kelompok' => $answer,
|
||||
...($required ? ['topik_konflik' => 'Pembagian hasil'] : []),
|
||||
]);
|
||||
app(SurveyKelompokTaniController::class)->update($request, $group);
|
||||
expect($group->refresh()->topik_konflik)->toBe($required ? 'Pembagian hasil' : null);
|
||||
expect(session('success'))->toBe('Data Sosial berhasil disimpan.');
|
||||
|
||||
($this->profileRequest)(['section' => 'sosial-konflik'], 'GET');
|
||||
$dom = ($this->profileDom)(view('produktivitas.survey-kelompok-tani.sosial-konflik', ['kelompokTani' => $group]));
|
||||
$input = $dom->query('//input[@id="sk-topik-konflik"]')->item(0);
|
||||
expect($input->hasAttribute('required'))->toBe($required);
|
||||
expect($input->hasAttribute('disabled'))->toBe(!$required);
|
||||
expect($dom->query('//label[@for="sk-topik-konflik"]/span[not(@hidden)]')->length)->toBe($required ? 1 : 0);
|
||||
})->with([
|
||||
['Pernah, sudah selesai', true], ['Pernah, masih berlanjut/belum selesai', true],
|
||||
['Tidak pernah', false], ['Tidak bersedia menjawab', false], [null, false],
|
||||
]);
|
||||
|
||||
test('conflict topic requirements and input follow the previous submission after validation', function () {
|
||||
$group = ($this->kelompok)(['konflik_kelompok' => 'Tidak pernah']);
|
||||
($this->profileRequest)([], 'GET');
|
||||
session()->flashInput(['konflik_kelompok' => 'Pernah, sudah selesai', 'topik_konflik' => 'Pembagian hasil']);
|
||||
$dom = ($this->profileDom)(view('produktivitas.survey-kelompok-tani.sosial-konflik', ['kelompokTani' => $group]));
|
||||
$input = $dom->query('//input[@id="sk-topik-konflik"]')->item(0);
|
||||
expect($input->hasAttribute('required'))->toBeTrue();
|
||||
expect($input->getAttribute('value'))->toBe('Pembagian hasil');
|
||||
expect($dom->query('//div[@id="sk-detail-konflik-wrapper"]')->item(0)->hasAttribute('style'))->toBeFalse();
|
||||
});
|
||||
|
||||
test('the last recorded aid cannot be deleted while the answer remains Pernah', function () {
|
||||
$group = ($this->kelompok)(['pernah_mendapatkan_bantuan' => true]);
|
||||
$aid = $group->bantuan()->create(['uid' => 'BKT-EXISTING', 'nama_program' => 'Program Lama', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit']);
|
||||
$controller = app(BantuanKelompokTaniController::class);
|
||||
$response = $controller->destroy($group, $aid);
|
||||
expect($response->getTargetUrl())->toEndWith('#kelompok-tani-notifications');
|
||||
expect($group->bantuan()->count())->toBe(1);
|
||||
$other = $group->bantuan()->create(['uid' => 'BKT-OTHER', 'nama_program' => 'Program Lain', 'penyelenggara' => 'Dinas', 'bentuk_bantuan' => 'Bibit']);
|
||||
$controller->destroy($group, $aid);
|
||||
expect($group->bantuan()->count())->toBe(1);
|
||||
$group->update(['pernah_mendapatkan_bantuan' => false]);
|
||||
$controller->destroy($group, $other);
|
||||
expect($group->bantuan()->count())->toBe(0);
|
||||
});
|
||||
Reference in New Issue
Block a user