import json from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] p = PROJECT_ROOT / 'docs' / 'openapi-rc.json' d = json.load(open(p, encoding='utf-8')) print('paths:', len(d['paths'])) assert len(d['paths']) == 125, f"Expected 125 paths, got {len(d['paths'])}" paths = d['paths'] required = [ '/review-weight-templates', '/profile/me/review-weights', '/profile/me/privacy', '/jobs/{jobId}/personalized-review-score', '/company/candidates', '/company/candidates/{applicationId}', '/profile/me/candidate-scoring', '/profile/me/candidate-scoring/dimensions/{dimension}', '/profile/me/candidate-scoring/trend', '/company/candidates/{applicationId}/scoring', '/profile/me/candidate-scoring/appeals', '/profile/me/candidate-scoring/appeals/{appealId}', '/profile/me/candidate-scoring/appeals/{appealId}/cancel', '/admin/candidate-scoring/appeals', '/admin/candidate-scoring/appeals/{appealId}/decision', '/admin/candidate-scoring/appeals/{appealId}/rollback', '/admin/candidate-scoring/appeals/{appealId}/history', '/admin/candidate-scoring/snapshots/{candidateUserId}/{dimension}/{period}/history', # 企业评分运营看板(7 个接口) '/company/scoring/dashboard/overview', '/company/scoring/dashboard/job-rankings', '/company/scoring/dashboard/job-rankings/{jobId}', '/company/scoring/dashboard/candidate-rankings', '/company/scoring/dashboard/candidate-rankings/{applicationId}', '/company/scoring/dashboard/trend', '/admin/scoring/dashboard/overview', # Offer 进阶(5 个 path / 6 个 operation) '/offers/{id}/counter-offers', '/offers/{id}/counter-offers/{coId}/accept', '/offers/{id}/counter-offers/{coId}/reject', '/offers/compare', '/offers/statistics', # 账号注销(2 个 path / 3 个 operation) '/profile/me/deletion', '/profile/me/deletion/cancel', # 个人数据导出(3 个 path / 4 个 operation;详情已覆盖状态查询,无需 /status) '/profile/me/data-export-tasks', '/profile/me/data-export-tasks/{taskId}', '/profile/me/data-export-tasks/{taskId}/download', # 结构化面试评分(3 个 path / 4 个 operation) '/interviews/{interviewId}/score', '/interviews/{interviewId}/score/submit', '/interviews/{interviewId}/score/history', # 同岗位竞争力排名(1 个 path / 1 个 operation) '/jobs/{jobId}/competition-ranking', # V33 举报与屏蔽(8 个 path / 9 个 operation) '/reports', '/reports/me', '/reports/{id}', '/blocks/{blockedUserId}', '/blocks/me', '/admin/reports', '/admin/reports/{id}', '/admin/reports/{id}/decision', ] for path in required: assert path in paths, f"Missing path: {path}" print(f" Found: {path}") assert 'get' in paths['/review-weight-templates'], "Missing GET /review-weight-templates" assert 'get' in paths['/profile/me/review-weights'], "Missing GET /profile/me/review-weights" assert 'put' in paths['/profile/me/review-weights'], "Missing PUT /profile/me/review-weights" assert 'get' in paths['/profile/me/privacy'], "Missing GET /profile/me/privacy" assert 'put' in paths['/profile/me/privacy'], "Missing PUT /profile/me/privacy" assert 'get' in paths['/jobs/{jobId}/personalized-review-score'], "Missing GET /jobs/{jobId}/personalized-review-score" assert 'get' in paths['/company/candidates'], "Missing GET /company/candidates" assert 'get' in paths['/company/candidates/{applicationId}'], "Missing GET /company/candidates/{applicationId}" assert 'get' in paths['/profile/me/candidate-scoring'], "Missing GET /profile/me/candidate-scoring" assert 'get' in paths['/profile/me/candidate-scoring/dimensions/{dimension}'], "Missing GET /profile/me/candidate-scoring/dimensions/{dimension}" assert 'get' in paths['/profile/me/candidate-scoring/trend'], "Missing GET /profile/me/candidate-scoring/trend" assert 'get' in paths['/company/candidates/{applicationId}/scoring'], "Missing GET /company/candidates/{applicationId}/scoring" # 评分治理(9 个接口落在 8 个路径:POST+GET 共享 /appeals) assert 'post' in paths['/profile/me/candidate-scoring/appeals'], "Missing POST /profile/me/candidate-scoring/appeals" assert 'get' in paths['/profile/me/candidate-scoring/appeals'], "Missing GET /profile/me/candidate-scoring/appeals" assert 'get' in paths['/profile/me/candidate-scoring/appeals/{appealId}'], "Missing GET .../appeals/{appealId}" assert 'post' in paths['/profile/me/candidate-scoring/appeals/{appealId}/cancel'], "Missing POST .../cancel" assert 'get' in paths['/admin/candidate-scoring/appeals'], "Missing GET /admin/candidate-scoring/appeals" assert 'post' in paths['/admin/candidate-scoring/appeals/{appealId}/decision'], "Missing POST .../decision" assert 'post' in paths['/admin/candidate-scoring/appeals/{appealId}/rollback'], "Missing POST .../rollback" assert 'get' in paths['/admin/candidate-scoring/appeals/{appealId}/history'], "Missing GET .../history" assert 'get' in paths['/admin/candidate-scoring/snapshots/{candidateUserId}/{dimension}/{period}/history'], "Missing GET snapshots history" # 企业评分运营看板(7 个 GET) assert 'get' in paths['/company/scoring/dashboard/overview'], "Missing GET /company/scoring/dashboard/overview" assert 'get' in paths['/company/scoring/dashboard/job-rankings'], "Missing GET /company/scoring/dashboard/job-rankings" assert 'get' in paths['/company/scoring/dashboard/job-rankings/{jobId}'], "Missing GET /company/scoring/dashboard/job-rankings/{jobId}" assert 'get' in paths['/company/scoring/dashboard/candidate-rankings'], "Missing GET /company/scoring/dashboard/candidate-rankings" assert 'get' in paths['/company/scoring/dashboard/candidate-rankings/{applicationId}'], "Missing GET /company/scoring/dashboard/candidate-rankings/{applicationId}" assert 'get' in paths['/company/scoring/dashboard/trend'], "Missing GET /company/scoring/dashboard/trend" assert 'get' in paths['/admin/scoring/dashboard/overview'], "Missing GET /admin/scoring/dashboard/overview" # Offer 进阶(6 个 operation / 5 个 path) assert 'post' in paths['/offers/{id}/counter-offers'], "Missing POST /offers/{id}/counter-offers" assert 'get' in paths['/offers/{id}/counter-offers'], "Missing GET /offers/{id}/counter-offers" assert 'patch' in paths['/offers/{id}/counter-offers/{coId}/accept'], "Missing PATCH .../accept" assert 'patch' in paths['/offers/{id}/counter-offers/{coId}/reject'], "Missing PATCH .../reject" assert 'get' in paths['/offers/compare'], "Missing GET /offers/compare" assert 'get' in paths['/offers/statistics'], "Missing GET /offers/statistics" # 账号注销(3 个 operation) assert 'get' in paths['/profile/me/deletion'], "Missing GET /profile/me/deletion" assert 'post' in paths['/profile/me/deletion'], "Missing POST /profile/me/deletion" assert 'post' in paths['/profile/me/deletion/cancel'], "Missing POST /profile/me/deletion/cancel" # 个人数据导出(4 个 operation / 3 个 path) assert 'post' in paths['/profile/me/data-export-tasks'], "Missing POST /profile/me/data-export-tasks" assert 'get' in paths['/profile/me/data-export-tasks'], "Missing GET /profile/me/data-export-tasks" assert 'get' in paths['/profile/me/data-export-tasks/{taskId}'], "Missing GET /profile/me/data-export-tasks/{taskId}" assert 'get' in paths['/profile/me/data-export-tasks/{taskId}/download'], "Missing GET .../download" print(" Personal data export endpoints present (4 operations / 3 paths)") # 同岗位竞争力排名(1 个 GET operation) assert 'get' in paths['/jobs/{jobId}/competition-ranking'], "Missing GET /jobs/{jobId}/competition-ranking" print(" Competition ranking endpoint present (1 GET operation)") # V33 举报与屏蔽(8 个 path / 9 个 operation;PUT+DELETE 共享 /blocks/{blockedUserId}) assert 'post' in paths['/reports'], "Missing POST /reports" assert 'get' in paths['/reports/me'], "Missing GET /reports/me" assert 'get' in paths['/reports/{id}'], "Missing GET /reports/{id}" assert 'put' in paths['/blocks/{blockedUserId}'], "Missing PUT /blocks/{blockedUserId}" assert 'delete' in paths['/blocks/{blockedUserId}'], "Missing DELETE /blocks/{blockedUserId}" assert 'get' in paths['/blocks/me'], "Missing GET /blocks/me" assert 'get' in paths['/admin/reports'], "Missing GET /admin/reports" assert 'get' in paths['/admin/reports/{id}'], "Missing GET /admin/reports/{id}" assert 'post' in paths['/admin/reports/{id}/decision'], "Missing POST /admin/reports/{id}/decision" print(" V33 report/block endpoints present (9 operations / 8 paths)") print(" Offer advance endpoints all present") print(" 26 operations all present") print(" Account deletion endpoints present (3 operations)") data = json.dumps(d) assert '"" : "#/components/schemas/' not in data, "Found empty ref key" print("No empty ref keys found") print("Valid JSON: True") print("All checks passed!")