226 lines
8.2 KiB
Bash
Executable File
226 lines
8.2 KiB
Bash
Executable File
#!/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
|