diff --git a/.env.example b/.env.example index 937bbcb..f83102d 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,7 @@ JKN_VCLAIM_USER_KEY= JKN_ANTREAN_USER_KEY= JKN_APOTEK_USER_KEY= JKN_PCARE_USER_KEY= +JKN_PCARE_USER_PASS= JKN_ICARE_USER_KEY= JKN_REKAM_MEDIS_USER_KEY= JKN_APLICARES_USER_KEY= diff --git a/README.md b/README.md index 608fb73..62a7e8d 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,13 @@ interface Config { * @default process.env.JKN_PCARE_USER_KEY */ pcareUserKey: string; + + /** + * Username dan Password PCare dari BPJS + * + * @default process.env.JKN_PCARE_USER_PASS + */ + pcareUserPass: string; /** * User key i-Care dari BPJS diff --git a/src/fetcher.ts b/src/fetcher.ts index 1f6d416..acd7755 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -68,6 +68,14 @@ export interface Config { */ pcareUserKey: string; + /** + * User dan Password PCare dari BPJS + * contoh: username:password + * + * @default process.env.JKN_PCARE_USER_PASS + */ + pcareUserPass: string; + /** * User key i-Care dari BPJS * @@ -229,6 +237,7 @@ export class Fetcher { antreanUserKey: process.env.JKN_ANTREAN_USER_KEY ?? '', apotekUserKey: process.env.JKN_APOTEK_USER_KEY, pcareUserKey: process.env.JKN_PCARE_USER_KEY ?? '', + pcareUserPass: process.env.JKN_PCARE_USER_PASS ?? '', icareUserKey: process.env.JKN_ICARE_USER_KEY, rekamMedisUserKey: process.env.JKN_REKAM_MEDIS_USER_KEY, throw: false, @@ -287,15 +296,17 @@ export class Fetcher { const userKey = this.userKeyMap[type]; if (!userKey) throw new Error(`failed to get user key of type "${type}"`); - const { consId, consSecret } = this.config; + const { consId, consSecret, pcareUserPass } = this.config; const timestamp = Math.round(Date.now() / 1000); const message = `${consId}&${timestamp}`; const signature = createHmac('SHA256', consSecret).update(message).digest('base64'); + const pcareAuth = `Basic ${Buffer.from(`${pcareUserPass}:095`).toString('base64')}`; return { 'X-cons-id': consId, 'X-timestamp': String(timestamp), 'X-signature': encodeURI(signature), - user_key: userKey + user_key: userKey, + 'X-Authorization': pcareAuth }; } @@ -328,7 +339,10 @@ export class Fetcher { try { const url = new URL(baseUrl[this.config.mode] + path); const init: RequestInit = { method: option.method ?? 'GET' }; - const headers = { ...this.getDefaultHeaders(type), ...(option.headers ?? {}) }; + const headers = { + ...this.getDefaultHeaders(type), + ...(option.headers ?? {}) + }; init.headers = headers; if (option.data) { @@ -417,7 +431,7 @@ function parseHtml(html?: string) { /** @internal */ export function normalizePath(path: SendOption['path']) { - const [pathname, params] = typeof path == 'string' ? [path] : path; + const [pathname, params] = typeof path === 'string' ? [path] : path; if (!pathname.startsWith('/')) throw new Error(`Path must start with "/"`); if (!params) return pathname; diff --git a/src/index.ts b/src/index.ts index 227e4bc..50c4f1c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,7 +34,7 @@ export default class JKN extends Fetcher { } get pcare(): PCare { - return this.cache.get('pcare', PCare); + return PCare.getInstance(this.cache); } get antreanFktp(): AntreanFKTP { diff --git a/src/pcare/index.ts b/src/pcare/index.ts index 7b6b328..041434e 100644 --- a/src/pcare/index.ts +++ b/src/pcare/index.ts @@ -1,12 +1,50 @@ +import { CachedApi } from '../base.js'; import { SendOption } from '../fetcher.js'; import { PCareBaseApi } from './base.js'; +import { Kunjungan } from './kunjungan.js'; +import { Peserta } from './peserta.js'; +import { Referensi } from './referensi.js'; +import { Spesialis } from './spesialis.js'; type RequestOption = SendOption; +export class PCare { + private static instance: PCare | undefined; + + private constructor(private readonly cache: CachedApi) {} + + static getInstance(cache: CachedApi): PCare { + if (!this.instance) { + this.instance = new PCare(cache); + } + return this.instance; + } + + get referensi() { + return this.cache.get('pcare_referensi', Referensi); + } + + get peserta() { + return this.cache.get('pcare_peserta', Peserta); + } + + get kunjungan() { + return this.cache.get('pcare_kunjungan', Kunjungan); + } + + get spesialis() { + return this.cache.get('pcare_spesialis', Spesialis); + } + + get api() { + return this.cache.get('pcare_partial', PartialRequest); + } +} + /** * Implement base api directly since this is for partial support */ -export class PCare extends PCareBaseApi { +class PartialRequest extends PCareBaseApi { async request(option: RequestOption) { return this.send(option); } diff --git a/src/pcare/kunjungan.ts b/src/pcare/kunjungan.ts new file mode 100644 index 0000000..1f665fa --- /dev/null +++ b/src/pcare/kunjungan.ts @@ -0,0 +1,345 @@ +import { PCareBaseApi } from './base.js'; + +export class Kunjungan extends PCareBaseApi { + /** + * Get Data Rujukan + * @param params param { nomor = Nomor Rujukan } + */ + async rujukan(params: { + /** Nomor Rujukan */ + nomor: string; + }) { + return this.send({ + name: `${this.name} Data Rujukan`, + path: ['/kunjungan/rujukan/:nomor', params], + method: 'GET' + }); + } + + /** + * Get Data Riwayat Kunjungan + * @param params param { nomor = Nomor Rujukan } + */ + async riwayat(params: { + /** Nomor Kartu Peserta */ + nomor: string; + }) { + return this.send<{ count: number; list: RiwayatKunjunganResult[] }>({ + name: `${this.name} Data Riwayat Kunjungan`, + path: ['/kunjungan/peserta/:nomor', params], + method: 'GET' + }); + } + + /** + * Add Data Kunjungan + * @param data InputRujukanKhusus | InputRujukanSpesialis + */ + async insert(data: InputKunjunganKhusus | InputKunjunganSpesialis) { + return this.send<{ field: string; messaage: string }>({ + name: `${this.name} Add Data Kunjungan`, + path: '/kunjungan', + method: 'POST', + data: data + }); + } + + /** + * Edit Data Kunjungan + * @param data InputUpdateKunjungan + */ + async update(data: InputUpdateKunjungan) { + return this.send({ + name: `${this.name} Edit Data Kunjungan`, + path: '/kunjungan', + method: 'PUT', + data: data + }); + } + + /** + * Delete Data Kunjungan + * @param params {nomor = Nomor Kunjungan} + */ + async delete(params: { + /** Nomor Kunjungan */ + nomor: string; + }) { + return this.send({ + name: `${this.name} Delete Data Kunjungan`, + path: ['/kunjungan/:nomor', params], + method: 'DELETE' + }); + } +} + +interface RujukanResult { + noRujukan: string; + ppk: { + kdPPK: string; + nmPPK: string; + alamat: string | null; + kc: { + kdKC: string; + nmKC: string; + alamat: string | null; + telp: string | null; + fax: string | null; + dati: { + kdProp: string | null; + kdDati: string; + nmDati: string; + }; + kdKR: { + kdKR: string; + nmKR: string; + alamat: string | null; + telp: string | null; + fax: string | null; + }; + }; + }; + tglKunjungan: string; + poli: { + kdPoli: string; + nmPoli: string; + }; + nokaPst: string; + nmPst: string; + tglLahir: string; + pisa: string; + ketPisa: string; + sex: string; + diag1: { + kdDiag: string; + nmDiag: string; + }; + diag2: string | null; + diag3: string | null; + catatan: string; + dokter: { + kdDokter: string; + nmDokter: string; + }; + tacc: { + nmTacc: string | null; + alasanTacc: string | null; + }; + infoDenda: string; +} + +interface RiwayatKunjunganResult { + noKunjungan: string; + tglKunjungan: string; + providerPelayanan: { + kdProvider: string; + nmProvider: string; + }; + peserta: { + noKartu: string; + nama: string | null; + hubunganKeluarga: string; + sex: string | null; + tglLahir: string | null; + tglMulaiAktif: string | null; + tglAkhirBerlaku: string | null; + kdPpkPst: string | null; + kdPpkGigi: string | null; + jnsKelas: string | null; + jnsPeserta: string | null; + golDarah: string | null; + noHP: string | null; + noKTP: string | null; + asuransi: string | null; + }; + poli: { + kdPoli: string; + nmPoli: string; + poliSakit: boolean; + }; + progProlanis: { + kdProgram: string; + nmProgram: string; + }; + keluhan: string; + diagnosa1: { + kdDiag: string; + nmDiag: string; + nonSpesialis: boolean; + }; + diagnosa2: { + kdDiag: string | null; + nmDiag: string | null; + nonSpesialis: boolean; + }; + diagnosa3: { + kdDiag: string | null; + nmDiag: string | null; + nonSpesialis: boolean; + }; + kesadaran: { + kdSadar: string; + nmSadar: string; + }; + sistole: number; + diastole: number; + beratBadan: number; + tinggiBadan: number; + respRate: number; + heartRate: number; + catatan: string; + rujukBalik: number; + providerAsalRujuk: { + kdProvider: string; + nmProvider: string | null; + }; + providerRujukLanjut: { + kdProvider: string; + nmProvider: string; + }; + pemFisikLain: string; + dokter: { + kdDokter: string; + nmDokter: string; + }; + statusPulang: { + kdStatusPulang: string; + nmStatusPulang: string; + }; + tkp: { + kdTkp: string; + nmTkp: string; + }; + poliRujukInternal: { + kdPoli: string | null; + nmPoli: string | null; + poliSakit: boolean; + }; + poliRujukLanjut: { + kdPoli: string; + nmPoli: string; + poliSakit: boolean; + }; + tglPulang: string; +} + +interface InputKunjunganKhusus { + noKunjungan: string | null; + noKartu: string; + tglDaftar: string; + kdPoli: string | null; + keluhan: string; + kdSadar: string; + sistole: number; + diastole: number; + beratBadan: number; + tinggiBadan: number; + respRate: number; + heartRate: number; + lingkarPerut: number; + kdStatusPulang: string; + tglPulang: string; + kdDokter: string; + kdDiag1: string; + kdDiag2: string | null; + kdDiag3: string | null; + kdPoliRujukInternal: string | null; + rujukLanjut: { + tglEstRujuk: string; + kdppk: string; + }; + kdTacc: number; + alasanTacc: string | null; + anamnesa: string; + alergiMakan: string; + alergiUdara: string; + alergiObat: string; + kdPrognosa: string; + terapiObat: string; + terapiNonObat: string; + bmhp: string; + suhu: string; +} + +interface InputKunjunganSpesialis { + noKunjungan: string | null; + noKartu: string; + tglDaftar: string; + kdPoli: string; + keluhan: string; + kdSadar: string; + sistole: number; + diastole: number; + beratBadan: number; + tinggiBadan: number; + respRate: number; + heartRate: number; + lingkarPerut: number; + kdStatusPulang: string; + tglPulang: string; + kdDokter: string; + kdDiag1: string; + kdDiag2: string | null; + kdDiag3: string | null; + kdPoliRujukInternal: string | null; + rujukLanjut: { + kdppk: string; + tglEstRujuk: string; + }; + kdTacc: number; + alasanTacc: string | null; + anamnesa: string; + alergiMakan: string; + alergiUdara: string; + alergiObat: string; + kdPrognosa: string; + terapiObat: string; + terapiNonObat: string; + bmhp: string; + suhu: string; +} + +interface InputUpdateKunjungan { + noKunjungan: string; + noKartu: string; + keluhan: string; + kdSadar: string; + sistole: number; + diastole: number; + beratBadan: number; + tinggiBadan: number; + respRate: number; + heartRate: number; + lingkarPerut: number; + kdStatusPulang: string; + tglPulang: string; + kdDokter: string; + kdDiag1: string; + kdDiag2: string | null; + kdDiag3: string | null; + kdPoliRujukInternal: string | null; + rujukLanjut: { + tglEstRujuk: string; + kdppk: string; + subSpesialis: { + kdSubSpesialis1: string; + kdSarana: string | null; + } | null; + khusus: { + kdKhusus: string; + kdSubSpesialis: string | null; + catatan: string; + } | null; + }; + kdTacc: number; + alasanTacc: string; + anamnesa: string; + alergiMakan: string; + alergiUdara: string; + alergiObat: string; + kdPrognosa: string; + terapiObat: string; + terapiNonObat: string; + bmhp: string; + suhu: string; +} diff --git a/src/pcare/peserta.ts b/src/pcare/peserta.ts new file mode 100644 index 0000000..92ce95e --- /dev/null +++ b/src/pcare/peserta.ts @@ -0,0 +1,73 @@ +import { PCareBaseApi } from './base.js'; + +export class Peserta extends PCareBaseApi { + /** + * Pencarian data peserta berdasarkan nomor kartu + */ + async nomorKartu(params: { + /** nomor kartu JKN atau BPJS */ + nomor: string; + }) { + return this.send({ + name: this.name + 'No. Kartu BPJS', + path: ['/peserta/:nomor', params], + method: 'GET' + }); + } + + /** + * Pencarian data peserta berdasarkan Jenis Kartu + */ + async jenisKartu(params: { + /** jenis kartu [nomor induk kependudukan = nik, nomor kartu BPJS = noka]*/ + jenis: string; + /** nomor NIK/NOKA BPJS */ + nomor: string; + }) { + return this.send({ + name: this.name + 'Peserta by Jenis Kartu', + path: ['/peserta/:jenis/:nomor', params], + method: 'GET' + }); + } +} + +interface DataPeserta { + noKartu: string; + nama: string; + hubunganKeluarga: string; + sex: string; + tglLahir: string; + tglMulaiAktif: string; + tglAkhirBerlaku: string; + kdProviderPst: { + kdProvider: string; + nmProvider: string; + }; + kdProviderGigi: { + kdProvider: string | null; + nmProvider: string | null; + }; + jnsKelas: { + nama: string; + kode: string; + }; + jnsPeserta: { + nama: string; + kode: string; + }; + golDarah: string; + noHP: string; + noKTP: string; + pstProl: string; + pstPrb: string; + aktif: boolean; + ketAktif: string; + asuransi: { + kdAsuransi: string | null; + nmAsuransi: string | null; + noAsuransi: string | null; + cob: boolean; + }; + tunggakan: number; +} diff --git a/src/pcare/referensi.ts b/src/pcare/referensi.ts new file mode 100644 index 0000000..f3dda80 --- /dev/null +++ b/src/pcare/referensi.ts @@ -0,0 +1,193 @@ +import { PCareBaseApi } from './base.js'; + +export class Referensi extends PCareBaseApi { + /** + * Get Data Alergi + * @param params param {kode = [01 = Makanan, 02 = Udara, 03 = Obat]} + */ + async alergi(params: { + /** Kode Jenis Alergi [01 = Makanan, 02 = Udara, 03 = Obat] */ + kode: string; + }) { + return this.send<{ count: number; list: AlergiResult[] }>({ + name: `${this.name} Data Alergi`, + path: ['/alergi/jenis/:kode', params], + method: 'GET' + }); + } + + /** + * Get Data Diagnosa + * @param params param {kode, row, limit} + */ + async diagnosa(params: { + /** Kode atau nama diagnosa */ + kode: string; + + /** Row data awal yang akan ditampilkan */ + row: number; + + /** Limit jumlah data yang akan ditampilkan */ + limit: number; + }) { + return this.send<{ count: number; list: DiagnosaResult[] }>({ + name: `${this.name} Data Diagnosa`, + path: ['/diagnosa/:kode/:row/:limit', params], + method: 'GET' + }); + } + + /** + * Get Data Dokter + * @param params params{row,limit} + */ + async dokter(params: { + /** Row data awal yang akan ditampilkan */ + row: number; + + /** Limit jumlah data yang akan ditampilkan */ + limit: number; + }) { + return this.send<{ count: number; list: DokterResult[] }>({ + name: `${this.name} Data Dokter`, + path: ['/dokter/:row/:limit', params], + method: 'GET' + }); + } + + /** + * Get Data Kesadaran + */ + async kesadaran() { + return this.send<{ count: number; list: KesadaranResult[] }>({ + name: `${this.name} Data Kesadaran`, + path: '/kesadaran', + method: 'GET' + }); + } + + /** + * Get Data Poli FKTP + * @param params params{row, limit} + */ + async poli(params: { row: number; limit: number }) { + return this.send<{ count: number; list: PoliResult[] }>({ + name: `${this.name} Data Poli FKTP`, + path: ['/poli/fktp/:row/:limit', params], + method: 'GET' + }); + } + + /** + * Get Data Prognosa + */ + async prognosa() { + return this.send<{ count: number; list: PrognosaResult[] }>({ + name: `${this.name} Data Prognosa`, + path: '/prognosa', + method: 'GET' + }); + } + + /** + * Get Status Pulang + */ + async statuspulang(params: { + /** status rawat inap true or false */ + ranap: boolean; + }) { + return this.send<{ count: number; list: StatusPulangResult[] }>({ + name: `${this.name} Status Pulang`, + path: `/statuspulang/rawatInap/${params.ranap}`, + method: 'GET' + }); + } + + /** + * Get Data Provider Rayonisasi + * @param params params{row, limit} + */ + async provider(params: { + /** Row data awal yang akan ditampilkan */ + row: number; + + /** Limit jumlah data yang akan ditampilkan */ + limit: number; + }) { + return this.send<{ count: number; list: ProviderResult[] }>({ + name: `${this.name} Data Provider Rayonisasi`, + path: ['/provider/:row/:limit', params], + method: 'GET' + }); + } +} + +interface PoliResult { + /** kode poliklinik */ + kdPoli: string; + + /** nama polikinink */ + nmPoli: string; + + /** poli sakit */ + poliSakit: boolean; +} + +interface KesadaranResult { + /** kode sadar */ + kdSadar: string; + + /** nama sadar */ + nmSadar: string; +} + +interface DokterResult { + /** kode dokter */ + kdDokter: string; + + /** nama dokter */ + nmDokter: string; +} + +interface DiagnosaResult { + /** kode diagnosa */ + kdDiag: string; + + /** nama diagnonsa */ + nmDiag: string; + + /** non-spesialis */ + nonSpesialis: boolean; +} + +interface AlergiResult { + /** kode alergi */ + kdAlergi: string; + + /** nama alergi */ + nmAlergi: string; +} + +interface PrognosaResult { + /** kode prognosa */ + kdPrognosa: string; + + /** nama prognosa */ + nmPrognosa: string; +} + +interface StatusPulangResult { + /** kode status pulang */ + kdStatusPulang: string; + + /** nama status pulang */ + nmStatusPulang: string; +} + +interface ProviderResult { + /** kode provider */ + kdProvider: string; + + /** nama provider */ + nmProvider: string; +} diff --git a/src/pcare/spesialis.ts b/src/pcare/spesialis.ts new file mode 100644 index 0000000..b08fa5d --- /dev/null +++ b/src/pcare/spesialis.ts @@ -0,0 +1,123 @@ +import { PCareBaseApi } from './base.js'; + +export class Spesialis extends PCareBaseApi { + /** + * Get Data Referensi Spesialis + */ + async get() { + return this.send<{ count: number; list: SpesialisResult[] }>({ + name: `${this.name} Data Referensi Spesialis`, + path: '/spesialis', + method: 'GET' + }); + } + + /** + * Get Data Referensi Sub Spesialis + * @param params params{kode} + */ + async sub(params: { + /** Kode Spesialis */ + kode: string; + }) { + return this.send<{ count: number; list: SubSpesialisResult[] }>({ + name: `${this.name} Data Referensi Sub Spesialis`, + path: ['/spesialis/:kode/subspesialis', params], + method: 'GET' + }); + } + + /** + * Get Data Referensi Sarana + */ + async sarana() { + return this.send<{ count: number; list: SaranaResult[] }>({ + name: `${this.name} Data Referensi Sarana`, + path: '/spesialis/sarana', + method: 'GET' + }); + } + + /** + * Get Data Referensi Khusus + */ + async khusus() { + return this.send<{ count: number; list: KhususResult[] }>({ + name: `${this.name} Data Referensi Khusus`, + path: '/spesialis/khusus', + method: 'GET' + }); + } + + /** + * Get Data Faskes Rujukan Sub Spesialis + */ + async faskesRujukanSubSpesialis(params: { + /** Kode Sub Spesialis */ + kodeSub: string; + + /** Kode Sarana */ + kodeSarana: string; + + /** Tanggal Estimasi Rujuk, format: dd-mm-yyyy */ + tanggal: string; + }) { + return this.send<{ count: number; list: FaskesRujukanSubSpesialis[] }>({ + name: `${this.name} Data Faskes Rujukan Sub Spesialis`, + path: [ + '/spesialis/rujuk/subspesialis/:kodeSub/sarana/:kodeSarana/tglEstRujuk/:tanggal', + params + ], + method: 'GET' + }); + } +} + +interface SpesialisResult { + /** kode spesialis */ + kdSpesialis: string; + + /** nama spesialis */ + nmSpesialis: string; +} + +interface SubSpesialisResult { + /** kode sub spesialis */ + kdSubSpesialis: string; + + /** nama sub spesialis */ + nmSubSpesialis: string; + + /** kode poli rujuk */ + kdPoliRujuk: string; +} + +interface SaranaResult { + /** kode sarana */ + kdSarana: string; + + /** nama sarana */ + nmSarana: string; +} + +interface KhususResult { + /** kode khusus */ + kdKhusus: string; + + /** nama khusus */ + nmKhusus: string; +} + +interface FaskesRujukanSubSpesialis { + kdppk: string; + nmppk: string; + alamatPpk: string; + telpPpk: string; + kelas: string; + nmkc: string; + distance: number; + jadwal: string; + jmlRujuk: number; + kapasitas: number; + persentase: number; +} diff --git a/test/pcare/kunjungan.test.ts b/test/pcare/kunjungan.test.ts new file mode 100644 index 0000000..161bd7c --- /dev/null +++ b/test/pcare/kunjungan.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; +import jkn from '../jkn'; + +describe('PCare - Kunjungan', { timeout: 25_000 }, () => { + it.concurrent('rujukan() - 500 wrong final block length', async () => { + const result = await jkn.pcare.kunjungan.rujukan({ nomor: '0114A0260815Y000003' }); + expect(result.metaData.code).toBe('500'); + }); + it.concurrent('rujukan() - 200 ok', async () => { + const result = await jkn.pcare.kunjungan.rujukan({ nomor: '0108B0110326Y000002' }); + expect(result.metaData.code).toBe(200); + }); + + it.concurrent('riwayat() - 200 ok', async () => { + const result = await jkn.pcare.kunjungan.riwayat({ nomor: '0002060616655' }); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.peserta.noKartu)).toContain('0002060616655'); + }); +}); diff --git a/test/pcare/partial.test.ts b/test/pcare/partial.test.ts new file mode 100644 index 0000000..5111782 --- /dev/null +++ b/test/pcare/partial.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest'; +import jkn from '../jkn'; + +describe('PCare - Partial Request', { timeout: 25_000 }, () => { + interface PCareDiagnosa { + count: number; + list: { + kdDiag: string; + nmDiag: string; + nonSpesialis: boolean; + }[]; + } + + it.concurrent('api() - 200 ok', async () => { + const result = await jkn.pcare.api.request({ + path: `/diagnosa/A00/1/5`, + method: 'GET' + }); + expect(result.metaData.code).toBe(200); + }); +}); diff --git a/test/pcare/peserta.test.ts b/test/pcare/peserta.test.ts new file mode 100644 index 0000000..5eeb005 --- /dev/null +++ b/test/pcare/peserta.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import jkn from '../jkn'; + +describe('PCare - Peserta', { timeout: 25_000 }, () => { + it.concurrent('nomorKartu() - 204 NO_CONTENT', async () => { + const result = await jkn.pcare.peserta.nomorKartu({ + nomor: '0000000000000' + }); + expect(result.metaData.code).toBe(204); + }); + it.concurrent('nomorKartu() - 200 ok', async () => { + const result = await jkn.pcare.peserta.nomorKartu({ + nomor: '0002060616655' + }); + expect(result.metaData.code).toBe(200); + expect(result.response?.noKartu).toBe('0002060616655'); + }); + + it.concurrent('jenisKartu(noka, nomor) - 204 NO_CONTENT', async () => { + const result = await jkn.pcare.peserta.jenisKartu({ + jenis: 'noka', + nomor: '0000000000000' + }); + expect(result.metaData.code).toBe(204); + }); + + it.concurrent('jenisKartu(noka, nomor) - 200 ok', async () => { + const result = await jkn.pcare.peserta.jenisKartu({ + jenis: 'noka', + nomor: '0002060616655' + }); + expect(result.metaData.code).toBe(200); + expect(result.response?.noKartu).toBe('0002060616655'); + }); + + it.concurrent('jenisKartu(nik, nomor) - 500 wrong final block length', async () => { + const result = await jkn.pcare.peserta.jenisKartu({ + jenis: 'nik', + nomor: '000000000000000' + }); + console.log(result); + expect(result.metaData.code).toBe('500'); + }); + + it.concurrent('jenisKartu(nik, nomor) - 200 ok', async () => { + const result = await jkn.pcare.peserta.jenisKartu({ + jenis: 'nik', + nomor: '1705065003000004' + }); + expect(result.metaData.code).toBe(200); + expect(result.response?.noKartu).toBe('0002060616655'); + }); +}); diff --git a/test/pcare/referensi.test.ts b/test/pcare/referensi.test.ts new file mode 100644 index 0000000..18e21d1 --- /dev/null +++ b/test/pcare/referensi.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import jkn from '../jkn'; + +describe('PCare - Referensi', { timeout: 25_000 }, () => { + it.concurrent('diagnosa() - 200 ok', async () => { + const result = await jkn.pcare.referensi.diagnosa({ kode: 'A00', row: 1, limit: 10 }); + expect(result.metaData.code).toBe(200); + }); + + it.concurrent('dokter() - 200 ok', async () => { + const result = await jkn.pcare.referensi.dokter({ row: 1, limit: 10 }); + expect(result.metaData.code).toBe(200); + }); + + it.concurrent('kesadaran() - 200 ok', async () => { + const result = await jkn.pcare.referensi.kesadaran(); + expect(result.metaData.code).toBe(200); + }); + + it.concurrent('poli() - 200 ok', async () => { + const result = await jkn.pcare.referensi.poli({ row: 1, limit: 10 }); + expect(result.metaData.code).toBe(200); + }); + + it.concurrent('alergi() - 200 ok', async () => { + const result = await jkn.pcare.referensi.alergi({ kode: '01' }); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.nmAlergi)).toContain('Seafood'); + }); + + it.concurrent('prognosa() - 200 ok', async () => { + const result = await jkn.pcare.referensi.prognosa(); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.kdPrognosa)).toContain('01'); + }); + + it.concurrent('satatuspulang(ranap = true) - 200 ok', async () => { + const result = await jkn.pcare.referensi.statuspulang({ ranap: true }); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.nmStatusPulang)).toContain('Sembuh'); + }); + + it.concurrent('satatuspulang(ranap = false) - 200 ok', async () => { + const result = await jkn.pcare.referensi.statuspulang({ ranap: false }); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.nmStatusPulang)).toContain('Berobat Jalan'); + }); + + it.concurrent('provider() - 200 ok', async () => { + const result = await jkn.pcare.referensi.provider({ row: 1, limit: 10 }); + expect(result.metaData.code).toBe(200); + }); +}); diff --git a/test/pcare/spesialis.test.ts b/test/pcare/spesialis.test.ts new file mode 100644 index 0000000..d17c0c2 --- /dev/null +++ b/test/pcare/spesialis.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; +import jkn from '../jkn'; + +describe('PCare - Referensi', { timeout: 25_000 }, () => { + it.concurrent('spesialis() - 200 ok', async () => { + const result = await jkn.pcare.spesialis.get(); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.kdSpesialis)).toContain('ANA'); + }); + + it.concurrent('subSpesialis() - 200 ok', async () => { + const result = await jkn.pcare.spesialis.sub({ kode: 'ANA' }); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.kdPoliRujuk)).toContain('ANA'); + }); + + it.concurrent('sarana() - 200 ok', async () => { + const result = await jkn.pcare.spesialis.sarana(); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.nmSarana)).toContain('REKAM MEDIK'); + }); + + it.concurrent('khusus() - 200 ok', async () => { + const result = await jkn.pcare.spesialis.khusus(); + expect(result.metaData.code).toBe(200); + expect(result.response?.list.map((d) => d.nmKhusus)).toContain('HEMODIALISA'); + }); + + it.concurrent('faskesRujukanSubSpesialis() - 200 ok', async () => { + const result = await jkn.pcare.spesialis.faskesRujukanSubSpesialis({ + kodeSub: '26', // kode subSpesialis untuk ANAK + kodeSarana: '1', // kode sarana untuk REKAM MEDIK + tanggal: '25-03-2026' + }); + expect(result.metaData.code).toBe(200); + }); +});