Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion tracdb/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import time_machine
from django.test import SimpleTestCase, TestCase
from django.urls import reverse

from .models import (
Attachment,
Expand All @@ -29,7 +30,7 @@ def test_router(self):


class TicketTestCase(TracDBCreateDatabaseMixin, TestCase):
databases = {"trac"}
databases = {"default", "trac"}

def _create_ticket(self, custom=None, **kwargs):
"""
Expand Down Expand Up @@ -224,6 +225,59 @@ def test_from_querystring_invalid_time(self):
with self.assertRaises(ValueError):
Ticket.objects.from_querystring("time=2024-10-24..")

def test_api_ticket_404(self):
no_ticket_url = reverse("api_ticket", args=[30000])
response = self.client.get(no_ticket_url)
self.assertEqual(response.status_code, 404)

def test_api_ticket_405(self):
ticket = self._create_ticket(summary="test")
ticket_url = reverse("api_ticket", args=[ticket.id])
post_response = self.client.post(ticket_url, {})
delete_response = self.client.delete(ticket_url)
self.assertEqual(post_response.status_code, 405)
self.assertEqual(delete_response.status_code, 405)

def test_api_ticket_200(self):
ticket = self._create_ticket(
reporter="reporter@email.com",
type="Bug",
summary="test summary",
description="test description",
severity="Normal",
resolution="fixed",
status="assigned",
custom={
"stage": "Accepted",
"has_patch": "1",
"needs_better_patch": "0",
"needs_tests": "0",
},
)

with self.assertNumQueries(1, using="trac"):
response = self.client.get(reverse("api_ticket", args=[ticket.id]))

self.assertEqual(response.status_code, 200)
self.assertJSONEqual(
response.content,
{
"id": ticket.id,
"type": "Bug",
"summary": "test summary",
"description": "test description",
"severity": "Normal",
"status": "assigned",
"resolution": "fixed",
"custom": {
"stage": "Accepted",
"has_patch": "1",
"needs_better_patch": "0",
"needs_tests": "0",
},
},
)


class TracTimeTestCase(SimpleTestCase):
def test_datetime_to_timestamp(self):
Expand Down
1 change: 1 addition & 0 deletions tracdb/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

urlpatterns = [
path("bouncing/", views.bouncing_tickets, name="bouncing_tickets"),
path("api/tickets/<int:ticket_id>", views.api_ticket, name="api_ticket"),
]
21 changes: 20 additions & 1 deletion tracdb/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from django import db
from django.shortcuts import render
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, render
from django.views.decorators.http import require_http_methods

from .models import Ticket
from .tractime import timestamp_to_datetime


Expand Down Expand Up @@ -29,3 +32,19 @@ def bouncing_tickets(request):
def dictfetchall(cursor):
desc = cursor.description
return [dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall()]


@require_http_methods(["GET"])
def api_ticket(request, ticket_id):
ticket_qs = Ticket.objects.with_custom().values(
"id",
"type",
"summary",
"description",
"severity",
"status",
"resolution",
"custom",
)
ticket = get_object_or_404(ticket_qs, id=ticket_id)
return JsonResponse(ticket)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice trick of using values() to get an out-of-the-box serializable object, I hadn't seen that before 👍🏻