148 lines
7.4 KiB
PHP
148 lines
7.4 KiB
PHP
<?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']]],
|
|
]);
|