#!/bin/bash BASE="http://localhost:3000/api/v1" RESULTS_FILE="/tmp/hms_test_results.txt" > "$RESULTS_FILE" # Login first LOGIN_RESP=$(curl -s "$BASE/auth/login" -H "Content-Type: application/json" -d '{"username":"admin","password":"Admin@2026"}') TOKEN=$(echo "$LOGIN_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['access_token'])" 2>/dev/null) REFRESH_TOKEN=$(echo "$LOGIN_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['refresh_token'])" 2>/dev/null) if [ -z "$TOKEN" ]; then echo "LOGIN FAILED - cannot continue" exit 1 fi echo "Login successful, TOKEN length: ${#TOKEN}" # Helper function test_endpoint() { local method=$1 local url=$2 local data="$3" local label=$4 local expected="$5" local resp_body="" local http_code="" if [ "$method" = "GET" ]; then RESP=$(curl -s -w "\nHTTP_CODE:%{http_code}" "$BASE$url" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" 2>/dev/null) elif [ "$method" = "DELETE" ]; then RESP=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X DELETE "$BASE$url" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" 2>/dev/null) else RESP=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X "$method" "$BASE$url" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d "$data" 2>/dev/null) fi http_code=$(echo "$RESP" | grep "HTTP_CODE:" | sed 's/HTTP_CODE://') resp_body=$(echo "$RESP" | grep -v "HTTP_CODE:") success=$(echo "$resp_body" | python3 -c "import sys,json; d=json.load(sys.stdin); print('true' if d.get('success') else 'false')" 2>/dev/null || echo "parse_error") local status="PASS" if [ -n "$expected" ]; then if [ "$http_code" != "$expected" ]; then status="FAIL" fi else if [ "$http_code" -ge 400 ] 2>/dev/null; then status="FAIL" fi fi echo "$status | $method $url | HTTP $http_code | success=$success | $label" >> "$RESULTS_FILE" # Return the body for chaining echo "$resp_body" } # ========================================== # AUTH MODULE (24 endpoints) # ========================================== echo "=== AUTH MODULE TESTS ===" >> "$RESULTS_FILE" # 1. POST /auth/login echo "PASS | POST /auth/login | HTTP 200 | success=true | Login" >> "$RESULTS_FILE" # 2. POST /auth/refresh test_endpoint POST "/auth/refresh" "{\"refresh_token\":\"$REFRESH_TOKEN\"}" "Token refresh" # Re-login since refresh may invalidate old token LOGIN_RESP=$(curl -s "$BASE/auth/login" -H "Content-Type: application/json" -d '{"username":"admin","password":"Admin@2026"}') TOKEN=$(echo "$LOGIN_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['access_token'])" 2>/dev/null) REFRESH_TOKEN=$(echo "$LOGIN_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['refresh_token'])" 2>/dev/null) # 3. POST /auth/logout - test last to keep token alive echo "PENDING | POST /auth/logout | - | - | Logout (tested last)" >> "$RESULTS_FILE" # 4. POST /auth/change-password (wrong password - expect 400 or error) test_endpoint POST "/auth/change-password" '{"current_password":"wrong_password","new_password":"NewPass123!"}' "Change password wrong current" "400" # 5. GET /users USERS_RESP=$(test_endpoint GET "/users?page=1&page_size=10" "" "User list") # 6. POST /users RAND=$(date +%s) CREATE_USER_RESP=$(test_endpoint POST "/users" "{\"username\":\"apitest_${RAND}\",\"password\":\"Test@2026pwd\",\"display_name\":\"API Test User\",\"email\":\"apitest_${RAND}@test.com\"}" "Create user") USER_ID=$(echo "$CREATE_USER_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) echo " -> Created user: $USER_ID" # 7. GET /users/{id} if [ -n "$USER_ID" ]; then test_endpoint GET "/users/$USER_ID" "" "Get user detail" fi # 8. PUT /users/{id} if [ -n "$USER_ID" ]; then test_endpoint PUT "/users/$USER_ID" '{"display_name":"API Test User Updated","email":"updated@test.com"}' "Update user" fi # 9. DELETE /users/{id} if [ -n "$USER_ID" ]; then test_endpoint DELETE "/users/$USER_ID" "" "Delete user (soft)" fi # 10. POST /users/{id}/roles - need user id and role id echo "PENDING | POST /users/{id}/roles | - | - | Assign roles (need user+role)" >> "$RESULTS_FILE" # 11. POST /users/{id}/reset-password echo "SKIP | POST /users/{id}/reset-password | - | - | Reset password (skip safety)" >> "$RESULTS_FILE" # 12. GET /roles ROLES_RESP=$(test_endpoint GET "/roles?page=1&page_size=10" "" "Role list") ROLE_ID=$(echo "$ROLES_RESP" | python3 -c "import sys,json; items=json.load(sys.stdin).get('data',{}).get('items',[]); print(items[0]['id'] if items else '')" 2>/dev/null) echo " -> First role: $ROLE_ID" # 13. POST /roles CREATE_ROLE_RESP=$(test_endpoint POST "/roles" "{\"name\":\"API Test Role ${RAND}\",\"code\":\"api_test_${RAND}\",\"description\":\"Test role by API test\"}" "Create role") NEW_ROLE_ID=$(echo "$CREATE_ROLE_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) echo " -> Created role: $NEW_ROLE_ID" # 14. GET /roles/permissions => same as GET /permissions (tested later as #20) # 15. GET /roles/{id} if [ -n "$NEW_ROLE_ID" ]; then test_endpoint GET "/roles/$NEW_ROLE_ID" "" "Get role detail" fi # 16. PUT /roles/{id} if [ -n "$NEW_ROLE_ID" ]; then test_endpoint PUT "/roles/$NEW_ROLE_ID" '{"name":"Updated API Test Role","description":"Updated"}' "Update role" fi # 17. DELETE /roles/{id} if [ -n "$NEW_ROLE_ID" ]; then test_endpoint DELETE "/roles/$NEW_ROLE_ID" "" "Delete role" fi # 18. GET /roles/{id}/permissions if [ -n "$ROLE_ID" ]; then test_endpoint GET "/roles/$ROLE_ID/permissions" "" "Get role permissions" fi # 19. POST /roles/{id}/permissions if [ -n "$ROLE_ID" ]; then test_endpoint POST "/roles/$ROLE_ID/permissions" '{"permission_ids":["user.list","user.create"]}' "Assign permissions to role" fi # 20. GET /permissions test_endpoint GET "/permissions" "" "Permission list" # 21. GET /organizations ORGS_RESP=$(test_endpoint GET "/organizations?page=1&page_size=10" "" "Organization list") # 22. POST /organizations CREATE_ORG_RESP=$(test_endpoint POST "/organizations" "{\"name\":\"API Test Org ${RAND}\",\"code\":\"TEST_ORG_${RAND}\",\"description\":\"Test org\"}" "Create organization") ORG_ID=$(echo "$CREATE_ORG_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) echo " -> Created org: $ORG_ID" # 23. PUT /organizations/{id} if [ -n "$ORG_ID" ]; then test_endpoint PUT "/organizations/$ORG_ID" '{"name":"Updated Org","description":"Updated"}' "Update organization" fi # 24. DELETE /organizations/{id} if [ -n "$ORG_ID" ]; then test_endpoint DELETE "/organizations/$ORG_ID" "" "Delete organization" fi # ========================================== # CONFIG MODULE (19 endpoints) # ========================================== echo "" >> "$RESULTS_FILE" echo "=== CONFIG MODULE TESTS ===" >> "$RESULTS_FILE" # 1. GET /config/dictionaries DICTS_RESP=$(test_endpoint GET "/config/dictionaries?page=1&page_size=10" "" "Dictionary list") # 2. POST /config/dictionaries CREATE_DICT_RESP=$(test_endpoint POST "/config/dictionaries" "{\"name\":\"API Test Dict ${RAND}\",\"code\":\"api_test_dict_${RAND}\",\"description\":\"Test dictionary\"}" "Create dictionary") DICT_ID=$(echo "$CREATE_DICT_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 3. PUT /config/dictionaries/{id} if [ -n "$DICT_ID" ]; then test_endpoint PUT "/config/dictionaries/$DICT_ID" '{"name":"Updated Dict","description":"Updated"}' "Update dictionary" fi # 4. DELETE /config/dictionaries/{id} if [ -n "$DICT_ID" ]; then test_endpoint DELETE "/config/dictionaries/$DICT_ID" "" "Delete dictionary" fi # 5. GET /config/dictionaries/items test_endpoint GET "/config/dictionaries/items?page=1&page_size=10" "" "Dictionary items list" # Create another dict for item tests CREATE_DICT_RESP2=$(test_endpoint POST "/config/dictionaries" "{\"name\":\"API Test Dict Items ${RAND}\",\"code\":\"api_test_items_${RAND}\"}" "Create dict for item test") DICT_ID2=$(echo "$CREATE_DICT_RESP2" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 6. POST /config/dictionaries/{dict_id}/items if [ -n "$DICT_ID2" ]; then CREATE_ITEM_RESP=$(test_endpoint POST "/config/dictionaries/$DICT_ID2/items" '{"label":"Test Item","value":"test_value","sort_order":1}' "Create dictionary item") ITEM_ID=$(echo "$CREATE_ITEM_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 7. PUT /config/dictionaries/{dict_id}/items/{item_id} if [ -n "$ITEM_ID" ]; then test_endpoint PUT "/config/dictionaries/$DICT_ID2/items/$ITEM_ID" '{"label":"Updated Item","value":"updated_value"}' "Update dictionary item" # 8. DELETE /config/dictionaries/{dict_id}/items/{item_id} test_endpoint DELETE "/config/dictionaries/$DICT_ID2/items/$ITEM_ID" "" "Delete dictionary item" fi fi # 9. GET /config/menus test_endpoint GET "/config/menus" "" "Menu list" # 10. POST /config/menus CREATE_MENU_RESP=$(test_endpoint POST "/config/menus" '{"name":"API Test Menu","path":"/test","icon":"test","sort_order":999,"type":"menu"}' "Create menu") MENU_ID=$(echo "$CREATE_MENU_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 11. PUT /config/menus/{id} if [ -n "$MENU_ID" ]; then test_endpoint PUT "/config/menus/$MENU_ID" '{"name":"Updated Menu","path":"/test-updated"}' "Update menu" fi # 12. DELETE /config/menus/{id} if [ -n "$MENU_ID" ]; then test_endpoint DELETE "/config/menus/$MENU_ID" "" "Delete menu" fi # 13. GET /menus/user test_endpoint GET "/menus/user" "" "User menu tree" # 14. GET /config/settings/{key} test_endpoint GET "/config/settings/system.title" "" "Get setting by key" # 15. PUT /config/settings/{key} test_endpoint PUT "/config/settings/system.title" '{"value":"HMS Health Platform"}' "Update setting" # 16. GET /config/numbering-rules test_endpoint GET "/config/numbering-rules?page=1&page_size=10" "" "Numbering rules list" # 17. POST /config/numbering-rules CREATE_NUM_RESP=$(test_endpoint POST "/config/numbering-rules" "{\"name\":\"API Test Rule ${RAND}\",\"code\":\"TEST_NUM_${RAND}\",\"prefix\":\"TST\",\"pattern\":\"{YYYY}{MM}-{SEQ}\",\"seq_length\":4}" "Create numbering rule") NUM_RULE_ID=$(echo "$CREATE_NUM_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 18. POST /config/numbering-rules/{id}/generate if [ -n "$NUM_RULE_ID" ]; then test_endpoint POST "/config/numbering-rules/$NUM_RULE_ID/generate" "{}" "Generate number" fi # 19. GET /config/languages test_endpoint GET "/config/languages" "" "Language list" # ========================================== # WORKFLOW MODULE (15 endpoints) # ========================================== echo "" >> "$RESULTS_FILE" echo "=== WORKFLOW MODULE TESTS ===" >> "$RESULTS_FILE" # 1. GET /workflow/definitions test_endpoint GET "/workflow/definitions?page=1&page_size=10" "" "Workflow definitions list" # 2. POST /workflow/definitions BPMN='' CREATE_WF_RESP=$(test_endpoint POST "/workflow/definitions" "{\"name\":\"API Test Workflow ${RAND}\",\"description\":\"Test workflow\",\"bpmn_xml\":\"${BPMN}\"}" "Create workflow definition") WF_DEF_ID=$(echo "$CREATE_WF_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 3. GET /workflow/definitions/{id} if [ -n "$WF_DEF_ID" ]; then test_endpoint GET "/workflow/definitions/$WF_DEF_ID" "" "Get workflow definition detail" # 4. PUT /workflow/definitions/{id} test_endpoint PUT "/workflow/definitions/$WF_DEF_ID" '{"name":"Updated Workflow","description":"Updated"}' "Update workflow definition" # 5. POST /workflow/definitions/{id}/publish test_endpoint POST "/workflow/definitions/$WF_DEF_ID/publish" "{}" "Publish workflow" fi # 6. POST /workflow/definitions/{id}/deprecate - create and publish first # Re-create for deprecate test WF_DEF2_RESP=$(test_endpoint POST "/workflow/definitions" "{\"name\":\"API Test Workflow Dep ${RAND}\",\"description\":\"For deprecate\",\"bpmn_xml\":\"${BPMN}\"}" "Create workflow for deprecate") WF_DEF2_ID=$(echo "$WF_DEF2_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) if [ -n "$WF_DEF2_ID" ]; then test_endpoint POST "/workflow/definitions/$WF_DEF2_ID/publish" "{}" "Publish for deprecate" test_endpoint POST "/workflow/definitions/$WF_DEF2_ID/deprecate" "{}" "Deprecate workflow" fi # 7. POST /workflow/instances WF_INST_RESP=$(test_endpoint POST "/workflow/instances" "{\"definition_id\":\"${WF_DEF_ID}\",\"variables\":{}}" "Start workflow instance") WF_INST_ID=$(echo "$WF_INST_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 8. GET /workflow/instances test_endpoint GET "/workflow/instances?page=1&page_size=10" "" "Workflow instances list" # 9. GET /workflow/instances/{id} if [ -n "$WF_INST_ID" ]; then test_endpoint GET "/workflow/instances/$WF_INST_ID" "" "Get instance detail" # 10. POST /workflow/instances/{id}/suspend test_endpoint POST "/workflow/instances/$WF_INST_ID/suspend" "{}" "Suspend instance" # 11. POST /workflow/instances/{id}/resume test_endpoint POST "/workflow/instances/$WF_INST_ID/resume" "{}" "Resume instance" # 12. POST /workflow/instances/{id}/terminate test_endpoint POST "/workflow/instances/$WF_INST_ID/terminate" "{}" "Terminate instance" fi # 13. GET /workflow/tasks/pending test_endpoint GET "/workflow/tasks/pending?page=1&page_size=10" "" "Pending tasks" # 14. GET /workflow/tasks/completed test_endpoint GET "/workflow/tasks/completed?page=1&page_size=10" "" "Completed tasks" # 15. POST /workflow/tasks/{id}/complete PENDING_TASK_RESP=$(test_endpoint GET "/workflow/tasks/pending?page=1&page_size=1" "" "Get pending task for complete test") TASK_ID=$(echo "$PENDING_TASK_RESP" | python3 -c "import sys,json; items=json.load(sys.stdin).get('data',{}).get('items',[]); print(items[0]['id'] if items else '')" 2>/dev/null) if [ -n "$TASK_ID" ]; then test_endpoint POST "/workflow/tasks/$TASK_ID/complete" '{"variables":{}}' "Complete task" else echo "SKIP | POST /workflow/tasks/{id}/complete | - | - | No pending task available" >> "$RESULTS_FILE" fi # ========================================== # MESSAGE MODULE (10 endpoints) # ========================================== echo "" >> "$RESULTS_FILE" echo "=== MESSAGE MODULE TESTS ===" >> "$RESULTS_FILE" # 1. GET /messages test_endpoint GET "/messages?page=1&page_size=10" "" "Message list" # 2. POST /messages CREATE_MSG_RESP=$(test_endpoint POST "/messages" '{"title":"API Test Message","content":"Test message content","type":"system","recipient_type":"user"}' "Send message") MSG_ID=$(echo "$CREATE_MSG_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 3. GET /messages/unread-count test_endpoint GET "/messages/unread-count" "" "Unread count" # 4. PUT /messages/{id}/read if [ -n "$MSG_ID" ]; then test_endpoint PUT "/messages/$MSG_ID/read" "{}" "Mark message read" fi # 5. PUT /messages/read-all test_endpoint PUT "/messages/read-all" "{}" "Mark all read" # 6. DELETE /messages/{id} if [ -n "$MSG_ID" ]; then test_endpoint DELETE "/messages/$MSG_ID" "" "Delete message" fi # 7. GET /message-templates test_endpoint GET "/message-templates?page=1&page_size=10" "" "Message templates list" # 8. POST /message-templates CREATE_TPL_RESP=$(test_endpoint POST "/message-templates" "{\"name\":\"API Test Template ${RAND}\",\"code\":\"test_tpl_${RAND}\",\"content\":\"Hello {{name}}\",\"channel\":\"system\"}" "Create template") TPL_ID=$(echo "$CREATE_TPL_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('id',''))" 2>/dev/null) # 9. PUT /message-templates/{id} if [ -n "$TPL_ID" ]; then test_endpoint PUT "/message-templates/$TPL_ID" '{"name":"Updated Template","content":"Hello {{name}}, updated"}' "Update template" fi # 10. GET /message-subscriptions test_endpoint GET "/message-subscriptions?page=1&page_size=10" "" "Subscriptions list" # ========================================== # Final: Test logout # ========================================== test_endpoint POST "/auth/logout" "{}" "Logout" # ========================================== # SUMMARY # ========================================== echo "" >> "$RESULTS_FILE" echo "=== SUMMARY ===" >> "$RESULTS_FILE" TOTAL=$(grep -c "^PASS\|^FAIL\|^SKIP\|^PENDING" "$RESULTS_FILE") PASSED=$(grep -c "^PASS" "$RESULTS_FILE") FAILED=$(grep -c "^FAIL" "$RESULTS_FILE") SKIPPED=$(grep -c "^SKIP" "$RESULTS_FILE") PENDING=$(grep -c "^PENDING" "$RESULTS_FILE") echo "Total: $TOTAL | Passed: $PASSED | Failed: $FAILED | Skipped: $SKIPPED | Pending: $PENDING" >> "$RESULTS_FILE" echo "" echo "===============================" echo "Test completed." echo "===============================" cat "$RESULTS_FILE"