5 echo "Usage:$0 <URL-to-test>"
9 echo "Error: No test URL given." >&2
16 CURL="curl --silent --show-error"
22 echo $1 | sed -e "s/./$2/g"
38 printf "%*s" $(( 52 - ${#1} )) | tr ' ' '.'
39 (( tests_total++ )) || true
42 # Result of test depends on the exit status of last command
48 (( tests_failed++ )) || true
52 # If we got an argument, append it after test result
60 # Print report of all previous test results
67 if [ "$tests_failed" == "" ]; then
68 echo "All $tests_total tests passed."
72 echo "$tests_failed of $tests_total tests failed."
78 # Does a string contain a regular expression pattern
82 # contains "All's well that ends well" "s.well"
88 # POST to a URL endpoint with optional JSON data
92 # curl_post <ENDPOINT> [data] [CURL_OPTIONS]
95 $CURL ${3:-} -X POST ${2:+-H 'Content-Type: application/json' -d "$2"} $URL/$1
98 # PUT to a URL endpoint with optional JSON data
102 # curl_post <ENDPOINT> [data] [CURL_OPTIONS]
105 $CURL ${3:-} -X PUT ${2:+-H 'Content-Type: application/json' -d "$2"} $URL/$1
108 # GET from a URL endpoint
112 # curl_get <ENDPOINT> [CURL_OPTIONS]
118 # Create a new game of the specified engine type
125 curl_post new/$1 | jq -r .
128 TEST_SECTION "LMNO (super-site for games)"
130 TEST_SUBSECTION "Testing home page"
131 home_page=$($CURL $URL)
133 TEST "Contains 'Join Game'"
134 contains "$home_page" "Join Game"
137 TEST "Contains 'Host a new game'"
138 contains "$home_page" "Host a new game"
141 TEST_SUBSECTION "Creating some new games"
144 empires_game_id=$(new_game empires)
145 test "$empires_game_id" != ""
146 TEST_END $empires_game_id
149 tictactoe_game_id=$(new_game tictactoe)
150 test "$tictactoe_game_id" != ""
151 TEST_END $tictactoe_game_id
153 TEST_SUBSECTION "Test redirects"
155 TEST "Redirect of /GAMEID at top level"
156 redirect=$(curl_get $empires_game_id)
157 test "$redirect" = "Moved Permanently. Redirecting to /empires/$empires_game_id/"
160 TEST "Redirect of lowercase /gameid at top level"
161 empires_game_id_lower=$(tr '[:upper:]' '[:lower:]' <<< $empires_game_id)
162 redirect=$(curl_get $empires_game_id_lower)
163 test "$redirect" = "Moved Permanently. Redirecting to /$empires_game_id/"
166 TEST "Redirect of lowercase /empires/gameid"
167 redirect=$(curl_get empires/$empires_game_id_lower)
168 test "$redirect" = "Moved Permanently. Redirecting to /empires/$empires_game_id/"
171 TEST_SECTION "Empires game"
173 empires_game_path=empires/$empires_game_id
175 TEST_SUBSECTION "Empires game /register"
179 curl_post $empires_game_path/register "{\"name\": \"$1\", \"character\": \"$2\"}"
182 empires_players_string()
184 curl_get $empires_game_path/players | jq -r .[].name | tr '\n' ','
187 empires_characters_string()
189 curl_get $empires_game_path/characters | jq -r .[] | tr '\n' ','
192 TEST "Registering a player returns an ID"
193 carl_id=$(empires_register Carl "Bugs Bunny" | jq -r .)
194 test "$carl_id" = "1"
197 TEST "Registering several more players"
198 empires_register Richard "Bob Hope" > /dev/null
199 empires_register Kevin "Elvis Presley" > /dev/null
200 empires_register Stacy Phineas > /dev/null
201 empires_register David "Red Power Ranger" > /dev/null
202 empires_register Nancy "Audrey Hepburn" > /dev/null
203 bogus_id=$(empires_register Bogus "Mr. Bogus")
206 TEST 'Verify complete players list (with "Bogus")'
207 players=$(empires_players_string)
208 test "$players" = "Carl,Richard,Kevin,Stacy,David,Nancy,Bogus,"
211 TEST 'Verify complete players list (with "Mr. Bogus")'
212 characters=$(empires_characters_string)
213 test "$characters" = "Bugs Bunny,Bob Hope,Elvis Presley,Phineas,Red Power Ranger,Audrey Hepburn,Mr. Bogus,"
216 TEST_SUBSECTION "Empires game /deregister"
220 curl_post $empires_game_path/deregister/$1
223 TEST "Removing the bogus player"
224 empires_deregister $bogus_id
227 TEST 'Verify modified players list (w/o "Bogus")"'
228 players=$(empires_players_string)
229 test "$players" = "Carl,Richard,Kevin,Stacy,David,Nancy,"
232 TEST 'Verify modified characters list (w/o "Mr. Bogus")'
233 characters=$(empires_characters_string)
234 test "$characters" = "Bugs Bunny,Bob Hope,Elvis Presley,Phineas,Red Power Ranger,Audrey Hepburn,"
237 TEST_SUBSECTION "Empires game /capture"
241 curl_post $empires_game_path/capture/$1/$2
244 empires_empires_string()
246 # Get empires as a compact string (much more compact than JSON)
247 curl_get $empires_game_path/empires | jq -c '.[] | [.id,.captures]' | tr '\n' ','
250 TEST "Verify empires before any captures"
251 empires=$(empires_empires_string)
252 test "$empires" = "[1,[]],[2,[]],[3,[]],[4,[]],[5,[]],[6,[]],"
255 TEST "Perform some captures"
262 TEST "Verify empires after captures"
263 empires=$(empires_empires_string)
264 test "$empires" = "[1,[2]],[2,[]],[3,[5,4]],[4,[6]],[5,[]],[6,[]],"
267 TEST_SUBSECTION "Empires game /liberate"
271 curl_post $empires_game_path/liberate/$1
274 TEST "Liberate a player"
278 TEST "Verify empires after liberate"
279 empires=$(empires_empires_string)
280 test "$empires" = "[1,[]],[2,[]],[3,[5,4]],[4,[6]],[5,[]],[6,[]],"
283 TEST_SUBSECTION "Empires game /reset"
287 curl_post $empires_game_path/reset
290 TEST "Reset the game"
294 TEST "Verify players is now empty"
295 players=$(empires_players_string)
299 TEST_SECTION "Tic Tac Toe game"
301 tictactoe_game_path=tictactoe/$tictactoe_game_id
305 curl_put /profile "{ \"nickname\": \"$1\" }" "-c .cookie-tictactoe"
310 curl_post $tictactoe_game_path/move "{ \"move\": $1 }" "-b .cookie-tictactoe"
313 tictactoe_player_info()
315 curl_get $tictactoe_game_path/events "-m 0.1 -b .cookie-tictactoe" 2>&1 \
316 | grep player-info -A 1 \
320 tictactoe_player_name()
322 curl_put $tictactoe_game_path/player "{ \"name\": \"$1\" }" "-b .cookie-tictactoe"
325 tictactoe_player_team()
327 curl_put $tictactoe_game_path/player "{ \"team\": \"$1\" }" "-b .cookie-tictactoe"
330 TEST_SUBSECTION "Tic Tac Toe player-info"
332 TEST "Hit LMNO /profile to set name to 'curl'"
333 tictactoe_profile curl
336 TEST "Verify player-info event reports 'curl' name"
337 result=$(tictactoe_player_info)
338 test "$result" = 'data: {"id":1,"name":"curl","team":""}'
341 TEST_SUBSECTION "Tic Tac Toe /player"
343 TEST "Change name to 'newname'"
344 tictactoe_player_name newname
345 result=$(tictactoe_player_info)
346 test "$result" = 'data: {"id":1,"name":"newname","team":""}'
349 TEST "Change team to 'X'"
350 tictactoe_player_team X
351 result=$(tictactoe_player_info)
352 test "$result" = 'data: {"id":1,"name":"newname","team":"X"}'
355 TEST "Change team to 'O'"
356 tictactoe_player_team O
357 result=$(tictactoe_player_info)
358 test "$result" = 'data: {"id":1,"name":"newname","team":"O"}'
361 TEST "Verify cannot change team to 'Z'"
362 tictactoe_player_team Z
363 result=$(tictactoe_player_info)
364 test "$result" = 'data: {"id":1,"name":"newname","team":"O"}'
367 TEST "Leave current team"
368 tictactoe_player_team ""
369 result=$(tictactoe_player_info)
370 test "$result" = 'data: {"id":1,"name":"newname","team":""}'
373 TEST_SUBSECTION "Tic Tac Toe /move"
375 TEST "First move doesn't require a team"
376 result=$(tictactoe_move 0)
377 test "$result" = '{"legal":true}'
380 TEST "Second move does require a team"
381 result=$(tictactoe_move 4)
382 test "$result" = '{"legal":false,"message":"It'"'"'s not your turn to move"}'
385 TEST "Illegal to move when it's not your turn"
386 tictactoe_player_team X
387 result=$(tictactoe_move 4)
388 test "$result" = '{"legal":false,"message":"It'"'"'s not your turn to move"}'
391 TEST "Legal move to center square"
392 tictactoe_player_team O
393 result=$(tictactoe_move 4)
394 test "$result" = '{"legal":true}'
397 TEST "Move to center square again is now illegal"
398 tictactoe_player_team X
399 result=$(tictactoe_move 4)
400 test "$result" = '{"legal":false,"message":"Square is already occupied"}'
403 TEST_SECTION "Empathy game"
405 TEST_SUBSECTION "Create a game and register 3 players"
407 TEST "Create the game"
408 empathy_game_id=$(new_game empathy)
409 test "$empathy_game_id" != ""
410 TEST_END $empathy_game_id
412 empathy_game_path=empathy/$empathy_game_id
416 cookie_file=".cookie-empathy-$1"
417 curl_put /profile "{ \"nickname\": \"$1\" }" "-c $cookie_file"
423 curl_get $1 "-m 0.1 $3" 2>&1 \
424 | grep "^event: $2" -A 1 \
426 | sed -e 's,^data: *,,'
429 empathy_player_name()
431 curl_get_event $empathy_game_path/events player-info "-b $1" | jq -r .name
434 TEST "Set 'alice' in session"
435 alice=$(empathy_profile alice)
436 test "$alice" = ".cookie-empathy-alice"
439 TEST "Register alice and verify name"
440 result=$(empathy_player_name $alice)
441 test "$result" = "alice"
445 bob=$(empathy_profile bob)
446 result=$(empathy_player_name $bob)
447 test "$result" = "bob"
450 TEST "Register charlie"
451 charlie=$(empathy_profile charlie)
452 result=$(empathy_player_name $charlie)
453 test "$result" = "charlie"
456 TEST_SUBSECTION "Category selection"
458 empathy_submit_prompt()
460 curl_post $empathy_game_path/prompts "{ \"items\": $2, \"prompt\": \"$3\"}" "-b $1"
463 TEST "Huge numbers are rejected"
464 result=$(empathy_submit_prompt $alice 10000 "10,000 Maniacs")
465 test "$result" = '{"valid":false,"message":"Maximum number of items is 20"}'
468 TEST "Submit a category"
469 prompt_id=$(empathy_submit_prompt $alice 4 "4 things on a beach" | jq .id)
470 test "$prompt_id" = "1"
475 curl_post $empathy_game_path/vote/$2 "" "-b $1"
478 TEST "Vote on this category"
479 empathy_vote $alice $prompt_id
485 curl_post $empathy_game_path/start/$2 "" "-b $1"
488 TEST "Start the game with this category"
489 empathy_start $alice $prompt_id
495 curl_post $empathy_game_path/answer/$2 "{ \"answers\": [$3]}" "-b $1"
498 TEST_SUBSECTION "Submitting answers"
500 TEST "Submit from a non-player fails"
501 result=$(empathy_answer bogus $prompt_id '"Sun", "Sand", "Water", "People"')
502 test "$result" = '{"valid":false,"message":"Player not found"}'
505 TEST "Submit from alice succeeds"
506 result=$(empathy_answer $alice $prompt_id '"sun", "sand", "water", "people"')
507 test "$result" = '{"valid":true}'
510 TEST "Submit from bob succeeds"
511 result=$(empathy_answer $bob $prompt_id '"sand", "sands", "SunLight", "towels"')
512 test "$result" = '{"valid":true}'
515 empathy_ambiguities()
517 curl_get_event $empathy_game_path/events game-state "-b $1" \
521 TEST "Judging hasn't started with player unsubmitted"
522 result=$(echo $(empathy_ambiguities $alice))
523 test "$result" = "null"
526 TEST "Submit from charlie succeeds"
527 result=$(empathy_answer $charlie $prompt_id '"SunShine", "Grains of Sand", "wafer", "people"')
528 test "$result" = '{"valid":true}'
531 TEST_SUBSECTION "Transition from answering to judging (no voting needed)"
533 TEST "Judging already started"
534 result=$(echo $(empathy_ambiguities $alice))
535 test "$result" != "null"
538 TEST_SUBSECTION "Judging answers"
540 empathy_ambiguities_list()
542 curl_get_event $empathy_game_path/events game-state "-b $1" \
546 TEST "Received all unique words"
547 # echo here is to strip newlines
548 result=$(echo $(empathy_ambiguities_list $alice))
549 test "$result" = '"Grains of Sand" "people" "sand" "sands" "sun" "SunLight" "SunShine" "towels" "wafer" "water"'
554 curl_post $empathy_game_path/judged/$2 "{ \"word_groups\": $3}" "-b $1"
557 TEST "Submit word groups from alice"
558 result=$(empathy_judged $alice $prompt_id '[["sun","SunLight","SunShine"],["sand","sands","Grains of Sand"],["water","wafer"]]')
559 test "$result" = '{"valid":true}'
562 TEST "Submit word groups from bob"
563 result=$(empathy_judged $bob $prompt_id '[["sands","grains of sand"],["water","wafer"]]')
564 test "$result" = '{"valid":true}'
569 curl_get_event $empathy_game_path/events game-state "-b $1" \
573 TEST "Scoring hasn't started with player unsubmitted"
574 result=$(echo $(empathy_scores $alice))
575 test "$result" = "null"
578 TEST "Submit word groups from charlie"
579 result=$(empathy_judged $charlie $prompt_id '[["SunLight","SunShine"],["sand","Grains of Sand"]]')
580 test "$result" = '{"valid":true}'
583 TEST_SUBSECTION "Transition from judging to scoring (no voting needed)"
585 TEST "Scoring already started"
586 result=$(echo $(empathy_scores $alice))
587 test "$result" != "null"
590 empathy_scores_names_numbers()
592 curl_get_event $empathy_game_path/events game-state "-b $1" \
593 | jq '.scores.scores[]|.player,.score'
596 TEST_SUBSECTION "Scoring"
598 TEST "Verify final scores as expected"
599 # echo here is to strip newlines
600 result=$(echo $(empathy_scores_names_numbers $alice))
601 test "$result" = '"charlie" 9 "alice" 8 "bob" 6'
604 empathy_words_submitted()
606 curl_get_event $empathy_game_path/events game-state "-b $1" \
607 | jq '.scores.words[].word'
610 TEST "Verify final list of words submitted"
611 # echo here is to strip newlines
612 result=$(echo $(empathy_words_submitted $alice))
613 test "$result" = '"Grains of Sand/sand/sands" "SunLight/SunShine" "wafer/water" "people" "sun" "towels"'
616 TEST_SUBSECTION "New game (using voting to advance phases)"
620 curl_post $empathy_game_path/reset
623 TEST "Any post to /reset resets the game"
628 TEST "Verify scoring is over"
629 result=$(echo $(empathy_scores $alice))
630 test "$result" = "null"
635 curl_post $empathy_game_path/answering/$2 "" "-b $1"
638 TEST "Start 4-player game, 3 submissions"
639 dale=$(empathy_profile dale)
640 result=$(empathy_player_name $dale)
641 test "$result" = "dale"
642 prompt_id=$(empathy_submit_prompt $alice 4 "3 little words" | jq .id)
643 empathy_start $alice $prompt_id
644 empathy_answer $alice $prompt_id '"I", "love", "you"' >/dev/null
645 empathy_answer $bob $prompt_id '"I", "love", "food"' >/dev/null
646 empathy_answer $charlie $prompt_id '"food", "is", "good"' >/dev/null
647 result=$(empathy_answering $dale $prompt_id)
648 test "$result" = '{"valid":true}'
651 TEST "Judging hasn't started with player unsubmitted"
652 result=$(echo $(empathy_ambiguities $alice))
653 test "$result" = "null"
656 empathy_end_answers()
658 curl_post $empathy_game_path/end-answers/$2 "" "-b $1"
661 TEST "Minority of players vote to end answering"
662 empathy_end_answers $alice $prompt_id
663 empathy_end_answers $bob $prompt_id
667 TEST "Judging still hasn't started"
668 result=$(echo $(empathy_ambiguities $alice))
669 test "$result" = "null"
672 TEST "Majority of players vote to end answering"
673 empathy_end_answers $charlie $prompt_id
677 TEST "Judging has now started"
678 result=$(echo $(empathy_ambiguities $alice))
679 test "$result" != "null"
682 TEST "Submit word groups from majority"
683 empathy_judged $alice $prompt_id '[]' >/dev/null
684 result=$(empathy_judged $bob $prompt_id '[]')
685 test "$result" = '{"valid":true}'
688 TEST "Scoring hasn't started with player unsubmitted"
689 result=$(echo $(empathy_scores $alice))
690 test "$result" = "null"
693 empathy_end_judging()
695 curl_post $empathy_game_path/end-judging/$2 "" "-b $1"
698 TEST "Minority of players vote to end judging"
699 empathy_end_judging $alice $prompt_id
703 TEST "Scoring still hasn't started"
704 result=$(echo $(empathy_scores $alice))
705 test "$result" = "null"
708 TEST "Majority of players vote to end judging"
709 empathy_end_judging $bob $prompt_id
713 TEST "Scoring has now started"
714 result=$(echo $(empathy_scores $alice))
715 test "$result" != "null"