cc-devflow 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +83 -0
- package/.claude/agents/architecture-designer.md +443 -0
- package/.claude/agents/bug-analyzer.md +382 -0
- package/.claude/agents/checklist-agent.md +175 -0
- package/.claude/agents/clarify-analyst.md +50 -0
- package/.claude/agents/code-reviewer.md +71 -0
- package/.claude/agents/codex-analyzer.md +39 -0
- package/.claude/agents/compatibility-checker.md +580 -0
- package/.claude/agents/consistency-checker.md +532 -0
- package/.claude/agents/impact-analyzer.md +441 -0
- package/.claude/agents/planner.md +230 -0
- package/.claude/agents/prd-writer.md +320 -0
- package/.claude/agents/project-guidelines-generator.md +1329 -0
- package/.claude/agents/qa-tester.md +313 -0
- package/.claude/agents/release-manager.md +295 -0
- package/.claude/agents/security-reviewer.md +314 -0
- package/.claude/agents/style-guide-generator.md +458 -0
- package/.claude/agents/tech-architect.md +516 -0
- package/.claude/agents/ui-designer.md +485 -0
- package/.claude/commands/code-review-high.md +58 -0
- package/.claude/commands/core-architecture.md +429 -0
- package/.claude/commands/core-guidelines.md +486 -0
- package/.claude/commands/core-roadmap.md +439 -0
- package/.claude/commands/core-style.md +293 -0
- package/.claude/commands/flow-archive.md +245 -0
- package/.claude/commands/flow-checklist.md +260 -0
- package/.claude/commands/flow-clarify.md +136 -0
- package/.claude/commands/flow-constitution.md +82 -0
- package/.claude/commands/flow-dev.md +134 -0
- package/.claude/commands/flow-epic.md +150 -0
- package/.claude/commands/flow-fix.md +104 -0
- package/.claude/commands/flow-ideate.md +214 -0
- package/.claude/commands/flow-init.md +313 -0
- package/.claude/commands/flow-new.md +394 -0
- package/.claude/commands/flow-prd.md +131 -0
- package/.claude/commands/flow-qa.md +93 -0
- package/.claude/commands/flow-release.md +92 -0
- package/.claude/commands/flow-restart.md +98 -0
- package/.claude/commands/flow-status.md +64 -0
- package/.claude/commands/flow-tech.md +142 -0
- package/.claude/commands/flow-ui.md +189 -0
- package/.claude/commands/flow-update.md +111 -0
- package/.claude/commands/flow-upgrade.md +115 -0
- package/.claude/commands/flow-verify.md +96 -0
- package/.claude/commands/problem-analyzer.md +60 -0
- package/.claude/config/quality-rules.yml +161 -0
- package/.claude/docs/SPEC_KIT_CONSTITUTION_ANALYSIS.md +426 -0
- package/.claude/docs/design/consistency-conflict-detection-algorithms.md +658 -0
- package/.claude/docs/design/intent-driven-input-design.md +380 -0
- package/.claude/docs/design/prd-version-management-design.md +437 -0
- package/.claude/docs/guides/INIT_TROUBLESHOOTING.md +117 -0
- package/.claude/docs/guides/NEW_TROUBLESHOOTING.md +151 -0
- package/.claude/docs/guides/ROADMAP_TROUBLESHOOTING.md +188 -0
- package/.claude/docs/guides/TASK_COMPLETION_MARKING.md +338 -0
- package/.claude/docs/templates/ARCHITECTURE_TEMPLATE.md +633 -0
- package/.claude/docs/templates/BACKLOG_TEMPLATE.md +261 -0
- package/.claude/docs/templates/CHECKLIST_TEMPLATE.md +52 -0
- package/.claude/docs/templates/CLARIFICATION_REPORT_TEMPLATE.md +206 -0
- package/.claude/docs/templates/CODE_REVIEW_TEMPLATE.md +71 -0
- package/.claude/docs/templates/EPIC_TEMPLATE.md +805 -0
- package/.claude/docs/templates/INIT_FLOW_TEMPLATE.md +213 -0
- package/.claude/docs/templates/INTENT_CLARIFICATION_TEMPLATE.md +57 -0
- package/.claude/docs/templates/NEW_ORCHESTRATION_TEMPLATE.md +148 -0
- package/.claude/docs/templates/PRD_TEMPLATE.md +562 -0
- package/.claude/docs/templates/RESEARCH_TEMPLATE.md +276 -0
- package/.claude/docs/templates/REVIEW-HIGH.md +57 -0
- package/.claude/docs/templates/ROADMAP_DIALOGUE_TEMPLATE.md +198 -0
- package/.claude/docs/templates/ROADMAP_TEMPLATE.md +310 -0
- package/.claude/docs/templates/STYLE_TEMPLATE.md +1266 -0
- package/.claude/docs/templates/TASKS_TEMPLATE.md +523 -0
- package/.claude/docs/templates/TECH_DESIGN_TEMPLATE.md +1019 -0
- package/.claude/docs/templates/UI_PROTOTYPE_TEMPLATE.md +1436 -0
- package/.claude/guides/agent-guides/agent-coordination-guide.md +459 -0
- package/.claude/guides/project-guidelines-system.md +463 -0
- package/.claude/guides/technical-guides/datetime-handling-guide.md +563 -0
- package/.claude/guides/technical-guides/git-github-guide.md +642 -0
- package/.claude/guides/technical-guides/test-execution-guide.md +618 -0
- package/.claude/guides/workflow-guides/bug-fix-orchestrator.md +217 -0
- package/.claude/guides/workflow-guides/flow-orchestrator.md +282 -0
- package/.claude/hooks/checklist-gate.js +397 -0
- package/.claude/hooks/error-handling-reminder.sh +12 -0
- package/.claude/hooks/error-handling-reminder.ts +459 -0
- package/.claude/hooks/post-tool-use-tracker.sh +280 -0
- package/.claude/hooks/pre-tool-use-guardrail.sh +36 -0
- package/.claude/hooks/pre-tool-use-guardrail.ts +342 -0
- package/.claude/hooks/skill-activation-prompt.sh +36 -0
- package/.claude/hooks/skill-activation-prompt.ts +214 -0
- package/.claude/hooks/state/skills-used-test-guard.json +3 -0
- package/.claude/rules/devflow-conventions.md +305 -0
- package/.claude/rules/project-constitution.md +748 -0
- package/.claude/schemas/constitution.schema.json +43 -0
- package/.claude/scripts/analyze-upgrade-impact.sh +200 -0
- package/.claude/scripts/archive-requirement.sh +351 -0
- package/.claude/scripts/calculate-checklist-completion.sh +243 -0
- package/.claude/scripts/calculate-quarter.sh +206 -0
- package/.claude/scripts/check-dependencies.sh +409 -0
- package/.claude/scripts/check-prerequisites.sh +232 -0
- package/.claude/scripts/check-task-status.sh +264 -0
- package/.claude/scripts/checklist-errors.sh +131 -0
- package/.claude/scripts/common.sh +570 -0
- package/.claude/scripts/consolidate-research.sh +182 -0
- package/.claude/scripts/create-requirement.sh +426 -0
- package/.claude/scripts/export-contracts.sh +117 -0
- package/.claude/scripts/extract-data-model.sh +78 -0
- package/.claude/scripts/generate-clarification-questions.sh +377 -0
- package/.claude/scripts/generate-clarification-report.sh +463 -0
- package/.claude/scripts/generate-quickstart.sh +146 -0
- package/.claude/scripts/generate-research-tasks.sh +157 -0
- package/.claude/scripts/generate-status-report.sh +523 -0
- package/.claude/scripts/generate-tech-analysis.sh +46 -0
- package/.claude/scripts/locate-requirement-in-roadmap.sh +233 -0
- package/.claude/scripts/manage-constitution.sh +602 -0
- package/.claude/scripts/mark-task-complete.sh +198 -0
- package/.claude/scripts/populate-research-tasks.sh +259 -0
- package/.claude/scripts/recover-workflow.sh +460 -0
- package/.claude/scripts/run-clarify-scan.sh +601 -0
- package/.claude/scripts/run-high-review.sh +62 -0
- package/.claude/scripts/run-problem-analysis.sh +68 -0
- package/.claude/scripts/setup-epic.sh +173 -0
- package/.claude/scripts/sync-roadmap-progress.sh +300 -0
- package/.claude/scripts/sync-task-marks.sh +199 -0
- package/.claude/scripts/test-clarify-scan.sh +515 -0
- package/.claude/scripts/update-agent-context.sh +806 -0
- package/.claude/scripts/validate-constitution.sh +567 -0
- package/.claude/scripts/validate-hooks.sh +487 -0
- package/.claude/scripts/validate-research.sh +332 -0
- package/.claude/scripts/validate-scope-boundary.sh +493 -0
- package/.claude/scripts/verify-setup.sh +37 -0
- package/.claude/settings.json +76 -0
- package/.claude/skills/_reference-implementations/README.md +96 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/SKILL.md +302 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/architecture-overview.md +451 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/async-and-errors.md +307 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/complete-examples.md +638 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/configuration.md +275 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/database-patterns.md +224 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/middleware-guide.md +213 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/routing-and-controllers.md +756 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/sentry-and-monitoring.md +336 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/services-and-repositories.md +789 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/testing-guide.md +235 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/validation-patterns.md +754 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/SKILL.md +399 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/common-patterns.md +331 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/complete-examples.md +872 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/component-patterns.md +502 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/data-fetching.md +767 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/file-organization.md +502 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/loading-and-error-states.md +501 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/performance.md +406 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/routing-guide.md +364 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/styling-guide.md +428 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/typescript-standards.md +418 -0
- package/.claude/skills/cc-devflow-orchestrator/SKILL.md +229 -0
- package/.claude/skills/constitution-guardian/SKILL.md +306 -0
- package/.claude/skills/devflow-constitution-quick-ref/SKILL.md +374 -0
- package/.claude/skills/devflow-file-standards/SKILL.md +353 -0
- package/.claude/skills/devflow-tdd-enforcer/SKILL.md +192 -0
- package/.claude/skills/skill-developer/ADVANCED.md +197 -0
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +306 -0
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +152 -0
- package/.claude/skills/skill-developer/SKILL.md +426 -0
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +315 -0
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +305 -0
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +514 -0
- package/.claude/skills/skill-rules.json +213 -0
- package/.claude/tests/README.md +300 -0
- package/.claude/tests/TODO.md +69 -0
- package/.claude/tests/__pycache__/test_analyze_upgrade_impact.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_consolidate_research.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_export_contracts.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_extract_data_model.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_generate_quickstart.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_generate_research_tasks.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/constitution/run_all_constitution_tests.sh +111 -0
- package/.claude/tests/constitution/test_agent_assignment.sh +207 -0
- package/.claude/tests/constitution/test_article_coverage.sh +201 -0
- package/.claude/tests/constitution/test_template_completeness.sh +150 -0
- package/.claude/tests/constitution/test_version_consistency.sh +120 -0
- package/.claude/tests/fixtures/spec_delta_full.md +16 -0
- package/.claude/tests/fixtures/tasks_progress_sample.md +5 -0
- package/.claude/tests/run-all-tests.sh +229 -0
- package/.claude/tests/scripts/run.sh +30 -0
- package/.claude/tests/scripts/test-framework.sh +128 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh +511 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak +504 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak2 +505 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak3 +506 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak4 +507 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak5 +508 -0
- package/.claude/tests/scripts/test_check_task_status.sh +499 -0
- package/.claude/tests/scripts/test_common.sh +244 -0
- package/.claude/tests/scripts/test_generate_status_report.sh +71 -0
- package/.claude/tests/scripts/test_mark_task_complete.sh +441 -0
- package/.claude/tests/scripts/test_mark_task_complete.sh.backup +410 -0
- package/.claude/tests/scripts/test_recover_workflow.sh +304 -0
- package/.claude/tests/scripts/test_setup_epic.sh +437 -0
- package/.claude/tests/scripts/test_sync_task_marks.sh +196 -0
- package/.claude/tests/scripts/test_validate_constitution.sh +74 -0
- package/.claude/tests/scripts/test_validate_research.sh +462 -0
- package/.claude/tests/slugify.bats +82 -0
- package/.claude/tests/test-framework.sh +732 -0
- package/.claude/tests/test_analyze_upgrade_impact.py +34 -0
- package/.claude/tests/test_consolidate_research.py +48 -0
- package/.claude/tests/test_export_contracts.py +43 -0
- package/.claude/tests/test_extract_data_model.py +33 -0
- package/.claude/tests/test_generate_quickstart.py +50 -0
- package/.claude/tests/test_generate_research_tasks.py +52 -0
- package/.claude/tsc-cache/6e64f818-6398-49ca-8623-581a9af85c44/edited-files.log +1 -0
- package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/affected-repos.txt +1 -0
- package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/edited-files.log +1 -0
- package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/affected-repos.txt +1 -0
- package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/edited-files.log +1 -0
- package/CHANGELOG.md +507 -0
- package/LICENSE +21 -0
- package/README.md +534 -0
- package/README.zh-CN.md +530 -0
- package/bin/adapt.js +240 -0
- package/bin/cc-devflow-cli.js +185 -0
- package/bin/cc-devflow.js +78 -0
- package/config/adapters.yml +5 -0
- package/config/schema/adapters.schema.json +44 -0
- package/docs/CLAUDE.md +26 -0
- package/docs/commands/README.md +61 -0
- package/docs/commands/README.zh-CN.md +55 -0
- package/docs/commands/core-roadmap.md +106 -0
- package/docs/commands/core-roadmap.zh-CN.md +102 -0
- package/docs/commands/core-style.md +405 -0
- package/docs/commands/core-style.zh-CN.md +405 -0
- package/docs/commands/flow-init.md +134 -0
- package/docs/commands/flow-init.zh-CN.md +163 -0
- package/docs/commands/flow-new.md +274 -0
- package/docs/commands/flow-new.zh-CN.md +270 -0
- package/docs/guides/getting-started.md +204 -0
- package/docs/guides/getting-started.zh-CN.md +152 -0
- package/lib/adapters/adapter-interface.js +57 -0
- package/lib/adapters/claude-adapter.js +74 -0
- package/lib/adapters/codex-adapter.js +40 -0
- package/lib/adapters/config-validator.js +68 -0
- package/lib/adapters/logger.js +42 -0
- package/lib/adapters/registry.js +153 -0
- package/lib/compiler/CLAUDE.md +92 -0
- package/lib/compiler/__tests__/drift.test.js +215 -0
- package/lib/compiler/__tests__/errors.test.js +184 -0
- package/lib/compiler/__tests__/incremental.test.js +174 -0
- package/lib/compiler/__tests__/integration.test.js +174 -0
- package/lib/compiler/__tests__/manifest.test.js +233 -0
- package/lib/compiler/__tests__/parser.test.js +456 -0
- package/lib/compiler/__tests__/schemas.test.js +301 -0
- package/lib/compiler/__tests__/skills-registry.test.js +125 -0
- package/lib/compiler/__tests__/transformer.test.js +286 -0
- package/lib/compiler/emitters/antigravity-emitter.js +171 -0
- package/lib/compiler/emitters/base-emitter.js +73 -0
- package/lib/compiler/emitters/codex-emitter.js +52 -0
- package/lib/compiler/emitters/cursor-emitter.js +31 -0
- package/lib/compiler/emitters/index.js +50 -0
- package/lib/compiler/emitters/qwen-emitter.js +39 -0
- package/lib/compiler/errors.js +119 -0
- package/lib/compiler/index.js +256 -0
- package/lib/compiler/manifest.js +242 -0
- package/lib/compiler/parser.js +258 -0
- package/lib/compiler/platforms.js +113 -0
- package/lib/compiler/resource-copier.js +320 -0
- package/lib/compiler/rules-emitters/__tests__/antigravity-rules-emitter.test.js +191 -0
- package/lib/compiler/rules-emitters/__tests__/codex-rules-emitter.test.js +109 -0
- package/lib/compiler/rules-emitters/__tests__/cursor-rules-emitter.test.js +123 -0
- package/lib/compiler/rules-emitters/__tests__/qwen-rules-emitter.test.js +123 -0
- package/lib/compiler/rules-emitters/antigravity-rules-emitter.js +253 -0
- package/lib/compiler/rules-emitters/base-rules-emitter.js +83 -0
- package/lib/compiler/rules-emitters/codex-rules-emitter.js +116 -0
- package/lib/compiler/rules-emitters/cursor-rules-emitter.js +98 -0
- package/lib/compiler/rules-emitters/index.js +71 -0
- package/lib/compiler/rules-emitters/qwen-rules-emitter.js +70 -0
- package/lib/compiler/schemas.js +144 -0
- package/lib/compiler/skills-registry.js +225 -0
- package/lib/compiler/transformer.js +236 -0
- package/package.json +50 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# test_validate_research.sh - 测试 validate-research.sh 的所有验证级别
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Purpose: 验证 research.md 质量检查脚本的正确性
|
|
6
|
+
# Coverage: LEVEL 1-5 验证、TODO 检测、结构验证、Constitution 合规
|
|
7
|
+
# =============================================================================
|
|
8
|
+
|
|
9
|
+
# 加载测试框架
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
source "$SCRIPT_DIR/../test-framework.sh"
|
|
12
|
+
|
|
13
|
+
# 脚本路径 (REPO_ROOT 已经指向仓库根目录)
|
|
14
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
15
|
+
VALIDATE_RESEARCH="$REPO_ROOT/.claude/scripts/validate-research.sh"
|
|
16
|
+
|
|
17
|
+
# ============================================================================
|
|
18
|
+
# 测试钩子 - 在每个测试前创建临时需求目录
|
|
19
|
+
# ============================================================================
|
|
20
|
+
|
|
21
|
+
setup_test() {
|
|
22
|
+
# 创建临时需求目录
|
|
23
|
+
TEST_REQ_DIR="$TEST_TMP_DIR/devflow/requirements/TEST-001"
|
|
24
|
+
mkdir -p "$TEST_REQ_DIR/research"
|
|
25
|
+
|
|
26
|
+
# 默认创建有效的 tasks.json
|
|
27
|
+
cat > "$TEST_REQ_DIR/research/tasks.json" <<'EOF'
|
|
28
|
+
{
|
|
29
|
+
"feature": "Test Feature",
|
|
30
|
+
"generatedAt": "2025-01-26T00:00:00Z",
|
|
31
|
+
"requirementDir": "devflow/requirements/TEST-001",
|
|
32
|
+
"tasks": [
|
|
33
|
+
{
|
|
34
|
+
"id": "R001",
|
|
35
|
+
"type": "clarification",
|
|
36
|
+
"prompt": "Test prompt",
|
|
37
|
+
"status": "open"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
EOF
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# ============================================================================
|
|
45
|
+
# LEVEL 1: File Existence Check
|
|
46
|
+
# ============================================================================
|
|
47
|
+
|
|
48
|
+
test_level1_research_md_missing() {
|
|
49
|
+
describe "LEVEL 1: Should fail when research.md is missing"
|
|
50
|
+
|
|
51
|
+
# Arrange - research.md 不存在
|
|
52
|
+
|
|
53
|
+
# Act - 捕获退出码
|
|
54
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
55
|
+
(
|
|
56
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > /dev/null 2>&1
|
|
57
|
+
echo $? > "$exit_code_file"
|
|
58
|
+
)
|
|
59
|
+
local exit_code=$(cat "$exit_code_file")
|
|
60
|
+
|
|
61
|
+
# Assert
|
|
62
|
+
[[ $exit_code -ne 0 ]] || test_fail "Should fail when research.md missing (exit code: $exit_code)"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
test_level1_research_md_exists() {
|
|
66
|
+
describe "LEVEL 1: Should pass when research.md exists"
|
|
67
|
+
|
|
68
|
+
# Arrange - 创建基本 research.md
|
|
69
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
70
|
+
# Research Summary
|
|
71
|
+
|
|
72
|
+
## Decisions
|
|
73
|
+
|
|
74
|
+
### R001 — Test
|
|
75
|
+
- Decision: Test decision
|
|
76
|
+
- Rationale: Test rationale
|
|
77
|
+
- Alternatives considered: Test alternatives
|
|
78
|
+
|
|
79
|
+
## Source Library
|
|
80
|
+
|
|
81
|
+
_None yet._
|
|
82
|
+
EOF
|
|
83
|
+
|
|
84
|
+
# Act
|
|
85
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
86
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
87
|
+
local output=$(cat "$output_file")
|
|
88
|
+
|
|
89
|
+
# Assert
|
|
90
|
+
assert_contains "$output" "✅ LEVEL 1 PASSED" "Should pass LEVEL 1"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# ============================================================================
|
|
94
|
+
# LEVEL 2: Structure Validation
|
|
95
|
+
# ============================================================================
|
|
96
|
+
|
|
97
|
+
test_level2_missing_research_summary() {
|
|
98
|
+
describe "LEVEL 2: Should fail when '## Research Summary' is missing"
|
|
99
|
+
|
|
100
|
+
# Arrange - 缺少 Research Summary 章节
|
|
101
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
102
|
+
# Some Other Title
|
|
103
|
+
|
|
104
|
+
## Decisions
|
|
105
|
+
|
|
106
|
+
### R001 — Test
|
|
107
|
+
- Decision: Test
|
|
108
|
+
- Rationale: Test
|
|
109
|
+
- Alternatives considered: Test
|
|
110
|
+
EOF
|
|
111
|
+
|
|
112
|
+
# Act
|
|
113
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
114
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
115
|
+
(
|
|
116
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
117
|
+
echo $? > "$exit_code_file"
|
|
118
|
+
)
|
|
119
|
+
local output=$(cat "$output_file")
|
|
120
|
+
local exit_code=$(cat "$exit_code_file")
|
|
121
|
+
|
|
122
|
+
# Assert
|
|
123
|
+
assert_contains "$output" "❌ LEVEL 2 FAILED" "Should fail LEVEL 2"
|
|
124
|
+
[[ $exit_code -ne 0 ]] || test_fail "Should exit with error code (exit code: $exit_code)"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
test_level2_missing_decisions_section() {
|
|
128
|
+
describe "LEVEL 2: Should fail when '## Decisions' is missing"
|
|
129
|
+
|
|
130
|
+
# Arrange
|
|
131
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
132
|
+
# Research Summary
|
|
133
|
+
|
|
134
|
+
## Some Other Section
|
|
135
|
+
|
|
136
|
+
Content here.
|
|
137
|
+
EOF
|
|
138
|
+
|
|
139
|
+
# Act
|
|
140
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
141
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
142
|
+
(
|
|
143
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
144
|
+
echo $? > "$exit_code_file"
|
|
145
|
+
)
|
|
146
|
+
local output=$(cat "$output_file")
|
|
147
|
+
local exit_code=$(cat "$exit_code_file")
|
|
148
|
+
|
|
149
|
+
# Assert
|
|
150
|
+
assert_contains "$output" "Missing section: ## Decisions" "Should report missing Decisions section"
|
|
151
|
+
[[ $exit_code -ne 0 ]] || test_fail "Should fail validation (exit code: $exit_code)"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
test_level2_no_decision_blocks() {
|
|
155
|
+
describe "LEVEL 2: Should fail when no Decision blocks found"
|
|
156
|
+
|
|
157
|
+
# Arrange - 有章节但无 Decision block
|
|
158
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
159
|
+
# Research Summary
|
|
160
|
+
|
|
161
|
+
## Decisions
|
|
162
|
+
|
|
163
|
+
_No decisions documented yet._
|
|
164
|
+
EOF
|
|
165
|
+
|
|
166
|
+
# Act
|
|
167
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
168
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
169
|
+
(
|
|
170
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
171
|
+
echo $? > "$exit_code_file"
|
|
172
|
+
)
|
|
173
|
+
local output=$(cat "$output_file")
|
|
174
|
+
|
|
175
|
+
# Assert
|
|
176
|
+
assert_contains "$output" "No Decision blocks found" "Should report no decision blocks"
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
test_level2_valid_structure() {
|
|
180
|
+
describe "LEVEL 2: Should pass with valid structure"
|
|
181
|
+
|
|
182
|
+
# Arrange
|
|
183
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
184
|
+
## Research Summary
|
|
185
|
+
|
|
186
|
+
## Decisions
|
|
187
|
+
|
|
188
|
+
### R001 — Test decision
|
|
189
|
+
- Decision: PostgreSQL
|
|
190
|
+
- Rationale: ACID compliance
|
|
191
|
+
- Alternatives considered: MongoDB
|
|
192
|
+
|
|
193
|
+
## Source Library
|
|
194
|
+
|
|
195
|
+
_None_
|
|
196
|
+
EOF
|
|
197
|
+
|
|
198
|
+
# Act
|
|
199
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
200
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
201
|
+
local output=$(cat "$output_file")
|
|
202
|
+
|
|
203
|
+
# Assert
|
|
204
|
+
assert_contains "$output" "✅ LEVEL 2 PASSED" "Should pass LEVEL 2"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# ============================================================================
|
|
208
|
+
# LEVEL 3: Content Quality
|
|
209
|
+
# ============================================================================
|
|
210
|
+
|
|
211
|
+
test_level3_todo_markers() {
|
|
212
|
+
describe "LEVEL 3: Should fail when TODO markers found"
|
|
213
|
+
|
|
214
|
+
# Arrange - 包含 TODO
|
|
215
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
216
|
+
# Research Summary
|
|
217
|
+
|
|
218
|
+
## Decisions
|
|
219
|
+
|
|
220
|
+
### R001 — Test
|
|
221
|
+
- Decision: TODO - fill decision outcome
|
|
222
|
+
- Rationale: TODO - explain why
|
|
223
|
+
- Alternatives considered: TODO - list alternatives
|
|
224
|
+
EOF
|
|
225
|
+
|
|
226
|
+
# Act
|
|
227
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
228
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
229
|
+
(
|
|
230
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
231
|
+
echo $? > "$exit_code_file"
|
|
232
|
+
)
|
|
233
|
+
local output=$(cat "$output_file")
|
|
234
|
+
local exit_code=$(cat "$exit_code_file")
|
|
235
|
+
|
|
236
|
+
# Assert
|
|
237
|
+
assert_contains "$output" "Found 3 TODO/PLACEHOLDER marker(s)" "Should detect TODO markers"
|
|
238
|
+
assert_contains "$output" "❌ LEVEL 3 FAILED" "Should fail LEVEL 3"
|
|
239
|
+
[[ $exit_code -ne 0 ]] || test_fail "Should exit with error (exit code: $exit_code)"
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
test_level3_placeholder_markers() {
|
|
243
|
+
describe "LEVEL 3: Should fail when {{PLACEHOLDER}} found"
|
|
244
|
+
|
|
245
|
+
# Arrange
|
|
246
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
247
|
+
# Research Summary
|
|
248
|
+
|
|
249
|
+
## Decisions
|
|
250
|
+
|
|
251
|
+
### R001 — Test
|
|
252
|
+
- Decision: {{FILL_THIS}}
|
|
253
|
+
- Rationale: Some rationale
|
|
254
|
+
- Alternatives considered: None
|
|
255
|
+
EOF
|
|
256
|
+
|
|
257
|
+
# Act
|
|
258
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
259
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
260
|
+
(
|
|
261
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
262
|
+
echo $? > "$exit_code_file"
|
|
263
|
+
)
|
|
264
|
+
local output=$(cat "$output_file")
|
|
265
|
+
local exit_code=$(cat "$exit_code_file")
|
|
266
|
+
|
|
267
|
+
# Assert
|
|
268
|
+
assert_contains "$output" "{{PLACEHOLDER}} marker(s)" "Should detect placeholder markers"
|
|
269
|
+
[[ $exit_code -ne 0 ]] || test_fail "Should fail validation (exit code: $exit_code)"
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
test_level3_no_quality_issues() {
|
|
273
|
+
describe "LEVEL 3: Should pass when no TODO/PLACEHOLDER"
|
|
274
|
+
|
|
275
|
+
# Arrange
|
|
276
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
277
|
+
# Research Summary
|
|
278
|
+
|
|
279
|
+
## Decisions
|
|
280
|
+
|
|
281
|
+
### R001 — Database choice
|
|
282
|
+
- Decision: PostgreSQL 15 with Prisma ORM
|
|
283
|
+
- Rationale: ACID compliance, type-safe access, team experience
|
|
284
|
+
- Alternatives considered: MongoDB (no ACID), MySQL (weaker JSON)
|
|
285
|
+
|
|
286
|
+
## Source Library
|
|
287
|
+
|
|
288
|
+
- research/internal/codebase.md
|
|
289
|
+
EOF
|
|
290
|
+
|
|
291
|
+
# Act
|
|
292
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
293
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
294
|
+
local output=$(cat "$output_file")
|
|
295
|
+
|
|
296
|
+
# Assert
|
|
297
|
+
assert_contains "$output" "✅ LEVEL 3 PASSED" "Should pass LEVEL 3"
|
|
298
|
+
assert_contains "$output" "No TODO/PLACEHOLDER markers" "Should confirm no markers"
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
# ============================================================================
|
|
302
|
+
# LEVEL 4: Tasks Validation
|
|
303
|
+
# ============================================================================
|
|
304
|
+
|
|
305
|
+
test_level4_invalid_tasks_json() {
|
|
306
|
+
describe "LEVEL 4: Should detect invalid tasks.json format"
|
|
307
|
+
|
|
308
|
+
# Arrange - 无效 JSON
|
|
309
|
+
echo "INVALID JSON" > "$TEST_REQ_DIR/research/tasks.json"
|
|
310
|
+
|
|
311
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
312
|
+
# Research Summary
|
|
313
|
+
|
|
314
|
+
## Decisions
|
|
315
|
+
|
|
316
|
+
### R001 — Test
|
|
317
|
+
- Decision: Test
|
|
318
|
+
- Rationale: Test
|
|
319
|
+
- Alternatives: Test
|
|
320
|
+
EOF
|
|
321
|
+
|
|
322
|
+
# Act
|
|
323
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
324
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1 || true
|
|
325
|
+
local output=$(cat "$output_file")
|
|
326
|
+
|
|
327
|
+
# Note: 当前 validate-research.sh 不验证 tasks.json 格式
|
|
328
|
+
# 这是一个潜在的改进点,暂时跳过
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
# ============================================================================
|
|
332
|
+
# LEVEL 5: Constitution Compliance
|
|
333
|
+
# ============================================================================
|
|
334
|
+
|
|
335
|
+
test_level5_speculative_language() {
|
|
336
|
+
describe "LEVEL 5: Should warn about speculative language"
|
|
337
|
+
|
|
338
|
+
# Arrange - 包含推测性语言
|
|
339
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
340
|
+
# Research Summary
|
|
341
|
+
|
|
342
|
+
## Decisions
|
|
343
|
+
|
|
344
|
+
### R001 — Database
|
|
345
|
+
- Decision: PostgreSQL
|
|
346
|
+
- Rationale: Might be better for future scaling
|
|
347
|
+
- Alternatives considered: MySQL could work too
|
|
348
|
+
EOF
|
|
349
|
+
|
|
350
|
+
# Act
|
|
351
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
352
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
353
|
+
local output=$(cat "$output_file")
|
|
354
|
+
|
|
355
|
+
# Assert - 应该有警告但不失败
|
|
356
|
+
assert_contains "$output" "speculative language" "Should warn about speculation"
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
test_level5_no_partial_implementation() {
|
|
360
|
+
describe "LEVEL 5: Should pass when no partial implementation language"
|
|
361
|
+
|
|
362
|
+
# Arrange
|
|
363
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
364
|
+
## Research Summary
|
|
365
|
+
|
|
366
|
+
## Decisions
|
|
367
|
+
|
|
368
|
+
### R001 — Test
|
|
369
|
+
- Decision: Full implementation approach
|
|
370
|
+
- Rationale: Complete solution without shortcuts
|
|
371
|
+
- Alternatives considered: Incremental approach rejected
|
|
372
|
+
EOF
|
|
373
|
+
|
|
374
|
+
# Act
|
|
375
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
376
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
377
|
+
local output=$(cat "$output_file")
|
|
378
|
+
|
|
379
|
+
# Assert
|
|
380
|
+
assert_contains "$output" "✅ LEVEL 4 PASSED" "Should pass Constitution check"
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
# ============================================================================
|
|
384
|
+
# 综合测试: 完整有效的 research.md
|
|
385
|
+
# ============================================================================
|
|
386
|
+
|
|
387
|
+
test_complete_valid_research() {
|
|
388
|
+
describe "Should pass all levels with complete valid research.md"
|
|
389
|
+
|
|
390
|
+
# Arrange - 创建完整的 research.md
|
|
391
|
+
cat > "$TEST_REQ_DIR/research/research.md" <<'EOF'
|
|
392
|
+
## Research Summary
|
|
393
|
+
|
|
394
|
+
Generated: 2025-01-26T12:00:00Z
|
|
395
|
+
|
|
396
|
+
## Decisions
|
|
397
|
+
|
|
398
|
+
### R001 — Research database choice for E-commerce Platform
|
|
399
|
+
- **Decision**: PostgreSQL 15 with Prisma ORM
|
|
400
|
+
- **Rationale**:
|
|
401
|
+
- PRD requires ACID transactions for order processing
|
|
402
|
+
- Prisma provides type-safe database access aligned with TypeScript stack
|
|
403
|
+
- Team has 3 years PostgreSQL production experience
|
|
404
|
+
- **Alternatives Considered**:
|
|
405
|
+
- MongoDB: No ACID transactions, unsuitable for financial operations
|
|
406
|
+
- MySQL: Weaker JSON support, no composite indexes
|
|
407
|
+
- Supabase: Vendor lock-in concerns
|
|
408
|
+
- **Source**: PRD.md:42
|
|
409
|
+
|
|
410
|
+
### R002 — Frontend framework selection
|
|
411
|
+
- **Decision**: Next.js 14 App Router with React Server Components
|
|
412
|
+
- **Rationale**:
|
|
413
|
+
- App Router provides better layout composition
|
|
414
|
+
- Server Components reduce client bundle size
|
|
415
|
+
- Streaming and Suspense support align with requirements
|
|
416
|
+
- **Alternatives Considered**:
|
|
417
|
+
- Pages Router: Deprecated, lacks RSC support
|
|
418
|
+
- Remix: Smaller ecosystem, team unfamiliarity
|
|
419
|
+
- **Source**: Tech-Choice:Frontend Framework
|
|
420
|
+
|
|
421
|
+
## Source Library
|
|
422
|
+
|
|
423
|
+
- research/internal/codebase-overview.md
|
|
424
|
+
- research/mcp/20250126/nextjs-docs.md
|
|
425
|
+
EOF
|
|
426
|
+
|
|
427
|
+
# Act
|
|
428
|
+
local output_file="$TEST_TMP_DIR/output.txt"
|
|
429
|
+
local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
|
|
430
|
+
(
|
|
431
|
+
bash "$VALIDATE_RESEARCH" "$TEST_REQ_DIR" --strict > "$output_file" 2>&1
|
|
432
|
+
echo $? > "$exit_code_file"
|
|
433
|
+
)
|
|
434
|
+
local output=$(cat "$output_file")
|
|
435
|
+
local exit_code=$(cat "$exit_code_file")
|
|
436
|
+
|
|
437
|
+
# Assert - 所有级别都应通过
|
|
438
|
+
assert_contains "$output" "✅ LEVEL 1 PASSED" "Should pass LEVEL 1"
|
|
439
|
+
assert_contains "$output" "✅ LEVEL 2 PASSED" "Should pass LEVEL 2"
|
|
440
|
+
assert_contains "$output" "✅ LEVEL 3 PASSED" "Should pass LEVEL 3"
|
|
441
|
+
assert_contains "$output" "✅ LEVEL 4 PASSED" "Should pass LEVEL 4"
|
|
442
|
+
assert_contains "$output" "✅ ALL VALIDATIONS PASSED" "Should pass all validations"
|
|
443
|
+
[[ $exit_code -eq 0 ]] || test_fail "Should exit with success code (exit code: $exit_code)"
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
# ============================================================================
|
|
447
|
+
# 运行所有测试
|
|
448
|
+
# ============================================================================
|
|
449
|
+
|
|
450
|
+
run_tests \
|
|
451
|
+
test_level1_research_md_missing \
|
|
452
|
+
test_level1_research_md_exists \
|
|
453
|
+
test_level2_missing_research_summary \
|
|
454
|
+
test_level2_missing_decisions_section \
|
|
455
|
+
test_level2_no_decision_blocks \
|
|
456
|
+
test_level2_valid_structure \
|
|
457
|
+
test_level3_todo_markers \
|
|
458
|
+
test_level3_placeholder_markers \
|
|
459
|
+
test_level3_no_quality_issues \
|
|
460
|
+
test_level5_speculative_language \
|
|
461
|
+
test_level5_no_partial_implementation \
|
|
462
|
+
test_complete_valid_research
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# slugify() Function Tests
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# REQ-003: Branch Naming Optimization (Chinese to Pinyin)
|
|
6
|
+
# Test Framework: bats-core
|
|
7
|
+
# =============================================================================
|
|
8
|
+
|
|
9
|
+
# -----------------------------------------------------------------------------
|
|
10
|
+
# Setup: Load common.sh before each test
|
|
11
|
+
# -----------------------------------------------------------------------------
|
|
12
|
+
setup() {
|
|
13
|
+
# Load the function under test
|
|
14
|
+
# BATS_TEST_DIRNAME is .claude/tests/, so ../scripts/ leads to .claude/scripts/
|
|
15
|
+
source "$BATS_TEST_DIRNAME/../scripts/common.sh"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# =============================================================================
|
|
19
|
+
# US2: English Input Compatibility (Regression Tests)
|
|
20
|
+
# =============================================================================
|
|
21
|
+
|
|
22
|
+
@test "slugify: English phrase converts to lowercase hyphenated" {
|
|
23
|
+
result=$(slugify "User Login Feature")
|
|
24
|
+
[ "$result" = "user-login-feature" ]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@test "slugify: English with numbers preserves numbers" {
|
|
28
|
+
result=$(slugify "API2.0")
|
|
29
|
+
[ "$result" = "api2-0" ]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@test "slugify: Empty input returns empty string" {
|
|
33
|
+
result=$(slugify "")
|
|
34
|
+
[ "$result" = "" ]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@test "slugify: Pure numbers preserved" {
|
|
38
|
+
result=$(slugify "123")
|
|
39
|
+
[ "$result" = "123" ]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# US1: Chinese Input Conversion Tests
|
|
44
|
+
# =============================================================================
|
|
45
|
+
|
|
46
|
+
@test "slugify: Pure Chinese converts to pinyin" {
|
|
47
|
+
result=$(slugify "用户登录功能")
|
|
48
|
+
[ "$result" = "yong-hu-deng-lu-gong-neng" ]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@test "slugify: Mixed Chinese-English converts correctly" {
|
|
52
|
+
result=$(slugify "OAuth2认证")
|
|
53
|
+
[ "$result" = "oauth2-ren-zheng" ]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@test "slugify: Chinese with special characters filters correctly" {
|
|
57
|
+
result=$(slugify "测试@#\$%功能")
|
|
58
|
+
[ "$result" = "ce-shi-gong-neng" ]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@test "slugify: Polyphone word uses default pronunciation" {
|
|
62
|
+
result=$(slugify "重庆")
|
|
63
|
+
[ "$result" = "chong-qing" ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# =============================================================================
|
|
67
|
+
# US3: Dependency Missing Warning Tests
|
|
68
|
+
# =============================================================================
|
|
69
|
+
|
|
70
|
+
@test "slugify: No warning for English input regardless of pypinyin" {
|
|
71
|
+
# English input should never trigger pypinyin path, so no warning
|
|
72
|
+
result=$(slugify "User Login" 2>&1)
|
|
73
|
+
# Should not contain "Warning" in output
|
|
74
|
+
[[ "$result" != *"Warning"* ]]
|
|
75
|
+
[ "$result" = "user-login" ]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@test "slugify: Warning function exists and handles missing pypinyin" {
|
|
79
|
+
# Verify _chinese_to_pinyin function exists and is callable
|
|
80
|
+
# The warning logic is embedded in the function
|
|
81
|
+
type _chinese_to_pinyin | grep -q "function"
|
|
82
|
+
}
|