3 # --------------------------------------
4 # REST API - Test Frameworks
5 # --------------------------
6 # https://github.com/subeshb1/api-test
7 # https://github.com/apiaryio/dredd
8 # https://github.com/vlucas/frisby
9 # https://github.com/bbyars/mountebank
10 # https://github.com/schemathesis/schemathesis
11 # https://github.com/ladjs/supertest
12 # https://github.com/taverntesting/tavern
13 # https://github.com/Kong/insomnia
14 # --------------------------------------
16 which curl
&> /dev
/null
19 echo "> curl not found"
23 which php
&> /dev
/null
26 echo "> php not found"
30 HOST
="${1:-localhost}"
34 # @see https://stackoverflow.com/a/5947802
37 # Black 0;30 Dark Gray 1;30
38 # Red 0;31 Light Red 1;31
39 # Green 0;32 Light Green 1;32
40 # Brown/Orange 0;33 Yellow 1;33
41 # Blue 0;34 Light Blue 1;34
42 # Purple 0;35 Light Purple 1;35
43 # Cyan 0;36 Light Cyan 1;36
44 # Light Gray 0;37 White 1;37
46 # .---------- constant part!
47 # vvvv vvvv-- the code from above
49 # NC='\033[0m' # No Color
50 # printf "I ${RED}love${NC} Stack Overflow\n"
52 # --------------------------------------
56 # - 'f': Failure message
57 # - 's': Success message
58 # - (empty): Normal message
60 # @param string $1 Message
61 # @param string $2 Flag
62 # --------------------------------------
71 if [[ 's' == "${flag}" ]]; then
72 echo -e "${gr}[✅ SUCCESS] ${message}${nc}"
73 elif [[ 'f' == "${flag}" ]]; then
74 echo -e "${rd}[❌ FAILURE] ${message}${nc}"
76 echo ">>>>>>>>>>>> ${message}"
80 # --------------------------------------
83 # Use following global variables to return/export values:
86 # - CURL_RESPONSE_HEADER
87 # - CURL_RESPONSE_DATA
89 # @param string $1 Path
90 # @param string $2 Method
91 # @param string $3 Data
92 # --------------------------------------
93 function callRestApi
{
95 CURL_RESPONSE_HEADER
=''
99 local method
="${2:-GET}"
102 if [[ ! -z "${data}" ]]; then
103 data
="--data ${data}"
106 curl
"${HOST}:${PORT}${path}" \
107 --request "${method}" \
108 --header "Content-Type: application/json" \
109 --header "Accept: application/json" \
110 --dump-header curl_response_header.txt \
111 --output curl_response_data.txt \
116 if [ -f curl_response_header.txt
]; then
117 CURL_RESPONSE_HEADER
=$
(cat curl_response_header.txt
)
118 rm curl_response_header.txt
121 if [ -f curl_response_data.txt
]; then
122 CURL_RESPONSE_DATA
=$
(cat curl_response_data.txt
)
123 rm curl_response_data.txt
127 # --------------------------------------
128 # Get the value from a response header
130 # @param string $1 Headers list
131 # @param string $2 Header name
132 # --------------------------------------
133 function getValueFromHeader
{
136 if [[ "code" == "${key}" ]]; then
137 echo $
(echo "${list}" |
grep '^HTTP/' | cut
-d' ' -f2 |
xargs)
139 echo $
(echo "${list}" |
grep "^${key}:" | cut
-d':' -f2 |
xargs)
143 # --------------------------------------
144 # Get a value from a JSON string
146 # @param string $1 JSON
147 # @param string $2 KEY
148 # --------------------------------------
149 function getValueFromJson
{
152 local php
=$
(cat << PHP
153 \$list = json_decode('${json}', true);
154 echo \$list['${key}'];
157 echo $
(php
-r "${php}")
160 # --------------------------------------
161 # Count items in JSON list
163 # @param string $1 JSON
164 # --------------------------------------
165 function countItemsInJsonList
{
167 local php
=$
(cat << PHP
168 \$list = json_decode('${json}', true);
172 echo $
(php
-r "${php}")
175 # --------------------------------------
176 # Get name for a given id from a JSON string
178 # @param string $1 JSON
179 # @param string $2 ID
180 # --------------------------------------
181 function getNameFromId
{
184 local php
=$
(cat << PHP
185 \$list = json_decode('${json}', true);
187 foreach (\$list as \$candidato) {
188 if (${id} == \$candidato['id']) {
189 \$name = \$candidato['name'];
196 echo $
(php
-r "${php}")
199 # --------------------------------------
200 # Get amount of votes for a given id from a JSON string
202 # @param string $1 JSON
203 # @param string $2 ID
204 # --------------------------------------
205 function getVotesFromId
{
208 local php
=$
(cat << PHP
209 \$list = json_decode('${json}', true);
211 foreach (\$list as \$candidato) {
212 if (${id} == \$candidato['id']) {
213 \$votes = \$candidato['votes'];
220 echo $
(php
-r "${php}")
223 # ====================================================================
225 # --------------------------------------
226 # Test candidate creation
228 # @param string $1 Candidate name
229 # --------------------------------------
230 function testCreateCandidate
{
233 echo '========================================'
234 msg
'Test create candidate'
236 callRestApi
'/candidates' 'POST' '{"name":"'"${name}"'"}'
238 if (( 0 != "${CURL_EXIT_CODE}" )); then
239 msg
'Failed curl call' f
241 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
243 if (( 200 != $code )); then
244 msg
'Failed to create candidate' f
248 local rname
="$(getValueFromJson "${CURL_RESPONSE_DATA}" "name
")"
249 flag
=$
([[ "${rname}" == "${name}" ]] && echo "s" ||
echo "f")
250 msg
"Candidate name (${name}, ${rname})" "${flag}"
252 NEW_ID
="$(getValueFromJson "${CURL_RESPONSE_DATA}" "id
")"
259 # --------------------------------------
260 # Test get list of candidates
262 # @param string $1 Items amount
263 # @param null|string $2 ID: If present will search the ID
264 # @param null|string $3 Name: If present will check name from ID search
265 # --------------------------------------
266 function testGetCandidates
{
271 echo '========================================'
272 msg
'Test get list of candidates'
274 callRestApi
"/candidates" 'GET'
276 if (( 0 != "${CURL_EXIT_CODE}" )); then
277 msg
'Failed curl call' f
279 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
281 if (( 200 != $code )); then
282 msg
'Failed to get list of candidates' f
284 local ramount
="$(countItemsInJsonList "${CURL_RESPONSE_DATA}")"
285 flag
=$
([[ "${amount}" == "${ramount}" ]] && echo "s" ||
echo "f")
286 msg
"Candidates listed (${amount}, ${ramount})" "${flag}"
288 if [[ -n "${id}" ]]; then
289 local rname
="$(getNameFromId "${CURL_RESPONSE_DATA}" "${id}")"
290 flag
=$
([[ -n "${rname}" ]] && echo "s" ||
echo "f")
291 msg
"Search id (${id}, ${rname})" "${flag}"
293 if [[ -n "${name}" ]]; then
294 flag
=$
([[ "${name}" == "${rname}" ]] && echo "s" ||
echo "f")
295 msg
"Candidate name (${name}, ${rname})" "${flag}"
304 # --------------------------------------
305 # Test delete candidate
307 # @param string $1 Candidate id
308 # --------------------------------------
309 function testDeleteCandidate
{
312 echo '========================================'
313 msg
'Test delete candidate'
315 callRestApi
"/candidates/${id}" 'DELETE'
317 if (( 0 != "${CURL_EXIT_CODE}" )); then
318 msg
'Failed curl call' f
320 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
322 if (( 200 != $code )); then
323 msg
'Failed to delete candidate' f
325 msg
'Candidate deleted' s
332 # --------------------------------------
333 # Test delete all candidates
334 # --------------------------------------
335 function testDeleteAllCandidates
{
336 echo '========================================'
337 msg
'Test delete all candidates'
339 callRestApi
"/candidates" 'DELETE'
341 if (( 0 != "${CURL_EXIT_CODE}" )); then
342 msg
'Failed curl call' f
344 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
346 if (( 200 != $code )); then
347 msg
'Failed to delete all candidates' f
349 msg
'All candidates deleted' s
356 # --------------------------------------
357 # Test vote a candidate
359 # @param string $1 Candidate id
360 # --------------------------------------
361 function testVoteCandiate
{
364 echo '========================================'
365 msg
'Test vote candidate'
367 callRestApi
'/vote' 'POST' '{"id":"'"${id}"'"}'
369 if (( 0 != "${CURL_EXIT_CODE}" )); then
370 msg
'Failed curl call' f
372 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
374 if (( 200 != $code )); then
375 msg
'Failed to vote a candidates' f
377 msg
'Candidate voted' s
384 # --------------------------------------
387 # @param string $1 List count
388 # @param string $2 Candidate id
389 # @param string $3 Candidate name
390 # @param string $4 Candidate votes
391 # --------------------------------------
392 function testVotesReport
{
398 echo '========================================'
399 msg
'Test votes report'
401 callRestApi
'/report' 'GET'
403 if (( 0 != "${CURL_EXIT_CODE}" )); then
404 msg
'Failed curl call' f
406 local code
="$(getValueFromHeader "${CURL_RESPONSE_HEADER}" "code
")"
408 if (( 200 != $code )); then
409 msg
'Failed to get votes report' f
413 local rcount
="$(countItemsInJsonList "${CURL_RESPONSE_DATA}")"
414 flag
=$
([[ "${rcount}" == "${count}" ]] && echo "s" ||
echo "f")
415 msg
"List count (${count}, ${rcount})" "${flag}"
417 local rname
="$(getNameFromId "${CURL_RESPONSE_DATA}" "${id}")"
418 flag
=$
([[ "${rname}" == "${name}" ]] && echo "s" ||
echo "f")
419 msg
"Candidate name (${name}, ${rname})" "${flag}"
421 local rvotes
="$(getVotesFromId "${CURL_RESPONSE_DATA}" "${id}")"
422 flag
=$
([[ "${rvotes}" == "${votes}" ]] && echo "s" ||
echo "f")
423 msg
"Candidate votes (${votes}, ${rvotes})" "${flag}"
430 # ====================================================================
432 # Reset database (delete and create)
433 # ----------------------------------
435 rm -f database.sqlite
436 sqlite3 database.sqlite
< votar.sql
438 # First Test (One Candidate)
439 # --------------------------
441 testDeleteAllCandidates
446 CANDIATE_0_NAME
='FIRST_TEST'
447 testCreateCandidate
"${CANDIATE_0_NAME}"
448 CANDIATE_0_ID
="${NEW_ID}"
451 testDeleteCandidate
"${CANDIATE_0_ID}"
454 testCreateCandidate
"${CANDIATE_0_NAME}"
455 CANDIATE_0_ID
="${NEW_ID}"
457 testGetCandidates
1 "${CANDIATE_0_ID}" "${CANDIATE_0_NAME}"
459 testVoteCandiate
"${CANDIATE_0_ID}"
461 testVotesReport
1 "${CANDIATE_0_ID}" "${CANDIATE_0_NAME}" 1
463 testDeleteAllCandidates
468 # Second Test (Multiple Candidates)
469 # ---------------------------------
471 testDeleteAllCandidates
476 CANDIATE_1_NAME
='Mate'
477 testCreateCandidate
"${CANDIATE_1_NAME}"
478 CANDIATE_1_ID
="${NEW_ID}"
479 testGetCandidates
1 "${CANDIATE_1_ID}" "${CANDIATE_1_NAME}"
482 CANDIATE_2_NAME
='Tea'
483 testCreateCandidate
"${CANDIATE_2_NAME}"
484 CANDIATE_2_ID
="${NEW_ID}"
485 testGetCandidates
2 "${CANDIATE_2_ID}" "${CANDIATE_2_NAME}"
488 CANDIATE_3_NAME
='Coffee'
489 testCreateCandidate
"${CANDIATE_3_NAME}"
490 CANDIATE_3_ID
="${NEW_ID}"
491 testGetCandidates
3 "${CANDIATE_3_ID}" "${CANDIATE_3_NAME}"
494 CANDIATE_TMP_NAME
='TEMPORAL'
495 testCreateCandidate
"${CANDIATE_TMP_NAME}"
496 CANDIATE_TMP_ID
="${NEW_ID}"
497 testGetCandidates
4 "${CANDIATE_TMP_ID}" "${CANDIATE_TMP_NAME}"
498 testDeleteCandidate
"${CANDIATE_TMP_ID}"
501 testVoteCandiate
"${CANDIATE_1_ID}"
502 testVoteCandiate
"${CANDIATE_1_ID}"
503 testVoteCandiate
"${CANDIATE_1_ID}"
504 testVoteCandiate
"${CANDIATE_2_ID}"
505 testVoteCandiate
"${CANDIATE_2_ID}"
506 testVoteCandiate
"${CANDIATE_3_ID}"
508 testVotesReport
3 "${CANDIATE_1_ID}" "${CANDIATE_1_NAME}" 3
509 testVotesReport
3 "${CANDIATE_2_ID}" "${CANDIATE_2_NAME}" 2
510 testVotesReport
3 "${CANDIATE_3_ID}" "${CANDIATE_3_NAME}" 1
512 testDeleteCandidate
"${CANDIATE_3_ID}"
516 testVotesReport
2 "${CANDIATE_1_ID}" "${CANDIATE_1_NAME}" 3
517 testVotesReport
2 "${CANDIATE_2_ID}" "${CANDIATE_2_NAME}" 2
519 testDeleteAllCandidates