Skip to content

Commit ad96496

Browse files
AbhayTopnoarkid15r
andauthored
Refactor of issue and release GraphQL queries (#1268)
* Refactor of issue and release GraphQL queries * Changes made after the recommendation of coderabbitai * Made changes on frontend test-cases * Update code * Update code --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
1 parent 56912c5 commit ad96496

File tree

11 files changed

+75
-76
lines changed

11 files changed

+75
-76
lines changed

backend/apps/github/graphql/nodes/user.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,11 @@ class RepositoryType(graphene.ObjectType):
1313
owner_key = graphene.String()
1414

1515

16-
class IssueType(graphene.ObjectType):
17-
"""GitHub issue type."""
18-
19-
created_at = graphene.Float()
20-
comments_count = graphene.Int()
21-
repository = graphene.Field(RepositoryType)
22-
title = graphene.String()
23-
url = graphene.String()
24-
25-
26-
class ReleaseType(graphene.ObjectType):
27-
"""GitHub release type."""
28-
29-
is_pre_release = graphene.Boolean()
30-
name = graphene.String()
31-
published_at = graphene.Float()
32-
repository = graphene.Field(RepositoryType)
33-
tag_name = graphene.String()
34-
url = graphene.String()
35-
36-
3716
class UserNode(BaseNode):
3817
"""GitHub user node."""
3918

4019
created_at = graphene.Float()
41-
issues = graphene.List(IssueType)
4220
issues_count = graphene.Int()
43-
releases = graphene.List(ReleaseType)
4421
releases_count = graphene.Int()
4522
updated_at = graphene.Float()
4623
url = graphene.String()
@@ -65,18 +42,10 @@ def resolve_created_at(self, info):
6542
"""Resolve created at."""
6643
return self.idx_created_at
6744

68-
def resolve_issues(self, info):
69-
"""Resolve issues."""
70-
return self.idx_issues
71-
7245
def resolve_issues_count(self, info):
7346
"""Resolve issues count."""
7447
return self.idx_issues_count
7548

76-
def resolve_releases(self, info):
77-
"""Resolve releases."""
78-
return self.idx_releases
79-
8049
def resolve_releases_count(self, info):
8150
"""Resolve releases count."""
8251
return self.idx_releases_count

backend/apps/github/graphql/queries/issue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ class IssueQuery(BaseQuery):
1313

1414
recent_issues = graphene.List(
1515
IssueNode,
16-
limit=graphene.Int(default_value=15),
16+
limit=graphene.Int(default_value=5),
1717
distinct=graphene.Boolean(default_value=False),
1818
login=graphene.String(required=False),
1919
)
2020

21-
def resolve_recent_issues(root, info, limit=15, distinct=False, login=None):
21+
def resolve_recent_issues(root, info, limit, distinct=False, login=None):
2222
"""Resolve recent issues with optional filtering.
2323
2424
Args:

backend/apps/github/graphql/queries/pull_request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class PullRequestQuery(BaseQuery):
1313

1414
recent_pull_requests = graphene.List(
1515
PullRequestNode,
16-
limit=graphene.Int(default_value=6),
16+
limit=graphene.Int(default_value=5),
1717
distinct=graphene.Boolean(default_value=False),
1818
login=graphene.String(required=False),
1919
)

backend/apps/github/graphql/queries/release.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,20 @@ class ReleaseQuery(BaseQuery):
1313

1414
recent_releases = graphene.List(
1515
ReleaseNode,
16-
limit=graphene.Int(default_value=15),
16+
limit=graphene.Int(default_value=6),
1717
distinct=graphene.Boolean(default_value=False),
18+
login=graphene.String(required=False),
1819
)
1920

20-
def resolve_recent_releases(root, info, limit=15, distinct=False):
21+
def resolve_recent_releases(root, info, limit, distinct=False, login=None):
2122
"""Resolve recent releases with optional distinct filtering.
2223
2324
Args:
2425
root (Any): The root query object.
2526
info (ResolveInfo): The GraphQL execution context.
2627
limit (int): Maximum number of releases to return.
2728
distinct (bool): Whether to return unique releases per author and repository.
29+
login (str): Optional GitHub username for filtering releases.
2830
2931
Returns:
3032
QuerySet: Queryset containing the filtered list of releases.
@@ -36,6 +38,11 @@ def resolve_recent_releases(root, info, limit=15, distinct=False):
3638
published_at__isnull=False,
3739
).order_by("-published_at")
3840

