da1bd48444
- Decouple framework installation: add install-laravel.sh and install-cakephp.sh, isolate skills and docs per framework, and auto-clean leftover artifacts - Remove all SonarQube configs, templates, and references - Enforce comprehensive test completeness: 100% public methods, edge cases, full branch coverage, exception paths, and state assertions - Replace all placeholder assertions in PHPUnit and Pest templates with full realistic implementations - Rename and update 10-comprehensive-test-coverage-guide.md
21 KiB
Executable File
21 KiB
Executable File
#!/usr/bin/env bash
# ==============================================================================
# SMARTGIFT AI - PHP UNIT TESTING TOOLKIT INSTALLER
# Hỗ trợ: Tách biệt riêng biệt cho Laravel & CakePHP
# Cài đặt bộ công cụ Unit Test vào bất kỳ source code nào mà KHÔNG CẦN clone repo về máy.
#
# Cách cài Laravel:
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash -s -- --laravel
# (hoặc đứng trong thư mục Laravel và chạy: .../install.sh | bash -> Tự động nhận diện)
#
# Cách cài CakePHP:
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash -s -- --cakephp
# (hoặc đứng trong thư mục CakePHP và chạy: .../install.sh | bash -> Tự động nhận diện)
# ==============================================================================
set -e
GREEN=''
YELLOW=''
BLUE=''
RED=''
CYAN=''
BOLD=''
NC=''
# Remote Repository URL công khai qua HTTPS
DEFAULT_REPO="https://git.smartgift.io.vn/Smartgift-AI/agent-unit-testing.git"
REPO_URL="${SG_TEST_REPO:-${LARAVEL_TEST_REPO:-$DEFAULT_REPO}}"
TARGET_DIR=""
GLOBAL_MODE=false
FORCE_MODE=false
FRAMEWORK_CHOICE=""
for arg in "$@"; do
case "$arg" in
--global|-g)
GLOBAL_MODE=true
;;
--force|-f)
FORCE_MODE=true
;;
--laravel|-l)
FRAMEWORK_CHOICE="laravel"
;;
--cakephp|-c)
FRAMEWORK_CHOICE="cakephp"
;;
--framework=*)
FRAMEWORK_CHOICE="${arg#*=}"
;;
--help|-h)
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} SMARTGIFT AI: PHP UNIT TESTING TOOLKIT INSTALLER${NC}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "Cách dùng:"
echo -e " 1. Cài đặt chuyên biệt cho LARAVEL:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --laravel${NC}"
echo -e " (Hoặc đứng trong thư mục Laravel và gõ: curl -fsSL <URL>/install.sh | bash)"
echo -e ""
echo -e " 2. Cài đặt chuyên biệt cho CAKEPHP:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --cakephp${NC}"
echo -e " (Hoặc đứng trong thư mục CakePHP và gõ: curl -fsSL <URL>/install.sh | bash)"
echo -e ""
echo -e " 3. Cài đặt Toàn Cục vào máy tính (Global Mode):"
echo -e " - Cho Laravel: ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --global --laravel${NC}"
echo -e " - Cho CakePHP: ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --global --cakephp${NC}"
echo -e ""
echo -e " 4. Cài đặt vào thư mục chỉ định:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- /duong-dan/source-code --laravel${NC}"
exit 0
;;
-*)
# Bỏ qua các flag khác
;;
*)
if [ -z "$TARGET_DIR" ]; then
TARGET_DIR="$arg"
fi
;;
esac
done
TARGET_DIR="${TARGET_DIR:-.}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} 🚀 SMARTGIFT AI - PHP UNIT TESTING TOOLKIT${NC}"
echo -e "${BLUE}===================================================================${NC}"
# 1. Tìm hoặc Tải nguồn tài nguyên (Local nếu có, hoặc tải tạm qua Git)
CLEANUP_TEMP=false
PACKAGE_ROOT=""
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR=""
if [ -f "$SOURCE" ]; then
SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" 2>/dev/null && pwd || echo "")"
fi
if [ -n "$SCRIPT_DIR" ] && [ -d "$SCRIPT_DIR/.claude/skills" ]; then
PACKAGE_ROOT="$SCRIPT_DIR"
echo -e "${GREEN}✓ Sử dụng tài nguyên có sẵn tại local.${NC}"
else
echo -e "${YELLOW}📥 Đang tải bộ công cụ từ remote repository...${NC}"
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'sg_unit_testing')"
if ! git clone --depth 1 "$REPO_URL" "$TMP_DIR" --quiet 2>/dev/null; then
echo -e "${RED}❌ Không thể clone từ repository: $REPO_URL${NC}"
rm -rf "$TMP_DIR"
exit 1
fi
PACKAGE_ROOT="$TMP_DIR"
CLEANUP_TEMP=true
echo -e "${GREEN}✓ Tải thành công!${NC}"
fi
cleanup() {
if [ "$CLEANUP_TEMP" = true ] && [ -d "$PACKAGE_ROOT" ]; then
rm -rf "$PACKAGE_ROOT"
fi
}
trap cleanup EXIT
# 2. Xác định Framework mục tiêu (Tách biệt hoàn toàn Laravel vs CakePHP)
TARGET_DIR="$(cd "$TARGET_DIR" 2>/dev/null && pwd || echo "$TARGET_DIR")"
FRAMEWORK=""
if [ -n "$FRAMEWORK_CHOICE" ]; then
FRAMEWORK="$FRAMEWORK_CHOICE"
echo -e "${GREEN}✓ Đã chọn Framework theo chỉ định: ${FRAMEWORK}${NC}"
elif [ "$GLOBAL_MODE" = false ]; then
# Tự động nhận diện từ source code
if [ -f "$TARGET_DIR/artisan" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"laravel/framework"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="laravel"
echo -e "${GREEN}✓ Tự động nhận diện dự án: Laravel${NC}"
elif [ -f "$TARGET_DIR/bin/cake" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"cakephp/cakephp"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="cakephp"
echo -e "${GREEN}✓ Tự động nhận diện dự án: CakePHP${NC}"
elif [ ! -f "$TARGET_DIR/composer.json" ]; then
FILE_COUNT=$(ls -A "$TARGET_DIR" 2>/dev/null | wc -l | tr -d ' ')
if [ "$FILE_COUNT" -le 2 ] || [ "$FORCE_MODE" = true ]; then
FRAMEWORK="laravel"
echo -e "${YELLOW}ℹ Thư mục mới/trống: Mặc định chọn kiến trúc Laravel.${NC}"
else
echo -e "${RED}❌ Thư mục '$TARGET_DIR' chưa có composer.json. Vui lòng thêm cờ --laravel hoặc --cakephp.${NC}"
exit 1
fi
else
echo -e "${RED}❌ Không thể tự động nhận diện Framework trong '$TARGET_DIR'.${NC}"
echo -e "Vui lòng chỉ định rõ flag cài đặt:"
echo -e " - Laravel: ${CYAN}bash install.sh --laravel${NC}"
echo -e " - CakePHP: ${CYAN}bash install.sh --cakephp${NC}"
exit 1
fi
else
# Global mode mà không truyền flag framework
FRAMEWORK="laravel"
echo -e "${YELLOW}ℹ Chế độ toàn cục: Mặc định cài đặt cho Laravel (dùng --cakephp để đổi sang CakePHP).${NC}"
fi
# ==============================================================================
# 3. XỬ LÝ CÀI ĐẶT TOÀN CỤC (GLOBAL MODE)
# ==============================================================================
if [ "$GLOBAL_MODE" = true ]; then
mkdir -p "$HOME/.claude/skills"
mkdir -p "$HOME/.local/bin"
if [ "$FRAMEWORK" = "laravel" ]; then
echo -e "${YELLOW}⚙️ Đang cài đặt chế độ Toàn Cục cho LARAVEL vào $HOME/.claude/...${NC}"
rm -rf "$HOME/.claude/skills/cakephp-"* 2>/dev/null || true
cp -R "$PACKAGE_ROOT/.claude/skills/laravel-"* "$HOME/.claude/skills/"
mkdir -p "$HOME/.claude/testing-docs-laravel/templates"
cp "$PACKAGE_ROOT/docs/"*.md "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/docs/components" "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/templates/phpunit" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/pest" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/docker" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$HOME/.claude/testing-docs-laravel/templates/"
cat << 'SUB_EOF' > "$HOME/.local/bin/laravel-test-init"
#!/usr/bin/env bash
TARGET_DIR="${1:-.}"
SOURCE_DIR="$HOME/.claude/testing-docs-laravel"
if [ ! -d "$TARGET_DIR" ]; then echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!"; exit 1; fi
echo "🚀 Đang khởi tạo test runner Laravel tại: $TARGET_DIR"
if [ -f "$SOURCE_DIR/templates/docker/test-runner.sh" ]; then
cp "$SOURCE_DIR/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
echo " ✓ Đã tạo $TARGET_DIR/test-runner.sh"
fi
if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then
cp "$SOURCE_DIR/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh"
fi
SUB_EOF
chmod +x "$HOME/.local/bin/laravel-test-init"
echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC CHO LARAVEL HOÀN TẤT THÀNH CÔNG!${NC}"
echo -e "Tại bất kỳ dự án Laravel nào, mở Claude Code và sử dụng:"
echo -e " • Setup môi trường: ${CYAN}/laravel-test-setup --install${NC}"
echo -e " • Viết & chạy test: ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " • Lệnh terminal: ${CYAN}laravel-test-init${NC}"
exit 0
elif [ "$FRAMEWORK" = "cakephp" ]; then
echo -e "${YELLOW}⚙️ Đang cài đặt chế độ Toàn Cục cho CAKEPHP vào $HOME/.claude/...${NC}"
rm -rf "$HOME/.claude/skills/laravel-"* 2>/dev/null || true
cp -R "$PACKAGE_ROOT/.claude/skills/cakephp-"* "$HOME/.claude/skills/"
mkdir -p "$HOME/.claude/testing-docs-cakephp/templates"
cp "$PACKAGE_ROOT/docs/"*.md "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/docs/cakephp" "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/templates/cakephp" "$HOME/.claude/testing-docs-cakephp/templates/"
cp -R "$PACKAGE_ROOT/templates/docker" "$HOME/.claude/testing-docs-cakephp/templates/"
cp -R "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$HOME/.claude/testing-docs-cakephp/templates/"
cat << 'SUB_EOF' > "$HOME/.local/bin/cakephp-test-init"
#!/usr/bin/env bash
TARGET_DIR="${1:-.}"
SOURCE_DIR="$HOME/.claude/testing-docs-cakephp"
if [ ! -d "$TARGET_DIR" ]; then echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!"; exit 1; fi
echo "🚀 Đang khởi tạo test runner CakePHP tại: $TARGET_DIR"
if [ -f "$SOURCE_DIR/templates/docker/test-runner.sh" ]; then
cp "$SOURCE_DIR/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
echo " ✓ Đã tạo $TARGET_DIR/test-runner.sh"
fi
if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then
cp "$SOURCE_DIR/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh"
fi
SUB_EOF
chmod +x "$HOME/.local/bin/cakephp-test-init"
echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC CHO CAKEPHP HOÀN TẤT THÀNH CÔNG!${NC}"
echo -e "Tại bất kỳ dự án CakePHP nào, mở Claude Code và sử dụng:"
echo -e " • Setup môi trường: ${CYAN}/cakephp-test-setup --install${NC}"
echo -e " • Viết & chạy test: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " • Lệnh terminal: ${CYAN}cakephp-test-init${NC}"
exit 0
fi
fi
# ==============================================================================
# 4. XỬ LÝ CÀI ĐẶT TRỰC TIẾP VÀO SOURCE CODE (PROJECT MODE - KHUYÊN DÙNG)
# ==============================================================================
if [ ! -d "$TARGET_DIR" ]; then
echo -e "${RED}Lỗi: Thư mục '$TARGET_DIR' không tồn tại!${NC}"
exit 1
fi
# ------------------------------------------------------------------------------
# 4A. CÀI ĐẶT CHUYÊN BIỆT CHO DỰ ÁN LARAVEL
# ------------------------------------------------------------------------------
if [ "$FRAMEWORK" = "laravel" ]; then
echo -e "📦 Đang cài đặt công cụ chuyên biệt cho ${GREEN}LARAVEL${NC} vào: ${YELLOW}$TARGET_DIR${NC}"
# Dọn dẹp triệt để bất kỳ file CakePHP nào nếu đã từng cài nhầm trước đây
rm -rf "$TARGET_DIR/.claude/skills/cakephp-"* 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/cakephp" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/cakephp" 2>/dev/null || true
# 1. Cài đặt DUY NHẤT các Skills của Laravel
mkdir -p "$TARGET_DIR/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/laravel-"* "$TARGET_DIR/.claude/skills/"
echo -e " ${GREEN}✓${NC} Đã cài bộ Skills chuyên biệt Laravel (laravel-*)"
# 2. Cài đặt tài liệu cẩm nang & rules cho Laravel (KHÔNG có CakePHP)
mkdir -p "$TARGET_DIR/.claude/testing-docs"
cp "$PACKAGE_ROOT/docs/"*.md "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/docs/components" "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$TARGET_DIR/.claude/testing-docs/"
mkdir -p "$TARGET_DIR/.claude/testing-docs/templates"
cp -R "$PACKAGE_ROOT/templates/phpunit" "$TARGET_DIR/.claude/testing-docs/templates/"
cp -R "$PACKAGE_ROOT/templates/pest" "$TARGET_DIR/.claude/testing-docs/templates/"
cp -R "$PACKAGE_ROOT/templates/configs" "$TARGET_DIR/.claude/testing-docs/templates/"
echo -e " ${GREEN}✓${NC} Đã đồng bộ tài liệu, rules & templates Laravel (.claude/testing-docs/)"
# 3. Tạo Smart Runner & Dependency Installer
cp "$PACKAGE_ROOT/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo -e " ${GREEN}✓${NC} Đã tạo smart runner: ./test-runner.sh và ./setup-test-deps.sh"
# 4. Cấu hình môi trường an toàn SQLite In-Memory cho Laravel
PHPUNIT_XML="$TARGET_DIR/phpunit.xml"
PHPUNIT_DIST="$TARGET_DIR/phpunit.xml.dist"
TARGET_XML=""
if [ -f "$PHPUNIT_XML" ]; then
TARGET_XML="$PHPUNIT_XML"
elif [ -f "$PHPUNIT_DIST" ]; then
TARGET_XML="$PHPUNIT_DIST"
fi
if [ -n "$TARGET_XML" ]; then
if ! grep -q 'name="DB_CONNECTION"' "$TARGET_XML" || ! grep -q 'value="sqlite"' "$TARGET_XML"; then
if grep -q '<php>' "$TARGET_XML"; then
sed -i.bak '/<php>/a <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_STORE" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="MAIL_MAILER" value="array"/>
' "$TARGET_XML" 2>/dev/null || true
rm -f "$TARGET_XML.bak" 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Đã cấu hình SQLite in-memory (:memory:) an toàn vào phpunit.xml"
fi
else
echo -e " ${GREEN}✓${NC} Cấu hình SQLite in-memory trong phpunit.xml đã sẵn sàng"
fi
fi
# 5. Tạo GitHub Actions CI workflow cho Laravel nếu có .git
if [ -d "$TARGET_DIR/.git" ]; then
mkdir -p "$TARGET_DIR/.github/workflows"
if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)"
fi
fi
echo -e "
${GREEN}${BOLD}🎉 CÀI ĐẶT THÀNH CÔNG CHO DỰ ÁN LARAVEL!${NC}"
echo -e "
${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}"
echo -e "1. Mở Claude Code tại source code này:"
echo -e " ${CYAN}claude${NC}"
echo -e "2. Gõ các lệnh chuyên biệt dành cho Laravel:"
echo -e " - Setup môi trường: ${CYAN}/laravel-test-setup --install${NC}"
echo -e " - Viết toàn bộ test: ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " - Viết test theo tầng: ${CYAN}/laravel-unit-test app/Services/${NC}"
echo -e " - Đánh giá chất lượng: ${CYAN}/laravel-test-review tests/Unit/...${NC}"
echo -e " - Sinh mã mock nhanh: ${CYAN}/laravel-mock-helper App\Contracts\...${NC}"
echo -e "3. Chạy test từ terminal bất kỳ lúc nào:"
echo -e " ${CYAN}./test-runner.sh${NC}"
echo -e " ${CYAN}./test-runner.sh --coverage${NC}"
# ------------------------------------------------------------------------------
# 4B. CÀI ĐẶT CHUYÊN BIỆT CHO DỰ ÁN CAKEPHP
# ------------------------------------------------------------------------------
elif [ "$FRAMEWORK" = "cakephp" ]; then
echo -e "📦 Đang cài đặt công cụ chuyên biệt cho ${GREEN}CAKEPHP${NC} vào: ${YELLOW}$TARGET_DIR${NC}"
# Dọn dẹp triệt để bất kỳ file Laravel nào nếu đã từng cài nhầm trước đây
rm -rf "$TARGET_DIR/.claude/skills/laravel-"* 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/components" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/phpunit" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/pest" 2>/dev/null || true
# 1. Cài đặt DUY NHẤT các Skills của CakePHP
mkdir -p "$TARGET_DIR/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/cakephp-"* "$TARGET_DIR/.claude/skills/"
echo -e " ${GREEN}✓${NC} Đã cài bộ Skills chuyên biệt CakePHP (cakephp-*)"
# 2. Cài đặt tài liệu cẩm nang & rules cho CakePHP (KHÔNG có Laravel)
mkdir -p "$TARGET_DIR/.claude/testing-docs"
cp "$PACKAGE_ROOT/docs/"*.md "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/docs/cakephp" "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$TARGET_DIR/.claude/testing-docs/"
mkdir -p "$TARGET_DIR/.claude/testing-docs/templates"
cp -R "$PACKAGE_ROOT/templates/cakephp" "$TARGET_DIR/.claude/testing-docs/templates/"
echo -e " ${GREEN}✓${NC} Đã đồng bộ tài liệu, rules & templates CakePHP (.claude/testing-docs/)"
# 3. Tạo Smart Runner & Dependency Installer
cp "$PACKAGE_ROOT/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo -e " ${GREEN}✓${NC} Đã tạo smart runner: ./test-runner.sh và ./setup-test-deps.sh"
# 4. Cấu hình PHPUnit cho CakePHP
if [ ! -f "$TARGET_DIR/phpunit.xml" ] && [ ! -f "$TARGET_DIR/phpunit.xml.dist" ]; then
cp "$PACKAGE_ROOT/templates/cakephp/configs/phpunit.xml.dist.template" "$TARGET_DIR/phpunit.xml.dist"
echo -e " ${GREEN}✓${NC} Đã tạo phpunit.xml.dist chuẩn cho CakePHP"
else
echo -e " ${GREEN}✓${NC} Đã phát hiện cấu hình PHPUnit CakePHP"
fi
if [ -f "$TARGET_DIR/config/app_local.php" ]; then
if grep -q "'test'" "$TARGET_DIR/config/app_local.php"; then
echo -e " ${GREEN}✓${NC} Cấu hình Datasources.test trong config/app_local.php đã sẵn sàng"
else
echo -e " ${YELLOW}ℹ${NC} Lưu ý: Hãy đảm bảo Datasources.test trong config/app_local.php sử dụng SQLite :memory:"
fi
fi
# 5. Tạo GitHub Actions CI workflow cho CakePHP nếu có .git
if [ -d "$TARGET_DIR/.git" ]; then
mkdir -p "$TARGET_DIR/.github/workflows"
if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions-cakephp.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)"
fi
fi
echo -e "
${GREEN}${BOLD}🎉 CÀI ĐẶT THÀNH CÔNG CHO DỰ ÁN CAKEPHP!${NC}"
echo -e "
${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}"
echo -e "1. Mở Claude Code tại source code này:"
echo -e " ${CYAN}claude${NC}"
echo -e "2. Gõ các lệnh chuyên biệt dành cho CakePHP:"
echo -e " - Setup môi trường: ${CYAN}/cakephp-test-setup --install${NC}"
echo -e " - Viết toàn bộ test: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " - Viết test theo tầng: ${CYAN}/cakephp-unit-test src/Model/Table/${NC}"
echo -e " - Đánh giá chất lượng: ${CYAN}/cakephp-test-review tests/TestCase/...${NC}"
echo -e " - Sinh mã mock nhanh: ${CYAN}/cakephp-mock-helper App\Service\...${NC}"
echo -e "3. Chạy test từ terminal bất kỳ lúc nào:"
echo -e " ${CYAN}./test-runner.sh${NC}"
echo -e " ${CYAN}./test-runner.sh --coverage${NC}"
fi
# ==============================================================================
# SMARTGIFT AI - PHP UNIT TESTING TOOLKIT INSTALLER
# Hỗ trợ: Tách biệt riêng biệt cho Laravel & CakePHP
# Cài đặt bộ công cụ Unit Test vào bất kỳ source code nào mà KHÔNG CẦN clone repo về máy.
#
# Cách cài Laravel:
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash -s -- --laravel
# (hoặc đứng trong thư mục Laravel và chạy: .../install.sh | bash -> Tự động nhận diện)
#
# Cách cài CakePHP:
# curl -fsSL https://raw.githubusercontent.com/<OWNER>/agent-unit-testing/main/install.sh | bash -s -- --cakephp
# (hoặc đứng trong thư mục CakePHP và chạy: .../install.sh | bash -> Tự động nhận diện)
# ==============================================================================
set -e
GREEN=''
YELLOW=''
BLUE=''
RED=''
CYAN=''
BOLD=''
NC=''
# Remote Repository URL công khai qua HTTPS
DEFAULT_REPO="https://git.smartgift.io.vn/Smartgift-AI/agent-unit-testing.git"
REPO_URL="${SG_TEST_REPO:-${LARAVEL_TEST_REPO:-$DEFAULT_REPO}}"
TARGET_DIR=""
GLOBAL_MODE=false
FORCE_MODE=false
FRAMEWORK_CHOICE=""
for arg in "$@"; do
case "$arg" in
--global|-g)
GLOBAL_MODE=true
;;
--force|-f)
FORCE_MODE=true
;;
--laravel|-l)
FRAMEWORK_CHOICE="laravel"
;;
--cakephp|-c)
FRAMEWORK_CHOICE="cakephp"
;;
--framework=*)
FRAMEWORK_CHOICE="${arg#*=}"
;;
--help|-h)
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} SMARTGIFT AI: PHP UNIT TESTING TOOLKIT INSTALLER${NC}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "Cách dùng:"
echo -e " 1. Cài đặt chuyên biệt cho LARAVEL:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --laravel${NC}"
echo -e " (Hoặc đứng trong thư mục Laravel và gõ: curl -fsSL <URL>/install.sh | bash)"
echo -e ""
echo -e " 2. Cài đặt chuyên biệt cho CAKEPHP:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --cakephp${NC}"
echo -e " (Hoặc đứng trong thư mục CakePHP và gõ: curl -fsSL <URL>/install.sh | bash)"
echo -e ""
echo -e " 3. Cài đặt Toàn Cục vào máy tính (Global Mode):"
echo -e " - Cho Laravel: ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --global --laravel${NC}"
echo -e " - Cho CakePHP: ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- --global --cakephp${NC}"
echo -e ""
echo -e " 4. Cài đặt vào thư mục chỉ định:"
echo -e " ${YELLOW}curl -fsSL <URL>/install.sh | bash -s -- /duong-dan/source-code --laravel${NC}"
exit 0
;;
-*)
# Bỏ qua các flag khác
;;
*)
if [ -z "$TARGET_DIR" ]; then
TARGET_DIR="$arg"
fi
;;
esac
done
TARGET_DIR="${TARGET_DIR:-.}"
echo -e "${BLUE}===================================================================${NC}"
echo -e "${CYAN}${BOLD} 🚀 SMARTGIFT AI - PHP UNIT TESTING TOOLKIT${NC}"
echo -e "${BLUE}===================================================================${NC}"
# 1. Tìm hoặc Tải nguồn tài nguyên (Local nếu có, hoặc tải tạm qua Git)
CLEANUP_TEMP=false
PACKAGE_ROOT=""
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR=""
if [ -f "$SOURCE" ]; then
SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" 2>/dev/null && pwd || echo "")"
fi
if [ -n "$SCRIPT_DIR" ] && [ -d "$SCRIPT_DIR/.claude/skills" ]; then
PACKAGE_ROOT="$SCRIPT_DIR"
echo -e "${GREEN}✓ Sử dụng tài nguyên có sẵn tại local.${NC}"
else
echo -e "${YELLOW}📥 Đang tải bộ công cụ từ remote repository...${NC}"
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'sg_unit_testing')"
if ! git clone --depth 1 "$REPO_URL" "$TMP_DIR" --quiet 2>/dev/null; then
echo -e "${RED}❌ Không thể clone từ repository: $REPO_URL${NC}"
rm -rf "$TMP_DIR"
exit 1
fi
PACKAGE_ROOT="$TMP_DIR"
CLEANUP_TEMP=true
echo -e "${GREEN}✓ Tải thành công!${NC}"
fi
cleanup() {
if [ "$CLEANUP_TEMP" = true ] && [ -d "$PACKAGE_ROOT" ]; then
rm -rf "$PACKAGE_ROOT"
fi
}
trap cleanup EXIT
# 2. Xác định Framework mục tiêu (Tách biệt hoàn toàn Laravel vs CakePHP)
TARGET_DIR="$(cd "$TARGET_DIR" 2>/dev/null && pwd || echo "$TARGET_DIR")"
FRAMEWORK=""
if [ -n "$FRAMEWORK_CHOICE" ]; then
FRAMEWORK="$FRAMEWORK_CHOICE"
echo -e "${GREEN}✓ Đã chọn Framework theo chỉ định: ${FRAMEWORK}${NC}"
elif [ "$GLOBAL_MODE" = false ]; then
# Tự động nhận diện từ source code
if [ -f "$TARGET_DIR/artisan" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"laravel/framework"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="laravel"
echo -e "${GREEN}✓ Tự động nhận diện dự án: Laravel${NC}"
elif [ -f "$TARGET_DIR/bin/cake" ] || ( [ -f "$TARGET_DIR/composer.json" ] && grep -q '"cakephp/cakephp"' "$TARGET_DIR/composer.json" ); then
FRAMEWORK="cakephp"
echo -e "${GREEN}✓ Tự động nhận diện dự án: CakePHP${NC}"
elif [ ! -f "$TARGET_DIR/composer.json" ]; then
FILE_COUNT=$(ls -A "$TARGET_DIR" 2>/dev/null | wc -l | tr -d ' ')
if [ "$FILE_COUNT" -le 2 ] || [ "$FORCE_MODE" = true ]; then
FRAMEWORK="laravel"
echo -e "${YELLOW}ℹ Thư mục mới/trống: Mặc định chọn kiến trúc Laravel.${NC}"
else
echo -e "${RED}❌ Thư mục '$TARGET_DIR' chưa có composer.json. Vui lòng thêm cờ --laravel hoặc --cakephp.${NC}"
exit 1
fi
else
echo -e "${RED}❌ Không thể tự động nhận diện Framework trong '$TARGET_DIR'.${NC}"
echo -e "Vui lòng chỉ định rõ flag cài đặt:"
echo -e " - Laravel: ${CYAN}bash install.sh --laravel${NC}"
echo -e " - CakePHP: ${CYAN}bash install.sh --cakephp${NC}"
exit 1
fi
else
# Global mode mà không truyền flag framework
FRAMEWORK="laravel"
echo -e "${YELLOW}ℹ Chế độ toàn cục: Mặc định cài đặt cho Laravel (dùng --cakephp để đổi sang CakePHP).${NC}"
fi
# ==============================================================================
# 3. XỬ LÝ CÀI ĐẶT TOÀN CỤC (GLOBAL MODE)
# ==============================================================================
if [ "$GLOBAL_MODE" = true ]; then
mkdir -p "$HOME/.claude/skills"
mkdir -p "$HOME/.local/bin"
if [ "$FRAMEWORK" = "laravel" ]; then
echo -e "${YELLOW}⚙️ Đang cài đặt chế độ Toàn Cục cho LARAVEL vào $HOME/.claude/...${NC}"
rm -rf "$HOME/.claude/skills/cakephp-"* 2>/dev/null || true
cp -R "$PACKAGE_ROOT/.claude/skills/laravel-"* "$HOME/.claude/skills/"
mkdir -p "$HOME/.claude/testing-docs-laravel/templates"
cp "$PACKAGE_ROOT/docs/"*.md "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/docs/components" "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/testing-docs-laravel/"
cp -R "$PACKAGE_ROOT/templates/phpunit" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/pest" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/docker" "$HOME/.claude/testing-docs-laravel/templates/"
cp -R "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$HOME/.claude/testing-docs-laravel/templates/"
cat << 'SUB_EOF' > "$HOME/.local/bin/laravel-test-init"
#!/usr/bin/env bash
TARGET_DIR="${1:-.}"
SOURCE_DIR="$HOME/.claude/testing-docs-laravel"
if [ ! -d "$TARGET_DIR" ]; then echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!"; exit 1; fi
echo "🚀 Đang khởi tạo test runner Laravel tại: $TARGET_DIR"
if [ -f "$SOURCE_DIR/templates/docker/test-runner.sh" ]; then
cp "$SOURCE_DIR/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
echo " ✓ Đã tạo $TARGET_DIR/test-runner.sh"
fi
if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then
cp "$SOURCE_DIR/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh"
fi
SUB_EOF
chmod +x "$HOME/.local/bin/laravel-test-init"
echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC CHO LARAVEL HOÀN TẤT THÀNH CÔNG!${NC}"
echo -e "Tại bất kỳ dự án Laravel nào, mở Claude Code và sử dụng:"
echo -e " • Setup môi trường: ${CYAN}/laravel-test-setup --install${NC}"
echo -e " • Viết & chạy test: ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " • Lệnh terminal: ${CYAN}laravel-test-init${NC}"
exit 0
elif [ "$FRAMEWORK" = "cakephp" ]; then
echo -e "${YELLOW}⚙️ Đang cài đặt chế độ Toàn Cục cho CAKEPHP vào $HOME/.claude/...${NC}"
rm -rf "$HOME/.claude/skills/laravel-"* 2>/dev/null || true
cp -R "$PACKAGE_ROOT/.claude/skills/cakephp-"* "$HOME/.claude/skills/"
mkdir -p "$HOME/.claude/testing-docs-cakephp/templates"
cp "$PACKAGE_ROOT/docs/"*.md "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/docs/cakephp" "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/rules/"* "$HOME/.claude/testing-docs-cakephp/"
cp -R "$PACKAGE_ROOT/templates/cakephp" "$HOME/.claude/testing-docs-cakephp/templates/"
cp -R "$PACKAGE_ROOT/templates/docker" "$HOME/.claude/testing-docs-cakephp/templates/"
cp -R "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$HOME/.claude/testing-docs-cakephp/templates/"
cat << 'SUB_EOF' > "$HOME/.local/bin/cakephp-test-init"
#!/usr/bin/env bash
TARGET_DIR="${1:-.}"
SOURCE_DIR="$HOME/.claude/testing-docs-cakephp"
if [ ! -d "$TARGET_DIR" ]; then echo "Lỗi: Thư mục '$TARGET_DIR' không tồn tại!"; exit 1; fi
echo "🚀 Đang khởi tạo test runner CakePHP tại: $TARGET_DIR"
if [ -f "$SOURCE_DIR/templates/docker/test-runner.sh" ]; then
cp "$SOURCE_DIR/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
echo " ✓ Đã tạo $TARGET_DIR/test-runner.sh"
fi
if [ -f "$SOURCE_DIR/templates/setup-dependencies.sh" ]; then
cp "$SOURCE_DIR/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo " ✓ Đã tạo $TARGET_DIR/setup-test-deps.sh"
fi
SUB_EOF
chmod +x "$HOME/.local/bin/cakephp-test-init"
echo -e "${GREEN}${BOLD}✓ CÀI ĐẶT TOÀN CỤC CHO CAKEPHP HOÀN TẤT THÀNH CÔNG!${NC}"
echo -e "Tại bất kỳ dự án CakePHP nào, mở Claude Code và sử dụng:"
echo -e " • Setup môi trường: ${CYAN}/cakephp-test-setup --install${NC}"
echo -e " • Viết & chạy test: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " • Lệnh terminal: ${CYAN}cakephp-test-init${NC}"
exit 0
fi
fi
# ==============================================================================
# 4. XỬ LÝ CÀI ĐẶT TRỰC TIẾP VÀO SOURCE CODE (PROJECT MODE - KHUYÊN DÙNG)
# ==============================================================================
if [ ! -d "$TARGET_DIR" ]; then
echo -e "${RED}Lỗi: Thư mục '$TARGET_DIR' không tồn tại!${NC}"
exit 1
fi
# ------------------------------------------------------------------------------
# 4A. CÀI ĐẶT CHUYÊN BIỆT CHO DỰ ÁN LARAVEL
# ------------------------------------------------------------------------------
if [ "$FRAMEWORK" = "laravel" ]; then
echo -e "📦 Đang cài đặt công cụ chuyên biệt cho ${GREEN}LARAVEL${NC} vào: ${YELLOW}$TARGET_DIR${NC}"
# Dọn dẹp triệt để bất kỳ file CakePHP nào nếu đã từng cài nhầm trước đây
rm -rf "$TARGET_DIR/.claude/skills/cakephp-"* 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/cakephp" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/cakephp" 2>/dev/null || true
# 1. Cài đặt DUY NHẤT các Skills của Laravel
mkdir -p "$TARGET_DIR/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/laravel-"* "$TARGET_DIR/.claude/skills/"
echo -e " ${GREEN}✓${NC} Đã cài bộ Skills chuyên biệt Laravel (laravel-*)"
# 2. Cài đặt tài liệu cẩm nang & rules cho Laravel (KHÔNG có CakePHP)
mkdir -p "$TARGET_DIR/.claude/testing-docs"
cp "$PACKAGE_ROOT/docs/"*.md "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/docs/components" "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$TARGET_DIR/.claude/testing-docs/"
mkdir -p "$TARGET_DIR/.claude/testing-docs/templates"
cp -R "$PACKAGE_ROOT/templates/phpunit" "$TARGET_DIR/.claude/testing-docs/templates/"
cp -R "$PACKAGE_ROOT/templates/pest" "$TARGET_DIR/.claude/testing-docs/templates/"
cp -R "$PACKAGE_ROOT/templates/configs" "$TARGET_DIR/.claude/testing-docs/templates/"
echo -e " ${GREEN}✓${NC} Đã đồng bộ tài liệu, rules & templates Laravel (.claude/testing-docs/)"
# 3. Tạo Smart Runner & Dependency Installer
cp "$PACKAGE_ROOT/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo -e " ${GREEN}✓${NC} Đã tạo smart runner: ./test-runner.sh và ./setup-test-deps.sh"
# 4. Cấu hình môi trường an toàn SQLite In-Memory cho Laravel
PHPUNIT_XML="$TARGET_DIR/phpunit.xml"
PHPUNIT_DIST="$TARGET_DIR/phpunit.xml.dist"
TARGET_XML=""
if [ -f "$PHPUNIT_XML" ]; then
TARGET_XML="$PHPUNIT_XML"
elif [ -f "$PHPUNIT_DIST" ]; then
TARGET_XML="$PHPUNIT_DIST"
fi
if [ -n "$TARGET_XML" ]; then
if ! grep -q 'name="DB_CONNECTION"' "$TARGET_XML" || ! grep -q 'value="sqlite"' "$TARGET_XML"; then
if grep -q '<php>' "$TARGET_XML"; then
sed -i.bak '/<php>/a <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_STORE" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="MAIL_MAILER" value="array"/>
' "$TARGET_XML" 2>/dev/null || true
rm -f "$TARGET_XML.bak" 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Đã cấu hình SQLite in-memory (:memory:) an toàn vào phpunit.xml"
fi
else
echo -e " ${GREEN}✓${NC} Cấu hình SQLite in-memory trong phpunit.xml đã sẵn sàng"
fi
fi
# 5. Tạo GitHub Actions CI workflow cho Laravel nếu có .git
if [ -d "$TARGET_DIR/.git" ]; then
mkdir -p "$TARGET_DIR/.github/workflows"
if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)"
fi
fi
echo -e "
${GREEN}${BOLD}🎉 CÀI ĐẶT THÀNH CÔNG CHO DỰ ÁN LARAVEL!${NC}"
echo -e "
${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}"
echo -e "1. Mở Claude Code tại source code này:"
echo -e " ${CYAN}claude${NC}"
echo -e "2. Gõ các lệnh chuyên biệt dành cho Laravel:"
echo -e " - Setup môi trường: ${CYAN}/laravel-test-setup --install${NC}"
echo -e " - Viết toàn bộ test: ${CYAN}/laravel-unit-test --all --run${NC}"
echo -e " - Viết test theo tầng: ${CYAN}/laravel-unit-test app/Services/${NC}"
echo -e " - Đánh giá chất lượng: ${CYAN}/laravel-test-review tests/Unit/...${NC}"
echo -e " - Sinh mã mock nhanh: ${CYAN}/laravel-mock-helper App\Contracts\...${NC}"
echo -e "3. Chạy test từ terminal bất kỳ lúc nào:"
echo -e " ${CYAN}./test-runner.sh${NC}"
echo -e " ${CYAN}./test-runner.sh --coverage${NC}"
# ------------------------------------------------------------------------------
# 4B. CÀI ĐẶT CHUYÊN BIỆT CHO DỰ ÁN CAKEPHP
# ------------------------------------------------------------------------------
elif [ "$FRAMEWORK" = "cakephp" ]; then
echo -e "📦 Đang cài đặt công cụ chuyên biệt cho ${GREEN}CAKEPHP${NC} vào: ${YELLOW}$TARGET_DIR${NC}"
# Dọn dẹp triệt để bất kỳ file Laravel nào nếu đã từng cài nhầm trước đây
rm -rf "$TARGET_DIR/.claude/skills/laravel-"* 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/components" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/phpunit" 2>/dev/null || true
rm -rf "$TARGET_DIR/.claude/testing-docs/templates/pest" 2>/dev/null || true
# 1. Cài đặt DUY NHẤT các Skills của CakePHP
mkdir -p "$TARGET_DIR/.claude/skills"
cp -R "$PACKAGE_ROOT/.claude/skills/cakephp-"* "$TARGET_DIR/.claude/skills/"
echo -e " ${GREEN}✓${NC} Đã cài bộ Skills chuyên biệt CakePHP (cakephp-*)"
# 2. Cài đặt tài liệu cẩm nang & rules cho CakePHP (KHÔNG có Laravel)
mkdir -p "$TARGET_DIR/.claude/testing-docs"
cp "$PACKAGE_ROOT/docs/"*.md "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/docs/cakephp" "$TARGET_DIR/.claude/testing-docs/"
cp -R "$PACKAGE_ROOT/rules/"* "$TARGET_DIR/.claude/testing-docs/"
mkdir -p "$TARGET_DIR/.claude/testing-docs/templates"
cp -R "$PACKAGE_ROOT/templates/cakephp" "$TARGET_DIR/.claude/testing-docs/templates/"
echo -e " ${GREEN}✓${NC} Đã đồng bộ tài liệu, rules & templates CakePHP (.claude/testing-docs/)"
# 3. Tạo Smart Runner & Dependency Installer
cp "$PACKAGE_ROOT/templates/docker/test-runner.sh" "$TARGET_DIR/test-runner.sh"
chmod +x "$TARGET_DIR/test-runner.sh"
cp "$PACKAGE_ROOT/templates/setup-dependencies.sh" "$TARGET_DIR/setup-test-deps.sh"
chmod +x "$TARGET_DIR/setup-test-deps.sh"
echo -e " ${GREEN}✓${NC} Đã tạo smart runner: ./test-runner.sh và ./setup-test-deps.sh"
# 4. Cấu hình PHPUnit cho CakePHP
if [ ! -f "$TARGET_DIR/phpunit.xml" ] && [ ! -f "$TARGET_DIR/phpunit.xml.dist" ]; then
cp "$PACKAGE_ROOT/templates/cakephp/configs/phpunit.xml.dist.template" "$TARGET_DIR/phpunit.xml.dist"
echo -e " ${GREEN}✓${NC} Đã tạo phpunit.xml.dist chuẩn cho CakePHP"
else
echo -e " ${GREEN}✓${NC} Đã phát hiện cấu hình PHPUnit CakePHP"
fi
if [ -f "$TARGET_DIR/config/app_local.php" ]; then
if grep -q "'test'" "$TARGET_DIR/config/app_local.php"; then
echo -e " ${GREEN}✓${NC} Cấu hình Datasources.test trong config/app_local.php đã sẵn sàng"
else
echo -e " ${YELLOW}ℹ${NC} Lưu ý: Hãy đảm bảo Datasources.test trong config/app_local.php sử dụng SQLite :memory:"
fi
fi
# 5. Tạo GitHub Actions CI workflow cho CakePHP nếu có .git
if [ -d "$TARGET_DIR/.git" ]; then
mkdir -p "$TARGET_DIR/.github/workflows"
if [ ! -f "$TARGET_DIR/.github/workflows/unit-tests.yml" ]; then
cp "$PACKAGE_ROOT/templates/ci/github-actions-cakephp.yml.template" "$TARGET_DIR/.github/workflows/unit-tests.yml"
echo -e " ${GREEN}✓${NC} Đã tạo CI/CD Quality Gate (.github/workflows/unit-tests.yml)"
fi
fi
echo -e "
${GREEN}${BOLD}🎉 CÀI ĐẶT THÀNH CÔNG CHO DỰ ÁN CAKEPHP!${NC}"
echo -e "
${YELLOW}${BOLD}BÂY GIỜ BẠN CÓ THỂ VIẾT UNIT TEST NGAY:${NC}"
echo -e "1. Mở Claude Code tại source code này:"
echo -e " ${CYAN}claude${NC}"
echo -e "2. Gõ các lệnh chuyên biệt dành cho CakePHP:"
echo -e " - Setup môi trường: ${CYAN}/cakephp-test-setup --install${NC}"
echo -e " - Viết toàn bộ test: ${CYAN}/cakephp-unit-test --all --run${NC}"
echo -e " - Viết test theo tầng: ${CYAN}/cakephp-unit-test src/Model/Table/${NC}"
echo -e " - Đánh giá chất lượng: ${CYAN}/cakephp-test-review tests/TestCase/...${NC}"
echo -e " - Sinh mã mock nhanh: ${CYAN}/cakephp-mock-helper App\Service\...${NC}"
echo -e "3. Chạy test từ terminal bất kỳ lúc nào:"
echo -e " ${CYAN}./test-runner.sh${NC}"
echo -e " ${CYAN}./test-runner.sh --coverage${NC}"
fi