mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-11 04:19:25 +00:00
Graph de famille en frontend (#820)
* Remove graphviz and use cytoscape.js instead * Frontend generated graphs * Make installation easier and faster * Better user experience * Family api and improved interface * Fix url history when using 0, improve button selection and reset reverse with reset button * Use klay layout * Add js translations and apply review comments
This commit is contained in:
committed by
GitHub
parent
bf96d8a10c
commit
f624b7c66d
187
core/tests/test_family.py
Normal file
187
core/tests/test_family.py
Normal file
@ -0,0 +1,187 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from model_bakery import baker
|
||||
|
||||
from core.baker_recipes import subscriber_user
|
||||
from core.models import User
|
||||
|
||||
|
||||
class TestFetchFamilyApi(TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
# Relations (A -> B means A is the godchild of B):
|
||||
# main_user -> user0 -> user3
|
||||
# -> user1 -> user6 -> user7 -> user8 -> user9
|
||||
# -> user2 -> user10
|
||||
#
|
||||
# main_user <- user3 <- user11
|
||||
# <- user12
|
||||
# <- user4 <- user13
|
||||
# <- user14
|
||||
# <- user15 <- user16
|
||||
# <- user5
|
||||
|
||||
cls.main_user = baker.make(User)
|
||||
cls.users = baker.make(User, _quantity=17)
|
||||
cls.main_user.godfathers.add(*cls.users[0:3])
|
||||
cls.main_user.godchildren.add(*cls.users[3:6])
|
||||
cls.users[1].godfathers.add(cls.users[6])
|
||||
cls.users[6].godfathers.add(cls.users[7])
|
||||
cls.users[7].godfathers.add(cls.users[8])
|
||||
cls.users[8].godfathers.add(cls.users[9])
|
||||
cls.users[2].godfathers.add(cls.users[10])
|
||||
|
||||
cls.users[3].godchildren.add(cls.users[11], cls.users[12])
|
||||
cls.users[4].godchildren.add(*cls.users[13:16])
|
||||
cls.users[15].godchildren.add(cls.users[16])
|
||||
|
||||
cls.root_user = baker.make(User, is_superuser=True)
|
||||
cls.subscriber_user = subscriber_user.make()
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
|
||||
def test_fetch_family_forbidden(self):
|
||||
# Anonymous user
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
)
|
||||
assert response.status_code == 403
|
||||
|
||||
self.client.force_login(baker.make(User)) # unsubscribed user
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
)
|
||||
assert response.status_code == 403
|
||||
|
||||
def test_fetch_family_hidden_user(self):
|
||||
self.main_user.is_subscriber_viewable = False
|
||||
self.main_user.save()
|
||||
for user_to_login, error_code in [
|
||||
(self.main_user, 200),
|
||||
(self.subscriber_user, 403),
|
||||
(self.root_user, 200),
|
||||
]:
|
||||
self.client.force_login(user_to_login)
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
)
|
||||
assert response.status_code == error_code
|
||||
|
||||
def test_fetch_family_with_zero_depth(self):
|
||||
"""Fetch the family with a depth of 0."""
|
||||
self.client.force_login(self.main_user)
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
+ f"?godfathers_depth=0&godchildren_depth=0"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert [u["id"] for u in response.json()["users"]] == [self.main_user.id]
|
||||
assert response.json()["relationships"] == []
|
||||
|
||||
def test_fetch_empty_family(self):
|
||||
empty_user = baker.make(User)
|
||||
self.client.force_login(empty_user)
|
||||
response = self.client.get(reverse("api:family_graph", args=[empty_user.id]))
|
||||
assert response.status_code == 200
|
||||
assert [u["id"] for u in response.json()["users"]] == [empty_user.id]
|
||||
assert response.json()["relationships"] == []
|
||||
|
||||
def test_fetch_whole_family(self):
|
||||
self.client.force_login(self.main_user)
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
+ f"?godfathers_depth=10&godchildren_depth=10"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert [u["id"] for u in response.json()["users"]] == [
|
||||
self.main_user.id,
|
||||
*[u.id for u in self.users],
|
||||
]
|
||||
self.assertCountEqual(
|
||||
response.json()["relationships"],
|
||||
[
|
||||
{"godfather": self.users[0].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[1].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[2].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[3].id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[4].id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[5].id},
|
||||
{"godfather": self.users[6].id, "godchild": self.users[1].id},
|
||||
{"godfather": self.users[7].id, "godchild": self.users[6].id},
|
||||
{"godfather": self.users[8].id, "godchild": self.users[7].id},
|
||||
{"godfather": self.users[9].id, "godchild": self.users[8].id},
|
||||
{"godfather": self.users[10].id, "godchild": self.users[2].id},
|
||||
{"godfather": self.users[3].id, "godchild": self.users[11].id},
|
||||
{"godfather": self.users[3].id, "godchild": self.users[12].id},
|
||||
{"godfather": self.users[4].id, "godchild": self.users[13].id},
|
||||
{"godfather": self.users[4].id, "godchild": self.users[14].id},
|
||||
{"godfather": self.users[4].id, "godchild": self.users[15].id},
|
||||
{"godfather": self.users[15].id, "godchild": self.users[16].id},
|
||||
],
|
||||
)
|
||||
|
||||
def test_fetch_family_first_level(self):
|
||||
"""Fetch only the first level of the family."""
|
||||
self.client.force_login(self.main_user)
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
+ f"?godfathers_depth=1&godchildren_depth=1"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert [u["id"] for u in response.json()["users"]] == [
|
||||
self.main_user.id,
|
||||
*[u.id for u in self.users[:6]],
|
||||
]
|
||||
self.assertCountEqual(
|
||||
response.json()["relationships"],
|
||||
[
|
||||
{"godfather": self.users[0].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[1].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[2].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[3].id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[4].id},
|
||||
{"godfather": self.main_user.id, "godchild": self.users[5].id},
|
||||
],
|
||||
)
|
||||
|
||||
def test_fetch_family_only_godfathers(self):
|
||||
"""Fetch only the godfathers."""
|
||||
self.client.force_login(self.main_user)
|
||||
response = self.client.get(
|
||||
reverse("api:family_graph", args=[self.main_user.id])
|
||||
+ f"?godfathers_depth=10&godchildren_depth=0"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert [u["id"] for u in response.json()["users"]] == [
|
||||
self.main_user.id,
|
||||
*[u.id for u in self.users[:3]],
|
||||
*[u.id for u in self.users[6:11]],
|
||||
]
|
||||
self.assertCountEqual(
|
||||
response.json()["relationships"],
|
||||
[
|
||||
{"godfather": self.users[0].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[1].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[2].id, "godchild": self.main_user.id},
|
||||
{"godfather": self.users[6].id, "godchild": self.users[1].id},
|
||||
{"godfather": self.users[7].id, "godchild": self.users[6].id},
|
||||
{"godfather": self.users[8].id, "godchild": self.users[7].id},
|
||||
{"godfather": self.users[9].id, "godchild": self.users[8].id},
|
||||
{"godfather": self.users[10].id, "godchild": self.users[2].id},
|
||||
],
|
||||
)
|
||||
|
||||
def test_nb_queries(self):
|
||||
# The number of queries should be 1 per level of existing depth.
|
||||
with self.assertNumQueries(0):
|
||||
self.main_user.get_family(godfathers_depth=0, godchildren_depth=0)
|
||||
with self.assertNumQueries(3):
|
||||
self.main_user.get_family(godfathers_depth=3, godchildren_depth=0)
|
||||
with self.assertNumQueries(3):
|
||||
self.main_user.get_family(godfathers_depth=0, godchildren_depth=3)
|
||||
with self.assertNumQueries(6):
|
||||
self.main_user.get_family(godfathers_depth=3, godchildren_depth=3)
|
||||
with self.assertNumQueries(4):
|
||||
# If a level is empty, the next ones should not be queried.
|
||||
self.main_user.get_family(godfathers_depth=0, godchildren_depth=10)
|
Reference in New Issue
Block a user