Files
web-antrean/docs/QMD.md
T

18 KiB

QMD — Quality Management Document

Project: Web Antrean — Sistem Manajemen Antrean Rawat Jalan RSSA Version: 1.0.0 Author: Akbar Stack: JavaScript · Vue 3 · TypeScript · Nuxt 3 · Vuetify 3 · Pinia Last Updated: 2026-05-25


🧠 AI Prompt — Cara Menggunakan Dokumen Ini

Salin prompt berikut ke Claude untuk membantu QA planning:

Kamu adalah QA engineer senior untuk project Nuxt 3 + Vue 3 + TypeScript.
Project: Web Antrean — Sistem manajemen antrean rawat jalan RSSA.

Fitur utama:
- Anjungan mandiri (kiosk registrasi pasien, pilih klinik/subspesialis)
- Check-in pasien via QR code
- Manajemen antrean loket (panggil, skip, recall, selesai)
- Manajemen antrean klinik & penunjang
- Real-time sync via WebSocket + polling fallback
- Dashboard monitoring & statistik
- Setting: master data (klinik, loket, penunjang, screen), hak akses (Keycloak role/group)
- Cetak tiket via thermal printer

Bantu aku membuat:
1. Test plan lengkap (unit, integration, E2E)
2. Test cases untuk fitur di atas
3. Definition of Done (DoD) per story
4. Checklist code review untuk Vue 3 + TypeScript
5. Standar kualitas kode (naming, linting, typing)

Format dalam tabel Markdown. Tool: Vitest, Cypress, Vue Test Utils, happy-dom.

1. Quality Objectives

Objektif Target Cara Ukur
Test Coverage (Unit) > 60% Vitest coverage report (npx vitest run --coverage)
Bug Rate (prod) < 5 bug/sprint Manual tracking / issue log
Code Review 100% PR di-review Git workflow
TypeScript strict Minimal any type ESLint + tsc --noEmit
WebSocket Reliability > 99% message delivery Monitoring log + polling fallback
Page Load < 3 detik Lighthouse / manual timing di jaringan LAN

2. Testing Strategy

2.1 Piramida Testing

        ▲
       /E2E\         ← Cypress (browser real)
      /──────\
     / Integ  \      ← Vitest + Nuxt Test Utils
    /──────────\
   /  Unit Test \    ← Vitest + Vue Test Utils + happy-dom
  /______________\

2.2 Test Toolchain

Tipe Tool Config File Status
Unit Vitest + happy-dom vitest.config.ts Terkonfigurasi
Component Vue Test Utils (@vue/test-utils) Terinstal
E2E Cypress cypress.config.ts Terkonfigurasi
Component (Cypress) Cypress Component Testing cypress.config.tscomponent Terkonfigurasi
Linting ESLint (Nuxt preset) eslint.config.mjs Terkonfigurasi
Type Check TypeScript (via Nuxt) tsconfig.json → extends .nuxt/tsconfig.json
Test Environment happy-dom vitest.config.tsenvironment: 'happy-dom'

2.3 Test Commands

# Unit & Component Tests
npm run test              # vitest (watch mode)
npm run test:ui           # vitest --ui (browser UI)

# E2E Tests
npm run cypress:open      # Cypress interactive
npm run cypress:run       # Cypress headless

# Linting
npx eslint .

# Type Check
npx nuxi typecheck

3. Test Cases

3.1 Unit Tests — Composables

ID Modul Test Case Expected Status
UT-001 useAuth.ts Login — mengembalikan user data setelah Keycloak auth user.value tidak null, memiliki id, roles, groups Todo
UT-002 useAuth.ts Logout — session di-clear dan redirect ke login page user.value menjadi null, navigasi ke /LoginPage Todo
UT-003 useQueue.js processNextQueue() — mengambil pasien berikutnya sesuai loketId Return pasien dengan status menunggu dan loketId yang cocok Todo
UT-004 useQueue.js processNextQueue() — skip pasien dari loket lain Pasien dari loket lain tidak terproses Todo
UT-005 useWebSocket.ts Koneksi sukses — state connected isConnected.value === true setelah open event Todo
UT-006 useWebSocket.ts Auto-reconnect setelah disconnect Reconnect attempt dalam < 5 detik Todo
UT-007 useCheckIn.ts Check-in valid QR — update status pasien Status pasien berubah ke hadir, return success Todo
UT-008 useCheckIn.ts Check-in invalid QR — error handling Return error message, status tidak berubah Todo
UT-009 useQRScanner.ts Inisialisasi scanner — kamera aktif Scanner instance terbuat tanpa error Todo
UT-010 useHakAkses.ts Fetch permissions — mapping role ke menu Menu permissions sesuai dengan role & group user Todo
UT-011 useThermalPrint.ts Generate tiket — format nomor antrean benar Output mengandung kode klinik + nomor urut Todo
UT-012 useClinicAPI.ts Fetch daftar klinik — return data klinik aktif Array klinik tidak kosong, setiap item punya id & nama Todo