41+
if login:
42+
queryset = queryset.filter(
43+
author__login=login,
44+
)
45+
3946
if distinct:
4047
latest_release_per_author = (
4148
queryset.filter(author_id=OuterRef("author_id"))

backend/tests/apps/github/graphql/nodes/user_test.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ def test_meta_configuration(self):
2525
"following_count",
2626
"id",
2727
"issues_count",
28-
"issues",
2928
"location",
3029
"login",
3130
"name",
3231
"public_repositories_count",
3332
"releases_count",
34-
"releases",
3533
"updated_at",
3634
"url",
3735
}

frontend/__tests__/unit/data/mockUserDetails.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@ export const mockUserDetailsData = {
1212
followingCount: 5,
1313
publicRepositoriesCount: 3,
1414
createdAt: 1723002473,
15-
issues: [
16-
{
17-
title: 'Test Issue',
18-
createdAt: 1723002473,
19-
commentsCount: 5,
20-
url: 'https://github.com/OWASP/Nest/issues/798',
21-
},
22-
],
23-
releases: [
24-
{
25-
isPreRelease: false,
26-
name: 'v1.0.0',
27-
publishedAt: 1723002473,
28-
tagName: '1.0.0',
29-
url: 'https://github.com/testuser/test-repo/releases/tag/1.0.0',
30-
},
31-
],
3215
},
16+
recentIssues: [
17+
{
18+
title: 'Test Issue',
19+
createdAt: 1723002473,
20+
commentsCount: 5,
21+
url: 'https://github.com/OWASP/Nest/issues/798',
22+
},
23+
],
24+
recentReleases: [
25+
{
26+
isPreRelease: false,
27+
name: 'v1.0.0',
28+
publishedAt: 1723002473,
29+
tagName: '1.0.0',
30+
url: 'https://github.com/testuser/test-repo/releases/tag/1.0.0',
31+
},
32+
],
3333
recentPullRequests: [
3434
{
3535
createdAt: 1723002473,

frontend/__tests__/unit/pages/About.test.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,27 @@ describe('About Component', () => {
230230
})
231231
})
232232

