synapse-hub 2.2.4 → 2.4.0

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.
Files changed (311) hide show
  1. package/.agents/agents/failure-analyst.md +11 -0
  2. package/.agents/agents/live-explorer.md +28 -0
  3. package/.agents/agents/orchestrator.md +20 -4
  4. package/.agents/agents/pom-crafter.md +12 -0
  5. package/.agents/agents/quality-gatekeeper.md +19 -4
  6. package/.agents/agents/test-runner.md +11 -0
  7. package/.agents/rules/communication-style.md +40 -0
  8. package/.agents/rules/context-engineering.md +23 -0
  9. package/.agents/rules/git-push-protocol.md +10 -16
  10. package/.agents/rules/graphify.md +14 -14
  11. package/.agents/rules/mandatory-playwright-live.md +29 -29
  12. package/.agents/rules/mobile_appium_rules.md +132 -0
  13. package/.agents/rules/performance_testing_rules.md +74 -0
  14. package/.agents/rules/systematic-debugging.md +6 -6
  15. package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +64 -215
  16. package/.agents/skills/agent-orchestration-multi-agent-optimize/examples/swarm_workload_config.json +12 -0
  17. package/.agents/skills/antigravity-test-sentinel/SKILL.md +3 -3
  18. package/.agents/skills/antigravity-test-sentinel/examples/dod_gate_policy.json +11 -0
  19. package/.agents/skills/api-network-mocking-interception/SKILL.md +1 -1
  20. package/.agents/skills/api-network-mocking-interception/examples/network_route_stub.json +9 -0
  21. package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +9 -9
  22. package/.agents/skills/api-spec-to-e2e-matrix/examples/sample_openapi.json +19 -0
  23. package/.agents/skills/architecture-decision-records/SKILL.md +35 -412
  24. package/.agents/skills/architecture-decision-records/examples/0001-record-architecture-decisions.md +12 -0
  25. package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +1 -1
  26. package/.agents/skills/auth-session-and-cookie-manager/examples/storage_state_sample.json +11 -0
  27. package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +80 -186
  28. package/.agents/skills/backend-load-and-stress-patterns/examples/k6_load_test_sample.js +13 -0
  29. package/.agents/skills/bats-testing-patterns/SKILL.md +1 -1
  30. package/.agents/skills/bats-testing-patterns/examples/cli_runner_test.bats +6 -0
  31. package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -614
  32. package/.agents/skills/clean-pom-crafter/SKILL.md +21 -3
  33. package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -28
  34. package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -138
  35. package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +2 -2
  36. package/.agents/skills/code-refactoring-refactor-clean/examples/refactored_page_sample.groovy +9 -0
  37. package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +5 -5
  38. package/.agents/skills/db-state-verifier-and-seeder/examples/db_fixture_seed.json +12 -0
  39. package/.agents/skills/e2e-testing-patterns/SKILL.md +1 -1
  40. package/.agents/skills/e2e-testing-patterns/examples/playwright_sharded_config.ts +12 -0
  41. package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -522
  42. package/.agents/skills/failure-autopsy-and-healing/SKILL.md +17 -3
  43. package/.agents/skills/failure-autopsy-and-healing/examples/sample_junit_failure.xml +8 -0
  44. package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -64
  45. package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -56
  46. package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -98
  47. package/.agents/skills/file-and-report-validator/SKILL.md +1 -1
  48. package/.agents/skills/file-and-report-validator/examples/sample_export_schema.json +14 -0
  49. package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +3 -3
  50. package/.agents/skills/flaky-test-sentinel-and-quarantine/examples/quarantine_registry.json +11 -0
  51. package/.agents/skills/gherkin-to-suite/SKILL.md +103 -0
  52. package/.agents/skills/gherkin-to-suite/examples/checkout.feature +39 -0
  53. package/.agents/skills/gherkin-to-suite/examples/suite_report_sample.json +334 -0
  54. package/.agents/skills/github-actions-templates/SKILL.md +47 -304
  55. package/.agents/skills/github-actions-templates/examples/matrix_test_pipeline.yml +8 -0
  56. package/.agents/skills/graphify-impact-analyzer/SKILL.md +6 -6
  57. package/.agents/skills/graphify-impact-analyzer/examples/dependency_blast_radius.json +8 -0
  58. package/.agents/skills/katalon-cli-runner/SKILL.md +2 -2
  59. package/.agents/skills/katalon-cli-runner/examples/headless_kre_exec.sh +3 -0
  60. package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -209
  61. package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -155
  62. package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -67
  63. package/.agents/skills/lam-script-generator/SKILL.md +42 -1
  64. package/.agents/skills/lam-script-generator/examples/user_story_sample.md +8 -0
  65. package/.agents/skills/lean-code-ladder/SKILL.md +83 -0
  66. package/.agents/skills/lean-code-ladder/examples/ladder_walkthrough.md +37 -0
  67. package/.agents/skills/meta-prompt-crafter/SKILL.md +107 -0
  68. package/.agents/skills/meta-prompt-crafter/examples/qa_prompt_template.md +35 -0
  69. package/.agents/skills/persistent-planning-files/SKILL.md +108 -0
  70. package/.agents/skills/persistent-planning-files/examples/task_plan_example.md +56 -0
  71. package/.agents/skills/playwright-live-interaction/SKILL.md +49 -1
  72. package/.agents/skills/playwright-live-interaction/examples/live_probe_script.js +5 -0
  73. package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -160
  74. package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -75
  75. package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -388
  76. package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -134
  77. package/.agents/skills/playwright-webapp-testing/SKILL.md +93 -0
  78. package/.agents/skills/playwright-webapp-testing/examples/server_lifecycle_playwright.py +63 -0
  79. package/.agents/skills/rbt-manual-testing/SKILL.md +150 -0
  80. package/.agents/skills/rbt-manual-testing/examples/checkout_rbt_manual_suite.md +25 -0
  81. package/.agents/skills/security-dast-sentinel/SKILL.md +54 -135
  82. package/.agents/skills/security-dast-sentinel/examples/dast_scan_config.json +10 -0
  83. package/.agents/skills/self-healing-locator/SKILL.md +24 -10
  84. package/.agents/skills/self-healing-locator/examples/aom_diff_sample.json +16 -0
  85. package/.agents/skills/skillspector-security-guard/SKILL.md +32 -90
  86. package/.agents/skills/skillspector-security-guard/examples/safe_mcp_config.json +12 -0
  87. package/.agents/skills/surgical-coding-principles/SKILL.md +89 -0
  88. package/.agents/skills/surgical-coding-principles/examples/surgical_vs_scope_creep.md +46 -0
  89. package/.agents/skills/synthetic-test-data-generator/SKILL.md +3 -3
  90. package/.agents/skills/synthetic-test-data-generator/examples/idempotent_data_recipe.json +9 -0
  91. package/.agents/skills/systematic-debugging/SKILL.md +100 -0
  92. package/.agents/skills/systematic-debugging/examples/four_phase_case.md +44 -0
  93. package/.agents/skills/test-driven-development/SKILL.md +114 -0
  94. package/.agents/skills/test-driven-development/examples/red_green_refactor_qa.md +78 -0
  95. package/.agents/skills/token-and-context-optimizer/SKILL.md +1 -1
  96. package/.agents/skills/token-and-context-optimizer/examples/distilled_log_sample.txt +3 -0
  97. package/.agents/skills/verification-before-completion/SKILL.md +100 -0
  98. package/.agents/skills/verification-before-completion/examples/evidence_log_example.md +46 -0
  99. package/.agents/skills/visual-regression-sentinel/SKILL.md +21 -1
  100. package/.agents/skills/visual-regression-sentinel/examples/visual_mask_rules.json +9 -0
  101. package/.agents/skills/wcag-audit-patterns/SKILL.md +3 -3
  102. package/.agents/skills/wcag-audit-patterns/examples/wcag_compliance_checklist.json +10 -0
  103. package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -541
  104. package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +1 -1
  105. package/.agents/skills/web-vitals-and-performance-profiler/examples/cwv_budget_policy.json +6 -0
  106. package/.agents/templates/completion_report.md +57 -57
  107. package/.agents/workflows/analyze_requirement_document.md +18 -0
  108. package/.agents/workflows/export_testcases_excel.md +32 -0
  109. package/.agents/workflows/generate_combinatorial_test_data.md +28 -0
  110. package/.agents/workflows/generate_cross_module_test_plan.md +37 -0
  111. package/.agents/workflows/generate_manual_testcases_rbt.md +56 -0
  112. package/.agents/workflows/generate_requirements_from_website.md +25 -0
  113. package/.agents/workflows/generate_testcases_from_requirements.md +21 -0
  114. package/.agents/workflows/graphify.md +10 -10
  115. package/.agents/workflows/verify.md +2 -2
  116. package/.cursor/rules/language.mdc +7 -7
  117. package/.cursor/rules/synapse-qa.mdc +23 -0
  118. package/.cursorrules +7 -0
  119. package/.pre-commit-hooks.yaml +14 -0
  120. package/.windsurfrules +7 -0
  121. package/AGENTS.md +54 -15
  122. package/CLAUDE.md +35 -12
  123. package/LICENSE +30 -0
  124. package/NOTICE +180 -0
  125. package/README.en.md +325 -0
  126. package/README.md +247 -516
  127. package/action.yml +51 -0
  128. package/benchmarks/qa_eval/README.md +71 -0
  129. package/benchmarks/qa_eval/build_dataset.py +677 -0
  130. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +22 -0
  131. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +22 -0
  132. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +22 -0
  133. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +22 -0
  134. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +22 -0
  135. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +21 -0
  136. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +21 -0
  137. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +21 -0
  138. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +21 -0
  139. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +21 -0
  140. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +23 -0
  141. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +23 -0
  142. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +23 -0
  143. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +23 -0
  144. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +23 -0
  145. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +22 -0
  146. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +22 -0
  147. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +22 -0
  148. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +22 -0
  149. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +23 -0
  150. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +22 -0
  151. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +22 -0
  152. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +22 -0
  153. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +22 -0
  154. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +22 -0
  155. package/benchmarks/qa_eval/eval_runner.py +418 -0
  156. package/benchmarks/qa_eval/reports/AB_METHODOLOGY_REPORT.md +83 -0
  157. package/benchmarks/qa_eval/reports/BENCHMARK_REPORT.md +69 -0
  158. package/benchmarks/qa_eval/reports/eval_results.json +105 -0
  159. package/bin/agent-qa.js +10 -3
  160. package/docs/ARCHITECTURE.md +107 -0
  161. package/docs/CI_CD_INTEGRATION.md +94 -0
  162. package/docs/CLI_REFERENCE.md +157 -0
  163. package/docs/CONTRIBUTING.md +91 -0
  164. package/docs/PLUGIN_DEVELOPMENT_GUIDE.md +126 -0
  165. package/docs/TOKEN_QUOTA_PLAYBOOK.md +41 -0
  166. package/docs/adopted-ecosystem-tools.md +87 -0
  167. package/docs/schemas/synapse.config.schema.json +64 -0
  168. package/examples/cypress-ecommerce-suite/README.md +45 -0
  169. package/examples/cypress-ecommerce-suite/cypress/e2e/checkout.cy.js +17 -0
  170. package/examples/cypress-ecommerce-suite/cypress/pages/BasePage.js +29 -0
  171. package/examples/cypress-ecommerce-suite/cypress/pages/CartPage.js +51 -0
  172. package/examples/cypress-ecommerce-suite/cypress.config.js +13 -0
  173. package/examples/cypress-ecommerce-suite/package.json +13 -0
  174. package/examples/katalon-suite/Keywords/pages/BasePage.groovy +19 -0
  175. package/examples/katalon-suite/Keywords/pages/DashboardPage.groovy +29 -0
  176. package/examples/katalon-suite/Keywords/pages/LoginPage.groovy +45 -0
  177. package/examples/katalon-suite/Profiles/default.glbl +12 -0
  178. package/examples/katalon-suite/README.md +18 -0
  179. package/examples/katalon-suite/Scripts/Auth/TC_LoginSuccess/Script1234567890.groovy +12 -0
  180. package/examples/katalon-suite/Scripts/Dashboard/TC_ViewSummary/Script1234567891.groovy +15 -0
  181. package/examples/katalon-suite/katalon_suite.prj +21 -0
  182. package/examples/playwright-crm-suite/README.md +40 -0
  183. package/examples/playwright-crm-suite/package.json +14 -0
  184. package/examples/playwright-crm-suite/pages/BasePage.ts +37 -0
  185. package/examples/playwright-crm-suite/pages/CustomerPage.ts +57 -0
  186. package/examples/playwright-crm-suite/pages/LoginPage.ts +32 -0
  187. package/examples/playwright-crm-suite/playwright.config.ts +27 -0
  188. package/examples/playwright-crm-suite/tests/auth.spec.ts +22 -0
  189. package/examples/playwright-crm-suite/tests/customers.spec.ts +33 -0
  190. package/examples/plugins/sample-custom-plugin/README.md +14 -0
  191. package/examples/plugins/sample-custom-plugin/plugin.json +16 -0
  192. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/SKILL.md +29 -0
  193. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/examples/audit_fixture.json +8 -0
  194. package/examples/plugins/sample-custom-plugin/tools/custom_security_headers.py +125 -0
  195. package/examples/practices/README.md +22 -0
  196. package/examples/practices/requirements/crm/requirements_contracts.md +292 -0
  197. package/examples/practices/requirements/crm/requirements_customers.md +462 -0
  198. package/examples/practices/requirements/crm/requirements_login.md +202 -0
  199. package/examples/practices/requirements/crm/requirements_projects.md +396 -0
  200. package/examples/practices/requirements/crm/requirements_tasks.md +343 -0
  201. package/examples/practices/requirements/ecommerce/requirements_category_brand.txt +402 -0
  202. package/examples/practices/requirements/jira/KAN-5/KAN-1/2026-04-03_04-28-27.png +0 -0
  203. package/examples/practices/requirements/jira/KAN-5/KAN-1/KAN-1_requirement.md +52 -0
  204. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-19.png +0 -0
  205. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-57.png +0 -0
  206. package/examples/practices/requirements/jira/KAN-5/KAN-4/KAN-4_requirement.md +119 -0
  207. package/examples/practices/requirements/jira/KAN-5/KAN-5_overview.md +9 -0
  208. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-08.png +0 -0
  209. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-23.png +0 -0
  210. package/examples/practices/requirements/jira/KAN-5/KAN-6/KAN-6_requirement.md +32 -0
  211. package/examples/practices/testcases/api/book_management_api_test_cases.md +144 -0
  212. package/examples/practices/testcases/api/user_management_api_test_cases.md +139 -0
  213. package/examples/practices/testcases/crm/test_cases_crm_login.md +148 -0
  214. package/examples/practices/testcases/crm/test_cases_customers.md +156 -0
  215. package/examples/pytest-api-suite/README.md +45 -0
  216. package/examples/pytest-api-suite/conftest.py +31 -0
  217. package/examples/pytest-api-suite/pages/user_api_client.py +36 -0
  218. package/examples/pytest-api-suite/requirements.txt +2 -0
  219. package/examples/pytest-api-suite/tests/test_user_api.py +44 -0
  220. package/examples/selenium-suite/README.md +18 -0
  221. package/examples/selenium-suite/pages/base_page.py +27 -0
  222. package/examples/selenium-suite/pages/login_page.py +29 -0
  223. package/examples/selenium-suite/pages/order_page.py +25 -0
  224. package/examples/selenium-suite/pytest.ini +6 -0
  225. package/examples/selenium-suite/requirements.txt +2 -0
  226. package/examples/selenium-suite/tests/test_login.py +10 -0
  227. package/examples/selenium-suite/tests/test_order.py +10 -0
  228. package/package.json +22 -7
  229. package/scripts/generate_skill_examples.py +244 -0
  230. package/scripts/install.ps1 +112 -0
  231. package/scripts/install_global_plugin.ps1 +94 -0
  232. package/scripts/install_global_plugin.sh +49 -0
  233. package/scripts/lint_skills.ps1 +57 -0
  234. package/scripts/package_dist.py +323 -0
  235. package/scripts/setup.sh +59 -0
  236. package/scripts/update_hub.ps1 +19 -0
  237. package/scripts/update_hub.sh +15 -0
  238. package/skills_manifest.json +209 -6
  239. package/synapse.config.json +30 -0
  240. package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +7 -7
  241. package/templates/PROJECT_STATE_TEMPLATE.md +1 -1
  242. package/templates/ai_bridges/CLAUDE.md +33 -16
  243. package/templates/ai_bridges/copilot-instructions.md +14 -21
  244. package/templates/ai_bridges/cursor_synapse_qa.mdc +17 -20
  245. package/templates/ai_bridges/windsurfrules +21 -21
  246. package/templates/ci/github-actions-synapse.yml +71 -4
  247. package/templates/welcome.html.tmpl +1674 -0
  248. package/tools/.infer_baseline.json +1102 -0
  249. package/tools/TOOLS_RUNBOOK.md +92 -130
  250. package/tools/__init__.py +26 -0
  251. package/tools/agent_canary.py +501 -501
  252. package/tools/analyze_project.py +31 -17
  253. package/tools/api_fuzzer.py +278 -6
  254. package/tools/author_integrity.py +6 -6
  255. package/tools/auto_heal.py +1 -1
  256. package/tools/browser_helpers.js +105 -7
  257. package/tools/bug_reporter.py +31 -1
  258. package/tools/bump_version.py +23 -3
  259. package/tools/cache_resolver.py +248 -14
  260. package/tools/check_env.py +55 -14
  261. package/tools/check_version_sync.py +153 -0
  262. package/tools/ci_healing_hook.py +1 -1
  263. package/tools/cli.py +263 -13
  264. package/tools/count_tokens.py +1257 -0
  265. package/tools/dashboard_generator.py +2638 -0
  266. package/tools/db_sandbox.py +198 -20
  267. package/tools/e2e_flow_prober.ps1 +12 -64
  268. package/tools/e2e_flow_prober.py +99 -0
  269. package/tools/e2e_flow_prober.sh +4 -0
  270. package/tools/flaky_detector.py +4 -3
  271. package/tools/generate_allure_report.ps1 +12 -29
  272. package/tools/generate_allure_report.py +77 -0
  273. package/tools/generate_allure_report.sh +4 -0
  274. package/tools/generate_jmx_plan.py +257 -58
  275. package/tools/generate_test_reports.ps1 +12 -134
  276. package/tools/generate_test_reports.py +133 -0
  277. package/tools/generate_test_reports.sh +4 -0
  278. package/tools/gherkin_suite.py +758 -0
  279. package/tools/git_pre_commit_guard.py +12 -6
  280. package/tools/goldfish_review.py +366 -0
  281. package/tools/heal_pr_automator.py +1 -1
  282. package/tools/heuristic_locator_matcher.py +170 -21
  283. package/tools/infer_linter.py +612 -70
  284. package/tools/lint_ai_docs.py +64 -0
  285. package/tools/matrix_sharder.py +1 -1
  286. package/tools/mcp_excel_server.ps1 +12 -250
  287. package/tools/mcp_excel_server.py +249 -0
  288. package/tools/mcp_excel_server.sh +4 -0
  289. package/tools/mcp_server.py +368 -144
  290. package/tools/md_to_xlsx.py +307 -0
  291. package/tools/micro_mutator.py +300 -69
  292. package/tools/omni_transpiler.py +2 -2
  293. package/tools/output_formatter.py +128 -0
  294. package/tools/pinpoint_failure.py +88 -88
  295. package/tools/project_state.py +2 -2
  296. package/tools/repo_map.py +1 -1
  297. package/tools/safety_firewall.py +196 -45
  298. package/tools/setup_project.py +294 -30
  299. package/tools/spec_drift_sentinel.py +439 -0
  300. package/tools/sync_agent_rules.py +248 -0
  301. package/tools/telemetry_correlator.py +45 -0
  302. package/tools/test_impact.py +51 -12
  303. package/tools/tms_sync_bridge.py +21 -5
  304. package/tools/universal_ir.py +3 -0
  305. package/tools/update_sentinel.py +87 -15
  306. package/tools/verify_all.ps1 +13 -0
  307. package/tools/verify_all.py +463 -79
  308. package/tools/visual_diff_canvas.py +1 -0
  309. package/tools/visual_som_helper.py +1 -1
  310. package/tools/watch_mode.py +305 -0
  311. package/tools/welcome_page.py +291 -0
