|
1 | | -from django.test import Client, TestCase, override_settings |
| 1 | +from django.test import override_settings |
2 | 2 |
|
3 | 3 | import json |
4 | | -from datetime import date, timedelta |
| 4 | +from datetime import date |
5 | 5 |
|
6 | | -from pgcommitfest.commitfest.models import CommitFest |
| 6 | +import pytest |
7 | 7 |
|
| 8 | +from pgcommitfest.commitfest.models import CommitFest |
8 | 9 |
|
9 | | -@override_settings(AUTO_CREATE_COMMITFESTS=False) |
10 | | -class NeedsCIEndpointTestCase(TestCase): |
11 | | - """Test the /api/v1/commitfests/needs_ci endpoint.""" |
| 10 | +pytestmark = pytest.mark.django_db |
12 | 11 |
|
13 | | - @classmethod |
14 | | - def setUpTestData(cls): |
15 | | - today = date.today() |
16 | 12 |
|
17 | | - # Create test commitfests with various statuses |
18 | | - cls.open_cf = CommitFest.objects.create( |
| 13 | +@pytest.fixture |
| 14 | +def commitfests(): |
| 15 | + """Create test commitfests with various statuses.""" |
| 16 | + return { |
| 17 | + "open": CommitFest.objects.create( |
19 | 18 | name="2025-01", |
20 | 19 | status=CommitFest.STATUS_OPEN, |
21 | | - startdate=today - timedelta(days=30), |
22 | | - enddate=today + timedelta(days=30), |
| 20 | + startdate=date(2025, 1, 1), |
| 21 | + enddate=date(2025, 1, 31), |
23 | 22 | draft=False, |
24 | | - ) |
25 | | - |
26 | | - cls.in_progress_cf = CommitFest.objects.create( |
| 23 | + ), |
| 24 | + "in_progress": CommitFest.objects.create( |
27 | 25 | name="2024-11", |
28 | 26 | status=CommitFest.STATUS_INPROGRESS, |
29 | | - startdate=today - timedelta(days=60), |
30 | | - enddate=today + timedelta(days=0), |
| 27 | + startdate=date(2024, 11, 1), |
| 28 | + enddate=date(2024, 11, 30), |
31 | 29 | draft=False, |
32 | | - ) |
33 | | - |
34 | | - # Previous CF that ended 3 days ago (should be included - within 7 day window) |
35 | | - cls.recent_previous_cf = CommitFest.objects.create( |
| 30 | + ), |
| 31 | + "recent_previous": CommitFest.objects.create( |
36 | 32 | name="2024-09", |
37 | 33 | status=CommitFest.STATUS_CLOSED, |
38 | | - startdate=today - timedelta(days=90), |
39 | | - enddate=today - timedelta(days=3), |
| 34 | + startdate=date(2024, 9, 1), |
| 35 | + enddate=date(2024, 9, 30), |
40 | 36 | draft=False, |
41 | | - ) |
42 | | - |
43 | | - # Old previous CF that ended 10 days ago (should be excluded - outside 7 day window) |
44 | | - cls.old_previous_cf = CommitFest.objects.create( |
| 37 | + ), |
| 38 | + "old_previous": CommitFest.objects.create( |
45 | 39 | name="2024-07", |
46 | 40 | status=CommitFest.STATUS_CLOSED, |
47 | | - startdate=today - timedelta(days=120), |
48 | | - enddate=today - timedelta(days=10), |
| 41 | + startdate=date(2024, 7, 1), |
| 42 | + enddate=date(2024, 7, 31), |
49 | 43 | draft=False, |
50 | | - ) |
51 | | - |
52 | | - # Draft commitfest |
53 | | - cls.draft_cf = CommitFest.objects.create( |
| 44 | + ), |
| 45 | + "draft": CommitFest.objects.create( |
54 | 46 | name="2025-03-draft", |
55 | 47 | status=CommitFest.STATUS_OPEN, |
56 | | - startdate=today + timedelta(days=60), |
57 | | - enddate=today + timedelta(days=120), |
| 48 | + startdate=date(2025, 3, 1), |
| 49 | + enddate=date(2025, 3, 31), |
58 | 50 | draft=True, |
59 | | - ) |
60 | | - |
61 | | - def setUp(self): |
62 | | - self.client = Client() |
63 | | - |
64 | | - def test_endpoint_returns_200(self): |
65 | | - """Test that the endpoint returns HTTP 200 OK.""" |
66 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
67 | | - self.assertEqual(response.status_code, 200) |
68 | | - |
69 | | - def test_response_is_valid_json(self): |
70 | | - """Test that the response is valid JSON.""" |
71 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
72 | | - try: |
73 | | - data = json.loads(response.content) |
74 | | - except json.JSONDecodeError: |
75 | | - self.fail("Response is not valid JSON") |
76 | | - |
77 | | - self.assertIn("commitfests", data) |
78 | | - self.assertIsInstance(data["commitfests"], dict) |
79 | | - |
80 | | - def test_response_content_type(self): |
81 | | - """Test that the response has correct Content-Type header.""" |
82 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
83 | | - self.assertEqual(response["Content-Type"], "application/json") |
84 | | - |
85 | | - def test_cors_header_present(self): |
86 | | - """Test that CORS header is present for API access.""" |
87 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
88 | | - self.assertEqual(response["Access-Control-Allow-Origin"], "*") |
89 | | - |
90 | | - def test_includes_open_commitfest(self): |
91 | | - """Test that open commitfests are included in response.""" |
92 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
93 | | - data = json.loads(response.content) |
94 | | - commitfests = data["commitfests"] |
95 | | - |
96 | | - # Should include the open commitfest |
97 | | - self.assertIn("open", commitfests) |
98 | | - self.assertEqual(commitfests["open"]["name"], self.open_cf.name) |
99 | | - |
100 | | - def test_includes_in_progress_commitfest(self): |
101 | | - """Test that in-progress commitfests are included in response.""" |
102 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
103 | | - data = json.loads(response.content) |
104 | | - commitfests = data["commitfests"] |
105 | | - |
106 | | - # Should include the in-progress commitfest |
107 | | - self.assertEqual(commitfests["in_progress"]["name"], self.in_progress_cf.name) |
108 | | - |
109 | | - def test_includes_recent_previous_commitfest(self): |
110 | | - """Test that recently ended commitfests are included (within 7 days).""" |
111 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
112 | | - data = json.loads(response.content) |
113 | | - commitfests = data["commitfests"] |
114 | | - |
115 | | - # Should include recent previous commitfest (ended 3 days ago) |
116 | | - self.assertIsNotNone(commitfests["previous"]) |
117 | | - |
118 | | - def test_excludes_old_previous_commitfest(self): |
119 | | - """Test that old commitfests are excluded (older than 7 days).""" |
120 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
121 | | - data = json.loads(response.content) |
122 | | - commitfests = data["commitfests"] |
123 | | - |
124 | | - # Should not include old previous commitfest (ended 10 days ago) |
125 | | - self.assertNotEqual( |
126 | | - commitfests["previous"]["name"], |
127 | | - self.old_previous_cf.name, |
128 | | - "Old previous commitfest should be excluded", |
129 | | - ) |
130 | | - |
131 | | - def test_excludes_next_open_and_final(self): |
132 | | - """Test that next_open and final are excluded from response.""" |
133 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
134 | | - data = json.loads(response.content) |
135 | | - commitfests = data["commitfests"] |
136 | | - |
137 | | - # These keys should not be present in the response |
138 | | - self.assertNotIn("next_open", commitfests) |
139 | | - self.assertNotIn("final", commitfests) |
140 | | - |
141 | | - def test_response_structure(self): |
142 | | - """Test that response has expected structure.""" |
143 | | - response = self.client.get("/api/v1/commitfests/needs_ci") |
144 | | - data = json.loads(response.content) |
145 | | - |
146 | | - # Top-level structure |
147 | | - self.assertIn("commitfests", data) |
148 | | - self.assertIsInstance(data["commitfests"], dict) |
149 | | - |
150 | | - # Check that commitfest objects have expected fields |
151 | | - commitfests = data["commitfests"] |
152 | | - for key, cf_data in commitfests.items(): |
153 | | - self.assertIsInstance(cf_data, dict) |
154 | | - # Basic fields that should be present |
155 | | - self.assertIn("id", cf_data) |
156 | | - self.assertIn("name", cf_data) |
157 | | - self.assertIn("status", cf_data) |
158 | | - self.assertIn("startdate", cf_data) |
159 | | - self.assertIn("enddate", cf_data) |
| 51 | + ), |
| 52 | + } |
| 53 | + |
| 54 | + |
| 55 | +def test_needs_ci_endpoint(client, commitfests): |
| 56 | + """Test the /api/v1/commitfests/needs_ci endpoint returns correct data.""" |
| 57 | + with override_settings(AUTO_CREATE_COMMITFESTS=False): |
| 58 | + response = client.get("/api/v1/commitfests/needs_ci") |
| 59 | + |
| 60 | + # Check response metadata |
| 61 | + assert response.status_code == 200 |
| 62 | + assert response["Content-Type"] == "application/json" |
| 63 | + assert response["Access-Control-Allow-Origin"] == "*" |
| 64 | + |
| 65 | + # Parse and compare response |
| 66 | + data = json.loads(response.content) |
| 67 | + |
| 68 | + expected = { |
| 69 | + "commitfests": { |
| 70 | + "open": { |
| 71 | + "id": commitfests["open"].id, |
| 72 | + "name": "2025-01", |
| 73 | + "status": "Open", |
| 74 | + "startdate": "2025-01-01", |
| 75 | + "enddate": "2025-01-31", |
| 76 | + }, |
| 77 | + "in_progress": { |
| 78 | + "id": commitfests["in_progress"].id, |
| 79 | + "name": "2024-11", |
| 80 | + "status": "In Progress", |
| 81 | + "startdate": "2024-11-01", |
| 82 | + "enddate": "2024-11-30", |
| 83 | + }, |
| 84 | + "draft": { |
| 85 | + "id": commitfests["draft"].id, |
| 86 | + "name": "2025-03-draft", |
| 87 | + "status": "Open", |
| 88 | + "startdate": "2025-03-01", |
| 89 | + "enddate": "2025-03-31", |
| 90 | + }, |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + assert data == expected |
0 commit comments