test_endpoints.sh 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #!/usr/bin/env bash
  2. #
  3. # test_endpoints.sh — Testa todos os endpoints da API nettown_backend.
  4. #
  5. # Faz login (POST /v1/login), obtém o JWT e reutiliza nas rotas protegidas.
  6. #
  7. # Uso:
  8. # ./test_endpoints.sh
  9. # BASE_URL=http://localhost:8080 EMAIL=admin@empresa.com PASSWORD=12345678 ./test_endpoints.sh
  10. # RUN_WRITE=1 ./test_endpoints.sh # inclui endpoints que ESCREVEM no banco
  11. #
  12. # Variáveis de ambiente:
  13. # BASE_URL Host da API (default: http://localhost:8080)
  14. # API_PREFIX Prefixo das rotas (default: /v1)
  15. # EMAIL E-mail de login (default: admin@empresa.com)
  16. # PASSWORD Senha de login (default: 12345678)
  17. # RUN_WRITE "1" para rodar também os endpoints de escrita (register,
  18. # change-password, agents, sla/configs). Default: 0 (somente leitura).
  19. #
  20. # Saída: 0 se nenhum teste falhou, 1 caso contrário.
  21. set -uo pipefail
  22. BASE_URL="${BASE_URL:-http://localhost:8080}"
  23. API_PREFIX="${API_PREFIX:-/v1}"
  24. EMAIL="${EMAIL:-admin@empresa.com}"
  25. PASSWORD="${PASSWORD:-12345678}"
  26. RUN_WRITE="${RUN_WRITE:-0}"
  27. BASE="${BASE_URL}${API_PREFIX}"
  28. TOKEN=""
  29. # Cores (desativadas se a saída não for um terminal).
  30. if [[ -t 1 ]]; then
  31. C_GREEN=$'\033[32m'; C_RED=$'\033[31m'; C_YELLOW=$'\033[33m'
  32. C_BLUE=$'\033[34m'; C_DIM=$'\033[2m'; C_RESET=$'\033[0m'
  33. else
  34. C_GREEN=""; C_RED=""; C_YELLOW=""; C_BLUE=""; C_DIM=""; C_RESET=""
  35. fi
  36. PASS=0; FAIL=0; SKIP=0
  37. have_jq() { command -v jq >/dev/null 2>&1; }
  38. # json_get <json> <jq_path> — extrai um valor do JSON (usa jq; senão, grep básico).
  39. json_get() {
  40. local json="$1" path="$2"
  41. if have_jq; then
  42. printf '%s' "$json" | jq -r "$path // empty" 2>/dev/null
  43. return
  44. fi
  45. # Fallback simples: pega o último campo com o nome final do path (ex.: .data.token -> token).
  46. local key="${path##*.}"
  47. printf '%s' "$json" | grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" \
  48. | head -n1 | sed -E "s/.*:[[:space:]]*\"([^\"]*)\"/\1/"
  49. }
  50. # Imprime um trecho curto do corpo da resposta.
  51. preview_body() {
  52. local body="$1"
  53. if have_jq; then
  54. printf '%s' "$body" | jq -c '{status, code, message}' 2>/dev/null || printf '%s' "$body" | head -c 200
  55. else
  56. printf '%s' "$body" | head -c 200
  57. fi
  58. }
  59. LAST_BODY=""
  60. LAST_CODE=""
  61. # call <method> <path> [json_data] — executa a requisição e popula LAST_BODY/LAST_CODE.
  62. call() {
  63. local method="$1" path="$2" data="${3:-}"
  64. local args=(-sS -X "$method" -H "Accept: application/json" -w $'\n%{http_code}' --max-time 30)
  65. if [[ -n "$TOKEN" ]]; then
  66. args+=(-H "Authorization: Bearer ${TOKEN}")
  67. fi
  68. if [[ -n "$data" ]]; then
  69. args+=(-H "Content-Type: application/json" -d "$data")
  70. fi
  71. local resp
  72. resp=$(curl "${args[@]}" "${BASE}${path}" 2>/dev/null)
  73. LAST_CODE=$(printf '%s' "$resp" | tail -n1)
  74. LAST_BODY=$(printf '%s' "$resp" | sed '$d')
  75. }
  76. # check <label> <method> <path> [json_data] — chama e avalia (2xx = passou).
  77. check() {
  78. local label="$1" method="$2" path="$3" data="${4:-}"
  79. call "$method" "$path" "$data"
  80. local mark color
  81. if [[ "$LAST_CODE" =~ ^2 ]]; then
  82. mark="PASS"; color="$C_GREEN"; PASS=$((PASS + 1))
  83. elif [[ "$LAST_CODE" =~ ^[45] ]]; then
  84. mark="FAIL"; color="$C_RED"; FAIL=$((FAIL + 1))
  85. else
  86. mark="FAIL"; color="$C_RED"; FAIL=$((FAIL + 1))
  87. [[ -z "$LAST_CODE" ]] && LAST_CODE="ERR"
  88. fi
  89. printf ' %s%-4s%s %-7s %-34s %shttp %s%s\n' \
  90. "$color" "$mark" "$C_RESET" "$method" "$path" "$C_DIM" "$LAST_CODE" "$C_RESET"
  91. printf ' %s%s%s\n' "$C_DIM" "$(preview_body "$LAST_BODY")" "$C_RESET"
  92. }
  93. skip() {
  94. local path="$1" reason="$2"
  95. SKIP=$((SKIP + 1))
  96. printf ' %sSKIP%s %-7s %-34s %s%s%s\n' "$C_YELLOW" "$C_RESET" "-" "$path" "$C_DIM" "$reason" "$C_RESET"
  97. }
  98. section() { printf '\n%s== %s ==%s\n' "$C_BLUE" "$1" "$C_RESET"; }
  99. # ----------------------------------------------------------------------------
  100. # 0. Sanity check
  101. # ----------------------------------------------------------------------------
  102. printf '%sAlvo:%s %s %sleitura+escrita:%s %s\n' \
  103. "$C_DIM" "$C_RESET" "$BASE" "$C_DIM" "$C_RESET" \
  104. "$([[ "$RUN_WRITE" == "1" ]] && echo sim || echo 'somente leitura')"
  105. have_jq || printf '%s(jq não encontrado — usando parser básico; instale jq para melhor saída)%s\n' "$C_YELLOW" "$C_RESET"
  106. # ----------------------------------------------------------------------------
  107. # 1. Login (obrigatório — sem token não dá para testar o resto)
  108. # ----------------------------------------------------------------------------
  109. section "Autenticação"
  110. LOGIN_PAYLOAD=$(printf '{"email":"%s","password":"%s"}' "$EMAIL" "$PASSWORD")
  111. check "login" POST "/login" "$LOGIN_PAYLOAD"
  112. TOKEN=$(json_get "$LAST_BODY" '.data.token')
  113. if [[ -z "$TOKEN" ]]; then
  114. printf '\n%sNão foi possível obter o JWT do login. Verifique BASE_URL/EMAIL/PASSWORD.%s\n' "$C_RED" "$C_RESET"
  115. printf 'Resposta: %s\n' "$LAST_BODY"
  116. exit 1
  117. fi
  118. printf ' %stoken obtido (%s...)%s\n' "$C_DIM" "${TOKEN:0:24}" "$C_RESET"
  119. # ----------------------------------------------------------------------------
  120. # 2. Perfil
  121. # ----------------------------------------------------------------------------
  122. section "Perfil"
  123. check "me" GET "/me"
  124. # ----------------------------------------------------------------------------
  125. # 3. Dashboards (somente leitura)
  126. # ----------------------------------------------------------------------------
  127. section "Dashboards (GET)"
  128. check "dashboard" GET "/dashboard/overview"
  129. check "analytics" GET "/analytics/sentiment/dashboard"
  130. check "personas" GET "/personas/overview"
  131. check "evolution" GET "/evolution/overview"
  132. check "executive" GET "/executive/dashboard"
  133. # ----------------------------------------------------------------------------
  134. # 4. Interações
  135. # ----------------------------------------------------------------------------
  136. section "Interações (GET)"
  137. check "interactions" GET "/interactions?page=1&per_page=5"
  138. # Tenta extrair um conversation_id da listagem para testar os detalhes.
  139. CONV_ID=""
  140. if have_jq; then
  141. CONV_ID=$(printf '%s' "$LAST_BODY" | jq -r '.data.items[0].conversationId // empty' 2>/dev/null)
  142. else
  143. CONV_ID=$(printf '%s' "$LAST_BODY" | grep -o '"conversationId":[0-9]*' | head -n1 | grep -o '[0-9]*')
  144. fi
  145. if [[ -n "$CONV_ID" ]]; then
  146. check "interaction-details" GET "/interactions/details?conversation_id=${CONV_ID}"
  147. else
  148. skip "/interactions/details" "nenhum conversation_id disponível na listagem"
  149. fi
  150. # ----------------------------------------------------------------------------
  151. # 5. Agentes (GET)
  152. # ----------------------------------------------------------------------------
  153. section "Agentes (GET)"
  154. check "agents" GET "/agents"
  155. # ----------------------------------------------------------------------------
  156. # 6. SLA (GET)
  157. # ----------------------------------------------------------------------------
  158. section "SLA (GET)"
  159. check "sla-configs" GET "/sla/configs"
  160. check "sla-live-status" GET "/sla/live-status"
  161. # ----------------------------------------------------------------------------
  162. # 7. Endpoints de ESCRITA (apenas com RUN_WRITE=1)
  163. # ----------------------------------------------------------------------------
  164. section "Escrita (POST)"
  165. if [[ "$RUN_WRITE" != "1" ]]; then
  166. skip "/register" "RUN_WRITE!=1 (cria usuário)"
  167. skip "/agents" "RUN_WRITE!=1 (cria/edita agente)"
  168. skip "/agents/status" "RUN_WRITE!=1 (altera status)"
  169. skip "/agents/escalation" "RUN_WRITE!=1 (altera escalonamento)"
  170. skip "/sla/configs" "RUN_WRITE!=1 (cria/edita SLA)"
  171. skip "/me/change-password" "RUN_WRITE!=1 (altera senha; revertido se rodado)"
  172. else
  173. TS=$(date +%s)
  174. # 7.1 Register — cria usuário com e-mail único para não colidir.
  175. REG_PAYLOAD=$(printf '{"name":"Teste %s","phone":"5511999990000","email":"teste+%s@example.com","role":"operator","password":"senha12345"}' "$TS" "$TS")
  176. check "register" POST "/register" "$REG_PAYLOAD"
  177. # 7.2 Agents — cria um agente e captura o id para os toggles.
  178. AGENT_PAYLOAD=$(printf '{"name":"Agente Teste %s","email":"agent+%s@example.com","department":"SAC","channels":["whatsapp"],"status":"Ativo","availableForEscalation":true}' "$TS" "$TS")
  179. check "agents-save" POST "/agents" "$AGENT_PAYLOAD"
  180. AGENT_ID=""
  181. if have_jq; then
  182. AGENT_ID=$(printf '%s' "$LAST_BODY" | jq -r '.data.id // empty' 2>/dev/null)
  183. else
  184. AGENT_ID=$(printf '%s' "$LAST_BODY" | grep -o '"id":[0-9]*' | head -n1 | grep -o '[0-9]*')
  185. fi
  186. if [[ -n "$AGENT_ID" ]]; then
  187. check "agents-status" POST "/agents/status" "$(printf '{"id":%s}' "$AGENT_ID")"
  188. check "agents-escalation" POST "/agents/escalation" "$(printf '{"id":%s}' "$AGENT_ID")"
  189. else
  190. skip "/agents/status" "agente de teste não retornou id"
  191. skip "/agents/escalation" "agente de teste não retornou id"
  192. fi
  193. # 7.3 SLA config — cria/atualiza um departamento de teste.
  194. SLA_PAYLOAD=$(printf '{"name":"TESTE %s","firstResponseH":1,"firstResponseM":30,"resolutionH":24,"alertPct":80}' "$TS")
  195. check "sla-save" POST "/sla/configs" "$SLA_PAYLOAD"
  196. # 7.4 Change password — troca e reverte para não travar o login.
  197. NEW_PW="${PASSWORD}_tmp1"
  198. check "change-password" POST "/me/change-password" \
  199. "$(printf '{"currentPassword":"%s","newPassword":"%s","confirmPassword":"%s"}' "$PASSWORD" "$NEW_PW" "$NEW_PW")"
  200. if [[ "$LAST_CODE" =~ ^2 ]]; then
  201. # Reverte para a senha original.
  202. check "change-password (revert)" POST "/me/change-password" \
  203. "$(printf '{"currentPassword":"%s","newPassword":"%s","confirmPassword":"%s"}' "$NEW_PW" "$PASSWORD" "$PASSWORD")"
  204. fi
  205. fi
  206. # ----------------------------------------------------------------------------
  207. # Resumo
  208. # ----------------------------------------------------------------------------
  209. printf '\n%s== Resumo ==%s\n' "$C_BLUE" "$C_RESET"
  210. printf ' %spassou:%s %d %sfalhou:%s %d %spulado:%s %d\n' \
  211. "$C_GREEN" "$C_RESET" "$PASS" "$C_RED" "$C_RESET" "$FAIL" "$C_YELLOW" "$C_RESET" "$SKIP"
  212. [[ "$FAIL" -eq 0 ]] && exit 0 || exit 1