From b80750020d876ad9c5df45956442bae73f666080 Mon Sep 17 00:00:00 2001 From: Konstantin Viberg Date: Tue, 5 Mar 2024 17:02:06 +0300 Subject: [PATCH 1/2] BANG-513: Fix expired_at field in admin and add tests --- its_on/admin/utils.py | 11 ++++++- its_on/admin/views/switches.py | 23 +++++++------- its_on/templates/switches/index.html | 6 ++-- tests/test_utils.py | 46 ++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/its_on/admin/utils.py b/its_on/admin/utils.py index 5f1636c..b70d64a 100644 --- a/its_on/admin/utils.py +++ b/its_on/admin/utils.py @@ -1,4 +1,5 @@ -from typing import List +import datetime +from typing import List, Dict from aiohttp import web from aiopg.sa.result import RowProxy @@ -51,3 +52,11 @@ async def get_switch_history(request: web.Request, switch: switches) -> List[Row ).order_by(switch_history.c.changed_at.desc()) result = await conn.execute(query) return await result.fetchall() + + +def annotate_switch_with_expiration_date(switch: switches) -> Dict: + if switch.is_active: + expires_at = switch.updated_at + datetime.timedelta(days=switch.ttl) + else: + expires_at = None + return {**dict(switch), 'expires_at': expires_at} diff --git a/its_on/admin/views/switches.py b/its_on/admin/views/switches.py index 99bc7ba..578c5a8 100644 --- a/its_on/admin/views/switches.py +++ b/its_on/admin/views/switches.py @@ -1,4 +1,5 @@ import datetime +from typing import Any, Dict, List, Optional, Union import aiohttp_jinja2 import psycopg2 @@ -9,7 +10,6 @@ from marshmallow.exceptions import ValidationError from multidict import MultiDictProxy from sqlalchemy.sql import Select -from typing import Any, Dict, List, Optional, Union from auth.decorators import login_required from its_on.admin.mixins import CreateMixin, GetObjectMixin, UpdateMixin @@ -20,7 +20,11 @@ SwitchDetailAdminPostRequestSchema, SwitchListAdminRequestSchema, ) -from its_on.admin.utils import get_switch_history, save_switch_history +from its_on.admin.utils import ( + annotate_switch_with_expiration_date, + get_switch_history, + save_switch_history, +) from its_on.models import switches from its_on.schemes import RemoteSwitchesDataSchema from its_on.utils import get_switch_badge_svg, get_switch_markdown_badge, utc_now @@ -35,26 +39,21 @@ class SwitchListAdminView(web.View): async def get(self) -> Dict[str, Union[Optional[List[RowProxy]], bool]]: request_params = self.validator.load(data=self.request.query) flags = await self.get_response_data(request_params) - # Move to dict because it's Raw - flag_dicts = [] - for flag in flags: - flag_dicts.append({ - **dict(flag), - 'estimate_at': flag.created_at + datetime.timedelta(days=flag.ttl), - }) groups = await self.get_distinct_groups(request_params) return { 'active_group': request_params.get('group'), - 'flags': flag_dicts, + 'flags': flags, 'groups': groups, 'show_copy_button': bool(settings.SYNC_FROM_ITS_ON_URL), } - async def get_response_data(self, request_params: Dict[str, Any]) -> List: + async def get_response_data(self, request_params: Dict[str, Any]) -> List[Dict]: async with self.request.app['db'].acquire() as conn: queryset = self.filter_queryset(self.get_queryset(), request_params) result = await conn.execute(queryset) - return await result.fetchall() + flags = await result.fetchall() + + return [annotate_switch_with_expiration_date(switch=flag) for flag in flags] async def get_distinct_groups(self, request_params: Dict[str, Any]) -> List[str]: async with self.request.app['db'].acquire() as conn: diff --git a/its_on/templates/switches/index.html b/its_on/templates/switches/index.html index d64eeef..2494fbf 100644 --- a/its_on/templates/switches/index.html +++ b/its_on/templates/switches/index.html @@ -47,7 +47,7 @@

Switches list

TTL Created at Updated at - Estimated at + Expires at Deleted at @@ -83,8 +83,8 @@

Switches list

{% endif %} - {% if flag.estimate_at %} - {{ flag.estimate_at.strftime('%Y-%m-%d') }} + {% if flag.expires_at %} + {{ flag.expires_at.strftime('%Y-%m-%d') }} {% else %} - {% endif %} diff --git a/tests/test_utils.py b/tests/test_utils.py index f3393c4..964402f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -4,6 +4,7 @@ from aiohttp.test_utils import make_mocked_request from anybadge import Badge +from its_on.admin.utils import annotate_switch_with_expiration_date from its_on.constants import ( SVG_BADGE_BACKGROUND_COLOR, SWITCH_NOT_FOUND_SVG_BADGE_PREFIX, @@ -164,3 +165,48 @@ async def test_get_switch_markdown_badge(switch_factory, client): markdown_badge = get_switch_markdown_badge(request, switch) assert markdown_badge == expected_badge + + +@pytest.mark.parametrize( + ('name', 'is_active', 'ttl', 'updated_at', 'expected_result'), + [ + ( + 'inactive_switch', + False, + 14, + datetime.datetime(2020, 5, 1), + None, + ), + ( + 'active_switch', + True, + 14, + datetime.datetime(2020, 5, 1), + datetime.date(2020, 5, 15), + ), + ( + 'other_active_switch', + True, + 21, + datetime.datetime(2020, 5, 5), + datetime.date(2020, 5, 26), + ) + ] +) +@pytest.mark.usefixtures('setup_tables_and_data') +@pytest.mark.freeze_time(datetime.datetime(2020, 5, 1, tzinfo=datetime.timezone.utc)) +async def test_annotate_flag_with_expiration_date( + switch_factory, name, is_active, ttl, updated_at, expected_result +): + switch = await switch_factory( + name=name, + is_active=is_active, + groups=('backend',), + ttl=ttl, + updated_at=updated_at, + deleted_at=None, + ) + + result = annotate_switch_with_expiration_date(switch=switch) + + assert (result['expires_at'] and result['expires_at'].date()) == expected_result From 7feeb9e15550cad393558ee7183fda7c8c6a0945 Mon Sep 17 00:00:00 2001 From: Konstantin Viberg Date: Thu, 7 Mar 2024 12:50:52 +0300 Subject: [PATCH 2/2] BANG-513: Fix trailing commas --- tests/test_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 964402f..a27eee5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -190,13 +190,13 @@ async def test_get_switch_markdown_badge(switch_factory, client): 21, datetime.datetime(2020, 5, 5), datetime.date(2020, 5, 26), - ) - ] + ), + ], ) @pytest.mark.usefixtures('setup_tables_and_data') @pytest.mark.freeze_time(datetime.datetime(2020, 5, 1, tzinfo=datetime.timezone.utc)) async def test_annotate_flag_with_expiration_date( - switch_factory, name, is_active, ttl, updated_at, expected_result + switch_factory, name, is_active, ttl, updated_at, expected_result, ): switch = await switch_factory( name=name,