diff --git a/backend/tests/apps/api/internal/mutations/api_key_test.py b/backend/tests/apps/api/internal/mutations/api_key_test.py
index 0d28b8e3d8..2e4715dcc1 100644
--- a/backend/tests/apps/api/internal/mutations/api_key_test.py
+++ b/backend/tests/apps/api/internal/mutations/api_key_test.py
@@ -1,4 +1,4 @@
-from datetime import timedelta
+from datetime import datetime, timedelta
from unittest.mock import MagicMock, patch
from uuid import uuid4
@@ -56,6 +56,35 @@ def test_create_api_key_success(self, mock_api_key_create, api_key_mutations):
assert result.api_key == mock_instance
assert result.raw_key == raw_key
+ @patch("apps.api.internal.mutations.api_key.ApiKey.create")
+ @patch("apps.api.internal.mutations.api_key.timezone.now")
+ def test_create_api_key_end_of_day_is_valid(
+ self, mock_now, mock_api_key_create, api_key_mutations
+ ):
+ """Ensure an end-of-day expiry on the current date is accepted."""
+ info = mock_info()
+ user = info.context.request.user
+ fixed_now = datetime(2026, 1, 1, 12, 0, tzinfo=timezone.utc)
+
+ mock_now.return_value = fixed_now
+
+ expires_at = datetime(2026, 1, 1, 23, 59, 59, 999000, tzinfo=timezone.utc)
+
+ mock_instance = MagicMock(spec=ApiKey)
+ mock_api_key_create.return_value = (mock_instance, "raw_key")
+
+ result = api_key_mutations.create_api_key(info, name="Valid Name", expires_at=expires_at)
+
+ mock_api_key_create.assert_called_once_with(
+ user=user, name="Valid Name", expires_at=expires_at
+ )
+
+ assert isinstance(result, CreateApiKeyResult)
+ assert result.ok
+ assert result.code == "SUCCESS"
+ assert result.api_key == mock_instance
+ assert result.raw_key == "raw_key"
+
@patch("apps.api.internal.mutations.api_key.ApiKey.create", return_value=None)
def test_create_api_key_limit_reached(self, mock_api_key_create, api_key_mutations):
"""Test creating an API key when the user has reached their active key limit."""
diff --git a/frontend/__tests__/unit/pages/ApiKeysPage.test.tsx b/frontend/__tests__/unit/pages/ApiKeysPage.test.tsx
index 49be7ba55d..d487bdd035 100644
--- a/frontend/__tests__/unit/pages/ApiKeysPage.test.tsx
+++ b/frontend/__tests__/unit/pages/ApiKeysPage.test.tsx
@@ -109,6 +109,16 @@ describe('ApiKeysPage Component', () => {
}
}
+ const toLocalEndOfDayIso = (date: string) => {
+ const [yearStr, monthStr, dayStr] = date.split('-')
+ const year = Number(yearStr)
+ const month = Number(monthStr)
+ const day = Number(dayStr)
+
+ const endOfDayLocal = new Date(year, month - 1, day, 23, 59, 59, 999)
+ return endOfDayLocal.toISOString()
+ }
+
beforeEach(() => setupMocks())
afterEach(() => jest.clearAllMocks())
@@ -154,7 +164,7 @@ describe('ApiKeysPage Component', () => {
fireEvent.click(screen.getByRole('button', { name: /create api key/i }))
const expectedDate = format(addDays(new Date(), 30), 'yyyy-MM-dd')
- const expectedIso = new Date(`${expectedDate}T00:00:00.000Z`).toISOString()
+ const expectedIso = toLocalEndOfDayIso(expectedDate)
await waitFor(() => {
expect(mockCreateMutation).toHaveBeenCalledWith({
@@ -176,7 +186,27 @@ describe('ApiKeysPage Component', () => {
expect(mockCreateMutation).toHaveBeenCalledWith({
variables: {
name: 'Custom Expiry Key',
- expiresAt: new Date('2025-12-31T00:00:00.000Z').toISOString(),
+ expiresAt: toLocalEndOfDayIso('2025-12-31'),
+ },
+ })
+ })
+ })
+
+ test('creates API key for today using end-of-day UTC', async () => {
+ render(