feat(cpone): migrate medrec endpoint
This commit is contained in:
191
internal/http/medrec_test.go
Normal file
191
internal/http/medrec_test.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"primaya-api/cpone-middleware/internal/repository"
|
||||
)
|
||||
|
||||
type fakePatientRepository struct {
|
||||
outcome repository.MedrecOutcome
|
||||
err error
|
||||
params repository.MedrecParams
|
||||
}
|
||||
|
||||
func (f *fakePatientRepository) StoreMedrec(_ context.Context, params repository.MedrecParams) (repository.MedrecOutcome, error) {
|
||||
f.params = params
|
||||
return f.outcome, f.err
|
||||
}
|
||||
|
||||
func TestStoreMedrecValidPayloadAndCreatedResponseParity(t *testing.T) {
|
||||
name := "BUDI SANTOS"
|
||||
birthDate := "1990-01-15"
|
||||
identityType := "KTP"
|
||||
identityNumber := "3174011501900001"
|
||||
phone := "081234567890"
|
||||
repo := &fakePatientRepository{outcome: repository.MedrecOutcome{
|
||||
HTTPStatus: http.StatusCreated,
|
||||
Success: true,
|
||||
Status: "created",
|
||||
Message: "Pasien berhasil disimpan",
|
||||
Data: repository.MedrecData{
|
||||
Patient: repository.MedrecPatient{
|
||||
MEDRECID: "00001235",
|
||||
Nama: &name,
|
||||
TanggalLahir: &birthDate,
|
||||
JenisNomerSosial: &identityType,
|
||||
NomerSosial: &identityNumber,
|
||||
Telepon: &phone,
|
||||
Ponsel: &phone,
|
||||
},
|
||||
IsNewPatient: true,
|
||||
},
|
||||
}}
|
||||
handler := Handler{patientRepo: repo}
|
||||
body := `{
|
||||
"rs":" primaya ",
|
||||
"nama":" Budi Santos ",
|
||||
"jenis_kelamin":"l",
|
||||
"tgl_lahir":"1990-01-15",
|
||||
"jenis_nomer_sosial":"ktp",
|
||||
"nomer_sosial":"3174-0115-0190-0001",
|
||||
"telepon":"+62 812-3456-7890",
|
||||
"ponsel":"0812 3456 7890",
|
||||
"email":" BUDI@Example.COM ",
|
||||
"tempat_lahir":" jakarta ",
|
||||
"alamat":" JL. CONTOH NO. 1 ",
|
||||
"propinsi":" DKI JAKARTA ",
|
||||
"kabupaten":" JAKARTA ",
|
||||
"kecamatan":" KECAMATAN CONTOH ",
|
||||
"kelurahan":" KELURAHAN CONTOH ",
|
||||
"kode_pos":" 12345 ",
|
||||
"channel":" cpone "
|
||||
}`
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body))
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.StoreMedrec(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusCreated {
|
||||
t.Fatalf("status = %d, want %d; body=%s", recorder.Code, http.StatusCreated, recorder.Body.String())
|
||||
}
|
||||
const expected = `{"success":true,"status":"created","message":"Pasien berhasil disimpan","data":{"patient":{"MEDRECID":"00001235","Nama":"BUDI SANTOS","TanggalLahir":"1990-01-15","JenisNomerSosial":"KTP","NomerSosial":"3174011501900001","Telepon":"081234567890","Ponsel":"081234567890"},"is_new_patient":true}}` + "\n"
|
||||
if recorder.Body.String() != expected {
|
||||
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
||||
}
|
||||
|
||||
if repo.params.HospitalCode != "PRIMAYA" || repo.params.Name != "BUDI SANTOS" || repo.params.Gender != "L" {
|
||||
t.Fatalf("basic normalization mismatch: %+v", repo.params)
|
||||
}
|
||||
if repo.params.IdentityType != "KTP" || repo.params.IdentityNumber != "3174011501900001" {
|
||||
t.Fatalf("identity normalization mismatch: %+v", repo.params)
|
||||
}
|
||||
if repo.params.Phone != "081234567890" || repo.params.Mobile != "081234567890" {
|
||||
t.Fatalf("phone normalization mismatch: %+v", repo.params)
|
||||
}
|
||||
if repo.params.Email != "budi@example.com" || repo.params.PlaceOfBirth != "JAKARTA" || repo.params.Channel != "CPONE" {
|
||||
t.Fatalf("text normalization mismatch: %+v", repo.params)
|
||||
}
|
||||
if repo.params.DateOfBirth.Format("2006-01-02") != "1990-01-15" {
|
||||
t.Fatalf("birth date mismatch: %s", repo.params.DateOfBirth)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreMedrecValidationParity(t *testing.T) {
|
||||
baseline := map[string]any{
|
||||
"rs": "PRIMAYA",
|
||||
"nama": "BUDI SANTOS",
|
||||
"jenis_kelamin": "L",
|
||||
"tgl_lahir": "1990-01-15",
|
||||
"jenis_nomer_sosial": "KTP",
|
||||
"nomer_sosial": "3174011501900001",
|
||||
"telepon": "081234567890",
|
||||
}
|
||||
|
||||
tomorrow := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(map[string]any)
|
||||
message string
|
||||
}{
|
||||
{name: "missing rs", mutate: func(p map[string]any) { delete(p, "rs") }, message: "Kode RS wajib diisi"},
|
||||
{name: "missing name", mutate: func(p map[string]any) { delete(p, "nama") }, message: "Nama pasien wajib diisi"},
|
||||
{name: "invalid gender", mutate: func(p map[string]any) { p["jenis_kelamin"] = "M" }, message: "Jenis kelamin harus L atau P"},
|
||||
{name: "invalid date format", mutate: func(p map[string]any) { p["tgl_lahir"] = "15-01-1990" }, message: "Tanggal lahir harus format Y-m-d"},
|
||||
{name: "future birth date", mutate: func(p map[string]any) { p["tgl_lahir"] = tomorrow }, message: "Tanggal lahir tidak boleh lebih dari hari ini"},
|
||||
{name: "missing identity", mutate: func(p map[string]any) { delete(p, "nomer_sosial") }, message: "NIK/nomer_sosial wajib diisi"},
|
||||
{name: "invalid ktp", mutate: func(p map[string]any) { p["nomer_sosial"] = "123" }, message: "NIK/KTP harus 16 digit angka"},
|
||||
{name: "missing phone", mutate: func(p map[string]any) { delete(p, "telepon") }, message: "Telepon atau ponsel wajib diisi"},
|
||||
{name: "invalid email", mutate: func(p map[string]any) { p["email"] = "invalid" }, message: "The email must be a valid email address."},
|
||||
{name: "long hospital code", mutate: func(p map[string]any) { p["rs"] = strings.Repeat("X", 21) }, message: "The rs must not be greater than 20 characters."},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
payload := make(map[string]any, len(baseline))
|
||||
for key, value := range baseline {
|
||||
payload[key] = value
|
||||
}
|
||||
test.mutate(payload)
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handler := Handler{patientRepo: &fakePatientRepository{}}
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(string(body)))
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.StoreMedrec(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusUnprocessableEntity {
|
||||
t.Fatalf("status = %d; body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
expected := `{"success":false,"status":"validation_error","message":` + strconvQuote(test.message) + `,"data":null}` + "\n"
|
||||
if recorder.Body.String() != expected {
|
||||
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreMedrecNikFallbackAndOutcomeForwarding(t *testing.T) {
|
||||
data := repository.PossibleDuplicateData{Candidates: []repository.MedrecPatient{}}
|
||||
repo := &fakePatientRepository{outcome: repository.MedrecOutcome{
|
||||
HTTPStatus: http.StatusConflict,
|
||||
Success: false,
|
||||
Status: "possible_duplicate",
|
||||
Message: "Ditemukan pasien dengan nama, tanggal lahir, dan nomor telepon yang sama atau sangat mirip",
|
||||
Data: data,
|
||||
}}
|
||||
handler := Handler{patientRepo: repo}
|
||||
body := `{"rs":"PRIMAYA","nama":"BUDI","jenis_kelamin":"P","tgl_lahir":"1990-01-15","nik":"3174011501900001","ponsel":"08123"}`
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body))
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.StoreMedrec(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusConflict || repo.params.IdentityType != "KTP" || repo.params.IdentityNumber != "3174011501900001" {
|
||||
t.Fatalf("unexpected result: status=%d params=%+v body=%s", recorder.Code, repo.params, recorder.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreMedrecRepositoryErrorParity(t *testing.T) {
|
||||
handler := Handler{patientRepo: &fakePatientRepository{err: errors.New("database unavailable")}}
|
||||
body := `{"rs":"PRIMAYA","nama":"BUDI","jenis_kelamin":"L","tgl_lahir":"1990-01-15","nomer_sosial":"3174011501900001","telepon":"08123"}`
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/cpone/patients/medrec", strings.NewReader(body))
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.StoreMedrec(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusInternalServerError {
|
||||
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
const expected = `{"success":false,"status":"error","message":"database unavailable","data":null}` + "\n"
|
||||
if recorder.Body.String() != expected {
|
||||
t.Fatalf("body mismatch\n got: %s\nwant: %s", recorder.Body.String(), expected)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user