233+
test('shows fallback when user data is missing', async () => {
234+
;(useQuery as jest.Mock).mockImplementation((query, options) => {
235+
if (options?.variables?.key === 'nest') {
236+
return mockProjectData
237+
} else if (options?.variables?.key === 'arkid15r') {
238+
return { data: null, loading: false, error: false }
239+
} else if (options?.variables?.key === 'kasya') {
240+
return mockUserData('kasya')
241+
} else if (options?.variables?.key === 'mamicidal') {
242+
return mockUserData('mamicidal')
243+
}
244+
return { loading: true }
245+
})
246+
247+
render(<About />)
248+
249+
await waitFor(() => {
250+
expect(screen.getByText(/No data available for arkid15r/i)).toBeInTheDocument()
251+
})
252+
})
253+
233254
test('renders top contributors section correctly', async () => {
234255
render(<About />)
235256

frontend/__tests__/unit/pages/UserDetails.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,15 +285,17 @@ describe('UserDetailsPage', () => {
285285
test('handles no recent issues gracefully', async () => {
286286
const noIssuesData = {
287287
...mockUserDetailsData,
288-
user: { ...mockUserDetailsData.user, issues: [] },
288+
recentIssues: [],
289289
}
290+
290291
;(useQuery as jest.Mock).mockReturnValue({
291292
data: noIssuesData,
292293
loading: false,
293294
error: null,
294295
})
295296

296297
render(<UserDetailsPage />)
298+
297299
await waitFor(() => {
298300
expect(screen.getByText('Recent Issues')).toBeInTheDocument()
299301
expect(screen.queryByText('Test Issue')).not.toBeInTheDocument()

frontend/src/api/queries/userQueries.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,24 @@ import { gql } from '@apollo/client'
22

33
export const GET_USER_DATA = gql`
44
query GetUser($key: String!) {
5-
recentPullRequests(login: $key) {
5+
recentIssues(limit: 5, login: $key) {
6+
commentsCount
67
createdAt
78
title
89
url
910
}
11+
recentPullRequests(limit: 5, login: $key) {
12+
createdAt
13+
title
14+
url
15+
}
16+
recentReleases(limit: 6, login: $key) {
17+
isPreRelease
18+
name
19+
publishedAt
20+
tagName
21+
url
22+
}
1023
topContributedRepositories(login: $key) {
1124
contributorsCount
1225
forksCount
@@ -25,24 +38,11 @@ export const GET_USER_DATA = gql`
2538
email
2639
followersCount
2740
followingCount
28-
issues {
29-
commentsCount
30-
createdAt
31-
title
32-
url
33-
}
3441
issuesCount
3542
location
3643
login
3744
name
3845
publicRepositoriesCount
39-
releases {
40-
isPreRelease
41-
name
42-
publishedAt
43-
tagName
44-
url
45-
}
4646
releasesCount
4747
url
4848
}

frontend/src/pages/UserDetails.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ import { toaster } from 'components/ui/toaster'
2323
const UserDetailsPage: React.FC = () => {
2424
const { userKey } = useParams()
2525
const [user, setUser] = useState<UserDetailsProps | null>()
26+
const [issues, setIssues] = useState<ProjectIssuesType[]>([])
2627
const [topRepositories, setTopRepositories] = useState<RepositoryCardProps[]>([])
2728
const [pullRequests, setPullRequests] = useState<PullRequestsType[]>([])
29+
const [releases, setReleases] = useState<ProjectReleaseType[]>([])
2830
const [data, setData] = useState<HeatmapData | null>(null)
2931
const [isLoading, setIsLoading] = useState<boolean>(true)
3032
const [username, setUsername] = useState('')
@@ -40,7 +42,9 @@ const UserDetailsPage: React.FC = () => {
4042
useEffect(() => {
4143
if (graphQLData) {
4244
setUser(graphQLData?.user)
45+
setIssues(graphQLData?.recentIssues)
4346
setPullRequests(graphQLData?.recentPullRequests)
47+
setReleases(graphQLData?.recentReleases)
4448
setTopRepositories(graphQLData?.topContributedRepositories)
4549
setIsLoading(false)
4650
}
@@ -101,7 +105,7 @@ const UserDetailsPage: React.FC = () => {
101105

102106
const formattedIssues: ProjectIssuesType[] = useMemo(() => {
103107
return (
104-
user?.issues?.map((issue) => ({
108+
issues?.map((issue) => ({
105109
commentsCount: issue.commentsCount,
106110
createdAt: issue.createdAt,
107111
title: issue.title,
@@ -114,7 +118,7 @@ const UserDetailsPage: React.FC = () => {
114118
url: issue.url,
115119
})) || []
116120
)
117-
}, [user])
121+
}, [issues, user])
118122

119123
const formattedPullRequest: ItemCardPullRequests[] = useMemo(() => {
120124
return (
@@ -134,7 +138,7 @@ const UserDetailsPage: React.FC = () => {
134138

135139
const formattedReleases: ProjectReleaseType[] = useMemo(() => {
136140
return (
137-
user?.releases?.map((release) => ({
141+
releases?.map((release) => ({
138142
isPreRelease: release.isPreRelease,
139143
name: release.name,
140144
publishedAt: release.publishedAt,
@@ -148,7 +152,7 @@ const UserDetailsPage: React.FC = () => {
148152
url: release.url,
149153
})) || []
150154
)
151-
}, [user])
155+
}, [releases, user])
152156

153157
if (isLoading) {
154158
return <LoadingSpinner />

0 commit comments

Comments
 (0)