diff --git a/CHANGELOG.md b/CHANGELOG.md index f36f659d..2f78e165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ +## v0.34.3 (2021-06-08) +### Fix +* TT-256 Avoid creating fake users from test ([`bbbcc94`](https://github.com/ioet/time-tracker-backend/commit/bbbcc94e9ead367a44c01272525559ebf73e3a9c)) + ## v0.34.2 (2021-06-02) ### Fix * TT-257 Fixed customer name null on get a specific project ([#295](https://github.com/ioet/time-tracker-backend/issues/295)) ([`bf2b24d`](https://github.com/ioet/time-tracker-backend/commit/bf2b24d69614d69bd446799d3d0bdb7fa0bc2126)) diff --git a/tests/conftest.py b/tests/conftest.py index a536eee4..ef24c3ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import copy from datetime import datetime, timedelta import jwt @@ -216,14 +217,15 @@ def time_entries_dao(): return time_entries_dao -@pytest.yield_fixture(scope="module") +@pytest.fixture(scope="module") def running_time_entry( time_entry_repository: TimeEntryCosmosDBRepository, owner_id: str, tenant_id: str, event_context: EventContext, ): - created_time_entry = time_entry_repository.create( + current_time_entry_repository = copy.copy(time_entry_repository) + created_time_entry = current_time_entry_repository.create( { "project_id": fake.uuid4(), "owner_id": owner_id, @@ -234,7 +236,7 @@ def running_time_entry( yield created_time_entry - time_entry_repository.delete_permanently( + current_time_entry_repository.delete_permanently( id=created_time_entry.id, event_context=event_context ) diff --git a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py index 3e7fdc91..fd23bd01 100644 --- a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py @@ -16,17 +16,19 @@ def test_TimeEntryQueryBuilder_is_subclass_CosmosDBQueryBuilder(): def test_add_sql_date_range_condition_should_update_where_list(): + start_date = "2021-03-19T05:07:00.000Z" + end_date = "2021-03-25T10:00:00.000Z" time_entry_query_builder = ( TimeEntryQueryBuilder().add_sql_date_range_condition( { - "start_date": "2021-03-19T05:07:00.000Z", - "end_date": "2021-03-25T10:00:00.000Z", + "start_date": start_date, + "end_date": end_date, } ) ) expected_params = [ - {"name": "@start_date", "value": "2021-03-19T05:07:00.000Z"}, - {"name": "@end_date", "value": "2021-03-25T10:00:00.000Z"}, + {"name": "@start_date", "value": start_date}, + {"name": "@end_date", "value": end_date}, ] assert len(time_entry_query_builder.where_conditions) == 1 assert len(time_entry_query_builder.parameters) == len(expected_params) @@ -38,8 +40,8 @@ def test_build_with_add_sql_date_range_condition(): TimeEntryQueryBuilder() .add_sql_date_range_condition( { - "start_date": "2021-03-19T05:00:00.000Z", - "end_date": "2021-03-20T10:00:00.000Z", + "start_date": "2021-04-19T05:00:00.000Z", + "end_date": "2021-04-20T10:00:00.000Z", } ) .build() @@ -55,3 +57,74 @@ def test_build_with_add_sql_date_range_condition(): assert remove_white_spaces(query) == remove_white_spaces(expected_query) assert len(time_entry_query_builder.where_conditions) == 1 assert len(time_entry_query_builder.get_parameters()) == 2 + + +def test_add_sql_interception_with_date_range_condition(): + start_date = "2021-01-19T05:07:00.000Z" + end_date = "2021-01-25T10:00:00.000Z" + + time_entry_query_builder = ( + TimeEntryQueryBuilder().add_sql_interception_with_date_range_condition( + start_date, end_date + ) + ) + + expected_params = [ + {"name": "@start_date", "value": start_date}, + {"name": "@end_date", "value": end_date}, + ] + + assert len(time_entry_query_builder.where_conditions) == 1 + assert len(time_entry_query_builder.parameters) == len(expected_params) + assert time_entry_query_builder.parameters == expected_params + + +def test_build_with_add_sql_interception_with_date_range_condition(): + start_date = "2021-02-19T05:07:00.000Z" + end_date = "2021-02-25T10:00:00.000Z" + time_entry_query_builder = ( + TimeEntryQueryBuilder() + .add_sql_interception_with_date_range_condition(start_date, end_date) + .build() + ) + + expected_query = """ + SELECT * FROM c + WHERE (((c.start_date BETWEEN @start_date AND @end_date) + OR (c.end_date BETWEEN @start_date AND @end_date)) + OR ((@start_date BETWEEN c.start_date AND c.end_date) + OR (@end_date BETWEEN c.start_date AND c.end_date))) + AND c.start_date!= @end_date + AND c.end_date!= @start_date + """ + + builder_query = time_entry_query_builder.get_query() + + assert remove_white_spaces(builder_query) == remove_white_spaces( + expected_query + ) + + +def test_add_sql_is_running_time_entry_condition_should_update_where_conditions_list(): + query_builder = ( + TimeEntryQueryBuilder().add_sql_is_running_time_entry_condition() + ) + + assert len(query_builder.where_conditions) == 1 + + +@pytest.mark.parametrize( + "expected_condition,expected_params", + [("c.id!=@ignore_id", {"name": "@ignore_id", "value": "nomatter"})], +) +def test_add_sql_ignore_id_condition_should_update_where_conditions_list( + expected_condition, expected_params +): + query_builder = TimeEntryQueryBuilder().add_sql_ignore_id_condition( + 'nomatter' + ) + + assert len(query_builder.where_conditions) == 1 + assert len(query_builder.parameters) == 1 + assert query_builder.where_conditions[0].strip() == expected_condition + assert query_builder.parameters[0] == expected_params diff --git a/time_tracker_api/time_entries/time_entries_query_builder.py b/time_tracker_api/time_entries/time_entries_query_builder.py index 03bec701..3147d43f 100644 --- a/time_tracker_api/time_entries/time_entries_query_builder.py +++ b/time_tracker_api/time_entries/time_entries_query_builder.py @@ -21,3 +21,34 @@ def add_sql_date_range_condition(self, date_range: tuple = None): ] ) return self + + def add_sql_interception_with_date_range_condition( + self, start_date, end_date + ): + condition = """ + (((c.start_date BETWEEN @start_date AND @end_date) + OR (c.end_date BETWEEN @start_date AND @end_date)) + OR ((@start_date BETWEEN c.start_date AND c.end_date) + OR (@end_date BETWEEN c.start_date AND c.end_date))) + AND c.start_date!= @end_date + AND c.end_date!= @start_date + """ + self.where_conditions.append(condition) + self.parameters.extend( + [ + {'name': '@start_date', 'value': start_date}, + {'name': '@end_date', 'value': end_date}, + ] + ) + return self + + def add_sql_is_running_time_entry_condition(self): + condition = "(NOT IS_DEFINED(c.end_date) OR c.end_date = null)" + self.where_conditions.append(condition) + return self + + def add_sql_ignore_id_condition(self, id: str = None): + if id: + self.where_conditions.append("c.id!=@ignore_id") + self.parameters.append({'name': '@ignore_id', 'value': id}) + return self diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index c4bc7f02..48d55672 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -42,13 +42,6 @@ def __init__(self): mapper=TimeEntryCosmosDBModel, ) - @staticmethod - def create_sql_ignore_id_condition(id: str): - if id is None: - return '' - else: - return "AND c.id!=@ignore_id" - def find_all_entries( self, event_context: EventContext, @@ -247,35 +240,25 @@ def find_interception_with_date_range( "owner_id": owner_id, "tenant_id": tenant_id, } - params = [ - {"name": "@start_date", "value": start_date}, - {"name": "@end_date", "value": end_date or current_datetime_str()}, - {"name": "@ignore_id", "value": ignore_id}, - ] - params.extend(self.generate_params(conditions)) + end_date = end_date or current_datetime_str() + + query_builder = ( + TimeEntryQueryBuilder() + .add_sql_interception_with_date_range_condition( + start_date, end_date + ) + .add_sql_where_equal_condition(conditions) + .add_sql_ignore_id_condition(ignore_id) + .add_sql_visibility_condition(visible_only) + .add_sql_order_by_condition('start_date', Order.DESC) + .build() + ) + + query_str = query_builder.get_query() + params = query_builder.get_parameters() + result = self.container.query_items( - query=""" - SELECT * FROM c - WHERE (((c.start_date BETWEEN @start_date AND @end_date) - OR (c.end_date BETWEEN @start_date AND @end_date)) - OR ((@start_date BETWEEN c.start_date AND c.end_date) - OR (@end_date BETWEEN c.start_date AND c.end_date))) - AND c.start_date!= @end_date - AND c.end_date!= @start_date - {conditions_clause} - {ignore_id_condition} - {visibility_condition} - {order_clause} - """.format( - ignore_id_condition=self.create_sql_ignore_id_condition( - ignore_id - ), - visibility_condition=self.create_sql_condition_for_visibility( - visible_only - ), - conditions_clause=self.create_sql_where_conditions(conditions), - order_clause=self.create_sql_order_clause(), - ), + query=query_str, parameters=params, partition_key=tenant_id, ) @@ -290,20 +273,23 @@ def find_running( "owner_id": owner_id, "tenant_id": tenant_id, } + + query_builder = ( + TimeEntryQueryBuilder() + .add_sql_is_running_time_entry_condition() + .add_sql_where_equal_condition(conditions) + .add_sql_visibility_condition(True) + .add_sql_offset_condition(0) + .add_sql_limit_condition(1) + .build() + ) + + query_str = query_builder.get_query() + params = query_builder.get_parameters() + result = self.container.query_items( - query=""" - SELECT * from c - WHERE (NOT IS_DEFINED(c.end_date) OR c.end_date = null) - {conditions_clause} - {visibility_condition} - OFFSET 0 LIMIT 1 - """.format( - visibility_condition=self.create_sql_condition_for_visibility( - True - ), - conditions_clause=self.create_sql_where_conditions(conditions), - ), - parameters=self.generate_params(conditions), + query=query_str, + parameters=params, partition_key=tenant_id, max_item_count=1, ) @@ -311,7 +297,7 @@ def find_running( function_mapper = self.get_mapper_or_dict(mapper) try: return function_mapper(next(result)) - except StopIteration as no_result: + except StopIteration: raise CustomError(HTTPStatus.NO_CONTENT) def validate_data(self, data, event_context: EventContext): diff --git a/time_tracker_api/version.py b/time_tracker_api/version.py index 3c92ca22..b0e56f63 100644 --- a/time_tracker_api/version.py +++ b/time_tracker_api/version.py @@ -1 +1 @@ -__version__ = '0.34.2' +__version__ = '0.34.3'