#!/usr/bin/env bash set -euo pipefail PASS=0; FAIL=0 ok() { echo " ✓ $*"; PASS=$((PASS+1)); } fail(){ echo " ✗ $*"; FAIL=$((FAIL+1)); } APP_URL="${APP_URL:-https://nimuli.com}" PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)" echo "" echo "═══════════════════════════════════════════" echo " Nimuli — Modal & Layout Verify" echo " $(date '+%Y-%m-%d %H:%M:%S')" echo "═══════════════════════════════════════════" # ── 1. PHP / Composer ───────────────────────── echo "" echo "[ 1 ] Dependencies" cd "$PROJECT_DIR" docker compose exec -T app php artisan --version &>/dev/null && ok "Laravel reachable" || fail "Laravel not reachable" # ── 2. wire-elements-modal present once ─────── echo "" echo "[ 2 ] Modal container in layout" LAYOUT="resources/views/layouts/nimuli-app.blade.php" MODAL_COUNT=$(grep -c "wire-elements-modal\|livewire-ui-modal" "$LAYOUT" || true) if [ "$MODAL_COUNT" -eq 1 ]; then ok "Exactly 1 modal container in layout" elif [ "$MODAL_COUNT" -eq 0 ]; then fail "No modal container found in layout" else fail "Duplicate modal containers ($MODAL_COUNT) — remove one" fi # ── 3. Echo in bootstrap.js ─────────────────── echo "" echo "[ 3 ] Laravel Echo" if grep -q "new Echo" "resources/js/bootstrap.js"; then ok "Echo instantiated in bootstrap.js" else fail "Echo missing from bootstrap.js" fi # ── 4. Cookie theme ─────────────────────────── echo "" echo "[ 4 ] Theme cookie" if grep -q "nimuli_theme" "bootstrap/app.php"; then ok "nimuli_theme excluded from cookie encryption" else fail "nimuli_theme not excluded from EncryptCookies" fi if grep -q "document.cookie.*nimuli_theme" "resources/js/bootstrap.js"; then ok "Theme cookie written in Alpine store (bootstrap.js)" else fail "Alpine theme store does not write cookie in bootstrap.js" fi if grep -q "request()->cookie('nimuli_theme')" "resources/views/layouts/nimuli-app.blade.php"; then ok "Layout reads theme cookie server-side" else fail "Layout does not read theme cookie server-side" fi # ── 5. PNG icons ────────────────────────────── echo "" echo "[ 5 ] Manifest icons" for f in favicon-16x16.png favicon-32x32.png apple-touch-icon.png android-chrome-192x192.png android-chrome-512x512.png; do if [ -f "public/$f" ]; then ok "$f present" else fail "$f missing from public/" fi done # ── 6. Modal component files ────────────────── echo "" echo "[ 6 ] Modal Livewire components" MODALS=( "app/Livewire/Modals/CreateLink.php" "app/Livewire/Modals/EditLink.php" "app/Livewire/Modals/DeleteLink.php" "app/Livewire/Modals/CreateWorkspace.php" "app/Livewire/Modals/DeleteWorkspace.php" "app/Livewire/Modals/InviteMember.php" "app/Livewire/Modals/EditMemberRole.php" "app/Livewire/Modals/RemoveMember.php" "app/Livewire/Modals/CreateWebhook.php" "app/Livewire/Modals/DeleteWebhook.php" "app/Livewire/Modals/CreateApiToken.php" "app/Livewire/Modals/RevokeApiToken.php" "app/Livewire/Modals/ConfirmAction.php" ) for modal in "${MODALS[@]}"; do if [ -f "$modal" ]; then ok "$(basename "$modal" .php)" else fail "MISSING: $modal" fi done # ── 7. Tests ────────────────────────────────── echo "" echo "[ 7 ] Test suite" TEST_OUT=$(docker compose exec -T app php artisan test 2>&1 || true) echo "$TEST_OUT" | tail -5 if echo "$TEST_OUT" | grep -qE "Tests:.*[1-9][0-9]* failed"; then fail "Test suite has failures — see output above" else ok "All tests pass" fi # ── 7b. Chart.js global ─────────────────────── echo "" echo "[ 7b ] Chart.js global" if grep -q "window\.Chart = Chart" "resources/js/bootstrap.js"; then ok "window.Chart registered in bootstrap.js" else fail "window.Chart missing from bootstrap.js" fi if grep -q "optimizeDeps" "vite.config.js"; then ok "optimizeDeps configured in vite.config.js" else fail "optimizeDeps missing from vite.config.js" fi # ── 8. Build compiles ───────────────────────── echo "" echo "[ 8 ] Vite build" if npm run build 2>&1 | grep -q "built in"; then ok "Vite build clean" else fail "Vite build errors — check output" fi # ── 9. Seeders ──────────────────────────────── echo "" echo "[ 9 ] Dev user seeder" DB_USER=$(sed -n 's/^DB_USERNAME=//p' "$PROJECT_DIR/.env") DB_PASS=$(sed -n 's/^DB_PASSWORD=//p' "$PROJECT_DIR/.env") DB_NAME=$(sed -n 's/^DB_DATABASE=//p' "$PROJECT_DIR/.env") USER_CNT=$(docker compose exec -T mysql mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" \ -se "SELECT COUNT(*) FROM users WHERE email='nexxo@nimuli.com';" 2>/dev/null || echo "0") if [ "${USER_CNT:-0}" -gt 0 ]; then ok "nexxo@nimuli.com exists in DB" else fail "nexxo@nimuli.com not found — run: php artisan db:seed" fi # ── 10. Modal trigger coverage ──────────────── echo "" echo "[ 10 ] Modal trigger coverage" declare -A TRIGGERS=( ["resources/views/livewire/pages/links/index.blade.php"]="create-link" ["resources/views/livewire/pages/qr-codes/index.blade.php"]="create-qr-code" ["resources/views/livewire/pages/bio/index.blade.php"]="create-bio-page" ["resources/views/livewire/pages/domains/index.blade.php"]="add-domain" ["resources/views/livewire/pages/team/members.blade.php"]="invite-member" ["resources/views/livewire/pages/settings/webhooks.blade.php"]="create-webhook" ["resources/views/livewire/pages/profile/security.blade.php"]="delete-account" ) for view in "${!TRIGGERS[@]}"; do modal="${TRIGGERS[$view]}" if [ -f "$view" ] && grep -q "$modal" "$view"; then ok "$(basename "$view" .blade.php) → $modal" elif [ ! -f "$view" ]; then fail "VIEW MISSING: $view" else fail "$(basename "$view" .blade.php) missing trigger for $modal" fi done # ── 11. Sidebar collapse store ───────────────── echo "" echo "[ 11 ] Sidebar Alpine store" if grep -q "collapsed" "resources/js/bootstrap.js"; then ok "sidebar.collapsed in Alpine store" else fail "sidebar.collapsed missing from Alpine store" fi if grep -q "sidebarCollapsed" "resources/js/bootstrap.js"; then ok "localStorage.sidebarCollapsed persisted" else fail "localStorage persistence missing from sidebar store" fi # ── 12. CurrentWorkspace service ────────────── echo "" echo "[ 12 ] Octane-safe CurrentWorkspace" if [ -f "app/Domains/Workspace/Services/CurrentWorkspace.php" ]; then ok "CurrentWorkspace service exists" else fail "CurrentWorkspace service MISSING" fi if [ -f "app/Listeners/ResetCurrentWorkspace.php" ]; then ok "ResetCurrentWorkspace listener exists" else fail "ResetCurrentWorkspace listener MISSING" fi if [ -f "app/helpers.php" ]; then ok "app/helpers.php exists" else fail "app/helpers.php MISSING" fi if grep -q "helpers.php" "composer.json"; then ok "helpers.php autoloaded in composer.json" else fail "helpers.php not autoloaded in composer.json" fi # ── Summary ─────────────────────────────────── echo "" echo "═══════════════════════════════════════════" TOTAL=$((PASS + FAIL)) echo " Passed: $PASS / $TOTAL" if [ "$FAIL" -gt 0 ]; then echo " Failed: $FAIL" echo "═══════════════════════════════════════════" echo "" exit 1 else echo " All checks passed ✓" echo "═══════════════════════════════════════════" echo "" fi