"""/api/v1/snippets — 공용 스니펫 CRUD + 내 usage.""" import sqlite3 from django.core.management import call_command from apps.snippets.models import Snippet def test_crud_and_usage(auth_api, user): r = auth_api.post("/api/v1/snippets", {"name": " alv filter ", "desc": "ALV 필터", "body": "x", "category": ""}, format="json") assert r.status_code == 201 and r.json()["data"]["name"] == "ALV_FILTER" and r.json()["data"]["category"] == "코드" assert auth_api.post("/api/v1/snippets", {"name": "alv-filter", "desc": "d", "body": "y"}, format="json").status_code == 409 # 하이픈도 같은 이름 assert auth_api.post("/api/v1/snippets", {"name": "", "desc": "d", "body": "y"}, format="json").status_code == 400 assert auth_api.post("/api/v1/snippets", {"name": "BBB", "desc": "d", "body": " "}, format="json").status_code == 400 assert auth_api.post("/api/v1/snippets", {"name": "CCC_OK", "body": "y"}, format="json").status_code == 400 # 설명 필수 r = auth_api.post("/api/v1/snippets", {"name": "필터", "desc": "d", "body": "y"}, format="json") assert r.status_code == 400 and "설명" in r.json()["message"] # 한글 이름 → 설명으로 안내 assert auth_api.post("/api/v1/snippets", {"name": "1ABC", "desc": "d", "body": "y"}, format="json").status_code == 400 assert auth_api.put("/api/v1/snippets/alv_filter", {"desc": " ", "body": "z"}, format="json").status_code == 400 r = auth_api.put("/api/v1/snippets/alv_filter", {"desc": "d", "body": "z", "category": "ALV"}, format="json") assert r.status_code == 200 and r.json()["data"]["body"] == "z" and r.json()["data"]["category"] == "ALV" for _ in range(2): r = auth_api.post("/api/v1/snippets/ALV_FILTER/use") assert r.json()["data"]["usageCount"] == 2 and r.json()["data"]["lastUsed"] > 0 lst = auth_api.get("/api/v1/snippets").json()["data"] assert lst[0]["name"] == "ALV_FILTER" and lst[0]["usageCount"] == 2 assert auth_api.delete("/api/v1/snippets/ALV_FILTER").json()["data"] == {"name": "ALV_FILTER"} assert auth_api.get("/api/v1/snippets").json()["data"] == [] def test_usage_is_per_user(auth_api, user, django_user_model, api): Snippet.objects.create(name="S", body="b") auth_api.post("/api/v1/snippets/S/use") other = django_user_model.objects.create_user(username="o@x.com", email="o@x.com", password="x") api.force_authenticate(other) assert api.get("/api/v1/snippets").json()["data"][0]["usageCount"] == 0 def test_import_from_sqlite(db, tmp_path): p = tmp_path / "old.db" con = sqlite3.connect(p) con.execute("CREATE TABLE snippets(name TEXT PRIMARY KEY, desc TEXT, body TEXT, category TEXT)") con.executemany("INSERT INTO snippets VALUES (?,?,?,?)", [("a b", "d", "x", "코드"), ("EMPTY", "", " ", "코드"), ("C", "", "y", "")]) con.commit() call_command("import_snippets", str(p)) names = {s.name: s for s in Snippet.objects.all()} assert set(names) == {"A_B", "C"} and names["C"].category == "코드" call_command("import_snippets", str(p)) # 이미 있으면 건너뜀 — 배포마다 돌아도 안전 assert Snippet.objects.count() == 2 Snippet.objects.create(name="LEGACY-ABAP", body="x") call_command("import_snippets", str(p)) assert not Snippet.objects.filter(name="LEGACY_ABAP").exists() # 새 규칙 이름으로 중복 생기지 않음 def test_legacy_name_still_editable(auth_api, user): Snippet.objects.create(name="IF_SUBRC-ABAP", desc="", body="IF sy-subrc = 0.") r = auth_api.put("/api/v1/snippets/IF_SUBRC-ABAP", {"desc": "sy-subrc 분기", "body": "IF sy-subrc = 0."}, format="json") assert r.status_code == 200 and r.json()["data"]["name"] == "IF_SUBRC-ABAP" def test_apply_snippet_meta(db, user, tmp_path): from apps.snippets.models import SnippetUsage Snippet.objects.create(name="IF_SUBRC-ABAP", desc="", body="IF sy-subrc = 0.") Snippet.objects.create(name="ALV_FILTER_ROWS", desc="ALV_FILTER", body="x") # 한글 없는 옛 설명 → 채움 Snippet.objects.create(name="KEEP_KO", desc="이미 한글", body="x") # 한글 설명 → 안 덮음 Snippet.objects.create(name="TAKEN", desc="d", body="x") Snippet.objects.create(name="OLD_ONE", desc="", body="x") SnippetUsage.objects.create(snippet_id="IF_SUBRC-ABAP", user=user, count=3) p = tmp_path / "meta.csv" p.write_text( "\n".join([ "name,new_name,desc", "IF_SUBRC-ABAP,CONTROL_IF_SUBRC_CHECK,sy-subrc 로 성공/실패 분기", "ALV_FILTER_ROWS,,ALV 에서 조건에 맞는 행만 필터", "KEEP_KO,,새 설명", "OLD_ONE,TAKEN,x", "GONE,,없는 것", ]), encoding="utf-8", ) call_command("apply_snippet_meta", str(p), "--dry-run") assert Snippet.objects.filter(name="IF_SUBRC-ABAP").exists() # 미리보기는 안 바꿈 call_command("apply_snippet_meta", str(p)) new = Snippet.objects.get(name="CONTROL_IF_SUBRC_CHECK") assert new.desc == "sy-subrc 로 성공/실패 분기" and not Snippet.objects.filter(name="IF_SUBRC-ABAP").exists() assert SnippetUsage.objects.get(snippet_id="CONTROL_IF_SUBRC_CHECK").count == 3 # 사용 기록 같이 옮김 assert Snippet.objects.get(name="ALV_FILTER_ROWS").desc == "ALV 에서 조건에 맞는 행만 필터" assert Snippet.objects.get(name="KEEP_KO").desc == "이미 한글" assert Snippet.objects.filter(name="OLD_ONE").exists() # 새 이름이 이미 있으면 건너뜀 call_command("apply_snippet_meta", str(p)) # 다시 돌려도 결과 같음 assert Snippet.objects.filter(name="CONTROL_IF_SUBRC_CHECK").count() == 1