3.2 Unit Tests — Stores (Pinia)

ID Modul Test Case Expected Status
UT-013 queueStore.js allPatients — menyimpan & mengembalikan daftar pasien State allPatients terisi array setelah fetch Todo
UT-014 queueStore.js currentProcessingPatient — isolasi per loket Setiap loket punya key unik di persisted state Todo
UT-015 clinicStore.js Fetch daftar klinik dari API clinics terisi data dari klinik-api Todo
UT-016 doctorStore.js Blacklist endpoint gagal Endpoint yang 500 di-blacklist, tidak di-retry spam Todo
UT-017 loketStore.js State loket terisolasi antar loket Operasi di loket A tidak mempengaruhi loket B Todo
UT-018 masterStore.js CRUD master klinik Create, read, update, delete berjalan tanpa error Todo
UT-019 permissionStore.ts Load permission sesuai role Permission loaded dan accessible via getter Todo

3.3 Unit Tests — Middleware

ID Modul Test Case Expected Status
UT-020 auth.ts User belum login → redirect ke /LoginPage navigateTo('/LoginPage') dipanggil Todo
UT-021 auth.ts User sudah login → lanjut ke halaman tujuan Tidak ada redirect Todo
UT-022 guest.ts User sudah login akses /LoginPage → redirect ke /dashboard navigateTo('/dashboard') dipanggil Todo
UT-023 permissions.ts User tanpa akses ke halaman → redirect/block Akses ditolak, redirect ke halaman authorized Todo
UT-024 checkPageAccess.ts Validasi hak akses per halaman berdasarkan group Halaman hanya bisa diakses sesuai permission Todo

3.4 Component Tests

ID Komponen Skenario Expected Status
CT-001 PatientCard.vue Render data pasien lengkap Nama, noRM, nomor antrean, status, subspesialis tampil Todo
CT-002 PatientCard.vue Status badge warna sesuai status menunggu = kuning, dipanggil = biru, selesai = hijau Todo
CT-003 CurrentPatientCard.vue Tampilkan pasien yang sedang diproses Data pasien aktif tampil dengan aksi (selesai, skip) Todo
CT-004 QueueActionsCard.vue Tombol aksi antrean (panggil, skip, recall) Semua tombol render dan emit event yang benar Todo
CT-005 TabelPatientData.vue Render tabel daftar pasien Kolom: nama, noRM, antrean, status, aksi tampil benar Todo
CT-006 SideBar.vue Menu render sesuai hak akses user Menu yang tidak diizinkan tidak tampil Todo
CT-007 PageHeader.vue Render judul halaman dan breadcrumb Judul dan navigasi sesuai route aktif Todo
CT-008 AppSnackbar.vue Notifikasi muncul dan auto-dismiss Snackbar tampil 3 detik lalu hilang Todo
CT-009 SelectionDialog.vue Dialog pilihan dengan konfirmasi Pilihan terseleksi, emit event saat konfirmasi Todo
CT-010 ProfileMenu.vue Tampil info user dan tombol logout Nama user tampil, klik logout memanggil useAuth().logout() Todo

3.5 E2E Tests (Cypress)

