Fix some errors related to watched and likes lists
parent
0d21f04a87
commit
bf57ace9a2
|
@ -189,29 +189,30 @@ class WatchedResourceModelSerializer(serializers.ModelSerializer):
|
||||||
#watchers is not a field from the model but can be attached in the get_queryset of the viewset.
|
#watchers is not a field from the model but can be attached in the get_queryset of the viewset.
|
||||||
#If that's the case we need to remove it before calling the super method
|
#If that's the case we need to remove it before calling the super method
|
||||||
watcher_field = self.fields.pop("watchers", None)
|
watcher_field = self.fields.pop("watchers", None)
|
||||||
instance = super(WatchedResourceModelSerializer, self).restore_object(attrs, instance)
|
self.validate_watchers(attrs, "watchers")
|
||||||
if instance is not None and self.validate_watchers(attrs, "watchers"):
|
new_watcher_ids = set(attrs.pop("watchers", []))
|
||||||
#A partial update can exclude the watchers field
|
obj = super(WatchedResourceModelSerializer, self).restore_object(attrs, instance)
|
||||||
if not "watchers" in attrs:
|
|
||||||
return instance
|
|
||||||
|
|
||||||
new_watcher_ids = set(attrs.get("watchers", None))
|
#A partial update can exclude the watchers field or if the new instance can still not be saved
|
||||||
old_watcher_ids = set(instance.get_watchers().values_list("id", flat=True))
|
if instance is None or len(new_watcher_ids) == 0:
|
||||||
adding_watcher_ids = list(new_watcher_ids.difference(old_watcher_ids))
|
return obj
|
||||||
removing_watcher_ids = list(old_watcher_ids.difference(new_watcher_ids))
|
|
||||||
|
|
||||||
User = apps.get_model("users", "User")
|
old_watcher_ids = set(obj.get_watchers().values_list("id", flat=True))
|
||||||
adding_users = User.objects.filter(id__in=adding_watcher_ids)
|
adding_watcher_ids = list(new_watcher_ids.difference(old_watcher_ids))
|
||||||
removing_users = User.objects.filter(id__in=removing_watcher_ids)
|
removing_watcher_ids = list(old_watcher_ids.difference(new_watcher_ids))
|
||||||
for user in adding_users:
|
|
||||||
services.add_watcher(instance, user)
|
|
||||||
|
|
||||||
for user in removing_users:
|
User = apps.get_model("users", "User")
|
||||||
services.remove_watcher(instance, user)
|
adding_users = User.objects.filter(id__in=adding_watcher_ids)
|
||||||
|
removing_users = User.objects.filter(id__in=removing_watcher_ids)
|
||||||
|
for user in adding_users:
|
||||||
|
services.add_watcher(obj, user)
|
||||||
|
|
||||||
instance.watchers = instance.get_watchers()
|
for user in removing_users:
|
||||||
|
services.remove_watcher(obj, user)
|
||||||
|
|
||||||
return instance
|
obj.watchers = obj.get_watchers()
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
def to_native(self, obj):
|
def to_native(self, obj):
|
||||||
#watchers is wasn't attached via the get_queryset of the viewset we need to manually add it
|
#watchers is wasn't attached via the get_queryset of the viewset we need to manually add it
|
||||||
|
|
|
@ -367,6 +367,23 @@ def get_watched(user_or_id, model):
|
||||||
params=(obj_type.id, user_id))
|
params=(obj_type.id, user_id))
|
||||||
|
|
||||||
|
|
||||||
|
def get_projects_watched(user_or_id):
|
||||||
|
"""Get the objects watched by an user.
|
||||||
|
|
||||||
|
:param user_or_id: :class:`~taiga.users.models.User` instance or id.
|
||||||
|
:param model: Show only objects of this kind. Can be any Django model class.
|
||||||
|
|
||||||
|
:return: Queryset of objects representing the votes of the user.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(user_or_id, get_user_model()):
|
||||||
|
user_id = user_or_id.id
|
||||||
|
else:
|
||||||
|
user_id = user_or_id
|
||||||
|
|
||||||
|
project_class = apps.get_model("projects", "Project")
|
||||||
|
return project_class.objects.filter(notify_policies__user__id=user_id).exclude(notify_policies__notify_level=NotifyLevel.ignore)
|
||||||
|
|
||||||
def add_watcher(obj, user):
|
def add_watcher(obj, user):
|
||||||
"""Add a watcher to an object.
|
"""Add a watcher to an object.
|
||||||
|
|
||||||
|
|
|
@ -165,27 +165,31 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
ref = serializers.IntegerField()
|
ref = serializers.IntegerField()
|
||||||
slug = serializers.CharField()
|
slug = serializers.CharField()
|
||||||
|
name = serializers.CharField()
|
||||||
subject = serializers.CharField()
|
subject = serializers.CharField()
|
||||||
tags = TagsField(default=[])
|
description = serializers.SerializerMethodField("get_description")
|
||||||
project = serializers.IntegerField()
|
|
||||||
assigned_to = serializers.IntegerField()
|
assigned_to = serializers.IntegerField()
|
||||||
total_watchers = serializers.IntegerField()
|
status = serializers.CharField()
|
||||||
|
status_color = serializers.CharField()
|
||||||
|
tags_colors = serializers.SerializerMethodField("get_tags_color")
|
||||||
|
created_date = serializers.DateTimeField()
|
||||||
|
is_private = serializers.SerializerMethodField("get_is_private")
|
||||||
|
|
||||||
is_voted = serializers.SerializerMethodField("get_is_voted")
|
is_voted = serializers.SerializerMethodField("get_is_voted")
|
||||||
is_watched = serializers.SerializerMethodField("get_is_watched")
|
is_watched = serializers.SerializerMethodField("get_is_watched")
|
||||||
|
|
||||||
created_date = serializers.DateTimeField()
|
total_watchers = serializers.IntegerField()
|
||||||
|
total_votes = serializers.IntegerField()
|
||||||
|
|
||||||
project_name = serializers.CharField()
|
project = serializers.SerializerMethodField("get_project")
|
||||||
project_slug = serializers.CharField()
|
project_name = serializers.SerializerMethodField("get_project_name")
|
||||||
project_is_private = serializers.CharField()
|
project_slug = serializers.SerializerMethodField("get_project_slug")
|
||||||
|
project_is_private = serializers.SerializerMethodField("get_project_is_private")
|
||||||
|
|
||||||
assigned_to_username = serializers.CharField()
|
assigned_to_username = serializers.CharField()
|
||||||
assigned_to_full_name = serializers.CharField()
|
assigned_to_full_name = serializers.CharField()
|
||||||
assigned_to_photo = serializers.SerializerMethodField("get_photo")
|
assigned_to_photo = serializers.SerializerMethodField("get_photo")
|
||||||
|
|
||||||
total_votes = serializers.IntegerField()
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# Don't pass the extra ids args up to the superclass
|
# Don't pass the extra ids args up to the superclass
|
||||||
self.user_votes = kwargs.pop("user_votes", {})
|
self.user_votes = kwargs.pop("user_votes", {})
|
||||||
|
@ -194,6 +198,38 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
# Instantiate the superclass normally
|
# Instantiate the superclass normally
|
||||||
super(FavouriteSerializer, self).__init__(*args, **kwargs)
|
super(FavouriteSerializer, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def _none_if_project(self, obj, property):
|
||||||
|
type = obj.get("type", "")
|
||||||
|
if type == "project":
|
||||||
|
return None
|
||||||
|
|
||||||
|
return obj.get(property)
|
||||||
|
|
||||||
|
def _none_if_not_project(self, obj, property):
|
||||||
|
type = obj.get("type", "")
|
||||||
|
if type != "project":
|
||||||
|
return None
|
||||||
|
|
||||||
|
return obj.get(property)
|
||||||
|
|
||||||
|
def get_project(self, obj):
|
||||||
|
return self._none_if_project(obj, "project")
|
||||||
|
|
||||||
|
def get_is_private(self, obj):
|
||||||
|
return self._none_if_not_project(obj, "project_is_private")
|
||||||
|
|
||||||
|
def get_project_name(self, obj):
|
||||||
|
return self._none_if_project(obj, "project_name")
|
||||||
|
|
||||||
|
def get_description(self, obj):
|
||||||
|
return self._none_if_not_project(obj, "description")
|
||||||
|
|
||||||
|
def get_project_slug(self, obj):
|
||||||
|
return self._none_if_project(obj, "project_slug")
|
||||||
|
|
||||||
|
def get_project_is_private(self, obj):
|
||||||
|
return self._none_if_project(obj, "project_is_private")
|
||||||
|
|
||||||
def get_is_voted(self, obj):
|
def get_is_voted(self, obj):
|
||||||
return obj["id"] in self.user_votes.get(obj["type"], [])
|
return obj["id"] in self.user_votes.get(obj["type"], [])
|
||||||
|
|
||||||
|
@ -201,6 +237,14 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
return obj["id"] in self.user_watching.get(obj["type"], [])
|
return obj["id"] in self.user_watching.get(obj["type"], [])
|
||||||
|
|
||||||
def get_photo(self, obj):
|
def get_photo(self, obj):
|
||||||
|
type = obj.get("type", "")
|
||||||
|
if type == "project":
|
||||||
|
return None
|
||||||
|
|
||||||
UserData = namedtuple("UserData", ["photo", "email"])
|
UserData = namedtuple("UserData", ["photo", "email"])
|
||||||
user_data = UserData(photo=obj["assigned_to_photo"], email=obj.get("assigned_to_email") or "")
|
user_data = UserData(photo=obj["assigned_to_photo"], email=obj.get("assigned_to_email") or "")
|
||||||
return get_photo_or_gravatar_url(user_data)
|
return get_photo_or_gravatar_url(user_data)
|
||||||
|
|
||||||
|
def get_tags_color(self, obj):
|
||||||
|
tags = obj.get("tags", [])
|
||||||
|
return [{"name": tc[0], "color": tc[1]} for tc in obj.get("tags_colors", []) if tc[0] in tags]
|
||||||
|
|
|
@ -31,7 +31,7 @@ from easy_thumbnails.exceptions import InvalidImageFormatError
|
||||||
from taiga.base import exceptions as exc
|
from taiga.base import exceptions as exc
|
||||||
from taiga.base.utils.urls import get_absolute_url
|
from taiga.base.utils.urls import get_absolute_url
|
||||||
from taiga.projects.notifications.choices import NotifyLevel
|
from taiga.projects.notifications.choices import NotifyLevel
|
||||||
|
from taiga.projects.notifications.services import get_projects_watched
|
||||||
from .gravatar import get_gravatar_url
|
from .gravatar import get_gravatar_url
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -179,6 +179,11 @@ def get_watched_content_for_user(user):
|
||||||
list.append(object_id)
|
list.append(object_id)
|
||||||
user_watches[ct_model] = list
|
user_watches[ct_model] = list
|
||||||
|
|
||||||
|
#Now for projects,
|
||||||
|
projects_watched = get_projects_watched(user)
|
||||||
|
project_content_type_model=ContentType.objects.get(app_label="projects", model="project").model
|
||||||
|
user_watches[project_content_type_model] = projects_watched.values_list("id", flat=True)
|
||||||
|
|
||||||
return user_watches
|
return user_watches
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,8 +191,9 @@ def _build_favourites_sql_for_projects(for_user):
|
||||||
sql = """
|
sql = """
|
||||||
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'watch' AS action,
|
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'watch' AS action,
|
||||||
tags, notifications_notifypolicy.project_id AS object_id, projects_project.id AS project,
|
tags, notifications_notifypolicy.project_id AS object_id, projects_project.id AS project,
|
||||||
slug AS slug, projects_project.name AS subject,
|
slug AS slug, projects_project.name AS name, null AS subject,
|
||||||
notifications_notifypolicy.created_at, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to
|
notifications_notifypolicy.created_at as created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to,
|
||||||
|
null as status, null as status_color
|
||||||
FROM notifications_notifypolicy
|
FROM notifications_notifypolicy
|
||||||
INNER JOIN projects_project
|
INNER JOIN projects_project
|
||||||
ON (projects_project.id = notifications_notifypolicy.project_id)
|
ON (projects_project.id = notifications_notifypolicy.project_id)
|
||||||
|
@ -203,8 +209,9 @@ def _build_favourites_sql_for_projects(for_user):
|
||||||
UNION
|
UNION
|
||||||
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'vote' AS action,
|
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'vote' AS action,
|
||||||
tags, votes_vote.object_id AS object_id, projects_project.id AS project,
|
tags, votes_vote.object_id AS object_id, projects_project.id AS project,
|
||||||
slug AS slug, projects_project.name AS subject,
|
slug AS slug, projects_project.name AS name, null AS subject,
|
||||||
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to
|
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to,
|
||||||
|
null as status, null as status_color
|
||||||
FROM votes_vote
|
FROM votes_vote
|
||||||
INNER JOIN projects_project
|
INNER JOIN projects_project
|
||||||
ON (projects_project.id = votes_vote.object_id)
|
ON (projects_project.id = votes_vote.object_id)
|
||||||
|
@ -216,7 +223,7 @@ def _build_favourites_sql_for_projects(for_user):
|
||||||
ON projects_project.id = type_watchers.project_id
|
ON projects_project.id = type_watchers.project_id
|
||||||
LEFT JOIN votes_votes
|
LEFT JOIN votes_votes
|
||||||
ON (projects_project.id = votes_votes.object_id AND {project_content_type_id} = votes_votes.content_type_id)
|
ON (projects_project.id = votes_votes.object_id AND {project_content_type_id} = votes_votes.content_type_id)
|
||||||
WHERE votes_vote.user_id = {for_user_id}
|
WHERE votes_vote.user_id = {for_user_id} AND {project_content_type_id} = votes_vote.content_type_id
|
||||||
"""
|
"""
|
||||||
sql = sql.format(
|
sql = sql.format(
|
||||||
for_user_id=for_user.id,
|
for_user_id=for_user.id,
|
||||||
|
@ -232,13 +239,16 @@ def _build_favourites_sql_for_type(for_user, type, table_name, ref_column="ref",
|
||||||
sql = """
|
sql = """
|
||||||
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'watch' AS action,
|
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'watch' AS action,
|
||||||
tags, notifications_watched.object_id AS object_id, {table_name}.{project_column} AS project,
|
tags, notifications_watched.object_id AS object_id, {table_name}.{project_column} AS project,
|
||||||
{slug_column} AS slug, {subject_column} AS subject,
|
{slug_column} AS slug, null AS name, {subject_column} AS subject,
|
||||||
notifications_watched.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, {assigned_to_column} AS assigned_to
|
notifications_watched.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, {assigned_to_column} AS assigned_to,
|
||||||
|
projects_{type}status.name as status, projects_{type}status.color as status_color
|
||||||
FROM notifications_watched
|
FROM notifications_watched
|
||||||
INNER JOIN django_content_type
|
INNER JOIN django_content_type
|
||||||
ON (notifications_watched.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
ON (notifications_watched.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
||||||
INNER JOIN {table_name}
|
INNER JOIN {table_name}
|
||||||
ON ({table_name}.id = notifications_watched.object_id)
|
ON ({table_name}.id = notifications_watched.object_id)
|
||||||
|
INNER JOIN projects_{type}status
|
||||||
|
ON (projects_{type}status.id = {table_name}.status_id)
|
||||||
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
||||||
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
||||||
LEFT JOIN votes_votes
|
LEFT JOIN votes_votes
|
||||||
|
@ -247,13 +257,16 @@ def _build_favourites_sql_for_type(for_user, type, table_name, ref_column="ref",
|
||||||
UNION
|
UNION
|
||||||
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'vote' AS action,
|
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'vote' AS action,
|
||||||
tags, votes_vote.object_id AS object_id, {table_name}.{project_column} AS project,
|
tags, votes_vote.object_id AS object_id, {table_name}.{project_column} AS project,
|
||||||
{slug_column} AS slug, {subject_column} AS subject,
|
{slug_column} AS slug, null AS name, {subject_column} AS subject,
|
||||||
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, votes_votes.count total_votes, {assigned_to_column} AS assigned_to
|
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, votes_votes.count total_votes, {assigned_to_column} AS assigned_to,
|
||||||
|
projects_{type}status.name as status, projects_{type}status.color as status_color
|
||||||
FROM votes_vote
|
FROM votes_vote
|
||||||
INNER JOIN django_content_type
|
INNER JOIN django_content_type
|
||||||
ON (votes_vote.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
ON (votes_vote.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
||||||
INNER JOIN {table_name}
|
INNER JOIN {table_name}
|
||||||
ON ({table_name}.id = votes_vote.object_id)
|
ON ({table_name}.id = votes_vote.object_id)
|
||||||
|
INNER JOIN projects_{type}status
|
||||||
|
ON (projects_{type}status.id = {table_name}.status_id)
|
||||||
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
||||||
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
||||||
LEFT JOIN votes_votes
|
LEFT JOIN votes_votes
|
||||||
|
@ -279,12 +292,18 @@ def get_favourites_list(for_user, from_user, type=None, action=None, q=None):
|
||||||
filters_sql += " AND action = '{action}' ".format(action=action)
|
filters_sql += " AND action = '{action}' ".format(action=action)
|
||||||
|
|
||||||
if q:
|
if q:
|
||||||
filters_sql += " AND to_tsvector(coalesce(subject, '')) @@ plainto_tsquery('{q}') ".format(q=q)
|
# We must transform a q like "proj exam" (should find "project example") to something like proj:* & exam:*
|
||||||
|
qs = ["{}:*".format(e) for e in q.split(" ")]
|
||||||
|
filters_sql += """ AND (
|
||||||
|
to_tsvector(coalesce(subject,'') || ' ' ||coalesce(entities.name,'') || ' ' ||coalesce(to_char(ref, '999'),'')) @@ to_tsquery('{q}')
|
||||||
|
)
|
||||||
|
""".format(q=" & ".join(qs))
|
||||||
|
|
||||||
sql = """
|
sql = """
|
||||||
-- BEGIN Basic info: we need to mix info from different tables and denormalize it
|
-- BEGIN Basic info: we need to mix info from different tables and denormalize it
|
||||||
SELECT entities.*,
|
SELECT entities.*,
|
||||||
projects_project.name as project_name, projects_project.slug as project_slug, projects_project.is_private as project_is_private,
|
projects_project.name as project_name, projects_project.description as description, projects_project.slug as project_slug, projects_project.is_private as project_is_private,
|
||||||
|
projects_project.tags_colors,
|
||||||
users_user.username assigned_to_username, users_user.full_name assigned_to_full_name, users_user.photo assigned_to_photo, users_user.email assigned_to_email
|
users_user.username assigned_to_username, users_user.full_name assigned_to_full_name, users_user.photo assigned_to_photo, users_user.email assigned_to_email
|
||||||
FROM (
|
FROM (
|
||||||
{userstories_sql}
|
{userstories_sql}
|
||||||
|
@ -332,7 +351,7 @@ def get_favourites_list(for_user, from_user, type=None, action=None, q=None):
|
||||||
-- END Permissions checking
|
-- END Permissions checking
|
||||||
{filters_sql}
|
{filters_sql}
|
||||||
|
|
||||||
ORDER BY entities.created_date;
|
ORDER BY entities.created_date DESC;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from_user_id = -1
|
from_user_id = -1
|
||||||
|
|
|
@ -9,6 +9,7 @@ from .. import factories as f
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
from taiga.users import models
|
from taiga.users import models
|
||||||
|
from taiga.users.serializers import FavouriteSerializer
|
||||||
from taiga.auth.tokens import get_token_for_user
|
from taiga.auth.tokens import get_token_for_user
|
||||||
from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS
|
from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS
|
||||||
from taiga.users.services import get_favourites_list
|
from taiga.users.services import get_favourites_list
|
||||||
|
@ -396,32 +397,43 @@ def test_get_favourites_list_valid_info_for_project():
|
||||||
viewer_user = f.UserFactory()
|
viewer_user = f.UserFactory()
|
||||||
watcher_user = f.UserFactory()
|
watcher_user = f.UserFactory()
|
||||||
|
|
||||||
project = f.ProjectFactory(is_private=False, name="Testing project")
|
project = f.ProjectFactory(is_private=False, name="Testing project", tags=['test', 'tag'])
|
||||||
project.add_watcher(watcher_user)
|
project.add_watcher(watcher_user)
|
||||||
content_type = ContentType.objects.get_for_model(project)
|
content_type = ContentType.objects.get_for_model(project)
|
||||||
vote = f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
vote = f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
||||||
|
|
||||||
project_vote_info = get_favourites_list(fav_user, viewer_user)[0]
|
raw_project_vote_info = get_favourites_list(fav_user, viewer_user)[0]
|
||||||
|
project_vote_info = FavouriteSerializer(raw_project_vote_info).data
|
||||||
|
|
||||||
assert project_vote_info["type"] == "project"
|
assert project_vote_info["type"] == "project"
|
||||||
assert project_vote_info["action"] == "vote"
|
assert project_vote_info["action"] == "vote"
|
||||||
assert project_vote_info["id"] == project.id
|
assert project_vote_info["id"] == project.id
|
||||||
assert project_vote_info["ref"] == None
|
assert project_vote_info["ref"] == None
|
||||||
assert project_vote_info["slug"] == project.slug
|
assert project_vote_info["slug"] == project.slug
|
||||||
assert project_vote_info["subject"] == project.name
|
assert project_vote_info["name"] == project.name
|
||||||
assert project_vote_info["tags"] == project.tags
|
assert project_vote_info["subject"] == None
|
||||||
assert project_vote_info["project"] == project.id
|
assert project_vote_info["description"] == project.description
|
||||||
assert project_vote_info["assigned_to"] == None
|
assert project_vote_info["assigned_to"] == None
|
||||||
|
assert project_vote_info["status"] == None
|
||||||
|
assert project_vote_info["status_color"] == None
|
||||||
|
|
||||||
|
tags_colors = {tc["name"]:tc["color"] for tc in project_vote_info["tags_colors"]}
|
||||||
|
assert "test" in tags_colors
|
||||||
|
assert "tag" in tags_colors
|
||||||
|
|
||||||
|
assert project_vote_info["is_private"] == project.is_private
|
||||||
|
assert project_vote_info["is_voted"] == False
|
||||||
|
assert project_vote_info["is_watched"] == False
|
||||||
assert project_vote_info["total_watchers"] == 1
|
assert project_vote_info["total_watchers"] == 1
|
||||||
assert project_vote_info["created_date"] == vote.created_date
|
assert project_vote_info["total_votes"] == 1
|
||||||
assert project_vote_info["project_name"] == project.name
|
assert project_vote_info["project"] == None
|
||||||
assert project_vote_info["project_slug"] == project.slug
|
assert project_vote_info["project_name"] == None
|
||||||
assert project_vote_info["project_is_private"] == project.is_private
|
assert project_vote_info["project_slug"] == None
|
||||||
|
assert project_vote_info["project_is_private"] == None
|
||||||
assert project_vote_info["assigned_to_username"] == None
|
assert project_vote_info["assigned_to_username"] == None
|
||||||
assert project_vote_info["assigned_to_full_name"] == None
|
assert project_vote_info["assigned_to_full_name"] == None
|
||||||
assert project_vote_info["assigned_to_photo"] == None
|
assert project_vote_info["assigned_to_photo"] == None
|
||||||
assert project_vote_info["assigned_to_email"] == None
|
|
||||||
assert project_vote_info["total_votes"] == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list_valid_info_for_not_project_types():
|
def test_get_favourites_list_valid_info_for_not_project_types():
|
||||||
|
@ -449,26 +461,37 @@ def test_get_favourites_list_valid_info_for_not_project_types():
|
||||||
vote = f.VoteFactory(content_type=content_type, object_id=instance.id, user=fav_user)
|
vote = f.VoteFactory(content_type=content_type, object_id=instance.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=instance.id, count=3)
|
f.VotesFactory(content_type=content_type, object_id=instance.id, count=3)
|
||||||
|
|
||||||
instance_vote_info = get_favourites_list(fav_user, viewer_user, type=object_type)[0]
|
raw_instance_vote_info = get_favourites_list(fav_user, viewer_user, type=object_type)[0]
|
||||||
|
instance_vote_info = FavouriteSerializer(raw_instance_vote_info).data
|
||||||
|
|
||||||
assert instance_vote_info["type"] == object_type
|
assert instance_vote_info["type"] == object_type
|
||||||
assert instance_vote_info["action"] == "vote"
|
assert instance_vote_info["action"] == "vote"
|
||||||
assert instance_vote_info["id"] == instance.id
|
assert instance_vote_info["id"] == instance.id
|
||||||
assert instance_vote_info["ref"] == instance.ref
|
assert instance_vote_info["ref"] == instance.ref
|
||||||
assert instance_vote_info["slug"] == None
|
assert instance_vote_info["slug"] == None
|
||||||
|
assert instance_vote_info["name"] == None
|
||||||
assert instance_vote_info["subject"] == instance.subject
|
assert instance_vote_info["subject"] == instance.subject
|
||||||
assert instance_vote_info["tags"] == instance.tags
|
assert instance_vote_info["description"] == None
|
||||||
assert instance_vote_info["project"] == instance.project.id
|
assert instance_vote_info["assigned_to"] == instance.assigned_to.id
|
||||||
assert instance_vote_info["assigned_to"] == assigned_to_user.id
|
assert instance_vote_info["status"] == instance.status.name
|
||||||
|
assert instance_vote_info["status_color"] == instance.status.color
|
||||||
|
|
||||||
|
tags_colors = {tc["name"]:tc["color"] for tc in instance_vote_info["tags_colors"]}
|
||||||
|
assert "test1" in tags_colors
|
||||||
|
assert "test2" in tags_colors
|
||||||
|
|
||||||
|
assert instance_vote_info["is_private"] == None
|
||||||
|
assert instance_vote_info["is_voted"] == False
|
||||||
|
assert instance_vote_info["is_watched"] == False
|
||||||
assert instance_vote_info["total_watchers"] == 1
|
assert instance_vote_info["total_watchers"] == 1
|
||||||
assert instance_vote_info["created_date"] == vote.created_date
|
assert instance_vote_info["total_votes"] == 3
|
||||||
|
assert instance_vote_info["project"] == instance.project.id
|
||||||
assert instance_vote_info["project_name"] == instance.project.name
|
assert instance_vote_info["project_name"] == instance.project.name
|
||||||
assert instance_vote_info["project_slug"] == instance.project.slug
|
assert instance_vote_info["project_slug"] == instance.project.slug
|
||||||
assert instance_vote_info["project_is_private"] == instance.project.is_private
|
assert instance_vote_info["project_is_private"] == instance.project.is_private
|
||||||
assert instance_vote_info["assigned_to_username"] == assigned_to_user.username
|
assert instance_vote_info["assigned_to_username"] == instance.assigned_to.username
|
||||||
assert instance_vote_info["assigned_to_full_name"] == assigned_to_user.full_name
|
assert instance_vote_info["assigned_to_full_name"] == instance.assigned_to.full_name
|
||||||
assert instance_vote_info["assigned_to_photo"] == ''
|
assert instance_vote_info["assigned_to_photo"] != ""
|
||||||
assert instance_vote_info["assigned_to_email"] == assigned_to_user.email
|
|
||||||
assert instance_vote_info["total_votes"] == 3
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list_permissions():
|
def test_get_favourites_list_permissions():
|
||||||
|
|
|
@ -46,6 +46,22 @@ def test_update_userstories_order_in_bulk():
|
||||||
model=models.UserStory)
|
model=models.UserStory)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_userstory_with_watchers(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
user_watcher = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
||||||
|
f.MembershipFactory.create(project=project, user=user_watcher, is_owner=True)
|
||||||
|
url = reverse("userstories-list")
|
||||||
|
|
||||||
|
data = {"subject": "Test user story", "project": project.id, "watchers": [user_watcher.id]}
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
print(response.data)
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert response.data["watchers"] == []
|
||||||
|
|
||||||
|
|
||||||
def test_create_userstory_without_status(client):
|
def test_create_userstory_without_status(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(owner=user)
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
|
Loading…
Reference in New Issue