test: strengthen Task 4 absence-exclusion tests (parity + behavioral POST guard)
This commit is contained in:
parent
5fa3efcf64
commit
86b0cb9dd6
@ -3542,4 +3542,47 @@ class ManagerSalariedAbsenceExclusionTests(TestCase):
|
||||
def test_absenceedit_supervisor_excludes_fixed(self):
|
||||
from core.forms import AbsenceEditForm
|
||||
qs = AbsenceEditForm(user=self.sup).fields['worker'].queryset
|
||||
self.assertIn(self.daily, qs)
|
||||
self.assertNotIn(self.mgr, qs)
|
||||
|
||||
def test_absence_log_post_rejects_manager_id(self):
|
||||
"""Behavioral guard (matches Task 3's POST-level rigor): the
|
||||
ModelMultipleChoiceField re-validates submitted worker ids against
|
||||
its excluded-fixed queryset. POSTing a manager's id must be rejected
|
||||
with a `workers` form error and create ZERO Absence rows for the
|
||||
manager — which also prevents the underlying bug this feature exists
|
||||
to stop: a paid manager-absence auto-creating a Bonus
|
||||
PayrollAdjustment at daily_rate. A daily worker POSTed with the SAME
|
||||
payload succeeds, proving the rejection is specific to the manager
|
||||
(pay_type='fixed') and not a broken payload."""
|
||||
self.client.force_login(self.admin)
|
||||
|
||||
# --- Manager id is rejected ---
|
||||
resp = self.client.post(reverse('absence_log'), data={
|
||||
'date': '2026-05-14',
|
||||
'reason': 'sick',
|
||||
'workers': [self.mgr.id],
|
||||
'notes': 'should be rejected',
|
||||
})
|
||||
# Form re-rendered (not a redirect to success/confirm flow).
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn('form', resp.context)
|
||||
self.assertIn('workers', resp.context['form'].errors)
|
||||
# No Absence row created for the manager — and therefore no
|
||||
# auto-created Bonus PayrollAdjustment leaking at daily_rate.
|
||||
self.assertEqual(Absence.objects.filter(worker=self.mgr).count(), 0)
|
||||
self.assertEqual(
|
||||
PayrollAdjustment.objects.filter(worker=self.mgr).count(), 0)
|
||||
|
||||
# --- Positive control: daily worker, identical payload, succeeds ---
|
||||
resp2 = self.client.post(reverse('absence_log'), data={
|
||||
'date': '2026-05-14',
|
||||
'reason': 'sick',
|
||||
'workers': [self.daily.id],
|
||||
'notes': 'legit daily absence',
|
||||
})
|
||||
# No conflicts → immediate create + redirect to the absence list.
|
||||
self.assertRedirects(
|
||||
resp2, reverse('absence_list'), fetch_redirect_response=False)
|
||||
self.assertEqual(Absence.objects.filter(worker=self.daily).count(), 1)
|
||||
self.assertEqual(Absence.objects.filter(worker=self.mgr).count(), 0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user