2023-07-21 21:35:19 +02:00
import datetime
2023-07-28 15:53:27 -03:00
from unittest . mock import patch
2023-07-21 21:35:19 +02:00
import pytest
2023-08-01 20:21:02 +02:00
import pytz
Add list shifts for swap request endpoint (#2697)
Example request/response:
`GET /api/internal/v1/shift_swaps/SSR3FJC9H3HZCHT/shifts`
```
{
"events": [
{
"all_day": false,
"start": "2023-08-01T00:00:00Z",
"end": "2023-08-01T03:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
},
{
"all_day": false,
"start": "2023-08-01T03:00:00Z",
"end": "2023-08-02T00:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
}
]
}
```
2023-07-31 15:13:35 -03:00
from django . utils import timezone
2023-07-21 21:35:19 +02:00
from apps . schedules import exceptions
Add list shifts for swap request endpoint (#2697)
Example request/response:
`GET /api/internal/v1/shift_swaps/SSR3FJC9H3HZCHT/shifts`
```
{
"events": [
{
"all_day": false,
"start": "2023-08-01T00:00:00Z",
"end": "2023-08-01T03:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
},
{
"all_day": false,
"start": "2023-08-01T03:00:00Z",
"end": "2023-08-02T00:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
}
]
}
```
2023-07-31 15:13:35 -03:00
from apps . schedules . models import CustomOnCallShift , ShiftSwapRequest
2023-08-02 12:26:45 +01:00
from apps . user_management . models import User
2023-07-21 21:35:19 +02:00
2023-08-01 20:21:02 +02:00
ROTATION_START = datetime . datetime ( 2150 , 8 , 29 , 0 , 0 , 0 , 0 , tzinfo = pytz . UTC )
2023-07-21 21:35:19 +02:00
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_soft_delete ( shift_swap_request_setup ) :
ssr , _ , _ = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
assert ssr . deleted_at is None
2023-07-28 15:53:27 -03:00
with patch ( " apps.schedules.models.shift_swap_request.refresh_ical_final_schedule " ) as mock_refresh_final :
ssr . delete ( )
2023-07-21 21:35:19 +02:00
ssr . refresh_from_db ( )
assert ssr . deleted_at is not None
2024-06-10 15:33:37 -04:00
mock_refresh_final . apply_async . assert_called_with ( ( ssr . schedule . pk , ) )
2023-07-28 15:53:27 -03:00
2023-07-21 21:35:19 +02:00
assert ShiftSwapRequest . objects . all ( ) . count ( ) == 0
assert ShiftSwapRequest . objects_with_deleted . all ( ) . count ( ) == 1
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_status_open ( shift_swap_request_setup ) - > None :
ssr , _ , _ = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
assert ssr . status == ShiftSwapRequest . Statuses . OPEN
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_status_taken ( shift_swap_request_setup ) - > None :
ssr , _ , benefactor = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
assert ssr . status == ShiftSwapRequest . Statuses . OPEN
2023-07-28 17:11:38 +02:00
assert ssr . is_taken is False
2023-07-21 21:35:19 +02:00
ssr . benefactor = benefactor
ssr . save ( )
assert ssr . status == ShiftSwapRequest . Statuses . TAKEN
2023-07-28 17:11:38 +02:00
assert ssr . is_taken is True
2023-07-21 21:35:19 +02:00
2023-08-04 14:43:54 -03:00
# taken in the past it's still taken
now = timezone . now ( )
ssr . swap_start = now - timezone . timedelta ( days = 2 )
ssr . save ( )
assert ssr . status == ShiftSwapRequest . Statuses . TAKEN
assert ssr . is_taken is True
assert ssr . is_past_due is False
2023-07-21 21:35:19 +02:00
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_status_past_due ( shift_swap_request_setup ) - > None :
ssr , _ , _ = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
assert ssr . status == ShiftSwapRequest . Statuses . OPEN
2023-07-28 17:11:38 +02:00
assert ssr . is_past_due is False
2023-07-21 21:35:19 +02:00
ssr . swap_start = ssr . swap_start - datetime . timedelta ( days = 5 )
ssr . save ( )
assert ssr . status == ShiftSwapRequest . Statuses . PAST_DUE
2023-07-28 17:11:38 +02:00
assert ssr . is_past_due is True
2023-07-21 21:35:19 +02:00
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_status_deleted ( shift_swap_request_setup ) - > None :
ssr , _ , _ = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
assert ssr . status == ShiftSwapRequest . Statuses . OPEN
2023-07-28 17:11:38 +02:00
assert ssr . is_deleted is False
2023-07-21 21:35:19 +02:00
ssr . delete ( )
assert ssr . status == ShiftSwapRequest . Statuses . DELETED
2023-07-28 17:11:38 +02:00
assert ssr . is_deleted is True
2023-07-21 21:35:19 +02:00
2023-09-07 16:59:54 +02:00
@patch ( " apps.schedules.tasks.shift_swaps.update_shift_swap_request_message " )
@patch ( " apps.schedules.tasks.shift_swaps.notify_beneficiary_about_taken_shift_swap_request " )
@patch ( " apps.schedules.models.shift_swap_request.refresh_ical_final_schedule " )
2023-07-21 21:35:19 +02:00
@pytest.mark.django_db
2023-09-07 16:59:54 +02:00
def test_take (
mock_refresh_final ,
mock_notify_beneficiary_about_taken_shift_swap_request ,
mock_update_shift_swap_request_message ,
shift_swap_request_setup ,
) - > None :
2023-07-28 17:11:38 +02:00
ssr , _ , benefactor = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
original_updated_at = ssr . updated_at
2023-09-07 16:59:54 +02:00
ssr . take ( benefactor )
2023-07-21 21:35:19 +02:00
assert ssr . benefactor == benefactor
assert ssr . updated_at != original_updated_at
2023-09-07 16:59:54 +02:00
mock_update_shift_swap_request_message . apply_async . assert_called_once_with ( ( ssr . pk , ) )
mock_notify_beneficiary_about_taken_shift_swap_request . apply_async . assert_called_once_with ( ( ssr . pk , ) )
2023-07-28 15:53:27 -03:00
# final schedule refresh was triggered
2024-06-10 15:33:37 -04:00
mock_refresh_final . apply_async . assert_called_with ( ( ssr . schedule . pk , ) )
2023-07-21 21:35:19 +02:00
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_take_only_works_for_open_requests ( shift_swap_request_setup ) - > None :
2023-07-21 21:35:19 +02:00
# already taken
2023-07-28 17:11:38 +02:00
ssr , _ , benefactor = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
ssr . benefactor = benefactor
ssr . save ( )
assert ssr . status == ShiftSwapRequest . Statuses . TAKEN
with pytest . raises ( exceptions . ShiftSwapRequestNotOpenForTaking ) :
ssr . take ( benefactor )
# past due
2023-07-28 17:11:38 +02:00
ssr , _ , benefactor = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
ssr . swap_start = ssr . swap_start - datetime . timedelta ( days = 5 )
ssr . save ( )
assert ssr . status == ShiftSwapRequest . Statuses . PAST_DUE
with pytest . raises ( exceptions . ShiftSwapRequestNotOpenForTaking ) :
ssr . take ( benefactor )
# deleted
2023-07-28 17:11:38 +02:00
ssr , _ , benefactor = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
ssr . delete ( )
assert ssr . status == ShiftSwapRequest . Statuses . DELETED
with pytest . raises ( exceptions . ShiftSwapRequestNotOpenForTaking ) :
ssr . take ( benefactor )
@pytest.mark.django_db
2023-07-28 17:11:38 +02:00
def test_take_own_ssr ( shift_swap_request_setup ) - > None :
ssr , beneficiary , _ = shift_swap_request_setup ( )
2023-07-21 21:35:19 +02:00
with pytest . raises ( exceptions . BeneficiaryCannotTakeOwnShiftSwapRequest ) :
ssr . take ( beneficiary )
Add list shifts for swap request endpoint (#2697)
Example request/response:
`GET /api/internal/v1/shift_swaps/SSR3FJC9H3HZCHT/shifts`
```
{
"events": [
{
"all_day": false,
"start": "2023-08-01T00:00:00Z",
"end": "2023-08-01T03:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
},
{
"all_day": false,
"start": "2023-08-01T03:00:00Z",
"end": "2023-08-02T00:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
}
]
}
```
2023-07-31 15:13:35 -03:00
2023-08-03 10:03:00 +02:00
@pytest.mark.skip (
" Skipping as flaky based on time of day that the test runs. Example failure here https://github.com/grafana/oncall/actions/runs/5747168275/job/15577755519?pr=2725#step:5:1005 "
)
Add list shifts for swap request endpoint (#2697)
Example request/response:
`GET /api/internal/v1/shift_swaps/SSR3FJC9H3HZCHT/shifts`
```
{
"events": [
{
"all_day": false,
"start": "2023-08-01T00:00:00Z",
"end": "2023-08-01T03:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
},
{
"all_day": false,
"start": "2023-08-01T03:00:00Z",
"end": "2023-08-02T00:00:00Z",
"users": [
{
"display_name": "testing",
"email": "testing",
"pk": "UWJWIN8MQ1GYL",
"avatar_full": "http://localhost:3000/avatar/ae2b1fca515949e5d54fb22b8ed95575",
"swap_request": {
"pk": "SSR3FJC9H3HZCHT"
}
}
],
"missing_users": [],
"priority_level": 1,
"source": "web",
"calendar_type": 0,
"is_empty": false,
"is_gap": false,
"is_override": false,
"shift": {
"pk": "OK9SS5YP42XRG"
}
}
]
}
```
2023-07-31 15:13:35 -03:00
@pytest.mark.django_db
def test_related_shifts ( shift_swap_request_setup , make_on_call_shift ) - > None :
ssr , beneficiary , _ = shift_swap_request_setup ( )
schedule = ssr . schedule
organization = schedule . organization
user = beneficiary
today = timezone . now ( ) . replace ( hour = 0 , minute = 0 , second = 0 , microsecond = 0 )
start = today + timezone . timedelta ( days = 2 )
duration = timezone . timedelta ( hours = 8 )
data = {
" start " : start ,
" rotation_start " : start ,
" duration " : duration ,
" priority_level " : 1 ,
" frequency " : CustomOnCallShift . FREQUENCY_DAILY ,
" schedule " : schedule ,
}
on_call_shift = make_on_call_shift (
organization = organization , shift_type = CustomOnCallShift . TYPE_ROLLING_USERS_EVENT , * * data
)
on_call_shift . add_rolling_users ( [ [ user ] ] )
events = ssr . shifts ( )
expected = [
# start, end, user, swap request ID
( start , start + duration , user . public_primary_key , ssr . public_primary_key ) ,
]
returned_events = [ ( e [ " start " ] , e [ " end " ] , e [ " users " ] [ 0 ] [ " pk " ] , e [ " users " ] [ 0 ] [ " swap_request " ] [ " pk " ] ) for e in events ]
assert returned_events == expected
2023-08-02 12:26:45 +01:00
@pytest.mark.django_db
def test_possible_benefactors ( shift_swap_request_setup ) - > None :
ssr , beneficiary , benefactor = shift_swap_request_setup ( )
with patch . object ( ssr . schedule , " related_users " ) as mock_related_users :
mock_related_users . return_value = User . objects . filter ( pk__in = [ beneficiary . pk , benefactor . pk ] )
2023-08-04 16:13:03 +01:00
assert list ( ssr . possible_benefactors ) == [ benefactor ]