ID Flow Steps Expected Status
E2E-001 Login 1. Buka / 2. Redirect ke /LoginPage 3. Klik login Keycloak 4. Isi credentials Redirect ke /dashboard, user session aktif Skeleton
E2E-002 Anjungan — Ambil Antrean 1. Buka /anjungan 2. Pilih klinik 3. Konfirmasi Nomor antrean di-generate, tiket tampil Todo
E2E-003 Anjungan Eksekutif — Pilih Subspesialis 1. Buka /anjungan 2. Pilih klinik eksekutif 3. Pilih subspesialis 4. Konfirmasi Antrean tercipta dengan subspesialis terpilih Todo
E2E-004 Check-in QR 1. Buka /check-in-pasien/check-in 2. Scan QR valid Status pasien update ke "hadir", notifikasi sukses Todo
E2E-005 Loket — Panggil Pasien 1. Login sebagai admin loket 2. Buka /admin-loket 3. Klik "Panggil Berikutnya" Pasien berikutnya tampil di current patient card Todo
E2E-006 Loket — Skip & Recall 1. Panggil pasien 2. Klik skip 3. Klik recall Pasien di-skip lalu bisa di-recall kembali Todo
E2E-007 Klinik — Lihat Daftar Pasien 1. Login sebagai admin klinik 2. Buka /admin-klinik Daftar pasien klinik tampil sesuai klinik user Todo
E2E-008 Dashboard — Statistik 1. Login sebagai superadmin 2. Buka /dashboard Chart statistik dan data antrean tampil Todo
E2E-009 Setting — CRUD Master Klinik 1. Buka /setting/master-klinik 2. Tambah klinik 3. Edit 4. Hapus Data klinik berhasil CRUD tanpa error Todo
E2E-010 Setting — Hak Akses 1. Buka /setting/hak-akses 2. Pilih role & group 3. Set permission 4. Simpan Hak akses tersimpan dan efektif Todo
E2E-011 WebSocket Sync 1. Buka admin loket di tab A 2. Buka display screen di tab B 3. Panggil pasien di tab A Tab B menampilkan nomor panggil dalam < 2 detik Todo
E2E-012 Auth Guard 1. Tanpa login, akses /dashboard Redirect ke /LoginPage Todo

4. Definition of Done (DoD)

Sebuah task/story dianggap Done jika:

  • Code sudah diimplementasi dan berjalan di dev server
  • Unit test ditulis untuk logic kritis (composable, store)
  • TypeScript: tidak ada error pada npx nuxi typecheck
  • ESLint: tidak ada error (npx eslint .)
  • Code review dilakukan minimal 1 orang
  • Tested manual di browser Chrome (target utama)
  • WebSocket sync diverifikasi antar device (jika fitur terkait real-time)
  • Responsive layout dicek untuk tablet (anjungan) dan desktop (admin)
  • Tidak ada console.log debugging yang tertinggal di production path
  • State antrean terisolasi per loket (jika fitur terkait loket)
  • Polling fallback 30 detik berfungsi sebagai safety net

5. Code Review Checklist

General

  • Logic mudah dibaca dan dipahami
  • Tidak ada dead code atau file .txt backup yang tersisa
  • Error handling ada di semua $fetch / useFetch call
  • Tidak ada hardcoded IP/URL (gunakan .env + runtimeConfig)
  • Tidak ada console.log di high-frequency path (WebSocket handler, polling loop)

Vue 3 + TypeScript

  • <script setup> digunakan (Composition API)
  • Props & emits memiliki type yang jelas
  • Minimal penggunaan any type (justified jika ada)
  • Composables dipakai untuk logic reusable (composables/use*.ts)
  • Reactive data menggunakan ref() / reactive() dengan benar
  • watch / computed digunakan daripada manual mutation

Nuxt 3 Specific

  • Data fetching pakai $fetch / useFetch / useAsyncData
  • Middleware auth terpasang di route yang memerlukan login
  • Server routes (proxy) mengikuti konvensi server/routes/[prefix]/[...].ts
  • Internal API mengikuti konvensi server/api/[resource].[method].ts
  • Environment variables diakses via useRuntimeConfig()

Pinia Store

  • Store menggunakan defineStore() dengan naming use[Name]Store
  • State yang perlu persisten menggunakan pinia-plugin-persistedstate
  • Key persisted state unik per loket/klinik (hindari konflik antar instance)
  • allPatients tetap single source of truth (tidak duplikasi state)

WebSocket

  • Client ID deterministic (bukan random) untuk targetable messaging
  • Auto-reconnect logic aktif
  • Polling fallback 30 detik sebagai safety net
  • Event handler tidak melakukan full re-render (surgical update)

6. Standar Kode

Naming Convention

Tipe Konvensi Contoh (Aktual)
Page (Vue) PascalCase Dashboard.vue, AdminLoket.vue
Component PascalCase PatientCard.vue, QueueActionsCard.vue
Composable camelCase + use prefix useWebSocket.ts, useQueue.js
Store (Pinia) camelCase + Store suffix queueStore.js, clinicStore.js
Middleware camelCase auth.ts, permissions.ts
Type/Interface PascalCase User, Permission, ApiResponse<T>
Constants SCREAMING_SNAKE API_BASE_URL, WS_API_URL
CSS Class kebab-case .patient-card, .queue-actions
Server API [resource].[method].ts permission.get.ts, validate-token.post.ts
Server Proxy Route [...].ts di folder prefix server/routes/visit-api/[...].ts

File Organization Rules

