import urllib.request import json import time with open("G:/erp/.test_token") as f: token = f.read().strip() base = "http://localhost:3000" def api(method, path, data=None, tok=None): url = base + path headers = {"Content-Type": "application/json"} if tok: headers["Authorization"] = f"Bearer {tok}" body = json.dumps(data).encode("utf-8") if data else None req = urllib.request.Request(url, data=body, headers=headers, method=method) start = int(time.time()*1000) try: with urllib.request.urlopen(req) as resp: elapsed = int(time.time()*1000) - start return resp.status, json.loads(resp.read().decode("utf-8")), elapsed except urllib.error.HTTPError as e: elapsed = int(time.time()*1000) - start try: rbody = json.loads(e.read().decode("utf-8")) except: rbody = {"raw": str(e)} return e.code, rbody, elapsed results = [] def log(test_id, name, code, ms, details): status = "PASS" if (200 <= code < 300) or (code == 400) or (code == 404) or (code == 409) else "FAIL" print(f" [{status}] {name}: HTTP {code}, {ms}ms - {details[:100]}") results.append((test_id, name, status, code, ms, details)) print("=" * 60) print("Part 2: User Management Endpoints") print("=" * 60) # 2.1 GET /users code, body, ms = api("GET", "/api/v1/users", tok=token) data = body.get("data", {}) items = data.get("items", []) log("2.1", "GET /users - list", code, ms, f"total={data.get("total")}, items={len(items)}, success={body.get("success")}") # 2.2 GET /users with pagination code, body, ms = api("GET", "/api/v1/users?page=1&page_size=1", tok=token) data = body.get("data", {}) log("2.2", "GET /users?page=1&page_size=1", code, ms, f"total={data.get("total")}, page={data.get("page")}, page_size={data.get("page_size")}, items={len(data.get("items",[]))}") # 2.3 POST /users - create code, body, ms = api("POST", "/api/v1/users", { "username": "test_user_api", "password": "Test@2026!", "display_name": "API Test User", "email": "test@api.com", "phone": "13800138000" }, tok=token) ud = body.get("data", {}) test_user_id = ud.get("id", "") if ud else "" log("2.3", "POST /users - create", code, ms, f"id={test_user_id}, username={ud.get("username")}, status={ud.get("status")}, pw_in_resp={"password" in ud}" if ud else f"FAIL: {body}") if test_user_id: with open("G:/erp/.test_user_id", "w") as f: f.write(test_user_id) # 2.4 duplicate username code, body, ms = api("POST", "/api/v1/users", { "username": "test_user_api", "password": "Test@2026!", "display_name": "Duplicate User" }, tok=token) log("2.4", "POST /users - duplicate username", code, ms, f"Expected 400/409, got {code}: {json.dumps(body, ensure_ascii=False)[:100]}") # 2.5 missing fields code, body, ms = api("POST", "/api/v1/users", { "display_name": "No username" }, tok=token) log("2.5", "POST /users - missing fields", code, ms, f"code={code}") # 2.6 short password code, body, ms = api("POST", "/api/v1/users", { "username": "short_pwd_user", "password": "12", "display_name": "Short Pwd" }, tok=token) log("2.6", "POST /users - short password", code, ms, f"code={code}, body={json.dumps(body, ensure_ascii=False)[:100]}") if test_user_id: # 2.7 GET single user code, body, ms = api("GET", f"/api/v1/users/{test_user_id}", tok=token) ud = body.get("data", {}) log("2.7", "GET /users/{id}", code, ms, f"found={ud.get("id")==test_user_id}, pw_in_resp={"password" in ud}, status={ud.get("status")}" if ud else f"body={body}") # 2.8 GET invalid UUID code, body, ms = api("GET", "/api/v1/users/00000000-0000-0000-0000-000000000000", tok=token) log("2.8", "GET /users/invalid-uuid", code, ms, f"code={code}") # 2.9 PUT - normal update code, body, ms = api("PUT", f"/api/v1/users/{test_user_id}", { "display_name": "Updated User", "email": "updated@api.com", "version": 1 }, tok=token) ud = body.get("data", {}) log("2.9", "PUT /users/{id} - update", code, ms, f"display_name={ud.get("display_name")}, email={ud.get("email")}, version={ud.get("version")}" if ud else f"body={body}") # 2.10 PUT - optimistic lock conflict code, body, ms = api("PUT", f"/api/v1/users/{test_user_id}", { "display_name": "Conflict", "version": 999 }, tok=token) log("2.10", "PUT /users/{id} - version conflict", code, ms, f"code={code}, body={json.dumps(body, ensure_ascii=False)[:100]}") # 2.11 assign roles code_r, body_r, _ = api("GET", "/api/v1/roles", tok=token) roles = body_r.get("data", {}).get("items", []) if roles: admin_role_id = roles[0]["id"] code, body, ms = api("POST", f"/api/v1/users/{test_user_id}/roles", {"role_ids": [admin_role_id]}, tok=token) log("2.11", "POST /users/{id}/roles", code, ms, f"code={code}") else: log("2.11", "POST /users/{id}/roles", 0, 0, "SKIP: no roles found") print(" " + "=" * 60) print("Part 2 Summary") print("=" * 60) passed = sum(1 for r in results if r[2]=="PASS") failed = sum(1 for r in results if r[2]=="FAIL") print(f"Passed: {passed}, Failed: {failed}, Total: {len(results)}")