Skip to content

Commit 42a83d2

Browse files
committed
Add: Tests for user
1 parent fb55d0c commit 42a83d2

10 files changed

Lines changed: 425 additions & 7 deletions

File tree

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ install:
2323
uv sync
2424

2525
test:
26-
PYTHONPATH=. .venv/bin/pytest
26+
PYTHONPATH=. .venv/bin/pytest
27+
28+
run-test:
29+
uv run python3 manage.py test
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"model": "auth.user",
4+
"pk": 1,
5+
"fields": {
6+
"first_name": "John",
7+
"last_name": "Thnb3324",
8+
"username": "oimjmnnname",
9+
"password": "password23"
10+
}
11+
},
12+
{
13+
"model": "auth.user",
14+
"pk": 2,
15+
"fields": {
16+
"first_name": "NameOf2User",
17+
"last_name": "LastNameOf2User",
18+
"username": "username2",
19+
"password": "zxcasdad3"
20+
}
21+
}
22+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 5.1.6 on 2025-05-23 13:34
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('labels', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelOptions(
14+
name='label',
15+
options={'ordering': ('id',)},
16+
),
17+
]

task_manager/settings.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
# SECURITY WARNING: don't run with debug turned on in production!
3333
DEBUG = os.getenv("DEBUG", False)
3434

35+
ENVIRONMENT = os.getenv("DJANGO_ENV", "dev")
36+
3537
ALLOWED_HOSTS = ['python-project-52-r4q7.onrender.com', 'localhost', '127.0.0.1', 'webserver']
3638

3739

@@ -93,12 +95,20 @@
9395
# Database
9496
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
9597

96-
DATABASES = {
97-
"default": dj_database_url.config(
98-
default=os.getenv("DATABASE_URL"),
99-
conn_max_age=600 # Опционально: время жизни подключения
100-
)
101-
}
98+
if ENVIRONMENT == 'prod':
99+
DATABASES = {
100+
"default": dj_database_url.config(
101+
default=os.getenv("DATABASE_URL"),
102+
conn_max_age=600
103+
)
104+
}
105+
else: # dev
106+
DATABASES = {
107+
'default': {
108+
'ENGINE': 'django.db.backends.sqlite3',
109+
'NAME': BASE_DIR / 'db.sqlite3',
110+
}
111+
}
102112

103113
# Password validation
104114
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 5.1.6 on 2025-05-23 13:34
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('statuses', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelOptions(
14+
name='status',
15+
options={'ordering': ('id',)},
16+
),
17+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 5.1.6 on 2025-05-23 13:34
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('tasks', '0003_alter_task_labels'),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelOptions(
14+
name='task',
15+
options={'ordering': ('id',)},
16+
),
17+
]
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from task_manager.users.forms import UserForm
2+
3+
from django.contrib.auth.models import User
4+
from task_manager.users.tests.testcase import UserTestCase
5+
6+
7+
class TestCustomUserCreationForm(UserTestCase):
8+
def get_form(self, overrides=None):
9+
data = self.valid_data.copy()
10+
if overrides:
11+
data.update(overrides)
12+
return UserForm(data=data)
13+
14+
def test_valid_data(self):
15+
form = self.get_form()
16+
self.assertTrue(form.is_valid())
17+
user = form.save()
18+
self.assertEqual(user.username, self.valid_data['username'])
19+
self.assertEqual(User.objects.count(), self.user_count + 1)
20+
21+
def test_missing_fields(self):
22+
cases = [
23+
{'username': self.valid_data['username']},
24+
{
25+
'username': self.valid_data['username'],
26+
'password1': 'test123', # NOSONAR
27+
},
28+
{'first_name': 'Test', 'last_name': 'User'},
29+
]
30+
31+
for data in cases:
32+
with self.subTest(data=data):
33+
form = UserForm(data=data)
34+
self.assertFalse(form.is_valid())
35+
36+
def test_password_too_short(self):
37+
invalid_data = self.valid_data.copy()
38+
invalid_data.update({
39+
'password1': '12', # NOSONAR
40+
'password2': '12' # NOSONAR
41+
})
42+
form = UserForm(data=invalid_data)
43+
self.assertFalse(form.is_valid())
44+
45+
def test_invalid_username(self):
46+
test_cases = [
47+
'!!!',
48+
'user#name',
49+
'user name',
50+
'x' * 151,
51+
]
52+
53+
for username in test_cases:
54+
with self.subTest(username=username):
55+
invalid_data = self.valid_data.copy()
56+
invalid_data['username'] = username
57+
form = UserForm(data=invalid_data)
58+
self.assertFalse(form.is_valid())
59+
self.assertIn('username', form.errors)
60+
61+
def test_passwords_do_not_match(self):
62+
form = self.get_form({'password2': 'Different123'}) # NOSONAR
63+
self.assertFalse(form.is_valid())
64+
self.assertIn('password2', form.errors)
65+
66+
def test_empty_strings(self):
67+
form = self.get_form({
68+
'first_name': '',
69+
'last_name': '',
70+
'username': '',
71+
})
72+
self.assertFalse(form.is_valid())
73+
self.assertIn('first_name', form.errors)
74+
self.assertIn('last_name', form.errors)
75+
76+
def test_duplicate_username(self):
77+
form = self.get_form({'username': 'oimjmnnname'})
78+
self.assertFalse(form.is_valid())
79+
self.assertIn('username', form.errors)
80+
81+
82+
class TestCustomUserChangeForm(UserTestCase):
83+
def get_form(self, overrides=None):
84+
data = self.update_data.copy()
85+
data.update({
86+
'password1': data.pop('password1'),
87+
'password2': data.pop('password2')
88+
})
89+
if overrides:
90+
data.update(overrides)
91+
return UserForm(data=data, instance=self.user1)
92+
93+
def test_valid_password_update(self):
94+
form = self.get_form()
95+
self.assertTrue(form.is_valid())
96+
user = form.save()
97+
self.assertEqual(user.username, self.update_data['username'])
98+
self.assertTrue(user.check_password(
99+
self.update_data['password1'] # NOSONAR
100+
))
101+
102+
def test_passwords_do_not_match(self):
103+
form = self.get_form({'password2': 'WrongConfirm'}) # NOSONAR
104+
self.assertFalse(form.is_valid())
105+
self.assertIn('password2', form.errors)
106+
107+
def test_short_password(self):
108+
form = self.get_form({
109+
'password1': '12', # NOSONAR
110+
'password2': '12' # NOSONAR
111+
})
112+
self.assertFalse(form.is_valid())
113+
self.assertIn('password2', form.errors)
114+
115+
def test_missing_password_fields(self):
116+
for case in [
117+
{'password1': '', 'password2': 'SomePassword'}, # NOSONAR
118+
{'password1': 'SomePassword', 'password2': ''} # NOSONAR
119+
]:
120+
with self.subTest(case=case):
121+
form = self.get_form(case)
122+
self.assertFalse(form.is_valid())
123+
self.assertTrue(
124+
'password1' in form.errors or 'password2' in form.errors
125+
)
126+
127+
def test_update_with_existing_valid_password(self):
128+
form = self.get_form({
129+
'password1': 'QueenInNorth456', # NOSONAR
130+
'password2': 'QueenInNorth456', # NOSONAR
131+
})
132+
self.assertTrue(form.is_valid())
133+
user = form.save()
134+
self.assertTrue(user.check_password('QueenInNorth456')) # NOSONAR

0 commit comments

Comments
 (0)