@@ -0,0 +1,144 @@
1
+ # API Test Cases: Book Management Module
2
+
3
+ > **Target API:** AnhTester Book Management API (v1.0.0)
4
+ > **Base URL:** `https://book.anhtester.com`
5
+ > **Auth Scheme:** Bearer Token (JWT via `Authorization: Bearer <accessToken>`)
6
+ > **Source Spec:** `https://book.anhtester.com/swagger/json`
7
+ > **Tag / Module:** `Book Management`
8
+ > **Quy chuẩn áp dụng:** ISO/IEC/IEEE 29119, OWASP API Security Top 10, Equivalence Partitioning (EP), Boundary Value Analysis (BVA), `api_rules.md`.
9
+
10
+ ---
11
+
12
+ ## 📋 Endpoint Catalog (Module Book Management)
13
+
14
+ | # | HTTP Method | Path | Description | Security | Total Test Cases |
15
+ |---|---|---|---|---|---|
16
+ | 1 | `GET` | `/api/book` | Danh sách sách (Phân trang, Search, Sort, Filter) | Public / Optional | 12 |
17
+ | 2 | `POST` | `/api/book` | Tạo sách mới | Bearer Auth | 20 |
18
+ | 3 | `GET` | `/api/book/{id}` | Chi tiết sách theo ID (Hỗ trợ tăng `viewCount`) | Public / Optional | 7 |
19
+ | 4 | `PATCH` | `/api/book/{id}` | Cập nhật thông tin sách theo ID | Bearer Auth | 13 |
20
+ | 5 | `DELETE` | `/api/book/{id}` | Xóa sách theo ID | Bearer Auth | 6 |
21
+ | **Tổng** | | | | | **58 Test Cases** |
22
+
23
+ ---
24
+
25
+ ## 🔍 Test Cases Chi Tiết Theo Endpoint
26
+
27
+ ### 1. `GET /api/book` — Danh Sách Sách (Pagination, Search, Sorting)
28
+
29
+ | TC ID | Scenario | Request Parameters | Expected Response | Priority | Testing Technique / Rule |
30
+ |---|---|---|---|---|---|
31
+ | `TC_BOOK_GET_001` | Happy Path — Lấy danh sách mặc định | Không truyền query params | **200 OK**<br>Body: `list` (mảng <= 10 items), `pagination` (`total`, `totalPage`, `currentPage`: 1, `lengthData`) | P1 | Happy Path / Baseline |
32
+ | `TC_BOOK_GET_002` | Pagination — Phân trang `page=2&limit=5` | Query: `page=2&limit=5` | **200 OK**<br>`currentPage`: 2, `lengthData` <= 5 | P1 | Equivalence Partitioning |
33
+ | `TC_BOOK_GET_003` | Search — Tìm kiếm theo tên/mô tả sách | Query: `search=Clean Code` | **200 OK**<br>Tất cả sách trong `list` có tên hoặc description chứa "Clean Code" | P1 | Functional Testing |
34
+ | `TC_BOOK_GET_004` | Search — Tìm kiếm từ khóa không tồn tại | Query: `search=non_existent_book_999` | **200 OK**<br>`list`: `[]`, `pagination.total`: 0 | P2 | Boundary Value Analysis |
35
+ | `TC_BOOK_GET_005` | Sorting — Sắp xếp theo giá (`price`) tăng dần | Query: `sort=price&sortBy=asc` | **200 OK**<br>`list` có giá sách tăng dần từ nhỏ tới lớn | P2 | Functional Testing |
36
+ | `TC_BOOK_GET_006` | Sorting — Sắp xếp theo `viewCount` giảm dần | Query: `sort=viewCount&sortBy=desc` | **200 OK**<br>`list` có sách được xem nhiều nhất xếp ở đầu | P2 | Functional Testing |
37
+ | `TC_BOOK_GET_007` | Sorting — Sắp xếp theo `updatedAt` giảm dần (mặc định) | Query: `sort=updatedAt&sortBy=desc` | **200 OK**<br>`list` được cập nhật mới nhất nằm ở đầu | P2 | Functional Testing |
38
+ | `TC_BOOK_GET_008` | Boundary — `page=99999` vượt tổng số trang | Query: `page=99999` | **200 OK**<br>`list`: `[]`, `currentPage`: 99999 | P2 | Boundary Value Analysis |
39
+ | `TC_BOOK_GET_009` | Negative — `sort` truyền trường không hỗ trợ | Query: `sort=invalid_column` | **400 Bad Request** / **422 Unprocessable Entity** | P3 | Input Validation |
40
+ | `TC_BOOK_GET_010` | Security — XSS Payload trong query `search` | Query: `search=<script>alert(1)</script>` | **200 OK**<br>Sanitized / Kết quả rỗng, không thực thi script | P2 | OWASP API8: Injection |
41
+ | `TC_BOOK_GET_011` | Unrestricted Resource Consumption — Spaming 100 requests | 100 Loop GET requests trong 1s | **429 Too Many Requests** / Rate limit header | P2 | OWASP API4: Unrestricted Resource Consumption |
42
+ | `TC_BOOK_GET_012` | Header — Content Negotiation (`Accept: application/xml`) | Header: `Accept: application/xml` | **406 Not Acceptable** hoặc **200 OK** (JSON default) | P3 | Protocol Standard |
43
+
44
+ ---
45
+
46
+ ### 2. `POST /api/book` — Tạo Sách Mới
47
+
48
+ | TC ID | Scenario | Request Body / Headers | Expected Response | Priority | Testing Technique / Rule |
49
+ |---|---|---|---|---|---|
50
+ | `TC_BOOK_POST_001` | Happy Path — Tạo sách đầy đủ tất cả thuộc tính | Header: `Authorization: Bearer <valid_token>`<br>Body: `{ "name": "Clean Code Java", "slug": "clean-code-java", "description": "Sách hướng dẫn viết code sạch", "status": "AVAILABLE", "categories": ["Category_ID_1"], "price": 150000, "pictures": ["https://img.com/book.jpg"] }` | **201 Created**<br>Body: `{ "msg": "Book created successfully" }` (hoặc book ID) | P1 | Happy Path |
51
+ | `TC_BOOK_POST_002` | Happy Path — Tạo sách chỉ có các trường bắt buộc (`name`, `status`, `categories`, `price`) | Body: `{ "name": "Refactoring", "status": "AVAILABLE", "categories": ["Category_ID_1"], "price": 120000 }` | **201 Created** | P1 | Equivalence Partitioning |
52
+ | `TC_BOOK_POST_003` | Negative — Auth: Không gửi Bearer Token | Header: Không có `Authorization` | **401 Unauthorized** / **403 Forbidden** | P1 | OWASP API2: Broken Auth |
53
+ | `TC_BOOK_POST_004` | Negative — Auth: Token không hợp lệ | Header: `Authorization: Bearer invalid_token` | **401 Unauthorized** | P1 | OWASP API2: Broken Auth |
54
+ | `TC_BOOK_POST_005` | Field "name" — Thiếu required field `name` | Body: `{ "status": "AVAILABLE", "categories": ["Cat1"], "price": 50000 }` | **400 Bad Request** / **422 Unprocessable Entity** | P1 | Field Validation |
55
+ | `TC_BOOK_POST_006` | Field "name" — Empty string / Whitespace | Body: `{ "name": " ", "status": "AVAILABLE", "categories": ["Cat1"], "price": 50000 }` | **400 / 422** | P2 | Boundary Value Analysis |
56
+ | `TC_BOOK_POST_007` | Field "categories" — Thiếu required field `categories` | Body: `{ "name": "Book No Cat", "status": "AVAILABLE", "price": 50000 }` | **400 / 422** | P1 | Field Validation |
57
+ | `TC_BOOK_POST_008` | Field "categories" — Mảng rỗng `[]` (Vi phạm `minItems: 1`) | Body: `{ "name": "Book Empty Cat", "status": "AVAILABLE", "categories": [], "price": 50000 }` | **400 / 422**<br>Lỗi danh mục phải có ít nhất 1 phần tử | P1 | Schema MinItems Constraint |
58
+ | `TC_BOOK_POST_009` | Field "price" — Thiếu required field `price` | Body: `{ "name": "Book No Price", "status": "AVAILABLE", "categories": ["Cat1"] }` | **400 / 422** | P1 | Field Validation |
59
+ | `TC_BOOK_POST_010` | Field "price" — Giá số âm (`price: -100`) | Body: `{ "name": "Book Negative Price", "status": "AVAILABLE", "categories": ["Cat1"], "price": -100 }` | **400 / 422** | P1 | Boundary Value Analysis |
60
+ | `TC_BOOK_POST_011` | Field "price" — Giá vượt mức tối đa (`price: 999999999999999`) | Body: `{ "name": "Over Price", "status": "AVAILABLE", "categories": ["Cat1"], "price": 999999999999999 }` | **400 / 422** (Vượt max `9000000000000`) | P2 | Boundary Value Analysis |
61
+ | `TC_BOOK_POST_012` | Field "status" — Giá trị ngoài Enum (không phải `AVAILABLE` / `UNAVAILABLE`) | Body: `{ "name": "Invalid Status", "status": "PENDING", "categories": ["Cat1"], "price": 50000 }` | **400 / 422** | P1 | Enum Validation |
62
+ | `TC_BOOK_POST_013` | Security — SQL Injection trong `name` | Body: `{ "name": "' OR 1=1; DROP TABLE books;--", "status": "AVAILABLE", "categories": ["Cat1"], "price": 50000 }` | **201 Created** (xem như string thường) hoặc **400** | P2 | OWASP API8: Injection |
63
+ | `TC_BOOK_POST_014` | Security — XSS Payload trong `description` | Body: `{ "name": "XSS Book", "description": "<svg onload=alert(1)>", "status": "AVAILABLE", "categories": ["Cat1"], "price": 50000 }` | **201 Created** (Sanitized) / **400** | P2 | OWASP API8: Injection |
64
+ | `TC_BOOK_POST_015` | Security — Mass Assignment (Gửi thuộc tính hệ thống `id`, `viewCount`, `createdAt`) | Body: `{ "name": "Hack Book", "status": "AVAILABLE", "categories": ["Cat1"], "price": 50000, "viewCount": 999999, "id": "custom_id" }` | **201 Created** (nhưng bỏ qua `viewCount`/`id`) hoặc **400** | P1 | OWASP API6: Mass Assignment |
65
+ | `TC_BOOK_POST_016` | Header — Content-Type Mismatch (`text/plain`) | Header: `Content-Type: text/plain` | **415 Unsupported Media Type** | P2 | Protocol Standard |
66
+ | `TC_BOOK_POST_017` | Malformed JSON — Cú pháp JSON lỗi | Body: `{ "name": "Test Book", "price": }` | **400 Bad Request** (JSON Parse Error) | P2 | Syntax Validation |
67
+ | `TC_BOOK_POST_018` | Oversized Payload — JSON body > 10MB | Body chứa description chuỗi 15MB | **413 Payload Too Large** | P3 | System Limits |
68
+ | `TC_BOOK_POST_019` | Concurrency — 2 Request POST tạo trùng slug/name cùng lúc | 2 Parallel threads gửi cùng 1 tên sách | 1 Request **201 Created**, 1 Request **409 Conflict** | P2 | Race Condition / Concurrency |
69
+ | `TC_BOOK_POST_020` | Field "categories" — Truyền danh mục ID không tồn tại | Body: `{ "name": "Invalid Cat", "status": "AVAILABLE", "categories": ["non_existent_cat_999"], "price": 50000 }` | **400 Bad Request** / **404 Not Found** | P1 | Foreign Key Integrity |
70
+
71
+ ---
72
+
73
+ ### 3. `GET /api/book/{id}` — Chi Tiết Sách Theo ID
74
+
75
+ | TC ID | Scenario | Request Parameters | Expected Response | Priority | Testing Technique / Rule |
76
+ |---|---|---|---|---|---|
77
+ | `TC_BOOK_GET_ID_001` | Happy Path — Lấy chi tiết sách tồn tại (`view=false`) | Path: `id`: ID sách hợp lệ<br>Query: `view=false` | **200 OK**<br>Body: `{ "id", "name", "description", "price", "currentPrice", "viewCount", "status", "categories", "promotions", ... }` | P1 | Happy Path |
78
+ | `TC_BOOK_GET_ID_002` | View Increment — Lấy chi tiết sách kèm tăng lượt xem (`view=true`) | Path: `id`: ID sách hợp lệ<br>Query: `view=true` | **200 OK**<br>`viewCount` mới = `viewCount` cũ + 1 | P1 | Business Logic / State Change |
79
+ | `TC_BOOK_GET_ID_003` | Schema Validation — Response khớp cấu trúc | Path: `id`: ID hợp lệ | **200 OK**<br>Tất cả các thuộc tính bắt buộc có trong schema | P1 | Schema Verification |
80
+ | `TC_BOOK_GET_ID_004` | Negative — `id` không tồn tại | Path: `id`: `non_existent_book_id_999` | **404 Not Found**<br>Body: `{ "msg": "Book not found" }` (hoặc tương tự) | P1 | Negative Testing |
81
+ | `TC_BOOK_GET_ID_005` | Negative — `id` rỗng hoặc ký tự đặc biệt | Path: `id`: `!@#$%^&*()` | **400 Bad Request** / **404 Not Found** | P2 | Boundary Value Analysis |
82
+ | `TC_BOOK_GET_ID_006` | Security — SQL Injection trong path `id` | Path: `id`: `1' OR '1'='1` | **400 Bad Request** / **404 Not Found** | P2 | OWASP API8: Injection |
83
+ | `TC_BOOK_GET_ID_007` | Security — Sensitive Data Exposure Check | Path: `id`: ID hợp lệ | **200 OK**<br>Xác nhận Response **KHÔNG làm lộ** thông tin tác giả nhạy cảm | P1 | OWASP API3: Property Level Auth |
84
+
85
+ ---
86
+
87
+ ### 4. `PATCH /api/book/{id}` — Cập Nhật Sách Theo ID
88
+
89
+ | TC ID | Scenario | Request Body / Headers | Expected Response | Priority | Testing Technique / Rule |
90
+ |---|---|---|---|---|---|
91
+ | `TC_BOOK_PATCH_001` | Happy Path — Cập nhật tên và giá sách | Path: `id` hợp lệ<br>Header: `Authorization: Bearer <valid_token>`<br>Body: `{ "name": "Clean Code 2nd Edition", "price": 180000 }` | **200 OK**<br>Body: `{ "msg": "Book updated successfully" }` | P1 | Happy Path |
92
+ | `TC_BOOK_PATCH_002` | Partial Update Check — Các trường không gửi được giữ nguyên | Gửi PATCH chỉ sửa `description`<br>Sau đó `GET /api/book/{id}` | **200 OK**<br>`description` đổi mới, `name`, `price`, `categories` giữ nguyên | P1 | PUT vs PATCH Standard |
93
+ | `TC_BOOK_PATCH_003` | State Change — Đổi trạng thái từ `AVAILABLE` sang `UNAVAILABLE` | Body: `{ "status": "UNAVAILABLE" }` | **200 OK** | P1 | State Transition |
94
+ | `TC_BOOK_PATCH_004` | Negative — Auth: Không gửi Bearer Token | Header: Không có `Authorization` | **401 Unauthorized** / **403 Forbidden** | P1 | OWASP API2: Broken Auth |
95
+ | `TC_BOOK_PATCH_005` | Security — BOLA / IDOR (Sửa sách do user/tác giả khác quản lý) | Token của User A, nhưng truyền `id` cuốn sách của User B | **403 Forbidden** (nếu hệ thống có phân quyền quản lý sách) | P1 | OWASP API1: BOLA / IDOR |
96
+ | `TC_BOOK_PATCH_006` | Negative — `id` không tồn tại | Path: `id`: `invalid_book_id_999` | **404 Not Found** | P1 | Negative Testing |
97
+ | `TC_BOOK_PATCH_007` | Field Validation — Cập nhật `price` thành số âm (`-5000`) | Body: `{ "price": -5000 }` | **400 Bad Request** / **422 Unprocessable Entity** | P1 | Boundary Value Analysis |
98
+ | `TC_BOOK_PATCH_008` | Field Validation — Cập nhật `status` thành giá trị ngoài Enum | Body: `{ "status": "DISCONTINUED" }` | **400 / 422** | P1 | Enum Validation |
99
+ | `TC_BOOK_PATCH_009` | Field Validation — Cập nhật `categories` thành mảng rỗng `[]` | Body: `{ "categories": [] }` | **400 / 422** (Vi phạm `minItems: 1`) | P1 | Schema Constraint |
100
+ | `TC_BOOK_PATCH_010` | Boundary — Request body rỗng `{}` | Body: `{}` | **200 OK** (không đổi gì) hoặc **400 Bad Request** | P3 | Edge Case |
101
+ | `TC_BOOK_PATCH_011` | Security — Mass Assignment (Cố tình cập nhật `viewCount`, `createdAt`) | Body: `{ "viewCount": 99999, "createdAt": "2000-01-01T00:00:00Z" }` | **200 OK** (ignore field nhạy cảm) hoặc **400** | P1 | OWASP API6: Mass Assignment |
102
+ | `TC_BOOK_PATCH_012` | Header — Content-Type Mismatch (`text/plain`) | Header: `Content-Type: text/plain` | **415 Unsupported Media Type** | P2 | Protocol Standard |
103
+ | `TC_BOOK_PATCH_013` | Foreign Key Check — Cập nhật `categories` chứa ID không tồn tại | Body: `{ "categories": ["fake_cat_id_999"] }` | **400 Bad Request** / **404 Not Found** | P1 | Data Integrity |
104
+
105
+ ---
106
+
107
+ ### 5. `DELETE /api/book/{id}` — Xóa Sách Theo ID
108
+
109
+ | TC ID | Scenario | Request / Headers | Expected Response | Priority | Testing Technique / Rule |
110
+ |---|---|---|---|---|---|
111
+ | `TC_BOOK_DELETE_001` | Happy Path — Xóa sách tồn tại thành công | Path: `id` của cuốn sách vừa tạo<br>Header: `Authorization: Bearer <valid_token>` | **200 OK**<br>Body: `{ "msg": "Book deleted successfully" }` | P1 | Happy Path |
112
+ | `TC_BOOK_DELETE_002` | Verification — Gọi GET lại sau khi DELETE | Sau khi DELETE thành công, gọi `GET /api/book/{id}` | **404 Not Found** | P1 | State Verification |
113
+ | `TC_BOOK_DELETE_003` | Security — BOLA / IDOR (Xóa sách của người dùng khác) | Token của User A, nhưng truyền `id` cuốn sách của User B | **403 Forbidden** | P1 | OWASP API1: BOLA / IDOR |
114
+ | `TC_BOOK_DELETE_004` | Negative — Auth: Không gửi Bearer Token | Header: Không có `Authorization` | **401 Unauthorized** / **403 Forbidden** | P1 | OWASP API2: Broken Auth |
115
+ | `TC_BOOK_DELETE_005` | Negative — Xóa sách không tồn tại | Path: `id`: `deleted_or_fake_book_id_999` | **404 Not Found** | P2 | Negative Testing |
116
+ | `TC_BOOK_DELETE_006` | Idempotency Check — Xóa lặp lại cùng 1 Book ID 2 lần liên tiếp | Lần 1: **200 OK**<br>Lần 2 (ngay sau đó): **404 Not Found** | **404 Not Found** ở lần 2 | P2 | Idempotency Check |
117
+
118
+ ---
119
+
120
+ ## 🔄 Dependencies & Execution Order (Chuỗi Phụ Thuộc)
121
+
122
+ ```mermaid
123
+ graph TD
124
+ A["1. POST /api/login<br>(Lấy Access Token)"] --> B["2. GET /api/category-book<br>(Lấy ID danh mục hợp lệ)"]
125
+ B --> C["3. POST /api/book<br>(Tạo Sách mới -> Lấy book_id)"]
126
+ C --> D["4. GET /api/book/{id}?view=true<br>(Xem chi tiết Sách & kiểm tra tăng viewCount)"]
127
+ D --> E["5. PATCH /api/book/{id}<br>(Cập nhật giá & thông tin Sách)"]
128
+ E --> F["6. DELETE /api/book/{id}<br>(Xóa Sách vừa tạo)"]
129
+ F --> G["7. GET /api/book/{id}<br>(Xác nhận 404 Not Found)"]
130
+ ```
131
+
132
+ ---
133
+
134
+ ## 📊 Test Data Matrix cho Module Book Management
135
+
136
+ | Field | Valid Example | Invalid Example | Boundary Example | Security & Protocol Payload |
137
+ |---|---|---|---|---|
138
+ | `name` | `"Clean Code Java"` | `""` (empty), `" "` (whitespace) | 1 char, 255 chars | `"<script>alert('XSS')</script>"`, `' OR 1=1--` |
139
+ | `description` | `"Sách hướng dẫn lập trình"` | — | Long text (10,000 chars) | `"<svg onload=alert(1)>"` |
140
+ | `categories` | `["cat_id_123"]` | `[]` (empty array), `"not_an_array"` | `["non_existent_id"]` | — |
141
+ | `price` | `150000` | `-100` (âm), `"abc"` (string) | `0`, `9000000000000` (max) | `999999999999999` (over max) |
142
+ | `status` | `"AVAILABLE"`, `"UNAVAILABLE"` | `"PENDING"`, `"INVALID"` | Case sensitivity: `"available"` | — |
143
+ | `pictures` | `["https://img.com/b.jpg"]` | `["not_a_valid_url"]` | `[]` | `"javascript:alert(1)"` |
144
+ | `Headers` | `Content-Type: application/json` | `Content-Type: text/plain` | `Accept: application/xml` | Missing Auth Token / Invalid Token |
@@ -0,0 +1,139 @@
1
+ # API Test Cases: User Management Module (Comprehensive Suite)
2
+
3
+ > **Target API:** AnhTester Book Management API (v1.0.0)
4
+ > **Base URL:** `https://book.anhtester.com`
5
+ > **Auth Scheme:** Bearer Token (JWT via `Authorization: Bearer <accessToken>`)
6
+ > **Source Spec:** `https://book.anhtester.com/swagger/json`
7
+ > **Quy chuẩn áp dụng:** ISO/IEC/IEEE 29119, OWASP API Security Top 10, Equivalence Partitioning (EP), Boundary Value Analysis (BVA), Error Guessing, `api_rules.md`.
8
+
9
+ ---
10
+
11
+ ## 📋 Endpoint Catalog (Module User Management)
12
+
13
+ | # | HTTP Method | Path | Description | Security | Total Test Cases |
14
+ |---|---|---|---|---|---|
15
+ | 1 | `GET` | `/api/user` | Danh sách users (Phân trang, Search, Sort) | Public / Optional | 12 |
16
+ | 2 | `POST` | `/api/user` | Tạo người dùng mới | Bearer Auth | 19 |
17
+ | 3 | `GET` | `/api/user/{id}` | Xem thông tin chi tiết user theo ID | Public / Optional | 6 |
18
+ | 4 | `PATCH` | `/api/user/{id}` | Cập nhật thông tin user theo ID | Bearer Auth | 12 |
19
+ | 5 | `DELETE` | `/api/user/{id}` | Xóa user theo ID | Bearer Auth | 5 |
20
+ | **Tổng** | | | | | **54 Test Cases** |
21
+
22
+ ---
23
+
24
+ ## 🔍 Test Cases Chi Tiết Theo Endpoint
25
+
26
+ ### 1. `GET /api/user` — Danh sách Users
27
+
28
+ | TC ID | Scenario | Request Parameters | Expected Response | Priority | Testing Technique / Rule |
29
+ |---|---|---|---|---|---|
30
+ | `TC_USER_GET_001` | Happy Path — Lấy danh sách mặc định | Không truyền query params | **200 OK**<br>Body: `list` (mảng <= 10 items), `pagination` (`total`, `totalPage`, `currentPage`: 1, `lengthData`) | P1 | Happy Path / Baseline |
31
+ | `TC_USER_GET_002` | Pagination — Phân trang `page=2&limit=5` | Query: `page=2&limit=5` | **200 OK**<br>`currentPage`: 2, `lengthData` <= 5 | P1 | Equivalence Partitioning |
32
+ | `TC_USER_GET_003` | Search — Tìm kiếm theo tên | Query: `search=AnhTester` | **200 OK**<br>Tất cả users trong `list` có chứa từ khóa "AnhTester" trong `name` hoặc `email` | P1 | Functional Testing |
33
+ | `TC_USER_GET_004` | Search — Tìm kiếm từ khóa không tồn tại | Query: `search=xyz_not_exist_999` | **200 OK**<br>`list`: `[]`, `pagination.total`: 0 | P2 | Boundary Value Analysis |
34
+ | `TC_USER_GET_005` | Sorting — Sắp xếp theo tên tăng dần | Query: `sort=name&sortBy=asc` | **200 OK**<br>`list` sắp xếp theo thứ tự `name` từ A-Z | P2 | Functional Testing |
35
+ | `TC_USER_GET_006` | Sorting — Sắp xếp theo `createdAt` giảm dần | Query: `sort=createdAt&sortBy=desc` | **200 OK**<br>`list` sắp xếp theo ngày tạo mới nhất lên đầu | P2 | Functional Testing |
36
+ | `TC_USER_GET_007` | Boundary — `page=99999` vượt tổng số trang | Query: `page=99999` | **200 OK**<br>`list`: `[]`, `currentPage`: 99999 | P2 | Boundary Value Analysis |
37
+ | `TC_USER_GET_008` | Negative — `limit=0` hoặc số âm | Query: `limit=-1` | **400 Bad Request** hoặc **422 Unprocessable Entity** | P3 | Input Validation |
38
+ | `TC_USER_GET_009` | Negative — `sort` truyền trường không tồn tại | Query: `sort=invalid_field` | **400 Bad Request** / Error message | P3 | Input Validation |
39
+ | `TC_USER_GET_010` | Security — XSS Payload trong query param `search` | Query: `search=<script>alert(1)</script>` | **200 OK**<br>Sanitized / Kết quả rỗng, không thực thi script | P2 | OWASP API8: Injection |
40
+ | `TC_USER_GET_011` | Rate Limiting — Gửi 100 requests liên tục trong 1 giây | Loop 100 GET requests | **429 Too Many Requests** (nếu có Rate Limiter) hoặc Header `X-RateLimit-Remaining` giảm dần | P2 | OWASP API4: Unrestricted Resource Consumption |
41
+ | `TC_USER_GET_012` | Header — Content Negotiation (`Accept: application/xml`) | Header: `Accept: application/xml` | **406 Not Acceptable** hoặc **200 OK** (trả JSON mặc định) | P3 | Protocol Standard / HTTP Header |
42
+
43
+ ---
44
+
45
+ ### 2. `POST /api/user` — Tạo User Mới
46
+
47
+ | TC ID | Scenario | Request Body / Headers | Expected Response | Priority | Testing Technique / Rule |
48
+ |---|---|---|---|---|---|
49
+ | `TC_USER_POST_001` | Happy Path — Tạo user với đầy đủ các trường | Header: `Authorization: Bearer <valid_token>`<br>Body: `{ "name": "Auto User", "email": "auto_user_1712049200@test.com", "password": "<TEST_PASSWORD>", "phone": "0987654321", "address": "Hà Nội", "isActive": true }` | **201 Created**<br>Body: `{ "msg": "User created successfully" }` (hoặc object user) | P1 | Happy Path |
50
+ | `TC_USER_POST_002` | Happy Path — Tạo user chỉ có required fields (`name`, `email`) | Body: `{ "name": "Minimal User", "email": "auto_min_1712049200@test.com" }` | **201 Created**<br>Password tự động dùng default `<DEFAULT_TEST_PWD>` | P1 | Equivalence Partitioning |
51
+ | `TC_USER_POST_003` | Negative — Auth: Không gửi Bearer Token | Header: Không có `Authorization` | **401 Unauthorized** / **403 Forbidden** | P1 | OWASP API2: Broken Authentication |
52
+ | `TC_USER_POST_004` | Negative — Auth: Token không hợp lệ / hết hạn | Header: `Authorization: Bearer invalid_token_123` | **401 Unauthorized** | P1 | OWASP API2: Broken Authentication |
53
+ | `TC_USER_POST_005` | Field "name" — Thiếu required field `name` | Body: `{ "email": "noname@test.com" }` | **400 Bad Request** / **422 Unprocessable Entity** | P1 | Field-Level Validation |
54
+ | `TC_USER_POST_006` | Field "name" — Empty string / Whitespace | Body: `{ "name": " ", "email": "test@test.com" }` | **400 / 422** | P2 | Boundary Value Analysis |
55
+ | `TC_USER_POST_007` | Field "email" — Thiếu required field `email` | Body: `{ "name": "No Email" }` | **400 / 422** | P1 | Field-Level Validation |
56
+ | `TC_USER_POST_008` | Field "email" — Sai định dạng email | Body: `{ "name": "Test", "email": "invalid_email_format" }` | **400 / 422** | P1 | Syntax Validation |
57
+ | `TC_USER_POST_009` | Field "email" — Email trùng lặp | Body: Email của user đã tồn tại trong DB | **400 / 409 Conflict** | P1 | Business Logic / Data Integrity |
58
+ | `TC_USER_POST_010` | Field "isActive" — Gửi sai data type (string thay vì boolean) | Body: `{ "name": "Test", "email": "valid@test.com", "isActive": "yes" }` | **400 / 422** | P2 | Type Mismatch Validation |
59
+ | `TC_USER_POST_011` | Field "avatarUrl" — URL sai định dạng | Body: `{ "name": "Test", "email": "valid@test.com", "avatarUrl": "not_a_valid_url" }` | **400 / 422** | P2 | Format Validation |
60
+ | `TC_USER_POST_012` | Field "password" — Password siêu dài (10,000 chars) | Body: `{ "name": "Test", "email": "longpass@test.com", "password": "A".repeat(10000) }` | **400 / 422** (Ngăn ngừa ReDoS/Memory Exhaustion) | P2 | OWASP API4 / Stress Test |
61
+ | `TC_USER_POST_013` | Security — SQL Injection trong `name` | Body: `{ "name": "' OR 1=1--", "email": "sqli_1712049200@test.com" }` | **201 Created** (xem như string thường) hoặc **400** | P2 | OWASP API8: Injection |
62
+ | `TC_USER_POST_014` | Security — XSS Payload trong `address` | Body: `{ "name": "XSS Test", "email": "xss_1712049200@test.com", "address": "<img src=x onerror=alert(1)>" }` | **201 Created** (Sanitized) / **400** | P2 | OWASP API8: Injection |
63
+ | `TC_USER_POST_015` | Security — Mass Assignment (Gửi trường nhạy cảm không phép) | Body: `{ "name": "Hacker", "email": "hacker@test.com", "role": "ADMIN", "isAdmin": true, "id": "custom_id_123" }` | **201 Created** (nhưng bỏ qua `role`/`isAdmin`/`id`) hoặc **400** | P1 | OWASP API6: Mass Assignment |
64
+ | `TC_USER_POST_016` | Header — Sai `Content-Type` (`text/plain`) | Header: `Content-Type: text/plain` | **415 Unsupported Media Type** / **400 Bad Request** | P2 | Protocol Standard |
65
+ | `TC_USER_POST_017` | Malformed JSON — Cú pháp JSON bị lỗi | Body: `{ "name": "Test", "email": }` | **400 Bad Request** (JSON Parse Error) | P2 | Error Handling |
66
+ | `TC_USER_POST_018` | Payload Size — Payload vượt quá giới hạn (e.g. > 10MB) | Body JSON dung lượng 15MB | **413 Payload Too Large** | P3 | System Limits |
67
+ | `TC_USER_POST_019` | Concurrency — 2 Request POST tạo cùng 1 email gửi đồng thời | 2 Parallel threads gửi cùng 1 email tại cùng 1 milisecond | 1 Request trả về **201 Created**, 1 Request trả về **409 Conflict** | P2 | Race Condition / Concurrency |
68
+
69
+ ---
70
+
71
+ ### 3. `GET /api/user/{id}` — Chi Tiết User Theo ID
72
+
73
+ | TC ID | Scenario | Path Parameter | Expected Response | Priority | Testing Technique / Rule |
74
+ |---|---|---|---|---|---|
75
+ | `TC_USER_GET_ID_001` | Happy Path — Lấy thông tin user tồn tại | `id`: ID hợp lệ của user sẵn có | **200 OK**<br>Body: `{ "id", "name", "email", "avatarUrl", "phone", "address", "isActive", "createdAt", "updatedAt" }` | P1 | Happy Path |
76
+ | `TC_USER_GET_ID_002` | Schema Check — Kiểm tra đầy đủ các thuộc tính trong Response | `id`: ID hợp lệ | **200 OK**<br>Các trường `id`, `name`, `email`, `isActive`, `createdAt`, `updatedAt` không bị null | P1 | Schema Validation |
77
+ | `TC_USER_GET_ID_003` | Negative — `id` không tồn tại | `id`: `non_exist_user_id_99999` | **404 Not Found**<br>Body: `{ "msg": "User not found" }` | P1 | Negative Testing |
78
+ | `TC_USER_GET_ID_004` | Negative — `id` rỗng hoặc ký tự đặc biệt | `id`: `!@#$%^&*()` | **400 Bad Request** / **404 Not Found** | P2 | Boundary Value Analysis |
79
+ | `TC_USER_GET_ID_005` | Security — SQL Injection trong path `id` | `id`: `1' OR '1'='1` | **400 Bad Request** / **404 Not Found** | P2 | OWASP API8: Injection |
80
+ | `TC_USER_GET_ID_006` | Security — Sensitive Data Exposure Check | `id`: ID hợp lệ | **200 OK**<br>Xác nhận Response **KHÔNG chứa** `password`, `hash`, `token`, hoặc `secretKey` | P1 | OWASP API3: Broken Object Property Level Authorization |
81
+
82
+ ---
83
+
84
+ ### 4. `PATCH /api/user/{id}` — Cập Nhật User Theo ID
85
+
86
+ | TC ID | Scenario | Request | Expected Response | Priority | Testing Technique / Rule |
87
+ |---|---|---|---|---|---|
88
+ | `TC_USER_PATCH_001` | Happy Path — Cập nhật tên và số điện thoại | Path: `id` hợp lệ<br>Header: `Authorization: Bearer <valid_token>`<br>Body: `{ "name": "Updated Name", "phone": "0912345678" }` | **200 OK**<br>Body: `{ "msg": "User updated successfully" }` | P1 | Happy Path |
89
+ | `TC_USER_PATCH_002` | Partial Update Check — Các trường không gửi giữ nguyên | Gửi PATCH chỉ cập nhật `address`<br>Sau đó `GET /api/user/{id}` | **200 OK**<br>Trường `address` đổi mới, `name` và `email` giữ nguyên | P1 | PUT vs PATCH Standard |
90
+ | `TC_USER_PATCH_003` | Happy Path — Đổi trạng thái `isActive` thành `false` | Body: `{ "isActive": false }` | **200 OK** | P1 | Functional Testing |
91
+ | `TC_USER_PATCH_004` | Negative — Auth: Không gửi Bearer Token | Header: Không có `Authorization` | **401 Unauthorized** / **403 Forbidden** | P1 | OWASP API2: Broken Authentication |
92
+ | `TC_USER_PATCH_005` | Security — BOLA / IDOR (Sửa profile của User khác) | Token của User A, nhưng truyền `id` của User B trong URL | **403 Forbidden** (User không có quyền sửa tài khoản khác) | P1 | OWASP API1: Broken Object Level Authorization (BOLA/IDOR) |
93
+ | `TC_USER_PATCH_006` | Negative — `id` không tồn tại | Path: `id`: `invalid_id_999` | **404 Not Found** | P1 | Negative Testing |
94
+ | `TC_USER_PATCH_007` | Negative — Cập nhật email thành email trùng với user khác | Body: `{ "email": "existing_other_user@test.com" }` | **400 Bad Request** / **409 Conflict** | P1 | Business Logic |
95
+ | `TC_USER_PATCH_008` | Negative — Cập nhật email sai định dạng | Body: `{ "email": "not_an_email" }` | **400 / 422** | P2 | Format Validation |
96
+ | `TC_USER_PATCH_009` | Boundary — Request body rỗng `{}` | Body: `{}` | **200 OK** (không đổi gì) hoặc **400 Bad Request** | P3 | Edge Case |
97
+ | `TC_USER_PATCH_010` | Security — Mass Assignment (Truyền field `role` / `createdAt`) | Body: `{ "role": "SUPER_ADMIN", "createdAt": "2000-01-01T00:00:00Z" }` | **200 OK** (ignore các field này) hoặc **400** | P1 | OWASP API6: Mass Assignment |
98
+ | `TC_USER_PATCH_011` | Security — Revoke Refresh Tokens khi thay đổi password | PATCH thay đổi `password`<br>Dùng token/refresh token cũ thực hiện request | **401 Unauthorized** | P1 | Token Lifecycle Security |
99
+ | `TC_USER_PATCH_012` | Header — Content-Type Mismatch | Header: `Content-Type: text/plain` | **415 Unsupported Media Type** | P2 | Protocol Standard |
100
+
101
+ ---
102
+
103
+ ### 5. `DELETE /api/user/{id}` — Xóa User Theo ID
104
+
105
+ | TC ID | Scenario | Request | Expected Response | Priority | Testing Technique / Rule |
106
+ |---|---|---|---|---|---|
107
+ | `TC_USER_DELETE_001` | Happy Path — Xóa user tồn tại thành công | Path: `id` của user vừa tạo<br>Header: `Authorization: Bearer <valid_token>` | **200 OK**<br>Body: `{ "msg": "User deleted successfully" }` | P1 | Happy Path |
108
+ | `TC_USER_DELETE_002` | Verification — Gọi GET lại sau khi DELETE | Sau khi DELETE thành công, gọi `GET /api/user/{id}` | **404 Not Found** | P1 | State Verification |
109
+ | `TC_USER_DELETE_003` | Security — BOLA / IDOR (Xóa tài khoản của User khác) | Token của User A, nhưng truyền `id` của User B | **403 Forbidden** | P1 | OWASP API1: BOLA / IDOR |
110
+ | `TC_USER_DELETE_004` | Negative — Xóa user không tồn tại | Path: `id`: `deleted_or_fake_id_999` | **404 Not Found** | P2 | Negative Testing |
111
+ | `TC_USER_DELETE_005` | Idempotency Check — Xóa lặp lại cùng 1 ID 2 lần liên tiếp | Lần 1: **200 OK**<br>Lần 2 (ngay sau đó): **404 Not Found** | **404 Not Found** ở lần 2 | P2 | Idempotency Check |
112
+
113
+ ---
114
+
115
+ ## 🔄 Dependencies & Execution Order (Chuỗi Phụ Thuộc)
116
+
117
+ ```mermaid
118
+ graph TD
119
+ A["1. POST /api/login<br>(Lấy Access Token)"] --> B["2. GET /api/user<br>(Lấy danh sách user hiện có)"]
120
+ B --> C["3. POST /api/user<br>(Tạo User mới -> Lấy user_id)"]
121
+ C --> D["4. GET /api/user/{id}<br>(Kiểm tra thông tin User vừa tạo)"]
122
+ D --> E["5. PATCH /api/user/{id}<br>(Cập nhật thông tin User)"]
123
+ E --> F["6. DELETE /api/user/{id}<br>(Xóa User vừa tạo)"]
124
+ F --> G["7. GET /api/user/{id}<br>(Xác nhận 404 Not Found)"]
125
+ ```
126
+
127
+ ---
128
+
129
+ ## 📊 Test Data Matrix Nâng Cao
130
+
131
+ | Field | Valid Example | Invalid Example | Boundary Example | Security & Protocol Payload |
132
+ |---|---|---|---|---|
133
+ | `name` | `"Nguyen Van A"` | `""` (empty), `" "` (whitespace) | `"A"` (1 char), 255 chars | `"<script>alert('XSS')</script>"`, `' OR 1=1--` |
134
+ | `email` | `"auto_user_1712049200@test.com"` | `"user@domain"`, `"no_at_sign.com"` | Shortest valid email: `"a@b.co"` | `' OR 1=1--` |
135
+ | `password` | `"<TEST_PASSWORD>"` | `""` | Default: `"<DEFAULT_TEST_PWD>"` | `"A".repeat(10000)` (ReDoS Check) |
136
+ | `phone` | `"0912345678"` | `"abc_not_number"` | `"0"` | `"+84912345678"` |
137
+ | `avatarUrl` | `"https://example.com/avatar.jpg"` | `"not_a_valid_url"` | `"ftp://server/file"` | `"javascript:alert(1)"` |
138
+ | `isActive` | `true` / `false` | `"yes"` (string) | `null` | — |
139
+ | `Headers` | `Content-Type: application/json` | `Content-Type: text/plain` | `Accept: application/xml` | Missing Auth Token / Invalid Token |
@@ -0,0 +1,148 @@
1
+ # TEST CASES — CRM LOGIN MODULE
2
+
3
+ | Thông tin | Chi tiết |
4
+ |-----------|----------|
5
+ | **Dự án** | CRM (Perfex CRM - Anh Tester Demo) |
6
+ | **Module** | Login |
7
+ | **URL** | https://crm.anhtester.com/admin/authentication |
8
+ | **Phương pháp** | AI-RBT (Risk-Based Testing) — FULL 6 bước |
9
+ | **Ngày tạo** | 2026-04-08 |
10
+ | **Tổng số TC** | 30 |
11
+
12
+ ---
13
+
14
+ ## TỔNG HỢP RISK LEVEL
15
+
16
+ | Module | Risk Level | Số TC |
17
+ |--------|-----------|-------|
18
+ | M2: Login Authentication | 🔴 High | 13 |
19
+ | M5: Security | 🔴 High | 6 |
20
+ | M3: Forgot Password | 🟡 Medium | 5 |
21
+ | M4: Logout | 🟡 Medium | 2 |
22
+ | M1: Login Form UI | 🟢 Low | 4 |
23
+
24
+ ---
25
+
26
+ ## TRACEABILITY MATRIX
27
+
28
+ | Requirement | Test Cases |
29
+ |------------|------------|
30
+ | AC-01 | TC_005 |
31
+ | AC-02 | TC_006 |
32
+ | AC-03 | TC_007 |
33
+ | AC-04 | TC_008 |
34
+ | AC-05 | TC_009 |
35
+ | AC-06 | TC_010, TC_011, TC_012 |
36
+ | AC-07 | TC_013, TC_014 |
37
+ | AC-08 | TC_018 |
38
+ | AC-09 | TC_019 |
39
+ | AC-10 | TC_020 |
40
+ | AC-11 | TC_023 |
41
+ | NFR-01 | TC_003, TC_028 |
42
+ | NFR-02 | TC_002 |
43
+ | NFR-03 | TC_030 |
44
+ | NFR-04 | TC_001 |
45
+ | NFR-05 | TC_001, TC_004 |
46
+ | Gap (no AC) | TC_015, TC_016, TC_017, TC_021, TC_022, TC_024, TC_025, TC_026, TC_027, TC_029 |
47
+
48
+ ---
49
+
50
+ ## BẢNG TEST CASES
51
+
52
+ ### M1: Login Form UI (🟢 Low Risk)
53
+
54
+ | TC ID | Module | Risk Level | Test Title | Pre-Condition | Test Steps | Expected Result | Priority | Test Data |
55
+ |-------|--------|-----------|------------|---------------|------------|-----------------|----------|-----------|
56
+ | CRM_LOGIN_TC_001 | M1: Login Form UI | 🟢 Low | Verify trang Login hiển thị đầy đủ các thành phần giao diện | Không | 1. Mở trình duyệt Chrome<br>2. Truy cập URL: `https://crm.anhtester.com/admin/authentication`<br>3. Quan sát toàn bộ trang Login | 1. Trình duyệt mở thành công<br>2. Trang Login tải hoàn chỉnh<br>3. Hiển thị đầy đủ:<br>- Logo "Anh Tester - Automation Testing"<br>- Tiêu đề "Login" (H1)<br>- Trường "Email Address" (textbox)<br>- Trường "Password" (textbox)<br>- Checkbox "Remember me" (không tick mặc định)<br>- Nút "Login" (xanh dương, full width)<br>- Link "Forgot Password?" (màu cam) | Medium | N/A |
57
+ | CRM_LOGIN_TC_002 | M1: Login Form UI | 🟢 Low | Verify trường Password hiển thị dạng masked | Không | 1. Truy cập trang Login<br>2. Click vào trường Password<br>3. Nhập: `TestPassword123`<br>4. Quan sát hiển thị ký tự trong trường Password | 1. Trang Login hiển thị<br>2. Trường Password được focus<br>3-4. Ký tự hiển thị dạng dấu chấm (●●●) hoặc dấu sao (***), KHÔNG hiển thị plaintext | Medium | Password: `TestPassword123` |
58
+ | CRM_LOGIN_TC_003 | M1: Login Form UI | 🟢 Low | Verify CSRF token hidden field tồn tại trong form | Không | 1. Truy cập trang Login<br>2. Inspect HTML form bằng DevTools (F12)<br>3. Tìm hidden field có name="csrf_token_name" | 1. Trang Login hiển thị<br>2. DevTools mở thành công<br>3. Tồn tại `<input type="hidden" name="csrf_token_name">` với value không rỗng, value là chuỗi token duy nhất | Low | N/A |
59
+ | CRM_LOGIN_TC_004 | M1: Login Form UI | 🟢 Low | Verify giao diện responsive trên viewport nhỏ | Không | 1. Truy cập trang Login trên Chrome<br>2. Mở DevTools → Toggle Device Toolbar<br>3. Chọn viewport: iPhone 14 (390×844)<br>4. Quan sát bố cục trang Login<br>5. Chuyển sang viewport: iPad (768×1024)<br>6. Quan sát bố cục | 1-2. DevTools mở thành công<br>3-4. Form Login hiển thị đầy đủ, không bị tràn, nút Login full width, các trường input đọc được<br>5-6. Form Login hiển thị đẹp, căn giữa, responsive | Low | Viewport 1: 390×844<br>Viewport 2: 768×1024 |
60
+
61
+ ---
62
+
63
+ ### M2: Login Authentication (🔴 High Risk)
64
+
65
+ | TC ID | Module | Risk Level | Test Title | Pre-Condition | Test Steps | Expected Result | Priority | Test Data |
66
+ |-------|--------|-----------|------------|---------------|------------|-----------------|----------|-----------|
67
+ | CRM_LOGIN_TC_005 | M2: Login Auth | 🔴 High | Đăng nhập thành công với Email và Password hợp lệ | Tài khoản admin đã tồn tại trong hệ thống | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: `123456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Email được nhập vào trường<br>3. Password được nhập (hiển thị masked)<br>4. Đăng nhập thành công:<br>- Chuyển hướng đến Dashboard (`/admin/`)<br>- Trang hiển thị tiêu đề "Dashboard"<br>- Không hiển thị thông báo lỗi | Critical | Email: `admin@example.com`<br>Password: `123456` |
68
+ | CRM_LOGIN_TC_006 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Để trống trường Email | Không | 1. Truy cập trang Login<br>2. Để trống trường Email<br>3. Nhập Password: `123456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Trường Email trống<br>3. Password được nhập<br>4. Hiển thị thông báo lỗi server-side:<br>- Text: **"The Email Address field is required."**<br>- Trong thẻ `<div class="alert alert-danger text-center">`<br>- Vẫn ở lại trang Login | High | Email: (trống)<br>Password: `123456` |
69
+ | CRM_LOGIN_TC_007 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Để trống trường Password | Không | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Để trống trường Password<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Email được nhập<br>3. Trường Password trống<br>4. Hiển thị thông báo lỗi server-side:<br>- Text: **"The Password field is required."**<br>- Trong thẻ `<div class="alert alert-danger text-center">`<br>- Vẫn ở lại trang Login | High | Email: `admin@example.com`<br>Password: (trống) |
70
+ | CRM_LOGIN_TC_008 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Để trống cả Email và Password | Không | 1. Truy cập trang Login<br>2. Để trống trường Email<br>3. Để trống trường Password<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Cả hai trường trống<br>4. Hiển thị **đồng thời 2 thông báo** lỗi server-side:<br>- **"The Email Address field is required."**<br>- **"The Password field is required."**<br>- Cả 2 trong `<div class="alert alert-danger text-center">`<br>- Vẫn ở lại trang Login | High | Email: (trống)<br>Password: (trống) |
71
+ | CRM_LOGIN_TC_009 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Email sai định dạng (thiếu @) | Không | 1. Truy cập trang Login<br>2. Nhập Email: `invalidemail`<br>3. Nhập Password: `123456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Email nhập không có ký tự @<br>3. Password được nhập<br>4. Trình duyệt **chặn form submit** và hiển thị HTML5 tooltip:<br>- **"Please include an '@' in the email address."** (hoặc tương đương theo ngôn ngữ trình duyệt)<br>- Form KHÔNG được gửi lên server<br>- Đây là client-side validation | High | Email: `invalidemail`<br>Password: `123456` |
72
+ | CRM_LOGIN_TC_010 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Email đúng định dạng nhưng không tồn tại | Không | 1. Truy cập trang Login<br>2. Nhập Email: `notexist_20260408@example.com`<br>3. Nhập Password: `WrongPass!456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Dữ liệu được nhập<br>4. Hiển thị thông báo lỗi server-side:<br>- Text: **"Invalid email or password"**<br>- Trong `<div class="alert alert-danger text-center">`<br>- Vẫn ở lại trang Login | High | Email: `notexist_20260408@example.com`<br>Password: `WrongPass!456` |
73
+ | CRM_LOGIN_TC_011 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Email đúng + Password sai | Tài khoản admin@example.com tồn tại | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: `SaiMatKhau!789`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Dữ liệu được nhập<br>4. Hiển thị thông báo:<br>- Text: **"Invalid email or password"**<br>- Thông báo **KHÔNG** tiết lộ rằng email tồn tại<br>- Vẫn ở lại trang Login | High | Email: `admin@example.com`<br>Password: `SaiMatKhau!789` |
74
+ | CRM_LOGIN_TC_012 | M2: Login Auth | 🔴 High | Đăng nhập thất bại - Email sai + Password đúng | Tài khoản admin@example.com tồn tại, password: 123456 | 1. Truy cập trang Login<br>2. Nhập Email: `wrong_admin@example.com`<br>3. Nhập Password: `123456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Dữ liệu được nhập<br>4. Hiển thị thông báo:<br>- Text: **"Invalid email or password"**<br>- Thông báo **KHÔNG** tiết lộ rằng password đúng<br>- Vẫn ở lại trang Login | High | Email: `wrong_admin@example.com`<br>Password: `123456` |
75
+ | CRM_LOGIN_TC_013 | M2: Login Auth | 🔴 High | Đăng nhập thành công với "Remember me" - Phiên duy trì sau đóng browser | Tài khoản admin đã tồn tại | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: `123456`<br>4. Tick checkbox "Remember me"<br>5. Click nút "Login"<br>6. Verify Dashboard hiển thị<br>7. Đóng hoàn toàn trình duyệt<br>8. Mở lại trình duyệt<br>9. Truy cập: `https://crm.anhtester.com/admin/` | 1. Trang Login hiển thị<br>2-3. Dữ liệu được nhập<br>4. Checkbox được tick<br>5-6. Đăng nhập thành công, Dashboard hiển thị<br>7-8. Trình duyệt đóng và mở lại<br>9. Truy cập trực tiếp Dashboard **KHÔNG** bị redirect về trang Login, phiên vẫn còn hiệu lực (duy trì 1 ngày) | Critical | Email: `admin@example.com`<br>Password: `123456`<br>Remember me: ✅ Tick |
76
+ | CRM_LOGIN_TC_014 | M2: Login Auth | 🔴 High | Đăng nhập KHÔNG tick "Remember me" - Phiên hết khi đóng browser | Tài khoản admin đã tồn tại | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: `123456`<br>4. KHÔNG tick "Remember me" (mặc định)<br>5. Click nút "Login"<br>6. Verify Dashboard hiển thị<br>7. Đóng hoàn toàn trình duyệt<br>8. Mở lại trình duyệt<br>9. Truy cập: `https://crm.anhtester.com/admin/` | 1. Trang Login hiển thị<br>2-3. Dữ liệu được nhập<br>4. Checkbox KHÔNG được tick<br>5-6. Đăng nhập thành công<br>7-8. Trình duyệt đóng và mở lại<br>9. Bị redirect về trang Login (`/admin/authentication`), phiên đã hết | High | Email: `admin@example.com`<br>Password: `123456`<br>Remember me: ❌ Không tick |
77
+ | CRM_LOGIN_TC_015 | M2: Login Auth | 🔴 High | Boundary - Nhập Email cực dài (1000+ ký tự) | Không | 1. Truy cập trang Login<br>2. Nhập Email: chuỗi 1001 ký tự `aaaaaa...aaa@example.com` (996 ký tự 'a' + @example.com)<br>3. Nhập Password: `123456`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Email dài được nhập (có thể bị cắt tùy browser)<br>3. Password được nhập<br>4. Hệ thống xử lý an toàn:<br>- Hiển thị thông báo lỗi HOẶC từ chối<br>- **KHÔNG crash, KHÔNG lỗi 500** | Medium | Email: 1001 ký tự (`aaa...a@example.com`)<br>Password: `123456` |
78
+ | CRM_LOGIN_TC_016 | M2: Login Auth | 🔴 High | Boundary - Nhập Password cực dài (1000+ ký tự) | Không | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: chuỗi 1001 ký tự `Aaaaaa...aaa1!` (lặp ký tự)<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2. Email được nhập<br>3. Password dài được nhập (masked)<br>4. Hệ thống xử lý an toàn:<br>- Hiển thị "Invalid email or password" HOẶC từ chối<br>- **KHÔNG crash, KHÔNG lỗi 500** | Medium | Email: `admin@example.com`<br>Password: 1001 ký tự |
79
+ | CRM_LOGIN_TC_017 | M2: Login Auth | 🔴 High | Truy cập trang Login khi đã đăng nhập → redirect Dashboard | Đã đăng nhập thành công, đang ở Dashboard | 1. Đăng nhập thành công với `admin@example.com`<br>2. Verify đang ở Dashboard<br>3. Thay đổi URL thủ công thành: `https://crm.anhtester.com/admin/authentication`<br>4. Nhấn Enter | 1-2. Đang ở Dashboard<br>3-4. Hệ thống tự động redirect về Dashboard (`/admin/`), **KHÔNG** hiển thị form Login khi đã authenticated | Medium | Email: `admin@example.com`<br>Password: `123456` |
80
+
81
+ ---
82
+
83
+ ### M3: Forgot Password (🟡 Medium Risk)
84
+
85
+ | TC ID | Module | Risk Level | Test Title | Pre-Condition | Test Steps | Expected Result | Priority | Test Data |
86
+ |-------|--------|-----------|------------|---------------|------------|-----------------|----------|-----------|
87
+ | CRM_LOGIN_TC_018 | M3: Forgot Password | 🟡 Medium | Click "Forgot Password?" chuyển đến trang khôi phục | Đang ở trang Login | 1. Truy cập trang Login<br>2. Click link "Forgot Password?" | 1. Trang Login hiển thị<br>2. Chuyển hướng đến URL: `https://crm.anhtester.com/admin/authentication/forgot_password`<br>- Hiển thị trường "Email Address"<br>- Hiển thị nút "Confirm" | High | N/A |
88
+ | CRM_LOGIN_TC_019 | M3: Forgot Password | 🟡 Medium | Gửi email khôi phục với email đã đăng ký | Đang ở trang Forgot Password, tài khoản admin@example.com tồn tại | 1. Truy cập trang Forgot Password<br>2. Nhập Email: `admin@example.com`<br>3. Click nút "Confirm" | 1. Trang Forgot Password hiển thị<br>2. Email được nhập<br>3. Hệ thống xử lý yêu cầu:<br>- Hiển thị thông báo xác nhận (ví dụ: email khôi phục đã được gửi)<br>- KHÔNG hiển thị thông báo lỗi | High | Email: `admin@example.com` |
89
+ | CRM_LOGIN_TC_020 | M3: Forgot Password | 🟡 Medium | Để trống Email trên trang Forgot Password → HTML5 validation | Đang ở trang Forgot Password | 1. Truy cập trang Forgot Password<br>2. Để trống trường Email<br>3. Click nút "Confirm" | 1. Trang Forgot Password hiển thị<br>2. Trường Email trống<br>3. Trình duyệt hiển thị HTML5 validation tooltip (trường có thuộc tính `required`):<br>- **"Please fill out this field."** (hoặc tương đương)<br>- Form KHÔNG được gửi lên server | High | Email: (trống) |
90
+ | CRM_LOGIN_TC_021 | M3: Forgot Password | 🟡 Medium | Nhập email chưa đăng ký trên trang Forgot Password | Đang ở trang Forgot Password | 1. Truy cập trang Forgot Password<br>2. Nhập Email: `khongtontai_20260408@example.com`<br>3. Click nút "Confirm" | 1. Trang Forgot Password hiển thị<br>2. Email được nhập<br>3. Hệ thống hiển thị thông báo chung (không tiết lộ email có tồn tại hay không):<br>- KHÔNG hiển thị "Email not found" hoặc tương tự<br>- Hành vi giống như email hợp lệ (bảo mật) | Medium | Email: `khongtontai_20260408@example.com` |
91
+ | CRM_LOGIN_TC_022 | M3: Forgot Password | 🟡 Medium | Nhập email sai định dạng trên trang Forgot Password | Đang ở trang Forgot Password | 1. Truy cập trang Forgot Password<br>2. Nhập Email: `emailkhonghople`<br>3. Click nút "Confirm" | 1. Trang Forgot Password hiển thị<br>2. Email sai định dạng được nhập<br>3. Trình duyệt hiển thị HTML5 validation tooltip:<br>- **"Please include an '@' in the email address."**<br>- Form KHÔNG được gửi lên server | Medium | Email: `emailkhonghople` |
92
+
93
+ ---
94
+
95
+ ### M4: Logout (🟡 Medium Risk)
96
+
97
+ | TC ID | Module | Risk Level | Test Title | Pre-Condition | Test Steps | Expected Result | Priority | Test Data |
98
+ |-------|--------|-----------|------------|---------------|------------|-----------------|----------|-----------|
99
+ | CRM_LOGIN_TC_023 | M4: Logout | 🟡 Medium | Đăng xuất từ Dashboard → quay về trang Login | Đã đăng nhập thành công, đang ở Dashboard | 1. Đăng nhập thành công<br>2. Verify đang ở Dashboard<br>3. Click vào profile dropdown (góc trên bên phải)<br>4. Click "Logout" | 1-2. Đang ở Dashboard<br>3. Dropdown menu hiển thị<br>4. Đăng xuất thành công:<br>- Chuyển hướng về trang Login (`/admin/authentication`)<br>- Form Login hiển thị<br>- KHÔNG còn hiển thị Dashboard | Critical | Email: `admin@example.com`<br>Password: `123456` |
100
+ | CRM_LOGIN_TC_024 | M4: Logout | 🟡 Medium | Sau logout, nhấn nút Back → không quay lại được Dashboard | Vừa đăng xuất thành công, đang ở trang Login | 1. Đăng nhập thành công<br>2. Đăng xuất (Logout)<br>3. Verify đang ở trang Login<br>4. Nhấn nút **Back** trên trình duyệt<br>5. Quan sát trang hiển thị | 1-2. Đăng nhập và đăng xuất thành công<br>3. Đang ở trang Login<br>4-5. Hệ thống **redirect về trang Login**, KHÔNG hiển thị lại Dashboard:<br>- Session đã bị hủy hoàn toàn<br>- Dữ liệu Dashboard KHÔNG hiển thị từ cache | High | Email: `admin@example.com`<br>Password: `123456` |
101
+
102
+ ---
103
+
104
+ ### M5: Security (🔴 High Risk)
105
+
106
+ | TC ID | Module | Risk Level | Test Title | Pre-Condition | Test Steps | Expected Result | Priority | Test Data |
107
+ |-------|--------|-----------|------------|---------------|------------|-----------------|----------|-----------|
108
+ | CRM_LOGIN_TC_025 | M5: Security | 🔴 High | SQL Injection vào trường Email | Không | 1. Truy cập trang Login<br>2. Nhập Email: `' OR 1=1 --`<br>3. Nhập Password: `anything`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Dữ liệu injection được nhập<br>4. Hệ thống xử lý an toàn:<br>- **KHÔNG** đăng nhập thành công<br>- Hiển thị thông báo lỗi validation HOẶC "Invalid email or password"<br>- **KHÔNG** lỗi SQL / lỗi 500<br>- **KHÔNG** tiết lộ cấu trúc database | Critical | Email: `' OR 1=1 --`<br>Password: `anything` |
109
+ | CRM_LOGIN_TC_026 | M5: Security | 🔴 High | XSS Script Injection vào trường Email | Không | 1. Truy cập trang Login<br>2. Nhập Email: `<script>alert('XSS')</script>`<br>3. Nhập Password: `123456`<br>4. Click nút "Login"<br>5. Quan sát trang kết quả | 1. Trang Login hiển thị<br>2-3. Dữ liệu XSS được nhập<br>4-5. Hệ thống xử lý an toàn:<br>- **KHÔNG** execute script (không popup alert)<br>- Script được escape/sanitize<br>- Hiển thị thông báo lỗi bình thường<br>- **KHÔNG** lỗi 500 | Critical | Email: `<script>alert('XSS')</script>`<br>Password: `123456` |
110
+ | CRM_LOGIN_TC_027 | M5: Security | 🔴 High | SQL Injection vào trường Password | Không | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com`<br>3. Nhập Password: `' OR '1'='1`<br>4. Click nút "Login" | 1. Trang Login hiển thị<br>2-3. Dữ liệu injection được nhập<br>4. Hệ thống xử lý an toàn:<br>- **KHÔNG** đăng nhập thành công<br>- Hiển thị "Invalid email or password"<br>- **KHÔNG** lỗi SQL / lỗi 500 | Critical | Email: `admin@example.com`<br>Password: `' OR '1'='1` |
111
+ | CRM_LOGIN_TC_028 | M5: Security | 🔴 High | CSRF token bị xóa/thay đổi → form submit bị từ chối | Không | 1. Truy cập trang Login<br>2. Mở DevTools (F12) → Inspect form<br>3. Tìm hidden field `csrf_token_name`<br>4. Thay đổi value thành: `invalid_token_12345`<br>5. Nhập Email: `admin@example.com`<br>6. Nhập Password: `123456`<br>7. Click nút "Login" | 1-3. CSRF token field tìm thấy<br>4. Value bị thay đổi thành token giả<br>5-6. Dữ liệu hợp lệ được nhập<br>7. Hệ thống **từ chối request**:<br>- KHÔNG đăng nhập thành công<br>- Hiển thị lỗi CSRF hoặc trang lỗi 403<br>- Bảo vệ chống CSRF hoạt động đúng | High | Email: `admin@example.com`<br>Password: `123456`<br>CSRF Token: `invalid_token_12345` |
112
+ | CRM_LOGIN_TC_029 | M5: Security | 🔴 High | Đăng nhập sai nhiều lần liên tiếp (Brute-force) | Không | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com` + Password: `SaiPass_1` → Click Login<br>3. Lặp lại bước 2 với password khác: `SaiPass_2`, `SaiPass_3`, ..., `SaiPass_10`<br>4. Quan sát sau 10 lần đăng nhập sai liên tiếp | 1. Trang Login hiển thị<br>2-3. Mỗi lần hiển thị "Invalid email or password"<br>4. **Ghi nhận hiện trạng** (RISK):<br>- Nếu hệ thống KHÔNG lockout → ghi bug/risk<br>- Hệ thống không crash, không lỗi 500 | High | Email: `admin@example.com`<br>Passwords: `SaiPass_1` → `SaiPass_10` (10 lần sai liên tiếp) |
113
+ | CRM_LOGIN_TC_030 | M5: Security | 🔴 High | Thông báo lỗi không tiết lộ email tồn tại hay không | Tài khoản admin@example.com tồn tại | 1. Truy cập trang Login<br>2. Nhập Email: `admin@example.com` (tồn tại) + Password sai: `WrongP@ss1`<br>3. Click Login → ghi nhận thông báo lỗi A<br>4. Nhập Email: `khongtontai@example.com` (không tồn tại) + Password: `WrongP@ss1`<br>5. Click Login → ghi nhận thông báo lỗi B<br>6. So sánh thông báo A và B | 1. Trang Login hiển thị<br>2-3. Thông báo A: "Invalid email or password"<br>4-5. Thông báo B: "Invalid email or password"<br>6. **Thông báo A = thông báo B** (giống hệt nhau):<br>- KHÔNG phân biệt "Email not found" vs "Wrong password"<br>- Thiết kế bảo mật đúng chuẩn | High | Email tồn tại: `admin@example.com`<br>Email không tồn tại: `khongtontai@example.com`<br>Password sai: `WrongP@ss1` |
114
+
115
+ ---
116
+
117
+ ## TỔNG HỢP AMBIGUITIES ĐÃ GIẢI QUYẾT
118
+
119
+ | # | Ambiguity | Giải quyết bằng |
120
+ |---|-----------|-----------------|
121
+ | AMB-01 | Không có account lockout | Assumption → TC_029 verify hiện trạng, ghi risk |
122
+ | AMB-02 | Không có min/max Password | Assumption → TC_016 test boundary 1001 ký tự |
123
+ | AMB-03 | Không có max Email | Assumption → TC_015 test boundary 1001 ký tự |
124
+ | AMB-04 | Hành vi email không tồn tại (Forgot Password) | Assumption → TC_021 verify thông báo chung |
125
+ | AMB-05 | Thời hạn link khôi phục | Không sinh TC (không thể verify manual) |
126
+ | AMB-06 | Thời gian Remember me | User trả lời: **1 ngày** → TC_013 |
127
+ | AMB-07 | Redirect khi đã authenticated | Assumption → TC_017 |
128
+ | AMB-08 | Back button sau logout | Assumption → TC_024 |
129
+ | AMB-09 | Copy-paste password | Không sinh TC riêng (hành vi mặc định browser) |
130
+ | AMB-10 | Không có CAPTCHA | Ghi nhận risk trong TC_029 |
131
+ | AMB-11 | Checkbox value="estimate" | Assumption → test chức năng thực tế (TC_013, TC_014) |
132
+ | AMB-12 | Nội dung email khôi phục | Không sinh TC (ngoài scope UI test) |
133
+
134
+ ---
135
+
136
+ ## THỐNG KÊ
137
+
138
+ | Tiêu chí | Số lượng |
139
+ |----------|----------|
140
+ | **Tổng TC** | **30** |
141
+ | Critical Priority | 5 (TC_005, TC_013, TC_023, TC_025, TC_026) |
142
+ | High Priority | 14 |
143
+ | Medium Priority | 8 |
144
+ | Low Priority | 3 |
145
+ | Kỹ thuật EP (Equivalence Partitioning) | TC_005-TC_012 (phân nhóm: đúng/sai/trống) |
146
+ | Kỹ thuật BVA (Boundary Value) | TC_015, TC_016 (email/password cực dài) |
147
+ | Kỹ thuật Decision Table | TC_006-TC_008 (tổ hợp Email trống + Password trống) |
148
+ | Kỹ thuật State Transition | TC_013, TC_014, TC_017, TC_023, TC_024 (trạng thái login/logout/session) |