Skip to content

Feat: Consumer-Side Contract Tests for OpenSID#1681

Open
pandigresik wants to merge 14 commits into
rilis-devfrom
feat/consumer-opensid
Open

Feat: Consumer-Side Contract Tests for OpenSID#1681
pandigresik wants to merge 14 commits into
rilis-devfrom
feat/consumer-opensid

Conversation

@pandigresik

Copy link
Copy Markdown
Contributor

Pull Request: Consumer-Side Contract Tests for OpenSID Request Validation

Description

Menambahkan consumer-side contract tests yang memvalidasi request payload OpenSID terhadap OpenAPI spec OpenDK (openapi/openapi.yaml). Menggunakan justinrainbow/json-schema untuk validasi JSON Schema dari request body yang didefinisikan di spec. Jika spec berubah secara incompatible (misalnya field required dihapus atau tipe data berubah), CI akan gagal sehingga mencegah breaking changes pada integrasi OpenSID-OpenDK.

Changes made:

  1. Contract Test Suite: tests/Contract/OpenApiContractTest.php — Pest test berbasis dataset yang memvalidasi 11 contoh request payload (7 success + 4 validation error) terhadap schema dari OpenAPI spec.

  2. Contoh Payload OpenSID: 11 file JSON di tests/Contract/examples/ mencakup skenario auth (login success, missing email, missing password), penduduk (hapus success, missing desa_id), laporan APBDes, laporan penduduk, pesan (kirim success, missing pesan, getpesan), dan identitas desa.

  3. CI Workflow: .github/workflows/contract.yml — job ringan tanpa database yang menjalankan validasi OpenAPI spec dan contract tests pada setiap PR ke master/rilis-dev/dev.

  4. Perbaikan Spec APBDes & Laporan Penduduk: app/Http/Controllers/Api/LaporanApbdesController.php dan LaporanPendudukController.php — annotation @bodyParam diperbaiki dari array menjadi object[] dengan properti child yang detail, sehingga Scribe menghasilkan schema yang benar (array of object, bukan array of string).

  5. Composer & npm Scripts: composer.json dan package.json — ditambahkan script test:contract untuk menjalankan contract tests.

  6. Test Configuration: phpunit.xml.dist dan tests/Pest.php — registrasi test suite Contract dan grup contract.

  7. Dokumentasi: docs/integration-testing.md — section 5 diperbarui dengan panduan lengkap menjalankan contract tests lokal, struktur direktori, CI pipeline, dan cara menambah contoh payload baru.

Reason for change:

  • Poin 1: Belum ada mekanisme otomatis untuk memvalidasi apakah request yang dikirim OpenSID sesuai dengan kontrak API yang diharapkan OpenDK
  • Poin 2: Perubahan di sisi OpenDK (provider) bisa merusak integrasi tanpa terdeteksi hingga runtime
  • Poin 3: Contract tests memberikan safety net agar breaking changes terdeteksi di CI, bukan di produksi

Impact of change:

Deteksi dini breaking changes: Jika OpenDK mengubah schema request (misalnya menambah field required, mengubah tipe data), contract tests gagal di CI
Source of truth ganda: OpenAPI spec sebagai kontrak + contoh payload sebagai konsumen — keduanya harus sinkron
CI ringan: Contract tests tidak perlu database, selesai < 1 detik
Onboarding lebih mudah: Developer OpenSID cukup lihat contoh payload JSON untuk memahami format request yang benar

Related Issue

#1673

Steps to Reproduce

Before (problem):

  1. OpenDK mengubah struktur request body endpoint integrasi
  2. Tidak ada validasi otomatis — perubahan tidak terdeteksi
  3. OpenSID mengirim request dengan format lama
  4. ❌ Runtime error atau data tidak tersimpan dengan benar

After (solution):

  1. Jalankan composer generate-openapi untuk regenerate spec dari kode
  2. Jalankan composer test:contract untuk validasi contoh payload
  3. CI menjalankan langkah yang sama setiap PR
  4. ✅ Jika spec berubah incompatible, build langsung gagal dengan pesan error detail

Testing on related features:

  • Contract tests ✅ 11/11 passed (22 assertions)
  • OpenAPI spec validation ✅ Valid YAML, 21 paths
  • CI workflow ✅ .github/workflows/contract.yml siap dijalankan

Checklist

  • I have complied with script writing rules
  • I have followed pull request review process
  • I have created [unit test/integration test] to verify the fix
  • Manual testing has been done in development environment
  • No console errors or warnings
  • Code has been reviewed by [at least 1 person]

Technical Details

Technical Explanation

Arsitektur Contract Tests:

tests/Contract/
├── OpenApiContractTest.php    # Pest test
└── examples/
    ├── auth/                  # 3 payload (1 success, 2 error)
    ├── penduduk/              # 2 payload (1 success, 1 error)
    ├── laporan-apbdes/        # 1 payload (success)
    ├── laporan-penduduk/      # 1 payload (success)
    ├── pesan/                 # 3 payload (2 success, 1 error)
    └── identitas-desa/        # 1 payload (success)

