"""Tests for the tickets package.""" from __future__ import annotations import json import tempfile from pathlib import Path import pytest from tickets.cli import main from tickets.models import Priority, Status, Ticket from tickets.store import TicketStore class TestTicketModel: def test_create_minimal_ticket(self) -> None: t = Ticket(title="Fix login bug") assert t.title == "Fix login bug" assert t.description == "" assert t.priority == Priority.MEDIUM assert t.status == Status.TODO assert t.id and len(t.id) == 8 def test_create_full_ticket(self) -> None: t = Ticket( title="Deploy v2.0", description="Ship the new release", priority=Priority.CRITICAL, status=Status.IN_PROGRESS, assignee="alice", tags=["deploy", "urgent"], ) assert t.priority == Priority.CRITICAL assert t.status == Status.IN_PROGRESS assert t.assignee == "alice" assert "urgent" in t.tags def test_roundtrip_dict(self) -> None: t = Ticket(title="Test", description="desc", tags=["a", "b"]) rt = Ticket.from_dict(t.to_dict()) assert rt.title == t.title assert rt.description == t.description assert rt.tags == t.tags assert rt.priority == t.priority def test_update_fields(self) -> None: t = Ticket(title="Old") t.update(title="New", status="done", priority="high") assert t.title == "New" assert t.status == Status.DONE assert t.priority == Priority.HIGH assert t.updated_at != t.created_at def test_accept_enum_or_string(self) -> None: t = Ticket(title="X", priority=Priority.LOW, status=Status.DONE) assert t.priority == Priority.LOW t.update(priority="critical", status="cancelled") assert t.priority == Priority.CRITICAL assert t.status == Status.CANCELLED class TestTicketStore: def test_add_and_retrieve(self) -> None: with tempfile.TemporaryDirectory() as d: fp = Path(d) / "t.json" store = TicketStore(fp) t = Ticket(title="Hello") store.add(t) assert t.id in store assert store[t.id].title == "Hello" def test_delete(self) -> None: with tempfile.TemporaryDirectory() as d: fp = Path(d) / "t.json" store = TicketStore(fp) store.add(Ticket(title="rm me")) tid = next(iter(store)) del store[tid] assert tid not in store def test_list_filtering(self) -> None: with tempfile.TemporaryDirectory() as d: fp = Path(d) / "t.json" store = TicketStore(fp) store.add(Ticket("a", status=Status.TODO, priority=Priority.LOW)) store.add(Ticket("b", status=Status.DONE, priority=Priority.HIGH)) store.add(Ticket("c", status=Status.DONE, priority=Priority.LOW)) assert len(store.list_tickets(status="done")) == 2 assert len(store.list_tickets(priority="high")) == 1 def test_persists_to_disk(self) -> None: with tempfile.TemporaryDirectory() as d: fp = Path(d) / "t.json" store = TicketStore(fp) store.add(Ticket("persist")) assert fp.exists() # Reload store2 = TicketStore(fp) assert len(store2) == 1 class TestCLI: def test_create_and_view(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: fp = tmp_path / "t.json" monkeypatch.setattr("tickets.cli.TicketStore", lambda: TicketStore(fp)) main(["create", "My ticket", "-d", "desc", "-p", "high"]) store = TicketStore(fp) assert len(store) == 1 tid = next(iter(store)) main(["view", tid]) main(["list", "-s", "todo"]) main(["list"]) def test_update(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: fp = tmp_path / "t.json" monkeypatch.setattr("tickets.cli.TicketStore", lambda: TicketStore(fp)) main(["create", "Old title"]) store = TicketStore(fp) tid = next(iter(store)) main(["update", tid, "-t", "New title", "-s", "done"]) store2 = TicketStore(fp) assert store2[tid].title == "New title" assert store2[tid].status == Status.DONE def test_delete_with_force(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: fp = tmp_path / "t.json" monkeypatch.setattr("tickets.cli.TicketStore", lambda: TicketStore(fp)) main(["create", "To delete"]) store = TicketStore(fp) assert len(store) == 1 tid = next(iter(store)) main(["delete", tid, "--force"]) store2 = TicketStore(fp) assert len(store2) == 0 def test_prefix_match(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: fp = tmp_path / "t.json" monkeypatch.setattr("tickets.cli.TicketStore", lambda: TicketStore(fp)) main(["create", "Ticket 1"]) store = TicketStore(fp) tid = next(iter(store)) prefix = tid[:4] # Should resolve via prefix main(["view", prefix])