Skip to content

Commit 6b495c5

Browse files
author
Gianluca Lefebvre
committed
Test secrets list filtering and ordering
1 parent d55b0e5 commit 6b495c5

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
from datetime import timedelta
2+
3+
from django.test import TestCase, override_settings
4+
from django.urls import reverse
5+
from django.utils.timezone import now
6+
from teamvault.apps.secrets.enums import AccessPolicy, ContentType, SecretStatus
7+
from teamvault.apps.secrets.models import Secret
8+
9+
from ..utils import COMMON_OVERRIDES, make_user, new_secret
10+
11+
12+
def _names(response):
13+
return [row['name'] for row in response.json()['results']]
14+
15+
16+
@override_settings(**COMMON_OVERRIDES)
17+
class SecretListFilterTests(TestCase):
18+
def setUp(self):
19+
self.owner = make_user('owner')
20+
self.client.force_login(self.owner)
21+
self.url = reverse('api.secret_list')
22+
23+
def _secret(self, name, *, status=SecretStatus.OK, last_read=None, **kwargs):
24+
secret = new_secret(self.owner, name=name, **kwargs)
25+
updates = {'status': status}
26+
if last_read is not None:
27+
updates['last_read'] = last_read
28+
Secret.objects.filter(pk=secret.pk).update(**updates)
29+
secret.refresh_from_db()
30+
return secret
31+
32+
def test_filter_status_needs_changing(self):
33+
self._secret('ok-one', status=SecretStatus.OK)
34+
self._secret('stale-one', status=SecretStatus.NEEDS_CHANGING)
35+
self._secret('stale-two', status=SecretStatus.NEEDS_CHANGING)
36+
37+
response = self.client.get(self.url, {'status': 'needs_changing'})
38+
39+
self.assertEqual(response.status_code, 200)
40+
self.assertEqual(sorted(_names(response)), ['stale-one', 'stale-two'])
41+
42+
def test_pagination_stable_on_tied_sort_key(self):
43+
base = now()
44+
for i in range(30):
45+
self._secret(f'tie-{i:02d}', last_read=base) # all identical last_read
46+
page1 = self.client.get(self.url, {'ordering': 'last_read', 'page': 1})
47+
page2 = self.client.get(self.url, {'ordering': 'last_read', 'page': 2})
48+
names = _names(page1) + _names(page2)
49+
self.assertEqual(len(names), len(set(names))) # no row on two pages / skipped
50+
51+
def test_order_by_last_read_ascending(self):
52+
base = now()
53+
self._secret('newest', last_read=base)
54+
self._secret('oldest', last_read=base - timedelta(days=2))
55+
self._secret('middle', last_read=base - timedelta(days=1))
56+
57+
response = self.client.get(self.url, {'ordering': 'last_read'})
58+
59+
self.assertEqual(response.status_code, 200)
60+
self.assertEqual(_names(response), ['oldest', 'middle', 'newest'])
61+
62+
def test_needs_changing_ordered_by_last_read(self):
63+
base = now()
64+
self._secret('ok', status=SecretStatus.OK, last_read=base)
65+
self._secret('stale-late', status=SecretStatus.NEEDS_CHANGING, last_read=base)
66+
self._secret(
67+
'stale-early',
68+
status=SecretStatus.NEEDS_CHANGING,
69+
last_read=base - timedelta(days=1),
70+
)
71+
72+
response = self.client.get(self.url, {'status': 'needs_changing', 'ordering': 'last_read'})
73+
74+
self.assertEqual(response.status_code, 200)
75+
self.assertEqual(_names(response), ['stale-early', 'stale-late'])
76+
77+
def test_filter_content_type_string_value(self):
78+
self._secret('a-password', content_type=ContentType.PASSWORD)
79+
self._secret('a-file', content_type=ContentType.FILE)
80+
81+
response = self.client.get(self.url, {'content_type': 'file'})
82+
83+
self.assertEqual(response.status_code, 200)
84+
self.assertEqual(_names(response), ['a-file'])
85+
86+
def test_filter_access_policy_string_value(self):
87+
self._secret('discoverable-one', access_policy=AccessPolicy.DISCOVERABLE)
88+
self._secret('hidden-one', access_policy=AccessPolicy.HIDDEN)
89+
90+
response = self.client.get(self.url, {'access_policy': 'hidden'})
91+
92+
self.assertEqual(response.status_code, 200)
93+
self.assertEqual(_names(response), ['hidden-one'])
94+
95+
def test_filter_name_icontains(self):
96+
self._secret('production-db')
97+
self._secret('staging-db')
98+
self._secret('unrelated')
99+
100+
response = self.client.get(self.url, {'name': 'db'})
101+
102+
self.assertEqual(response.status_code, 200)
103+
self.assertEqual(sorted(_names(response)), ['production-db', 'staging-db'])
104+
105+
def test_invalid_status_value_returns_400(self):
106+
response = self.client.get(self.url, {'status': 'bogus'})
107+
self.assertEqual(response.status_code, 400)
108+
109+
def test_deleted_status_is_not_an_allowed_choice(self):
110+
response = self.client.get(self.url, {'status': 'deleted'})
111+
self.assertEqual(response.status_code, 400)

0 commit comments

Comments
 (0)