Alur validasi:

  1. Pest dataset('contract_examples') membaca openapi/openapi.yaml dan semua file JSON contoh
  2. Untuk setiap contoh, fungsi getRequestSchema() mengekstrak schema JSON dari paths[path][method].requestBody.content.application/json.schema
  3. JsonSchema\Validator::validate() memvalidasi payload terhadap schema dengan mode CHECK_MODE_NORMAL
  4. Test should_succeed: true → assert isValid() === true; should_succeed: false → assert isValid() === false

Scribe Annotation Fix:
Sebelumnya @bodyParam laporan_apbdes array menghasilkan items: type: string di spec. Diperbaiki menjadi @bodyParam laporan_apbdes object[] dengan child fields menggunakan dot notation, sehingga Scribe menghasilkan items: type: object dengan properti yang benar.

Configuration changes

  • composer.json — tambah dev dependency justinrainbow/json-schema dan script test:contract
  • phpunit.xml.dist — tambah test suite Contract
  • package.json — tambah script test:contract

Dependencies added

  • justinrainbow/json-schema: ^6.10 — JSON Schema validation library
  • marc-mabe/php-enum: ^4.4 — dependency dari justinrainbow/json-schema

Testing

Manual Testing

  • composer test:contract — 11 tests passed, 22 assertions
  • php bin/validate-openapi.php — OpenAPI spec valid (3.0.3, 21 paths)
  • Negative test cases (4 payloads) properly rejected
  • composer generate-openapi — spec regenerate sukses

Automated Testing

  • Contract Tests — 11 test cases (data-driven)
  • CI Workflow — .github/workflows/contract.yml (tanpa database)

Screenshots / Video

Test Output:

PASS  Tests\Contract\OpenApiContractTest
✓ request payload matches OpenAPI spec: Auth login success
✓ request payload matches OpenAPI spec: Auth login missing password
✓ request payload matches OpenAPI spec: Auth login missing email
✓ request payload matches OpenAPI spec: Penduduk hapus success
✓ request payload matches OpenAPI spec: Penduduk hapus missing desa_id
✓ request payload matches OpenAPI spec: Laporan APBDes sync success
✓ request payload matches OpenAPI spec: Laporan Penduduk sync success
✓ request payload matches OpenAPI spec: Pesan kirim success
✓ request payload matches OpenAPI spec: Pesan kirim missing pesan
✓ request payload matches OpenAPI spec: Pesan getpesan success
✓ request payload matches OpenAPI spec: Identitas desa sync success

Tests:  11 passed (22 assertions)
Duration: 0.38s

Breaking Changes

None — semua perubahan bersifat additive (menambah test suite, memperbaiki completeness spec).

Migration Guide

Not required.

References

- Update config/scribe.php with proper auth, routes, and OpenAPI config
- Add artisan command scribe:copy-openapi to copy spec to repo root
- Add composer scripts: generate-openapi, validate-openapi
- Add openapi.yaml (initial generated spec with 54 endpoints)
- Add CI workflow: openapi.yml (generate & validate on PR/push)
- Update test.yml to also copy & validate OpenAPI spec
- Add docs/integration-testing.md with local dev instructions
- Add SCRIBE_AUTH_KEY to .env.example
- Fix CekDesa rule: lazy-load DB query in message() instead of constructor
- Add missing test() method to PendudukController
- Regenerate openapi.yaml (now 61 paths, covering all api.php routes)
- Remove outdated note about missing endpoints from docs
- Add @group and @bodyParam/response annotations to all api/v1 controllers
- Add meaningful summaries to frontend API controllers
- Fix AuthController login with proper Scribe annotations
- Regenerate openapi.yaml with all 61 paths properly described
- Each OpenSID submission endpoint now has documented body params & response
- Remove api/frontend/* from scribe route prefixes
- Regenerate spec: 21 paths, focused on OpenSID endpoints only
- Add detailed ZIP column contracts to controller docblocks
- Separate JSON vs ZIP endpoints with proper @bodyParam types
- Add ZIP contract validation table to docs/integration-testing.md
- Add sample ZIP generator script and Pest contract test example
- Each file upload endpoint now documents expected internal file format
- Add Pest-based contract tests validating 11 request payloads vs OpenAPI spec
- Create example JSON payloads for auth, penduduk, laporan, pesan, identitas-desa
- Add contract.yml CI workflow (no DB needed, runs on PR to master/dev)
- Fix laporan_apbdes & laporan_penduduk controller annotations for proper object[] schema
- Add composer test:contract and npm run test:contract scripts
- Document running contract tests locally in docs/integration-testing.md

Issue: #1673
@pandigresik
pandigresik requested a review from vickyrolanda July 20, 2026 06:36
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI PR Review sedang antri di server...

Proses review akan segera dimulai di background — hasil akan muncul sebagai komentar setelah selesai.
Powered by CrewAI · PR #1681

@pandigresik pandigresik changed the title Feat/consumer opensid Feat: Consumer-Side Contract Tests for OpenSID Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant