Skip to content

Commit 83ea460

Browse files
committed
added backend test cases
1 parent 968cdc2 commit 83ea460

16 files changed

Lines changed: 207 additions & 32 deletions

File tree

backend/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ test-backend:
158158
--cache-from nest-test-backend \
159159
-f backend/docker/Dockerfile.test backend \
160160
-t nest-test-backend
161-
@docker run -e DJANGO_CONFIGURATION=Test --rm nest-test-backend pytest
161+
@docker run -e DJANGO_CONFIGURATION=Test --rm nest-test-backend pytest --full-trace -s
162162

163163
update-backend-dependencies:
164164
@CMD="poetry update" $(MAKE) exec-backend-command
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
"""Core User queries."""
1+
"""Core User mutations."""
22

33
from .user import AuthUserMutation

backend/apps/nest/graphql/mutations/user.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import graphene
44
import requests
5-
from django.db import transaction
65

76
from apps.nest.graphql.nodes.user import AuthUserNode
87
from apps.nest.models import User
@@ -18,7 +17,6 @@ class Arguments:
1817

1918
auth_user = graphene.Field(AuthUserNode)
2019

21-
@transaction.atomic
2220
def mutate(self, info, access_token):
2321
"""Mutate method for user authentication."""
2422
response = requests.post(

backend/apps/nest/migrations/0001_initial.py

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,108 @@
66

77

88
class Migration(migrations.Migration):
9-
109
initial = True
1110

1211
dependencies = [
13-
('auth', '0012_alter_user_first_name_max_length'),
12+
("auth", "0012_alter_user_first_name_max_length"),
1413
]
1514

1615
operations = [
1716
migrations.CreateModel(
18-
name='User',
17+
name="User",
1918
fields=[
20-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21-
('password', models.CharField(max_length=128, verbose_name='password')),
22-
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
23-
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
24-
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
25-
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
26-
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
27-
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
28-
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
29-
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
30-
('github_id', models.CharField(max_length=255, unique=True, verbose_name='GitHub ID')),
31-
('username', models.CharField(max_length=150, unique=True, verbose_name='Username')),
32-
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
33-
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
19+
(
20+
"id",
21+
models.BigAutoField(
22+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
23+
),
24+
),
25+
("password", models.CharField(max_length=128, verbose_name="password")),
26+
(
27+
"last_login",
28+
models.DateTimeField(blank=True, null=True, verbose_name="last login"),
29+
),
30+
(
31+
"is_superuser",
32+
models.BooleanField(
33+
default=False,
34+
help_text="Designates that this user has all permissions without explicitly assigning them.",
35+
verbose_name="superuser status",
36+
),
37+
),
38+
(
39+
"first_name",
40+
models.CharField(blank=True, max_length=150, verbose_name="first name"),
41+
),
42+
(
43+
"last_name",
44+
models.CharField(blank=True, max_length=150, verbose_name="last name"),
45+
),
46+
(
47+
"email",
48+
models.EmailField(blank=True, max_length=254, verbose_name="email address"),
49+
),
50+
(
51+
"is_staff",
52+
models.BooleanField(
53+
default=False,
54+
help_text="Designates whether the user can log into this admin site.",
55+
verbose_name="staff status",
56+
),
57+
),
58+
(
59+
"is_active",
60+
models.BooleanField(
61+
default=True,
62+
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
63+
verbose_name="active",
64+
),
65+
),
66+
(
67+
"date_joined",
68+
models.DateTimeField(
69+
default=django.utils.timezone.now, verbose_name="date joined"
70+
),
71+
),
72+
(
73+
"github_id",
74+
models.CharField(max_length=255, unique=True, verbose_name="GitHub ID"),
75+
),
76+
(
77+
"username",
78+
models.CharField(max_length=150, unique=True, verbose_name="Username"),
79+
),
80+
(
81+
"groups",
82+
models.ManyToManyField(
83+
blank=True,
84+
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
85+
related_name="user_set",
86+
related_query_name="user",
87+
to="auth.group",
88+
verbose_name="groups",
89+
),
90+
),
91+
(
92+
"user_permissions",
93+
models.ManyToManyField(
94+
blank=True,
95+
help_text="Specific permissions for this user.",
96+
related_name="user_set",
97+
related_query_name="user",
98+
to="auth.permission",
99+
verbose_name="user permissions",
100+
),
101+
),
34102
],
35103
options={
36-
'verbose_name_plural': 'users',
37-
'db_table': 'user',
38-
'ordering': ['username'],
39-
'indexes': [models.Index(fields=['username'], name='user_usernam_b79065_idx')],
104+
"verbose_name_plural": "users",
105+
"db_table": "user",
106+
"ordering": ["username"],
107+
"indexes": [models.Index(fields=["username"], name="user_usernam_b79065_idx")],
40108
},
41109
managers=[
42-
('objects', django.contrib.auth.models.UserManager()),
110+
("objects", django.contrib.auth.models.UserManager()),
43111
],
44112
),
45113
]

backend/settings/base.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ class Base(Configuration):
1515
if ENVIRONMENT == "Test":
1616
from dotenv import load_dotenv
1717

18-
load_dotenv(BASE_DIR / ".env.example")
18+
load_dotenv(BASE_DIR / ".env")
1919

2020
ALLOWED_HOSTS = values.ListValue()
2121
CORS_ALLOW_CREDENTIALS = True
2222
DEBUG = False
23-
RELEASE_VERSION = values.Value(environ_name="RELEASE_VERSION")
24-
SENTRY_DSN = values.SecretValue(environ_name="SENTRY_DSN")
2523
SITE_NAME = "localhost"
2624
SITE_URL = "http://localhost:8000"
2725

backend/tests/apps/nest/__init__.py

Whitespace-only changes.

backend/tests/apps/nest/graphql/__init__.py

Whitespace-only changes.

backend/tests/apps/nest/graphql/mutations/__init__.py

Whitespace-only changes.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from unittest.mock import MagicMock, patch
2+
3+
import pytest
4+
5+
from apps.nest.graphql.mutations.user import GitHubAuth
6+
7+
8+
@pytest.fixture
9+
def mock_github_response():
10+
return {"data": {"viewer": {"id": "gh123", "login": "testuser"}}}
11+
12+
13+
def test_github_auth_new_user(mock_github_response):
14+
"""Test mutation without using the database"""
15+
with (
16+
patch("apps.nest.graphql.mutations.user.requests.post") as mock_post,
17+
patch("apps.nest.graphql.mutations.user.User.objects") as mock_objects,
18+
):
19+
mock_post.return_value = MagicMock(
20+
status_code=200,
21+
json=MagicMock(return_value=mock_github_response),
22+
raise_for_status=MagicMock(),
23+
)
24+
25+
mock_qs = MagicMock()
26+
mock_qs.first.return_value = None
27+
mock_objects.filter.return_value = mock_qs
28+
29+
# Simulate user creation
30+
mock_user = MagicMock()
31+
mock_objects.create.return_value = mock_user
32+
33+
result = GitHubAuth.mutate(None, MagicMock(), "valid_token")
34+
35+
mock_post.assert_called_once()
36+
mock_objects.filter.assert_called_once_with(github_id="gh123")
37+
mock_objects.create.assert_called_once_with(github_id="gh123", username="testuser")
38+
assert result.auth_user == mock_user
39+
40+
41+
def test_github_auth_existing_user(mock_github_response):
42+
"""Test existing user flow without using the database"""
43+
with (
44+
patch("apps.nest.graphql.mutations.user.requests.post") as mock_post,
45+
patch("apps.nest.graphql.mutations.user.User.objects") as mock_objects,
46+
):
47+
mock_post.return_value = MagicMock(
48+
status_code=200,
49+
json=MagicMock(return_value=mock_github_response),
50+
raise_for_status=MagicMock(),
51+
)
52+
53+
mock_user = MagicMock()
54+
mock_qs = MagicMock()
55+
mock_qs.first.return_value = mock_user
56+
mock_objects.filter.return_value = mock_qs
57+
58+
result = GitHubAuth.mutate(None, MagicMock(), "valid_token")
59+
60+
mock_post.assert_called_once()
61+
mock_objects.filter.assert_called_once_with(github_id="gh123")
62+
mock_objects.create.assert_not_called()
63+
assert result.auth_user == mock_user

backend/tests/apps/nest/graphql/nodes/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)