import asyncio from datetime import datetime, timezone from unittest.mock import patch import pytest from dateutil.relativedelta import relativedelta from bot.utils import time from tests.helpers import AsyncMock @pytest.mark.parametrize( ('delta', 'precision', 'max_units', 'expected'), ( (relativedelta(days=2), 'seconds', 1, '2 days'), (relativedelta(days=2, hours=2), 'seconds', 2, '2 days and 2 hours'), (relativedelta(days=2, hours=2), 'seconds', 1, '2 days'), (relativedelta(days=2, hours=2), 'days', 2, '2 days'), # Does not abort for unknown units, as the unit name is checked # against the attribute of the relativedelta instance. (relativedelta(days=2, hours=2), 'elephants', 2, '2 days and 2 hours'), # Very high maximum units, but it only ever iterates over # each value the relativedelta might have. (relativedelta(days=2, hours=2), 'hours', 20, '2 days and 2 hours'), ) ) def test_humanize_delta( delta: relativedelta, precision: str, max_units: int, expected: str ): assert time.humanize_delta(delta, precision, max_units) == expected @pytest.mark.parametrize('max_units', (-1, 0)) def test_humanize_delta_raises_for_invalid_max_units(max_units: int): with pytest.raises(ValueError, match='max_units must be positive'): time.humanize_delta(relativedelta(days=2, hours=2), 'hours', max_units) @pytest.mark.parametrize( ('stamp', 'expected'), ( ('Sun, 15 Sep 2019 12:00:00 GMT', datetime(2019, 9, 15, 12, 0, 0, tzinfo=timezone.utc)), ) ) def test_parse_rfc1123(stamp: str, expected: str): assert time.parse_rfc1123(stamp) == expected @patch('asyncio.sleep', new_callable=AsyncMock) def test_wait_until(sleep_patch): start = datetime(2019, 1, 1, 0, 0) then = datetime(2019, 1, 1, 0, 10) # No return value assert asyncio.run(time.wait_until(then, start)) is None sleep_patch.assert_called_once_with(10 * 60) @pytest.mark.parametrize( ('date_from', 'date_to', 'parts', 'expected'), ( (datetime(2019, 12, 12, 0, 1), datetime(2019, 12, 12, 12, 0, 5), 2, '11 hours, 59 minutes'), (datetime(2019, 12, 12, 0, 1), datetime(2019, 12, 12, 12, 0, 5), 1, '11 hours'), (datetime(2019, 12, 12, 0, 1), datetime(2019, 12, 12, 12, 0, 5), None, '11 hours, 59 minutes, 5 seconds'), (datetime(2019, 12, 12, 0, 0), datetime(2019, 12, 11, 23, 59), 2, '1 minute'), (datetime(2019, 11, 23, 20, 9), datetime(2019, 11, 30, 20, 15), 2, '1 week, 6 minutes'), (datetime(2019, 11, 23, 20, 9), datetime(2019, 4, 25, 20, 15), 2, '7 months, 2 weeks'), (datetime(2019, 11, 23, 20, 9), datetime(2019, 4, 25, 20, 15), None, '7 months, 2 weeks, 1 day, 23 hours, 54 minutes'), (datetime(2019, 11, 23, 20, 58), datetime(2019, 11, 23, 21, 3), 2, '5 minutes'), (datetime(2019, 11, 23, 23, 59), datetime(2019, 11, 24, 0, 0), 2, '1 minute'), (datetime(2019, 11, 23, 23, 59), datetime(2022, 11, 23, 23, 0), 2, '3 years, 3 months'), (datetime(2019, 11, 23, 23, 59), datetime(2019, 11, 23, 23, 49, 5), 2, '9 minutes, 55 seconds'), ) ) def test_get_duration(date_from: datetime, date_to: datetime, parts: int, expected: str): assert time.get_duration(date_from, date_to, parts) == expected @pytest.mark.parametrize( ('expiry', 'date_from', 'parts', 'expected'), ( ('2019-12-12T00:01:00Z', datetime(2019, 12, 12, 12, 0, 5), 2, '2019-12-12 00:01 (11 hours, 59 minutes)'), ('2019-12-12T00:01:00Z', datetime(2019, 12, 12, 12, 0, 5), 1, '2019-12-12 00:01 (11 hours)'), ('2019-12-12T00:01:00Z', datetime(2019, 12, 12, 12, 0, 5), None, '2019-12-12 00:01 (11 hours, 59 minutes, 5 seconds)'), ('2019-12-12T00:00:00Z', datetime(2019, 12, 11, 23, 59), 2, '2019-12-12 00:00 (1 minute)'), ('2019-11-23T20:09:00Z', datetime(2019, 11, 30, 20, 15), 2, '2019-11-23 20:09 (1 week, 6 minutes)'), ('2019-11-23T20:09:00Z', datetime(2019, 4, 25, 20, 15), 2, '2019-11-23 20:09 (7 months, 2 weeks)'), ('2019-11-23T20:09:00Z', datetime(2019, 4, 25, 20, 15), None, '2019-11-23 20:09 (7 months, 2 weeks, 1 day, 23 hours, 54 minutes)'), ('2019-11-23T20:58:00Z', datetime(2019, 11, 23, 21, 3), 2, '2019-11-23 20:58 (5 minutes)'), ('2019-11-23T23:59:00Z', datetime(2019, 11, 24, 0, 0), 2, '2019-11-23 23:59 (1 minute)'), ('2019-11-23T23:59:00Z', datetime(2022, 11, 23, 23, 0), 2, '2019-11-23 23:59 (3 years, 3 months)'), ('2019-11-23T23:59:00Z', datetime(2019, 11, 23, 23, 49, 5), 2, '2019-11-23 23:59 (9 minutes, 55 seconds)'), (None, datetime(2019, 11, 23, 23, 49, 5), 2, None), ) ) def test_get_duration_from_expiry(expiry: str, date_from: datetime, parts: int, expected: str): assert time.get_duration_from_expiry(expiry, date_from, parts) == expected