# ✅ Good — composable terpisah untuk concern berbeda
composables/
  useAuth.ts          ← Authentication logic
  useWebSocket.ts     ← WebSocket connection management
  useQueue.js         ← Queue business logic
  useCheckIn.ts       ← Check-in flow
  useThermalPrint.ts  ← Thermal printer integration

# ✅ Good — komponen terorganisir per fitur
components/
  common/             ← Reusable (AppSnackbar, Avatar, PageHeader)
  layout/             ← Layout (SideBar, ProfileMenu)
  features/
    queue/            ← PatientCard, CurrentPatientCard, QueueActionsCard
    antrean/          ← Komponen anjungan
    master/           ← Komponen setting master data
    monitoring/       ← Komponen monitoring pasien

# ❌ Bad — logic besar langsung di <script setup> page
pages/AdminLoket.vue  ← Jangan taruh >100 baris logic di sini, extract ke composable

Code Pattern — Composable

// ✅ Good — typed composable dengan error handling
export function useClinicAPI() {
  const config = useRuntimeConfig()

  async function fetchClinics(): Promise<Clinic[]> {
    try {
      const data = await $fetch('/klinik-api/clinics')
      return data
    } catch (error) {
      console.error('Failed to fetch clinics:', error)
      return []
    }
  }

  return { fetchClinics }
}

// ❌ Bad — untyped, no error handling
export function useClinicAPI() {
  async function fetchClinics() {
    const data = await $fetch('/klinik-api/clinics') // bisa crash
    return data
  }
  return { fetchClinics }
}

7. CI/CD Quality Gates

Catatan: CI/CD belum diimplementasi. Berikut rencana pipeline saat siap.

# GitHub Actions — quality checks (planned)
name: Quality Gate

on:
  push:
    branches: [main, dev]
  pull_request:
    branches: [main]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install Dependencies
        run: npm ci

      - name: Type Check
        run: npx nuxi typecheck

      - name: Lint
        run: npx eslint .

      - name: Unit Tests
        run: npx vitest run --coverage

      - name: Build
        run: npx nuxt build

Manual Quality Gate (Saat Ini)

Sebelum merge / deploy, lakukan checklist manual berikut:

  • npx nuxi typecheck — tidak ada error
  • npx eslint . — tidak ada error
  • npm run test — semua test pass
  • npm run build — build sukses tanpa error
  • Test manual di browser Chrome di jaringan LAN (http://10.10.150.175:3000)
  • Verifikasi WebSocket sync antara admin & display screen
  • Pastikan Docker build berhasil (docker compose build)

8. Bug Severity Matrix

Level Deskripsi Contoh di Web Antrean SLA Fix
🔴 Critical App crash / data loss / security breach WebSocket down total → antrean tidak sync, Keycloak auth bypass, pasien kehilangan antrean < 4 jam
🟠 High Fitur utama tidak bisa dipakai Tombol panggil pasien tidak berfungsi, anjungan tidak bisa generate antrean, QR scanner error < 1 hari
🟡 Medium Fitur minor terganggu, ada workaround Thermal print gagal (pasien masih bisa lihat di layar), statistik dashboard delayed < 3 hari
🟢 Low UI/kosmetik, tidak mengganggu fungsi Alignment card tidak rapi, warna badge sedikit off, tooltip tidak muncul Backlog

Known Issues & Mitigasi

Issue Severity Mitigasi Saat Ini
WebSocket disconnect saat jaringan LAN tidak stabil 🔴 Auto-reconnect + polling fallback 30 detik
Endpoint 500 menyebabkan request spam 🟠 Blacklist endpoint gagal di doctorStore.js
console.log verbose di WebSocket handler 🟢 Dibersihkan di high-frequency path
Race condition antar loket 🟠 State isolasi per loketId + unique storage key
Mixed JS/TS — beberapa store masih .js 🟢 Migrasi bertahap ke .ts

9. Technical Debt Tracker

Item Impact Priority Plan
Store files masih .js (queueStore, clinicStore, dll) Type safety rendah 🟡 Medium Migrasi bertahap ke TypeScript
queueStore.js terlalu besar (141KB) Sulit maintain & test 🟠 High Pecah menjadi sub-stores per concern
Tidak ada test coverage saat ini Regresi tidak terdeteksi 🟠 High Mulai dari composable kritis
CI/CD belum ada Manual quality gate 🟡 Medium Setup GitHub Actions
Beberapa file backup (.txt, old_*.vue) masih ada Noise di codebase 🟢 Low Cleanup & gitignore

10. Changelog

Versi Tanggal Author Perubahan
1.0.0 2026-05-25 Akbar Initial QMD — dibuat berdasarkan kondisi project aktual