Skip to content

Commit 92c336e

Browse files
committed
Added backend unit tests
1 parent 6985eff commit 92c336e

16 files changed

Lines changed: 455 additions & 0 deletions

tests/api/__init__.py

Whitespace-only changes.

tests/api/test_helpers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from fastadmin.api.helpers import sanitize
2+
3+
4+
async def test_sanitize():
5+
assert sanitize("true") is True
6+
assert sanitize("false") is False
7+
assert sanitize("null") is None
8+
assert sanitize("foo") == "foo"

tests/api/tortoise/__init__.py

Whitespace-only changes.

tests/api/tortoise/conftest.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import asyncio
2+
import pytest
3+
from tortoise import Tortoise
4+
5+
from tests.api.tortoise.models import Tournament, Event, User
6+
7+
8+
9+
@pytest.fixture(scope="session", autouse=True)
10+
async def tortoise_db():
11+
await Tortoise.init(
12+
db_url='sqlite://:memory:',
13+
modules={'models': ['tests.api.tortoise.models']}
14+
)
15+
await Tortoise.generate_schemas()
16+
yield Tortoise.get_connection('default')
17+
await Tortoise.close_connections()
18+
19+
20+
@pytest.fixture
21+
async def superuser():
22+
user = await User.create(username='Test User', password='password', is_superuser=True)
23+
yield user
24+
await user.delete()
25+
26+
27+
@pytest.fixture
28+
async def user():
29+
user = await User.create(username='Test User', password='password')
30+
yield user
31+
await user.delete()
32+
33+
34+
@pytest.fixture
35+
async def tournament():
36+
tournament = await Tournament.create(name='Test Tournament')
37+
yield tournament
38+
await tournament.delete()
39+
40+
41+
@pytest.fixture
42+
async def event(tournament, user):
43+
event = await Event.create(name='Test Event', tournament=tournament)
44+
await event.participants.add(user)
45+
yield event
46+
await event.delete()

tests/api/tortoise/helpers.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from fastadmin import TortoiseModelAdmin, register
2+
3+
4+
async def sign_in(client, user):
5+
6+
@register(user.__class__)
7+
class UserAdmin(TortoiseModelAdmin):
8+
async def authenticate(self, username, password):
9+
obj = await user.__class__.filter(username=username, password=password, is_superuser=True).first()
10+
if not obj:
11+
return None
12+
return obj.id
13+
14+
r = await client.post(
15+
"/api/sign-in",
16+
json={
17+
"username": user.username,
18+
"password": user.password,
19+
}
20+
)
21+
assert r.status_code == 200
22+
assert r.json() is None
23+
return r.cookies

tests/api/tortoise/models.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from tortoise.models import Model
2+
from tortoise import fields
3+
4+
5+
class BaseModel(Model):
6+
id = fields.IntField(pk=True)
7+
created_at = fields.DatetimeField(auto_now_add=True)
8+
updated_at = fields.DatetimeField(auto_now=True)
9+
10+
class Meta:
11+
abstract = True
12+
13+
14+
class Tournament(BaseModel):
15+
name = fields.CharField(max_length=255)
16+
17+
def __str__(self):
18+
return self.name
19+
20+
21+
class Event(BaseModel):
22+
name = fields.CharField(max_length=255)
23+
24+
tournament = fields.ForeignKeyField('models.Tournament', related_name='events')
25+
participants = fields.ManyToManyField('models.User', related_name='events')
26+
27+
def __str__(self):
28+
return self.name
29+
30+
31+
class User(BaseModel):
32+
username = fields.CharField(max_length=255)
33+
password = fields.CharField(max_length=255)
34+
is_superuser = fields.BooleanField(default=False)
35+
36+
def __str__(self):
37+
return self.username

tests/api/tortoise/test_add.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from fastadmin import TortoiseModelAdmin, register
2+
3+
from tests.api.tortoise.helpers import sign_in
4+
from fastadmin.models.helpers import unregister_admin_model
5+
6+
7+
async def test_add(superuser, tournament, event, client):
8+
9+
@register(event.__class__)
10+
class EventAdmin(TortoiseModelAdmin):
11+
pass
12+
13+
await sign_in(client, superuser)
14+
r = await client.post(
15+
f"/api/add/{event.__class__.__name__}",
16+
json={
17+
"name": "new name",
18+
"tournament_id": tournament.id,
19+
"participants": [superuser.id],
20+
}
21+
)
22+
assert r.status_code == 200
23+
item = r.json()
24+
event = await event.__class__.get(id=item["id"])
25+
assert item["name"] == "new name"
26+
assert item["tournament_id"] == tournament.id
27+
assert item["created_at"] == event.created_at.isoformat()
28+
assert item["updated_at"] == event.updated_at.isoformat()
29+
assert item["participants"] == [superuser.id]
30+
31+
32+
async def test_add_401(superuser, tournament, event, client):
33+
r = await client.post(
34+
f"/api/add/{event.__class__.__name__}",
35+
json={
36+
"name": "new name",
37+
"tournament_id": tournament.id,
38+
"participants": [superuser.id],
39+
}
40+
)
41+
assert r.status_code == 401
42+
43+
44+
async def test_add_404(superuser, tournament, event, client):
45+
unregister_admin_model([event.__class__])
46+
await sign_in(client, superuser)
47+
r = await client.post(
48+
f"/api/add/{event.__class__.__name__}",
49+
json={
50+
"name": "new name",
51+
"tournament_id": tournament.id,
52+
"participants": [superuser.id],
53+
}
54+
)
55+
assert r.status_code == 404

