|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Tests Next Build's use of JSON:API and the Decoupled Router. |
| 3 | +# |
| 4 | +# Usage: next-build.sh [env-name] |
| 5 | +# env-name: Optional environment name (e.g., tugboat, dev, staging, prod) |
| 6 | +# Maps to next/envs/.env.{env-name} |
| 7 | +# If not provided, auto-detects from CMS_ENVIRONMENT_TYPE |
| 8 | + |
| 9 | +set -euo pipefail |
| 10 | + |
| 11 | +export NVM_DIR="$HOME/.nvm" |
| 12 | +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" |
| 13 | +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" |
| 14 | +source ~/.bashrc |
| 15 | + |
| 16 | +repo_root="$(git rev-parse --show-toplevel)" |
| 17 | +# shellcheck source=/dev/null |
| 18 | +source "${repo_root}/.env" |
| 19 | + |
| 20 | +# Determine APP_ENV: use argument if provided, otherwise auto-detect from CMS_ENVIRONMENT_TYPE |
| 21 | +if [ -n "${1:-}" ]; then |
| 22 | + if [ "$1" = "local" ]; then |
| 23 | + APP_ENV="example" |
| 24 | + else |
| 25 | + APP_ENV="$1" |
| 26 | + fi |
| 27 | +else |
| 28 | + # Auto-detect based on CMS_ENVIRONMENT_TYPE |
| 29 | + case "${CMS_ENVIRONMENT_TYPE:-}" in |
| 30 | + tugboat) APP_ENV="tugboat" ;; |
| 31 | + prod) APP_ENV="prod" ;; |
| 32 | + staging) APP_ENV="staging" ;; |
| 33 | + dev) APP_ENV="dev" ;; |
| 34 | + *) APP_ENV="" ;; # Fall back to env-loader defaults |
| 35 | + esac |
| 36 | +fi |
| 37 | + |
| 38 | +if [ -n "${APP_ENV}" ]; then |
| 39 | + echo "Using APP_ENV: ${APP_ENV}" |
| 40 | +fi |
| 41 | + |
| 42 | +DRUPAL_ADDRESS="${DRUPAL_ADDRESS:-${DRUSH_OPTIONS_URI:-http://localhost}}" |
| 43 | +FAILURES=0 |
| 44 | + |
| 45 | +# Generic HTTP test helper - returns body on stdout, exits non-zero on failure |
| 46 | +http_get() { |
| 47 | + local url="$1" |
| 48 | + local response body http_code |
| 49 | + response=$(curl -gsS -w '\n%{http_code}' "$url" 2>&1) || return 1 |
| 50 | + http_code="${response##*$'\n'}" |
| 51 | + body="${response%$'\n'*}" |
| 52 | + |
| 53 | + if [[ "$http_code" != 200 ]]; then |
| 54 | + echo "HTTP $http_code: $url" >&2 |
| 55 | + return 1 |
| 56 | + fi |
| 57 | + printf '%s' "$body" |
| 58 | +} |
| 59 | + |
| 60 | +run_test() { |
| 61 | + local name="$1"; shift |
| 62 | + printf 'Testing: %s... ' "$name" |
| 63 | + out=`$@` |
| 64 | + exit_code="$?" |
| 65 | + if [ "$exit_code" = "0" ]; then |
| 66 | + echo "PASSED" |
| 67 | + else |
| 68 | + echo "FAILED: Test '$name' failed with the above output" |
| 69 | + ((FAILURES++)) || true |
| 70 | + fi |
| 71 | +} |
| 72 | + |
| 73 | +# Test assertions |
| 74 | +assert_json_path() { |
| 75 | + local body="$1" path="$2" |
| 76 | + jq -e "$path" <<<"$body" >/dev/null |
| 77 | +} |
| 78 | + |
| 79 | +router_get_uuid() { |
| 80 | + local path="$1" |
| 81 | + local body |
| 82 | + body=$(http_get "${DRUPAL_ADDRESS}/router/translate-path?path=$(jq -rn --arg p "$path" '$p|@uri')") || return 1 |
| 83 | + assert_json_path "$body" '.jsonapi.individual' || return 1 |
| 84 | + jq -r '.entity.uuid' <<<"$body" |
| 85 | +} |
| 86 | + |
| 87 | +router_has_uuid() { |
| 88 | + local uuid |
| 89 | + uuid=$(router_get_uuid "$1") || return 1 |
| 90 | + [[ -n "$uuid" && "$uuid" != "null" ]] |
| 91 | + |
| 92 | + printf "$uuid... " |
| 93 | +} |
| 94 | + |
| 95 | +jsonapi_has_data() { |
| 96 | + local endpoint="$1" |
| 97 | + local body |
| 98 | + body=$(http_get "${DRUPAL_ADDRESS}${endpoint}") || return 1 |
| 99 | + |
| 100 | + echo $body | jq -rj '.data[0].id' |
| 101 | + printf '... ' |
| 102 | + |
| 103 | + assert_json_path "$body" '.data[0].id' |
| 104 | +} |
| 105 | + |
| 106 | +router_to_jsonapi_flow() { |
| 107 | + local path="$1" content_type="$2" |
| 108 | + local uuid jsonapi_body |
| 109 | + |
| 110 | + uuid=$(router_get_uuid "$path") || return 1 |
| 111 | + [[ -n "$uuid" && "$uuid" != "null" ]] || return 1 |
| 112 | + |
| 113 | + jsonapi_body=$(http_get "${DRUPAL_ADDRESS}/jsonapi/node/${content_type}/${uuid}") || return 1 |
| 114 | + [[ "$(jq -r '.data.id' <<<"$jsonapi_body")" == "$uuid" ]] |
| 115 | +} |
| 116 | + |
| 117 | +next_build() { |
| 118 | + cd ./next || return 1 |
| 119 | + # silence npm install stderr which outputs when the node version is already installed |
| 120 | + nvm install 2>/dev/null && nvm use || return 1 |
| 121 | + APP_ENV="${APP_ENV}" BUILD_OPTION=static yarn export || return 1 |
| 122 | + cd .. |
| 123 | +} |
| 124 | + |
| 125 | +echo "Testing against: ${DRUPAL_ADDRESS}" |
| 126 | +echo "" |
| 127 | + |
| 128 | +# Router tests |
| 129 | +run_test "Router: VAMC system page" router_has_uuid "/boston-health-care" |
| 130 | +run_test "Router: Event listing" router_has_uuid "/boston-health-care/events" |
| 131 | +run_test "Router: Story listing" router_has_uuid "/boston-health-care/stories" |
| 132 | +run_test "Router: Locations listing" router_has_uuid "/boston-health-care/locations" |
| 133 | + |
| 134 | +# JSON:API tests |
| 135 | +run_test "JSON:API: VAMC system nodes" jsonapi_has_data "/jsonapi/node/health_care_region_page?page[limit]=1" |
| 136 | +run_test "JSON:API: Event listing nodes" jsonapi_has_data "/jsonapi/node/event_listing?page[limit]=1" |
| 137 | +run_test "JSON:API: Story listing nodes" jsonapi_has_data "/jsonapi/node/story_listing?page[limit]=1" |
| 138 | + |
| 139 | +# Full flow tests |
| 140 | +run_test "Flow: VAMC system" router_to_jsonapi_flow "/boston-health-care" "health_care_region_page" |
| 141 | +run_test "Flow: Event listing" router_to_jsonapi_flow "/boston-health-care/events" "event_listing" |
| 142 | + |
| 143 | +# Next-build test (ensure next-build is not broken in this environment) |
| 144 | +run_test "Build: next-build" next_build |
| 145 | + |
| 146 | +echo "" |
| 147 | +echo "Failures: $FAILURES" |
| 148 | + |
| 149 | +exit $((FAILURES > 0)) |
0 commit comments