Files
gochat/backend/scripts/fix_test_route_params.py
T
rogee aeddedf2a3 Reorganize repo: backend/, deploy/, docs/ layout + AGENTS.md
Restructure the monorepo into clear top-level directories:
- backend/: Go module root (cmd, internal, pkg, configs, migrations,
  docs/swagger, scripts, tests, go.mod, Makefile, .air.toml)
- deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd
- docs/: project documentation + reports/ (moved from repo root)
- AGENTS.md: new AI coding-agent guide at repo root

Update all references to the new layout:
- Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root)
- docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile,
  env_file ../../.env, volume mounts ../../backend:/app
- deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile
- CI: working-directory: backend for go commands, file deploy/docker/Dockerfile,
  coverage path backend/coverage.out, health_check backend/scripts/
- backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../
- README: architecture tree, quickstart, config paths updated

Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh,
gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to
preserve history. Build, vet, SQLite tests, and docker compose config verified.
2026-07-07 14:44:12 +08:00

127 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""Fix test route param names to match handler parseUintParam expectations."""
import os, re, glob
HANDLER_DIR = "internal/handler/api/v1"
TEST_DIR = "internal/handler/api/v1"
def extract_handler_params(handler_file):
"""Extract all parseUintParam(c, "xxx") param names from a handler."""
params = set()
with open(handler_file) as f:
for line in f:
m = re.findall(r'parseUintParam\(c,\s*"([^"]+)"', line)
params.update(m)
return params
def find_handler_for_test(test_file):
"""Map test file to its handler file."""
# e.g. agent_bot_handler_test.go -> agent_bot_handler.go
base = test_file.replace("_test.go", ".go")
base = base.replace("_crud_test.go", "_crud_handler.go")
base = base.replace("_suite_test.go", "_suite_handler.go")
handler_path = os.path.join(HANDLER_DIR, base)
if os.path.exists(handler_path):
return handler_path
# Try removing suffixes
for suffix in ["_handler_crud", "_handler_suite", "_handler_test"]:
candidate = base.replace(suffix + ".go", "_handler.go")
candidate = os.path.join(HANDLER_DIR, candidate)
if os.path.exists(candidate):
return candidate
return None
# Build handler param map
handler_params = {}
for f in sorted(glob.glob(os.path.join(HANDLER_DIR, "*_handler.go"))):
params = extract_handler_params(f)
if params:
handler_params[os.path.basename(f)] = params
# Special known mappings for non-_handler.go test files
SPECIAL_MAPS = {
"csat_survey_handler_test.go": {"id": "csat_survey_id"},
"csat_survey_update_test.go": {"id": "csat_survey_id"},
"draft_message_handler_test.go": {"id": "draft_id"},
"notification_handler_test.go": {"id": "notification_id"},
"message_handler_test.go": {"id": "message_id"},
"conversation_handler_crud_test.go": {"id": "conversation_id"},
"conversation_handler_test.go": {"id": "conversation_id"},
"conversation_participant_handler_test.go": {"id": "user_id"},
"automation_rule_handler_test.go": {"id": "automation_id"},
"agent_bot_handler_test.go": {"id": "agent_bot_id"},
"contact_handler_crud_test.go": {"id": "contact_id"},
"account_handler_test.go": {"id": "account_id"},
"account_saml_settings_handler_test.go": {"id": "saml_setting_id"},
"inbox_handler_test.go": {"id": "inbox_id"},
"integration_hook_handler_test.go": {"id": "hook_id"},
"integration_hook_handler_suite_test.go": {"id": "hook_id"},
"label_handler_test.go": {"id": "label_id"},
"team_handler_test.go": {"id": "team_id"},
"sla_policy_handler_test.go": {"id": "sla_policy_id"},
"custom_filter_handler_test.go": {"id": "custom_filter_id"},
"canned_response_handler_test.go": {"id": "canned_response_id"},
"banner_handler_test.go": {"id": "banner_id"},
"audit_handler_test.go": {"id": "audit_id"},
"captain_custom_tool_crud_handler_test.go": {"id": "custom_tool_id"},
"captain_custom_tool_test_handler_test.go": {"id": "custom_tool_id"},
"category_handler_test.go": {"id": "category_id"},
"company_handler_test.go": {"id": "company_id"},
"mfa_handler_test.go": {"id": "mfa_id"},
"search_handler_test.go": {"id": "search_id"},
"auto_reply_rule_handler_test.go": {"id": "auto_reply_rule_id"},
"bot_rule_handler_test.go": {"id": "bot_rule_id"},
"copilot_suggestion_handler_test.go": {"id": "copilot_suggestion_id"},
"rag_handler_test.go": {"id": "rag_source_id"},
"platform_e2e_test.go": {"id": "agent_bot_id"},
"platform_agent_bot_handler_test.go": {"id": "agent_bot_id"},
"push_subscription_handler_test.go": {"id": "push_subscription_id"},
"webhook_subscription_handler_test.go": {"id": "webhook_subscription_id"},
"installation_config_handler_test.go": {"id": "installation_config_id"},
"custom_attribute_definition_handler_test.go": {"id": "custom_attribute_definition_id"},
"agent_bot_inbox_handler_test.go": {"id": "agent_bot_inbox_id"},
"assignment_policy_v2_handler_test.go": {"id": "assignment_policy_id"},
"conversation_insight_handler_test.go": {"id": "conversation_id"},
"webwidget_offline_handler_test.go": {"id": "inbox_id"},
"tiktok_channel_handler_test.go": {"id": "inbox_id"},
"assignable_agent_handler_test.go": {"id": "inbox_id"},
}
# Also extract from handler files to verify/expand the map
for hf, params in handler_params.items():
test_name = hf.replace("_handler.go", "_handler_test.go")
non_id_params = [p for p in params if p != "id" and p != "account_id" and p != "conversation_id"]
# Find the resource-specific param (e.g. "agent_bot_id", "automation_id")
resource_params = [p for p in params if p.endswith("_id") and p not in ("account_id", "conversation_id", "user_id", "contact_id")]
if resource_params and test_name not in SPECIAL_MAPS:
for rp in resource_params:
if "id" in SPECIAL_MAPS.get(test_name, {}):
continue
SPECIAL_MAPS[test_name] = {"id": rp}
changes = 0
for test_file in sorted(glob.glob(os.path.join(TEST_DIR, "*_test.go"))):
basename = os.path.basename(test_file)
if basename not in SPECIAL_MAPS:
continue
id_map = SPECIAL_MAPS[basename]
with open(test_file) as f:
content = f.read()
new_content = content
# Replace :id" route params with correct names
for old, new in id_map.items():
# Pattern: "/:id" -> "/:new_name"
new_content = new_content.replace(f'"/:{old}"', f'"/:{new}"')
# Also handle patterns like "/:id/clone" etc
new_content = re.sub(rf'"/:{old}/', f'"/:{new}/', new_content)
if new_content != content:
with open(test_file, 'w') as f:
f.write(new_content)
changes += 1
print(f" Fixed: {basename} ({id_map})")
print(f"\nTotal files fixed: {changes}")