diff --git a/graphql_api/context.py b/graphql_api/context.py index 2161944e77..6454767935 100644 --- a/graphql_api/context.py +++ b/graphql_api/context.py @@ -1,4 +1,5 @@ from typing import Generic, TypeVar + from graphql.type.definition import GraphQLResolveInfo T = TypeVar("T") diff --git a/graphql_api/tests/test_context.py b/graphql_api/tests/test_context.py deleted file mode 100644 index 3e5e24b406..0000000000 --- a/graphql_api/tests/test_context.py +++ /dev/null @@ -1,78 +0,0 @@ -import unittest -from typing import Optional, Protocol, Any -from graphql import GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString, GraphQLResolveInfo - -from graphql_api.context import TypedResolverInfo - - -class MockContextProtocol(Protocol): - repository: Optional[str] - - -class MockContext(MockContextProtocol): - def __init__(self, repository: Optional[str] = None): - self.repository = repository - - -def create_mock_graphql_resolve_info(context: MockContext) -> TypedResolverInfo[MockContext]: - """ - Helper function to create a mock TypedResolverInfo object for testing. - """ - mock_field_name = "mockField" - mock_field_nodes = [] # Normally, this would be a list of AST nodes, empty for simplicity - mock_return_type = GraphQLString - mock_parent_type = GraphQLObjectType( - name="MockParent", - fields={"mockField": GraphQLField(GraphQLString)} - ) - mock_path = [] # Path should be a valid list, not None - mock_schema = GraphQLSchema(query=mock_parent_type) - mock_fragments = {} - mock_root_value = None - mock_operation = None - mock_variable_values = {} - mock_is_awaitable = False - - # Create a mock instance of TypedResolverInfo - info = TypedResolverInfo( - field_name=mock_field_name, - field_nodes=mock_field_nodes, - return_type=mock_return_type, - parent_type=mock_parent_type, - path=mock_path, - schema=mock_schema, - fragments=mock_fragments, - root_value=mock_root_value, - operation=mock_operation, - variable_values=mock_variable_values, - context=context, # The mock context - is_awaitable=mock_is_awaitable, - ) - - return info - - -class TestTypedResolverInfoGenerics(unittest.TestCase): - def test_typed_resolver_info_stores_context(self): - # Create a concrete context instance with repository data - mock_context = MockContext(repository="Test Repository") - - # Create a TypedResolverInfo with the mock context - typed_info = create_mock_graphql_resolve_info(mock_context) - - # Assert that context is stored and accessible with correct typing - self.assertEqual(typed_info.context.repository, "Test Repository") - - def test_typed_resolver_info_handles_optional_none(self): - # Create a concrete context instance with repository as None - mock_context = MockContext(repository=None) - - # Create a TypedResolverInfo with the mock context - typed_info = create_mock_graphql_resolve_info(mock_context) - - # Assert that context repository is None - self.assertIsNone(typed_info.context.repository) - - -if __name__ == '__main__': - unittest.main() diff --git a/graphql_api/tests/test_coverage_analytics.py b/graphql_api/tests/test_coverage_analytics.py index bdad2d96ee..4970a43028 100644 --- a/graphql_api/tests/test_coverage_analytics.py +++ b/graphql_api/tests/test_coverage_analytics.py @@ -2,10 +2,9 @@ from django.test import TransactionTestCase from django.utils import timezone -from freezegun import freeze_time from codecov_auth.tests.factories import OwnerFactory -from core.models import Repository # Import the actual model, not the factory +from core.models import Repository from core.tests.factories import ( CommitFactory, RepositoryFactory, @@ -13,15 +12,14 @@ from .helper import GraphQLTestHelper -# Queries for reuse -query_coverage_analytics = """ -query CoverageAnalytics($owner:String!, $repo: String!, $interval: MeasurementInterval!) { +query_coverage_analytics_base_fields = """ +query CoverageAnalytics($owner:String!, $repo: String!) { owner(username:$owner) { repository(name: $repo) { __typename ... on Repository { name - coverageAnalytics(interval: $interval) { + coverageAnalytics { %s } } @@ -33,33 +31,30 @@ } """ -default_coverage_analytics_fields = """ +default_coverage_analytics_base_fields = """ percentCovered commitSha hits misses lines - measurements(interval: $interval) { - timestamp - max - min - avg - } """ -class TestFetchCoverageAnalytics(GraphQLTestHelper, TransactionTestCase): +class TestFetchCoverageAnalyticsBaseFields(GraphQLTestHelper, TransactionTestCase): def fetch_coverage_analytics( - self, repo_name, interval="INTERVAL_1_DAY", fields=None + self, repo_name, fields=None ): - query = query_coverage_analytics % (fields or default_coverage_analytics_fields) - variables = {"owner": "codecov-user", "repo": repo_name, "interval": interval} + query = query_coverage_analytics_base_fields % (fields or default_coverage_analytics_base_fields) + variables = {"owner": "codecov-user", "repo": repo_name} return self.gql_request(query=query, owner=self.owner, variables=variables) def setUp(self): self.owner = OwnerFactory(username="codecov-user") self.yaml = {"test": "test"} - self.repo = RepositoryFactory( + + def test_coverage_analytics_base_fields(self): + # Create repo, commit, and coverage data + repo = RepositoryFactory( author=self.owner, active=True, private=True, @@ -68,102 +63,82 @@ def setUp(self): language="erlang", languages=[], ) - - # Ensure the repository is saved correctly - self.repo.save() - self.assertTrue( - self.repo.pk, "Repository should be saved and have a primary key." - ) - - @freeze_time("2021-01-01") - def test_full_coverage_analytics(self): - """Test with full coverage analytics fields""" - # Create commit and coverage data - hour_ago = timezone.make_aware(datetime.datetime(2020, 12, 31, 23, 0)) # Fixed + hour_ago = timezone.make_aware(datetime.datetime(2020, 12, 31, 23, 0)) coverage_commit = CommitFactory( - repository=self.repo, + repository=repo, totals={"c": 75, "h": 30, "m": 10, "n": 40}, timestamp=hour_ago, ) - CommitFactory(repository=self.repo, totals={"c": 85}) + CommitFactory(repository=repo, totals={"c": 85}) - # Ensure the repository's timestamp is updated - self.repo.updatestamp = timezone.now() # Use timezone-aware datetime - self.repo.save() + # Update the timestamp and save to db + repo.updatestamp = timezone.now() + repo.save() + self.assertTrue( + repo.pk, "Repository should be saved and have a primary key." + ) - # Query the database using the actual model (Repository) - repo_from_db = Repository.objects.get( - pk=self.repo.pk - ) # Use the Repository model, not the factory + # Query the db using the repository model + repo_from_db = Repository.objects.get(pk=repo.pk) self.assertIsNotNone(repo_from_db.updatestamp) # Fetch the coverage analytics data - coverage_data = self.fetch_coverage_analytics(self.repo.name) - - print(coverage_data) + coverage_analytics_data = self.fetch_coverage_analytics(repo.name) + # Define the expected response expected_response = { "__typename": "Repository", - "name": self.repo.name, + "name": repo.name, "coverageAnalytics": { "percentCovered": 75, "commitSha": coverage_commit.commitid, "hits": 30, "misses": 10, "lines": 40, - "measurements": [], # Assuming measurements are empty for now }, } - assert coverage_data["owner"]["repository"] == expected_response - - # - # @freeze_time("2021-01-01") - # def test_partial_coverage_analytics(self): - # """Test fetching partial fields (only percentCovered)""" - # CommitFactory(repository=self.repo, totals={"c": 75, "h": 30, "m": 10, "n": 40}) - # - # self.repo.updatestamp = datetime.datetime.now() - # self.repo.save() - # - # fields = "percentCovered" - # coverage_data = self.fetch_coverage_analytics(self.repo.name, fields=fields) - # assert coverage_data["owner"]["repository"]["coverageAnalytics"]["percentCovered"] == 75 - # - # @freeze_time("2021-01-01") - # def test_measurements_coverage_analytics(self): - # """Test fetching only measurements subfield""" - # CommitFactory( - # repository=self.repo, - # totals={"c": 75, "h": 30, "m": 10, "n": 40}, - # timestamp=datetime.datetime.now() - datetime.timedelta(hours=1), - # ) - # - # self.repo.updatestamp = datetime.datetime.now() - # self.repo.save() - # - # fields = "measurements(interval: $interval) { timestamp max }" - # coverage_data = self.fetch_coverage_analytics(self.repo.name, fields=fields) - # assert coverage_data["owner"]["repository"]["coverageAnalytics"]["measurements"] == [] - # - # def test_coverage_analytics_no_commit(self): - # """Test case where no commits exist for coverage data""" - # repo = RepositoryFactory( - # author=self.owner, - # active=True, - # private=True, - # name="empty-repo", - # yaml=self.yaml, - # language="erlang", - # languages=[], - # ) - # repo.save() - # - # coverage_data = self.fetch_coverage_analytics(repo.name) - # assert coverage_data["owner"]["repository"]["coverageAnalytics"] == { - # "percentCovered": None, - # "commitSha": None, - # "hits": None, - # "misses": None, - # "lines": None, - # "measurements": [], - # } + + # Compare the actual data with the expected data + assert coverage_analytics_data["owner"]["repository"] == expected_response + + def test_coverage_analytics_base_fields_partial(self): + repo = RepositoryFactory( + author=self.owner, + active=True, + private=True, + name="b", + yaml=self.yaml, + language="erlang", + languages=[], + ) + hour_ago = timezone.make_aware(datetime.datetime(2020, 12, 31, 23, 0)) + CommitFactory(repository=repo, totals={"c": 75, "h": 30, "m": 10, "n": 40}, timestamp=hour_ago) + repo.updatestamp = timezone.now() + repo.save() + + fields = "percentCovered" + coverage_data = self.fetch_coverage_analytics(repo.name, fields=fields) + print(coverage_data) + assert coverage_data["owner"]["repository"]["coverageAnalytics"]["percentCovered"] == 75 + + def test_coverage_analytics_no_commit(self): + """Test case where no commits exist for coverage data""" + repo = RepositoryFactory( + author=self.owner, + active=True, + private=True, + name="empty-repo", + yaml=self.yaml, + language="erlang", + languages=[], + ) + repo.save() + + coverage_data = self.fetch_coverage_analytics(repo.name) + assert coverage_data["owner"]["repository"]["coverageAnalytics"] == { + "percentCovered": None, + "commitSha": None, + "hits": None, + "misses": None, + "lines": None, + } diff --git a/graphql_api/tests/test_coverage_analytics_measurements.py b/graphql_api/tests/test_coverage_analytics_measurements.py index 9094eb5989..83adb499ce 100644 --- a/graphql_api/tests/test_coverage_analytics_measurements.py +++ b/graphql_api/tests/test_coverage_analytics_measurements.py @@ -1,14 +1,106 @@ -from datetime import datetime, timezone +import datetime from unittest.mock import patch from django.test import TransactionTestCase, override_settings +from django.utils import timezone +from freezegun import freeze_time from codecov_auth.tests.factories import OwnerFactory -from core.tests.factories import RepositoryFactory +from core.tests.factories import ( + CommitFactory, + RepositoryFactory, +) from timeseries.models import Interval from .helper import GraphQLTestHelper +query_coverage_analytics_with_interval = """ +query CoverageAnalytics($owner:String!, $repo: String!, $interval: MeasurementInterval!) { + owner(username:$owner) { + repository(name: $repo) { + __typename + ... on Repository { + name + coverageAnalytics { + %s + } + } + ... on ResolverError { + message + } + } + } +} +""" + +default_coverage_analytics_measurements_fields = """ + measurements(interval: $interval) { + timestamp + avg + min + max + } +""" + + +class TestFetchCoverageAnalyticsWithInterval(GraphQLTestHelper, TransactionTestCase): + databases = {'default', 'timeseries'} + + def fetch_coverage_analytics( + self, repo_name, fields=None, interval=None + ): + query = query_coverage_analytics_with_interval % (fields or default_coverage_analytics_measurements_fields) + variables = {"owner": "codecov-user", "repo": repo_name, "interval": interval} + + return self.gql_request(query=query, owner=self.owner, variables=variables) + + def setUp(self): + self.owner = OwnerFactory(username="codecov-user") + self.yaml = {"test": "test"} + + @freeze_time("2022-01-02") + def test_coverage_analytics_with_interval(self): + """Test with interval argument to fetch coverage data in a specific time range""" + # Create repo, commit, and coverage data within different intervals + repo = RepositoryFactory( + author=self.owner, + active=True, + private=True, + name="test", + yaml=self.yaml, + language="erlang", + languages=[], + ) + one_day_ago = timezone.make_aware(datetime.datetime(2022, 1, 1, 0, 0)) + CommitFactory(repository=repo, totals={"c": 65, "h": 20, "m": 5, "n": 25}, timestamp=one_day_ago) + + two_days_ago = timezone.make_aware(datetime.datetime(2022, 1, 2, 0, 0)) + CommitFactory(repository=repo, totals={"c": 75, "h": 30, "m": 10, "n": 40}, timestamp=two_days_ago) + + # Save repository + repo.updatestamp = timezone.now() + repo.save() + self.assertTrue( + repo.pk, "Repository should be saved and have a primary key." + ) + + # Fetch the coverage analytics data with interval + interval = "INTERVAL_1_DAY" + coverage_analytics_data = self.fetch_coverage_analytics(repo.name, default_coverage_analytics_measurements_fields, interval=interval) + + # Define the expected response based on the interval + expected_response = { + "__typename": "Repository", + "name": repo.name, + "coverageAnalytics": { + "measurements": [ + {'avg': 65.0, 'max': 65.0, 'min': 65.0, 'timestamp': '2022-01-01T00:00:00+00:00'}, + {'avg': 75.0, 'max': 75.0, 'min': 75.0, 'timestamp': '2022-01-02T00:00:00+00:00'} + ] + }, + } + assert coverage_analytics_data["owner"]["repository"] == expected_response + @patch("timeseries.helpers.repository_coverage_measurements_with_fallback") class TestMeasurement(TransactionTestCase, GraphQLTestHelper): @@ -37,7 +129,7 @@ def _request(self, variables=None): }} """ data = self.gql_request(query, owner=self.owner, variables=variables) - return data["owner"]["repository"]["coverage_analytics"]["measurements"] + return data["owner"]["repository"]["coverageAnalytics"]["measurements"] def setUp(self): self.org = OwnerFactory(username="test-org") @@ -53,8 +145,8 @@ def test_measurements_timeseries_enabled( self, repository_coverage_measurements_with_fallback ): repository_coverage_measurements_with_fallback.return_value = [ - {"timestamp_bin": datetime(2022, 1, 1), "min": 1, "max": 2, "avg": 1.5}, - {"timestamp_bin": datetime(2022, 1, 2), "min": 3, "max": 4, "avg": 3.5}, + {"timestamp_bin": datetime.datetime(2022, 1, 1), "min": 1, "max": 2, "avg": 1.5}, + {"timestamp_bin": datetime.datetime(2022, 1, 2), "min": 3, "max": 4, "avg": 3.5}, ] assert self._request() == [ @@ -71,49 +163,49 @@ def test_measurements_timeseries_enabled( repository_coverage_measurements_with_fallback.assert_called_once_with( self.repo, Interval.INTERVAL_1_DAY, - start_date=datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - end_date=datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), + start_date=datetime.datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + end_date=datetime.datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), branch=None, ) - # - # @override_settings(TIMESERIES_ENABLED=False) - # def test_measurements_timeseries_not_enabled( - # self, repository_coverage_measurements_with_fallback - # ): - # repository_coverage_measurements_with_fallback.return_value = [ - # {"timestamp_bin": datetime(2022, 1, 1), "min": 1, "max": 2, "avg": 1.5}, - # {"timestamp_bin": datetime(2022, 1, 2), "min": 3, "max": 4, "avg": 3.5}, - # ] - # - # assert self._request() == [ - # {"timestamp": "2022-01-01T00:00:00", "min": 1.0, "max": 2.0, "avg": 1.5}, - # {"timestamp": "2022-01-02T00:00:00", "min": 3.0, "max": 4.0, "avg": 3.5}, - # { - # "timestamp": "2022-01-03T00:00:00+00:00", - # "min": None, - # "max": None, - # "avg": None, - # }, - # ] - # - # repository_coverage_measurements_with_fallback.assert_called_once_with( - # self.repo, - # Interval.INTERVAL_1_DAY, - # start_date=datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - # end_date=datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), - # branch=None, - # ) - # - # @override_settings(TIMESERIES_ENABLED=True) - # def test_measurements_branch(self, repository_coverage_measurements_with_fallback): - # repository_coverage_measurements_with_fallback.return_value = [] - # self._request(variables={"branch": "foo"}) - # - # repository_coverage_measurements_with_fallback.assert_called_once_with( - # self.repo, - # Interval.INTERVAL_1_DAY, - # start_date=datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - # end_date=datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), - # branch="foo", - # ) + + @override_settings(TIMESERIES_ENABLED=False) + def test_measurements_timeseries_not_enabled( + self, repository_coverage_measurements_with_fallback + ): + repository_coverage_measurements_with_fallback.return_value = [ + {"timestamp_bin": datetime.datetime(2022, 1, 1), "min": 1, "max": 2, "avg": 1.5}, + {"timestamp_bin": datetime.datetime(2022, 1, 2), "min": 3, "max": 4, "avg": 3.5}, + ] + + assert self._request() == [ + {"timestamp": "2022-01-01T00:00:00", "min": 1.0, "max": 2.0, "avg": 1.5}, + {"timestamp": "2022-01-02T00:00:00", "min": 3.0, "max": 4.0, "avg": 3.5}, + { + "timestamp": "2022-01-03T00:00:00+00:00", + "min": None, + "max": None, + "avg": None, + }, + ] + + repository_coverage_measurements_with_fallback.assert_called_once_with( + self.repo, + Interval.INTERVAL_1_DAY, + start_date=datetime.datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + end_date=datetime.datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), + branch=None, + ) + + @override_settings(TIMESERIES_ENABLED=True) + def test_measurements_branch(self, repository_coverage_measurements_with_fallback): + repository_coverage_measurements_with_fallback.return_value = [] + self._request(variables={"branch": "foo"}) + + repository_coverage_measurements_with_fallback.assert_called_once_with( + self.repo, + Interval.INTERVAL_1_DAY, + start_date=datetime.datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + end_date=datetime.datetime(2022, 1, 3, 0, 0, 0, tzinfo=timezone.utc), + branch="foo", + ) diff --git a/graphql_api/types/coverage_analytics/coverage_analytics.py b/graphql_api/types/coverage_analytics/coverage_analytics.py index 26c4ae128a..54ca2d5e67 100644 --- a/graphql_api/types/coverage_analytics/coverage_analytics.py +++ b/graphql_api/types/coverage_analytics/coverage_analytics.py @@ -1,15 +1,15 @@ import logging from dataclasses import dataclass from datetime import datetime -from typing import Any, Iterable, List, Optional, Union, Protocol +from typing import Any, Iterable, Optional, Union from ariadne import ObjectType, UnionType +from graphql.type.definition import GraphQLResolveInfo import timeseries.helpers as timeseries_helpers from codecov.db import sync_to_async -from graphql_api.context import TypedResolverInfo +from core.models import Repository from graphql_api.types.errors.errors import NotFoundError -from graphql_api.types.repository.repository import Repository from timeseries.helpers import fill_sparse_measurements from timeseries.models import Interval, MeasurementSummary @@ -20,28 +20,19 @@ coverage_analytics_result_bindable: UnionType = UnionType("CoverageAnalyticsResult") -# CoverageAnalytics is the GraphQL type related to a repo's coverage analytics +# CoverageAnalyticsProps is information passed from parent resolver (repository) +# to the coverage analytics resolver @dataclass -class CoverageAnalytics: - hits: int - misses: int - lines: int - commit_sha: str - percent_covered: float - measurements: List[MeasurementSummary] - - -# CoverageAnalyticsContext is the expected Ariadne GraphQL context at this level -class CoverageAnalyticsContext(Protocol): - repository: Optional[Repository] +class CoverageAnalyticsProps: + repository: Repository @coverage_analytics_result_bindable.type_resolver def resolve_coverage_analytics_result_type( - obj: Union[CoverageAnalytics, NotFoundError], *_: Any + obj: Union[CoverageAnalyticsProps, NotFoundError], *_: Any ) -> Optional[str]: - if isinstance(obj, CoverageAnalytics): - return "CoverageAnalytics" + if isinstance(obj, CoverageAnalyticsProps): + return "CoverageAnalyticsProps" elif isinstance(obj, NotFoundError): return "NotFoundError" return None @@ -49,57 +40,50 @@ def resolve_coverage_analytics_result_type( @coverage_analytics_bindable.field("percentCovered") def resolve_percent_covered( - coverage_analytics: CoverageAnalytics, info: TypedResolverInfo[CoverageAnalyticsContext] + parent: CoverageAnalyticsProps, info: GraphQLResolveInfo ) -> Optional[float]: - repository = info.context.repository - return repository.recent_coverage if repository else None + return parent.repository.recent_coverage if parent else None @coverage_analytics_bindable.field("commitSha") def resolve_commit_sha( - coverage_analytics: CoverageAnalytics, info: TypedResolverInfo[CoverageAnalyticsContext] + parent: CoverageAnalyticsProps, info: GraphQLResolveInfo ) -> Optional[str]: - repository = info.context.repository - return repository.coverage_sha if repository else None + return parent.repository.coverage_sha if parent else None @coverage_analytics_bindable.field("hits") def resolve_hits( - coverage_analytics: CoverageAnalytics, info: TypedResolverInfo[CoverageAnalyticsContext] + parent: CoverageAnalyticsProps, info: GraphQLResolveInfo ) -> Optional[int]: - repository = info.context.repository - return repository.hits if repository else None + return parent.repository.hits if parent else None @coverage_analytics_bindable.field("misses") def resolve_misses( - coverage_analytics: CoverageAnalytics, info: TypedResolverInfo[CoverageAnalyticsContext] + parent: CoverageAnalyticsProps, info: GraphQLResolveInfo ) -> Optional[int]: - repository = info.context.repository - return repository.misses if repository else None + return parent.repository.misses if parent else None @coverage_analytics_bindable.field("lines") def resolve_lines( - coverage_analytics: CoverageAnalytics, info: TypedResolverInfo[CoverageAnalyticsContext] + parent: CoverageAnalyticsProps, info: GraphQLResolveInfo ) -> Optional[int]: - repository = info.context.repository - return repository.lines if repository else None + return parent.repository.lines if parent else None @coverage_analytics_bindable.field("measurements") async def resolve_measurements( - coverage_analytics: CoverageAnalytics, - info: TypedResolverInfo[CoverageAnalyticsContext], - interval: Interval, - before: Optional[datetime] = None, - after: Optional[datetime] = None, - branch: Optional[str] = None, + parent: CoverageAnalyticsProps, + info: GraphQLResolveInfo, + interval: Optional[Interval] = None, + before: Optional[datetime] = None, + after: Optional[datetime] = None, + branch: Optional[str] = None, ) -> Iterable[MeasurementSummary]: - repository = info.context.repository - coverage_data = await sync_to_async(timeseries_helpers.repository_coverage_measurements_with_fallback)( - repository, + parent.repository, interval, start_date=after, end_date=before, diff --git a/graphql_api/types/repository/repository.graphql b/graphql_api/types/repository/repository.graphql index 828dc4ff4d..4a8ef0484d 100644 --- a/graphql_api/types/repository/repository.graphql +++ b/graphql_api/types/repository/repository.graphql @@ -104,7 +104,7 @@ type Repository { "CoverageAnalytics are fields related to Codecov's Coverage product offering" coverageAnalytics( - interval: MeasurementInterval! + interval: MeasurementInterval after: DateTime before: DateTime branch: String diff --git a/graphql_api/types/repository/repository.py b/graphql_api/types/repository/repository.py index 5c66326b36..8ffa7cf05c 100644 --- a/graphql_api/types/repository/repository.py +++ b/graphql_api/types/repository/repository.py @@ -26,7 +26,9 @@ queryset_to_connection_sync, ) from graphql_api.helpers.lookahead import lookahead -from graphql_api.types.coverage_analytics.coverage_analytics import CoverageAnalytics +from graphql_api.types.coverage_analytics.coverage_analytics import ( + CoverageAnalyticsProps, +) from graphql_api.types.enums import OrderingDirection from graphql_api.types.errors.errors import NotFoundError, OwnerNotActivatedError from services.components import ComponentMeasurements @@ -602,19 +604,7 @@ async def resolve_test_results( def resolve_coverage_analytics( repository: Repository, info: GraphQLResolveInfo, - interval: Interval, - before: Optional[datetime] = None, - after: Optional[datetime] = None, - branch: Optional[str] = None, -) -> CoverageAnalytics: - """ - Returns an empty CoverageAnalytics object, to be populated by field resolvers. - """ - return CoverageAnalytics( - percent_covered=0.0, - commit_sha="", - hits=0, - misses=0, - lines=0, - measurements=[] +) -> CoverageAnalyticsProps: + return CoverageAnalyticsProps( + repository=repository, )