tests/api/tortoise/test_auth.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from tests.api.tortoise.helpers import sign_in
2+
from fastadmin import TortoiseModelAdmin, register
3+
4+
from fastadmin.models.helpers import unregister_admin_model
5+
6+
7+
async def test_api_sign_in_401_invalid_password(superuser, client):
8+
class UserAdmin(TortoiseModelAdmin):
9+
async def authenticate(self, username, password):
10+
obj = await superuser.__class__.filter(username=username, password=password, is_superuser=True).first()
11+
if not obj:
12+
return None
13+
return obj.id
14+
15+
r = await client.post(
16+
"/api/sign-in",
17+
json={
18+
"username": superuser.username,
19+
"password": "invalid",
20+
}
21+
)
22+
assert r.status_code == 401
23+
24+
25+
async def test_api_sign_in_401(superuser, client):
26+
class UserAdmin(TortoiseModelAdmin):
27+
async def authenticate(self, username, password):
28+
obj = await superuser.__class__.filter(username=username, password=password, is_superuser=True).first()
29+
if not obj:
30+
return None
31+
return obj.id
32+
33+
unregister_admin_model([superuser.__class__])
34+
35+
r = await client.post(
36+
"/api/sign-in",
37+
json={
38+
"username": superuser.username,
39+
"password": superuser.password,
40+
}
41+
)
42+
assert r.status_code == 401
43+
44+
45+
async def test_api_sign_in(superuser, client):
46+
assert await sign_in(client, superuser)
47+
48+
49+
async def test_api_me(superuser, client):
50+
await sign_in(client, superuser)
51+
52+
r = await client.get(
53+
"/api/me",
54+
)
55+
assert r.status_code == 200
56+
me = r.json()
57+
assert me["id"] == superuser.id
58+
assert me["username"] == superuser.username
59+
60+
61+
async def test_api_sign_out(superuser, client):
62+
await sign_in(client, superuser)
63+
64+
r = await client.post(
65+
"/api/sign-out",
66+
)
67+
assert r.status_code == 200
68+
69+
r = await client.get(
70+
"/api/me",
71+
)
72+
assert r.status_code == 401

tests/api/tortoise/test_change.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from fastadmin import TortoiseModelAdmin, register
2+
3+
from tests.api.tortoise.helpers import sign_in
4+
from fastadmin.models.helpers import unregister_admin_model
5+
6+
7+
async def test_change(superuser, event, client):
8+
9+
@register(event.__class__)
10+
class EventAdmin(TortoiseModelAdmin):
11+
pass
12+
13+
await sign_in(client, superuser)
14+
r = await client.patch(
15+
f"/api/change/{event.__class__.__name__}/{event.id}",
16+
json={
17+
"name": "new name",
18+
"participants": [superuser.id],
19+
}
20+
)
21+
assert r.status_code == 200
22+
23+
event = await event.__class__.get(id=event.id)
24+
item = r.json()
25+
assert item["id"] == event.id
26+
assert item["name"] == event.name
27+
assert item["tournament_id"] == event.tournament_id
28+
assert item["created_at"] == event.created_at.isoformat()
29+
assert item["updated_at"] == event.updated_at.isoformat()
30+
assert item["participants"] == [superuser.id]
31+
32+
33+
async def test_change_401(superuser, tournament, event, client):
34+
r = await client.patch(
35+
f"/api/change/{event.__class__.__name__}/{event.id}",
36+
json={
37+
"name": "new name",
38+
"participants": [superuser.id],
39+
}
40+
)
41+
assert r.status_code == 401
42+
43+
44+
async def test_change_404(superuser, event, client):
45+
unregister_admin_model([event.__class__])
46+
await sign_in(client, superuser)
47+
r = await client.patch(
48+
f"/api/change/{event.__class__.__name__}/{event.id}",
49+
json={
50+
"name": "new name",
51+
"participants": [superuser.id],
52+
}
53+
)
54+
assert r.status_code == 404
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from fastadmin import TortoiseModelAdmin, register
2+
3+
from tests.api.tortoise.helpers import sign_in
4+
5+
6+
async def test_configuration(superuser, event, client):
7+
8+
@register(event.__class__)
9+
class EventAdmin(TortoiseModelAdmin):
10+
pass
11+
12+
await sign_in(client, superuser)
13+
r = await client.get(
14+
f"/api/configuration",
15+
)
16+
assert r.status_code == 200
17+
data = r.json()
18+
assert data

0 commit comments

Comments
 (0)