Skip to content

Commit 5ead2a2

Browse files
Yashgupta9330arkid15rkasya
authored
Added Issue and Releases Field (#625)
* added field * changed in frontend * changed * fixed * added dark theme support * Update code * Update code * fetched from graphql * fixed graphql error * added test for both backend and frontend * fixed linting and test * fixed linting and test * Update code --------- Co-authored-by: Arkadii Yakovets <[email protected]> Co-authored-by: Kate Golovanova <[email protected]>
1 parent 88625c4 commit 5ead2a2

File tree

14 files changed

+544
-121
lines changed

14 files changed

+544
-121
lines changed
+74
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,92 @@
11
"""GitHub user GraphQL node."""
22

3+
import graphene
4+
35
from apps.common.graphql.nodes import BaseNode
46
from apps.github.models.user import User
57

68

9+
class RepositoryType(graphene.ObjectType):
10+
"""Repository type for nested objects."""
11+
12+
key = graphene.String()
13+
owner_key = graphene.String()
14+
15+
16+
class IssueType(graphene.ObjectType):
17+
"""GitHub issue type."""
18+
19+
created_at = graphene.Float()
20+
comments_count = graphene.Int()
21+
number = graphene.Int()
22+
repository = graphene.Field(RepositoryType)
23+
title = 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+
35+
736
class UserNode(BaseNode):
837
"""GitHub user node."""
938

39+
# Existing fields
40+
created_at = graphene.Float()
41+
updated_at = graphene.Float()
42+
url = graphene.String()
43+
44+
# New fields for issues and releases
45+
issues = graphene.List(IssueType)
46+
issues_count = graphene.Int()
47+
releases = graphene.List(ReleaseType)
48+
releases_count = graphene.Int()
49+
1050
class Meta:
1151
model = User
1252
fields = (
1353
"avatar_url",
54+
"bio",
55+
"company",
1456
"email",
57+
"followers_count",
58+
"following_count",
1559
"id",
60+
"location",
1661
"login",
1762
"name",
63+
"public_repositories_count",
1864
)
65+
66+
def resolve_created_at(self, info):
67+
"""Resolve user created at."""
68+
return self.idx_created_at
69+
70+
def resolve_updated_at(self, info):
71+
"""Resolve user updated at."""
72+
return self.idx_updated_at
73+
74+
def resolve_url(self, info):
75+
"""Resolve user URL."""
76+
return self.url
77+
78+
def resolve_issues(self, info):
79+
"""Resolve user issues."""
80+
return self.idx_issues
81+
82+
def resolve_issues_count(self, info):
83+
"""Resolve user issues count."""
84+
return self.idx_issues_count
85+
86+
def resolve_releases(self, info):
87+
"""Resolve user releases."""
88+
return self.idx_releases
89+
90+
def resolve_releases_count(self, info):
91+
"""Resolve user releases count."""
92+
return self.idx_releases_count
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""GitHub GraphQL queries."""
22

33
from apps.github.graphql.queries.repository import RepositoryQuery
4+
from apps.github.graphql.queries.user import UserQuery
45

56

6-
class GithubQuery(RepositoryQuery):
7+
class GithubQuery(RepositoryQuery, UserQuery):
78
"""GitHub query."""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""OWASP github GraphQL queries."""
2+
3+
import graphene
4+
5+
from apps.common.graphql.queries import BaseQuery
6+
from apps.github.graphql.nodes.user import UserNode
7+
from apps.github.models.user import User
8+
9+
10+
class UserQuery(BaseQuery):
11+
"""User queries."""
12+
13+
user = graphene.Field(UserNode, login=graphene.String(required=True))
14+
15+
def resolve_user(root, info, login):
16+
"""Resolve user by login."""
17+
try:
18+
return User.objects.get(login=login)
19+
except User.DoesNotExist:
20+
return None

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

+23-9
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,26 @@ def test_user_node_inheritance(self):
1414

1515
def test_meta_configuration(self):
1616
"""Test if Meta is properly configured."""
17-
assert UserNode._meta.model == User
18-
expected_fields = {
19-
"avatar_url",
20-
"email",
21-
"id",
22-
"login",
23-
"name",
24-
}
25-
assert set(UserNode._meta.fields) == expected_fields
17+
18+
assert UserNode._meta.model == User
19+
expected_fields = {
20+
"avatar_url",
21+
"bio",
22+
"company",
23+
"created_at",
24+
"email",
25+
"followers_count",
26+
"following_count",
27+
"id",
28+
"issues_count",
29+
"issues",
30+
"location",
31+
"login",
32+
"name",
33+
"public_repositories_count",
34+
"releases_count",
35+
"releases",
36+
"updated_at",
37+
"url",
38+
}
39+
assert set(UserNode._meta.fields) == expected_fields
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Test cases for UserQuery."""
2+
3+
from unittest.mock import Mock, patch
4+
5+
import pytest
6+
from graphene import Field, NonNull, String
7+
8+
from apps.common.graphql.queries import BaseQuery
9+
from apps.github.graphql.nodes.user import UserNode
10+
from apps.github.graphql.queries.user import UserQuery
11+
from apps.github.models.user import User
12+
13+
14+
class TestUserQuery:
15+
"""Test cases for UserQuery class."""
16+
17+
@pytest.fixture()
18+
def mock_info(self):
19+
"""GraphQL info mock fixture."""
20+
return Mock()
21+
22+
@pytest.fixture()
23+
def mock_user(self):
24+
"""User mock fixture."""
25+
return Mock(spec=User)
26+
27+
def test_user_query_inheritance(self):
28+
"""Test if UserQuery inherits from BaseQuery."""
29+
assert issubclass(UserQuery, BaseQuery)
30+
31+
def test_resolve_user_existing(self, mock_user, mock_info):
32+
"""Test resolving an existing user."""
33+
with patch("apps.github.models.user.User.objects.get") as mock_get:
34+
mock_get.return_value = mock_user
35+
36+
result = UserQuery.resolve_user(None, mock_info, login="test-user")
37+
38+
assert result == mock_user
39+
mock_get.assert_called_once_with(login="test-user")
40+
41+
def test_resolve_user_not_found(self, mock_info):
42+
"""Test resolving a non-existent user."""
43+
with patch("apps.github.models.user.User.objects.get") as mock_get:
44+
mock_get.side_effect = User.DoesNotExist
45+
46+
result = UserQuery.resolve_user(None, mock_info, login="non-existent")
47+
48+
assert result is None
49+
mock_get.assert_called_once_with(login="non-existent")
50+
51+
def test_user_field_configuration(self):
52+
"""Test if user field is properly configured."""
53+
user_field = UserQuery._meta.fields.get("user")
54+
55+
assert isinstance(user_field, Field)
56+
assert user_field.type == UserNode
57+
assert "login" in user_field.args
58+
59+
login_arg = user_field.args["login"]
60+
assert isinstance(login_arg.type, NonNull)
61+
assert login_arg.type.of_type == String
+6-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
export const mockUserData = {
22
users: [
33
{
4+
avatar_url: 'https://example.com/avatar1.jpg',
5+
company: 'OWASP',
46
key: 'user_1',
7+
login: 'user_1',
58
name: 'John Doe',
6-
company: 'OWASP',
7-
avatar_url: 'https://example.com/avatar1.jpg',
89
},
910
{
11+
avatar_url: 'https://example.com/avatar2.jpg',
12+
company: 'Security Co',
1013
key: 'user_2',
14+
login: 'user_2',
1115
name: 'Jane Smith',
12-
company: 'Security Co',
13-
avatar_url: 'https://example.com/avatar2.jpg',
1416
},
1517
],
1618
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
export const mockUserDetailsData = {
2+
user: {
3+
login: 'testuser',
4+
name: 'Test User',
5+
avatarUrl: 'https://example.com/avatar.jpg',
6+
url: 'https://github.com/testuser',
7+
bio: 'This is a test user',
8+
company: 'Test Company',
9+
location: 'Test Location',
10+
11+
followersCount: 10,
12+
followingCount: 5,
13+
publicRepositoriesCount: 3,
14+
createdAt: 1723002473,
15+
issues: [
16+
{
17+
number: 1,
18+
title: 'Test Issue',
19+
createdAt: 1723002473,
20+
commentsCount: 5,
21+
repository: {
22+
key: 'test-repo',
23+
ownerKey: 'testuser',
24+
},
25+
},
26+
],
27+
releases: [
28+
{
29+
name: 'v1.0.0',
30+
tagName: '1.0.0',
31+
isPreRelease: false,
32+
publishedAt: 1723002473,
33+
repository: {
34+
key: 'test-repo',
35+
ownerKey: 'testuser',
36+
},
37+
},
38+
],
39+
},
40+
}

0 commit comments

Comments
 (0)