US #2929: Ability to edit commit and see their history

remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro Alonso 2016-05-09 11:50:49 +02:00 committed by David Barragán Merino
parent 4e8495a167
commit 81b41529d2
10 changed files with 1102 additions and 58 deletions

View File

@ -1,5 +1,9 @@
# Changelog # # Changelog #
## 2.2.0 ??? (unreleased)
### Features
- [API] edit comment endpoint: comment owners and project admins can edit existing comments
## 2.1.0 Ursus Americanus (2016-05-03) ## 2.1.0 Ursus Americanus (2016-05-03)

View File

@ -23,6 +23,7 @@ from taiga.base import response
from taiga.base.decorators import detail_route from taiga.base.decorators import detail_route
from taiga.base.api import ReadOnlyListViewSet from taiga.base.api import ReadOnlyListViewSet
from taiga.base.api.utils import get_object_or_404 from taiga.base.api.utils import get_object_or_404
from taiga.mdrender.service import render as mdrender
from . import permissions from . import permissions
from . import serializers from . import serializers
@ -56,42 +57,93 @@ class HistoryViewSet(ReadOnlyListViewSet):
return response.Ok(serializer.data) return response.Ok(serializer.data)
@detail_route(methods=['get'])
def comment_versions(self, request, pk):
obj = self.get_object()
history_entry_id = request.QUERY_PARAMS.get('id', None)
history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first()
self.check_permissions(request, 'comment_versions', history_entry)
if history_entry is None:
return response.NotFound()
history_entry.attach_user_info_to_comment_versions()
return response.Ok(history_entry.comment_versions)
@detail_route(methods=['post'])
def edit_comment(self, request, pk):
obj = self.get_object()
history_entry_id = request.QUERY_PARAMS.get('id', None)
history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first()
obj = services.get_instance_from_key(history_entry.key)
comment = request.DATA.get("comment", None)
self.check_permissions(request, 'edit_comment', history_entry)
if history_entry is None:
return response.NotFound()
if comment is None:
return response.BadRequest({"error": _("comment is required")})
if history_entry.delete_comment_date or history_entry.delete_comment_user:
return response.BadRequest({"error": _("deleted comments can't be edited")})
# comment_versions can be None if there are no historic versions of the comment
comment_versions = history_entry.comment_versions or []
comment_versions.append({
"date": history_entry.created_at,
"comment": history_entry.comment,
"comment_html": history_entry.comment_html,
"user": {
"id": request.user.pk,
}
})
history_entry.edit_comment_date = timezone.now()
history_entry.comment = comment
history_entry.comment_html = mdrender(obj.project, comment)
history_entry.comment_versions = comment_versions
history_entry.save()
return response.Ok()
@detail_route(methods=['post']) @detail_route(methods=['post'])
def delete_comment(self, request, pk): def delete_comment(self, request, pk):
obj = self.get_object() obj = self.get_object()
comment_id = request.QUERY_PARAMS.get('id', None) history_entry_id = request.QUERY_PARAMS.get('id', None)
comment = services.get_history_queryset_by_model_instance(obj).filter(id=comment_id).first() history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first()
self.check_permissions(request, 'delete_comment', comment) self.check_permissions(request, 'delete_comment', history_entry)
if comment is None: if history_entry is None:
return response.NotFound() return response.NotFound()
if comment.delete_comment_date or comment.delete_comment_user: if history_entry.delete_comment_date or history_entry.delete_comment_user:
return response.BadRequest({"error": _("Comment already deleted")}) return response.BadRequest({"error": _("Comment already deleted")})
comment.delete_comment_date = timezone.now() history_entry.delete_comment_date = timezone.now()
comment.delete_comment_user = {"pk": request.user.pk, "name": request.user.get_full_name()} history_entry.delete_comment_user = {"pk": request.user.pk, "name": request.user.get_full_name()}
comment.save() history_entry.save()
return response.Ok() return response.Ok()
@detail_route(methods=['post']) @detail_route(methods=['post'])
def undelete_comment(self, request, pk): def undelete_comment(self, request, pk):
obj = self.get_object() obj = self.get_object()
comment_id = request.QUERY_PARAMS.get('id', None) history_entry_id = request.QUERY_PARAMS.get('id', None)
comment = services.get_history_queryset_by_model_instance(obj).filter(id=comment_id).first() history_entry = services.get_history_queryset_by_model_instance(obj).filter(id=history_entry_id).first()
self.check_permissions(request, 'undelete_comment', comment) self.check_permissions(request, 'undelete_comment', history_entry)
if comment is None: if history_entry is None:
return response.NotFound() return response.NotFound()
if not comment.delete_comment_date and not comment.delete_comment_user: if not history_entry.delete_comment_date and not history_entry.delete_comment_user:
return response.BadRequest({"error": _("Comment not deleted")}) return response.BadRequest({"error": _("Comment not deleted")})
comment.delete_comment_date = None history_entry.delete_comment_date = None
comment.delete_comment_user = None history_entry.delete_comment_user = None
comment.save() history_entry.save()
return response.Ok() return response.Ok()
# Just for restframework! Because it raises # Just for restframework! Because it raises

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-05-12 11:10
from __future__ import unicode_literals
from django.db import migrations, models
import django_pgjson.fields
class Migration(migrations.Migration):
dependencies = [
('history', '0008_auto_20150508_1028'),
]
operations = [
migrations.AddField(
model_name='historyentry',
name='comment_versions',
field=django_pgjson.fields.JsonField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name='historyentry',
name='edit_comment_date',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]

View File

@ -67,6 +67,10 @@ class HistoryEntry(models.Model):
delete_comment_date = models.DateTimeField(null=True, blank=True, default=None) delete_comment_date = models.DateTimeField(null=True, blank=True, default=None)
delete_comment_user = JsonField(null=True, blank=True, default=None) delete_comment_user = JsonField(null=True, blank=True, default=None)
# Historic version of comments
comment_versions = JsonField(null=True, blank=True, default=None)
edit_comment_date = models.DateTimeField(null=True, blank=True, default=None)
# Flag for mark some history entries as # Flag for mark some history entries as
# hidden. Hidden history entries are important # hidden. Hidden history entries are important
# for save but not important to preview. # for save but not important to preview.
@ -111,6 +115,20 @@ class HistoryEntry(models.Model):
self._owner = owner self._owner = owner
self._prefetched_owner = True self._prefetched_owner = True
def attach_user_info_to_comment_versions(self):
if not self.comment_versions:
return
from taiga.users.serializers import UserSerializer
user_ids = [v["user"]["id"] for v in self.comment_versions if "user" in v and "id" in v["user"]]
users_by_id = {u.id: u for u in get_user_model().objects.filter(id__in=user_ids)}
for version in self.comment_versions:
user = users_by_id.get(version["user"]["id"], None)
if user:
version["user"] = UserSerializer(user).data
@cached_property @cached_property
def values_diff(self): def values_diff(self):
result = {} result = {}

View File

@ -33,32 +33,41 @@ class IsCommentOwner(PermissionComponent):
return obj.user and obj.user.get("pk", "not-pk") == request.user.pk return obj.user and obj.user.get("pk", "not-pk") == request.user.pk
class IsCommentProjectOwner(PermissionComponent): class IsCommentProjectAdmin(PermissionComponent):
def check_permissions(self, request, view, obj=None): def check_permissions(self, request, view, obj=None):
model = get_model_from_key(obj.key) model = get_model_from_key(obj.key)
pk = get_pk_from_key(obj.key) pk = get_pk_from_key(obj.key)
project = model.objects.get(pk=pk) project = model.objects.get(pk=pk)
return is_project_admin(request.user, project) return is_project_admin(request.user, project)
class UserStoryHistoryPermission(TaigaResourcePermission): class UserStoryHistoryPermission(TaigaResourcePermission):
retrieve_perms = HasProjectPerm('view_project') retrieve_perms = HasProjectPerm('view_project')
delete_comment_perms = IsCommentProjectOwner() | IsCommentOwner() edit_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectOwner() | IsCommentDeleter() delete_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectAdmin() | IsCommentDeleter()
comment_versions_perms = IsCommentProjectAdmin() | IsCommentOwner()
class TaskHistoryPermission(TaigaResourcePermission): class TaskHistoryPermission(TaigaResourcePermission):
retrieve_perms = HasProjectPerm('view_project') retrieve_perms = HasProjectPerm('view_project')
delete_comment_perms = IsCommentProjectOwner() | IsCommentOwner() edit_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectOwner() | IsCommentDeleter() delete_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectAdmin() | IsCommentDeleter()
comment_versions_perms = IsCommentProjectAdmin() | IsCommentOwner()
class IssueHistoryPermission(TaigaResourcePermission): class IssueHistoryPermission(TaigaResourcePermission):
retrieve_perms = HasProjectPerm('view_project') retrieve_perms = HasProjectPerm('view_project')
delete_comment_perms = IsCommentProjectOwner() | IsCommentOwner() edit_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectOwner() | IsCommentDeleter() delete_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectAdmin() | IsCommentDeleter()
comment_versions_perms = IsCommentProjectAdmin() | IsCommentOwner()
class WikiHistoryPermission(TaigaResourcePermission): class WikiHistoryPermission(TaigaResourcePermission):
retrieve_perms = HasProjectPerm('view_project') retrieve_perms = HasProjectPerm('view_project')
delete_comment_perms = IsCommentProjectOwner() | IsCommentOwner() edit_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectOwner() | IsCommentDeleter() delete_comment_perms = IsCommentProjectAdmin() | IsCommentOwner()
undelete_comment_perms = IsCommentProjectAdmin() | IsCommentDeleter()
comment_versions_perms = IsCommentProjectAdmin() | IsCommentOwner()

View File

@ -33,9 +33,11 @@ class HistoryEntrySerializer(serializers.ModelSerializer):
values_diff = I18NJsonField(i18n_fields=HISTORY_ENTRY_I18N_FIELDS) values_diff = I18NJsonField(i18n_fields=HISTORY_ENTRY_I18N_FIELDS)
user = serializers.SerializerMethodField("get_user") user = serializers.SerializerMethodField("get_user")
delete_comment_user = JsonField() delete_comment_user = JsonField()
comment_versions = JsonField()
class Meta: class Meta:
model = models.HistoryEntry model = models.HistoryEntry
exclude = ("comment_versions",)
def get_user(self, entry): def get_user(self, entry):
user = {"pk": None, "username": None, "name": None, "photo": None, "is_active": False} user = {"pk": None, "username": None, "name": None, "photo": None, "is_active": False}

View File

@ -91,6 +91,20 @@ def get_pk_from_key(key:str) -> object:
return pk return pk
def get_instance_from_key(key:str) -> object:
"""
Get instance from key
"""
model = get_model_from_key(key)
pk = get_pk_from_key(key)
try:
obj = model.objects.get(pk=pk)
return obj
except model.DoesNotExist:
# Catch simultaneous DELETE request
return None
def register_values_implementation(typename:str, fn=None): def register_values_implementation(typename:str, fn=None):
""" """
Register values implementation for specified typename. Register values implementation for specified typename.

View File

@ -44,7 +44,6 @@ def _clean_description_fields(values_diff):
def on_new_history_entry(sender, instance, created, **kwargs): def on_new_history_entry(sender, instance, created, **kwargs):
if instance._importing: if instance._importing:
return return
@ -81,6 +80,10 @@ def on_new_history_entry(sender, instance, created, **kwargs):
if instance.delete_comment_date: if instance.delete_comment_date:
extra_data["comment_deleted"] = True extra_data["comment_deleted"] = True
# Detect edited comment
if instance.comment_versions is not None and len(instance.comment_versions)>0:
extra_data["comment_edited"] = True
created_datetime = instance.created_at created_datetime = instance.created_at
_push_to_timelines(project, user, obj, event_type, created_datetime, extra_data=extra_data) _push_to_timelines(project, user, obj, event_type, created_datetime, extra_data=extra_data)

View File

@ -1,6 +1,11 @@
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone
from taiga.base.utils import json
from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS
from taiga.projects.history.models import HistoryEntry
from taiga.projects.history.choices import HistoryType
from taiga.projects.history.services import make_key_from_model_object
from tests import factories as f from tests import factories as f
from tests.utils import helper_test_http_method, disconnect_signals, reconnect_signals from tests.utils import helper_test_http_method, disconnect_signals, reconnect_signals
@ -21,11 +26,11 @@ def teardown_module(module):
def data(): def data():
m = type("Models", (object,), {}) m = type("Models", (object,), {})
m.registered_user = f.UserFactory.create() m.registered_user = f.UserFactory.create(full_name="registered_user")
m.project_member_with_perms = f.UserFactory.create() m.project_member_with_perms = f.UserFactory.create(full_name="project_member_with_perms")
m.project_member_without_perms = f.UserFactory.create() m.project_member_without_perms = f.UserFactory.create(full_name="project_member_without_perms")
m.project_owner = f.UserFactory.create() m.project_owner = f.UserFactory.create(full_name="project_owner")
m.other_user = f.UserFactory.create() m.other_user = f.UserFactory.create(full_name="other_user")
m.public_project = f.ProjectFactory(is_private=False, m.public_project = f.ProjectFactory(is_private=False,
anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)), anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
@ -76,39 +81,33 @@ def data():
return m return m
#########################################################
## User stories
#########################################################
@pytest.fixture @pytest.fixture
def data_us(data): def data_us(data):
m = type("Models", (object,), {}) m = type("Models", (object,), {})
m.public_user_story = f.UserStoryFactory(project=data.public_project, ref=1) m.public_user_story = f.UserStoryFactory(project=data.public_project, ref=1)
m.public_history_entry = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing public",
key=make_key_from_model_object(m.public_user_story),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_user_story1 = f.UserStoryFactory(project=data.private_project1, ref=5) m.private_user_story1 = f.UserStoryFactory(project=data.private_project1, ref=5)
m.private_history_entry1 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 1",
key=make_key_from_model_object(m.private_user_story1),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_user_story2 = f.UserStoryFactory(project=data.private_project2, ref=9) m.private_user_story2 = f.UserStoryFactory(project=data.private_project2, ref=9)
return m m.private_history_entry2 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 2",
key=make_key_from_model_object(m.private_user_story2),
@pytest.fixture diff={},
def data_task(data): user={"pk": data.project_member_with_perms.pk})
m = type("Models", (object,), {})
m.public_task = f.TaskFactory(project=data.public_project, ref=2)
m.private_task1 = f.TaskFactory(project=data.private_project1, ref=6)
m.private_task2 = f.TaskFactory(project=data.private_project2, ref=10)
return m
@pytest.fixture
def data_issue(data):
m = type("Models", (object,), {})
m.public_issue = f.IssueFactory(project=data.public_project, ref=3)
m.private_issue1 = f.IssueFactory(project=data.private_project1, ref=7)
m.private_issue2 = f.IssueFactory(project=data.private_project2, ref=11)
return m
@pytest.fixture
def data_wiki(data):
m = type("Models", (object,), {})
m.public_wiki = f.WikiPageFactory(project=data.public_project, slug=4)
m.private_wiki1 = f.WikiPageFactory(project=data.private_project1, slug=8)
m.private_wiki2 = f.WikiPageFactory(project=data.private_project2, slug=12)
return m return m
@ -133,6 +132,222 @@ def test_user_story_history_retrieve(client, data, data_us):
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_user_story_action_edit_comment(client, data, data_us):
public_url = "{}?id={}".format(
reverse('userstory-history-edit-comment', kwargs={"pk": data_us.public_user_story.pk}),
data_us.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('userstory-history-edit-comment', kwargs={"pk": data_us.private_user_story1.pk}),
data_us.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('userstory-history-edit-comment', kwargs={"pk": data_us.private_user_story2.pk}),
data_us.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
data = json.dumps({"comment": "testing update comment"})
results = helper_test_http_method(client, 'post', public_url, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url1, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url2, data, users)
assert results == [401, 403, 403, 200, 200]
def test_user_story_action_delete_comment(client, data, data_us):
public_url = "{}?id={}".format(
reverse('userstory-history-delete-comment', kwargs={"pk": data_us.public_user_story.pk}),
data_us.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('userstory-history-delete-comment', kwargs={"pk": data_us.private_user_story1.pk}),
data_us.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('userstory-history-delete-comment', kwargs={"pk": data_us.private_user_story2.pk}),
data_us.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_us.public_history_entry.delete_comment_date = None
data_us.public_history_entry.delete_comment_user = None
data_us.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_us.private_history_entry1.delete_comment_date = None
data_us.private_history_entry1.delete_comment_user = None
data_us.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_us.private_history_entry2.delete_comment_date = None
data_us.private_history_entry2.delete_comment_user = None
data_us.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_user_story_action_undelete_comment(client, data, data_us):
public_url = "{}?id={}".format(
reverse('userstory-history-undelete-comment', kwargs={"pk": data_us.public_user_story.pk}),
data_us.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('userstory-history-undelete-comment', kwargs={"pk": data_us.private_user_story1.pk}),
data_us.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('userstory-history-undelete-comment', kwargs={"pk": data_us.private_user_story2.pk}),
data_us.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_us.public_history_entry.delete_comment_date = timezone.now()
data_us.public_history_entry.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_us.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_us.private_history_entry1.delete_comment_date = timezone.now()
data_us.private_history_entry1.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_us.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_us.private_history_entry2.delete_comment_date = timezone.now()
data_us.private_history_entry2.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_us.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_user_story_action_comment_versions(client, data, data_us):
public_url = "{}?id={}".format(
reverse('userstory-history-comment-versions', kwargs={"pk": data_us.public_user_story.pk}),
data_us.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('userstory-history-comment-versions', kwargs={"pk": data_us.private_user_story1.pk}),
data_us.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('userstory-history-comment-versions', kwargs={"pk": data_us.private_user_story2.pk}),
data_us.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner,
]
results = helper_test_http_method(client, 'get', public_url, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url1, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200]
#########################################################
## Tasks
#########################################################
@pytest.fixture
def data_task(data):
m = type("Models", (object,), {})
m.public_task = f.TaskFactory(project=data.public_project, ref=2)
m.public_history_entry = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing public",
key=make_key_from_model_object(m.public_task),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_task1 = f.TaskFactory(project=data.private_project1, ref=6)
m.private_history_entry1 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 1",
key=make_key_from_model_object(m.private_task1),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_task2 = f.TaskFactory(project=data.private_project2, ref=10)
m.private_history_entry2 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 2",
key=make_key_from_model_object(m.private_task2),
diff={},
user={"pk": data.project_member_with_perms.pk})
return m
def test_task_history_retrieve(client, data, data_task): def test_task_history_retrieve(client, data, data_task):
public_url = reverse('task-history-detail', kwargs={"pk": data_task.public_task.pk}) public_url = reverse('task-history-detail', kwargs={"pk": data_task.public_task.pk})
private_url1 = reverse('task-history-detail', kwargs={"pk": data_task.private_task1.pk}) private_url1 = reverse('task-history-detail', kwargs={"pk": data_task.private_task1.pk})
@ -154,6 +369,222 @@ def test_task_history_retrieve(client, data, data_task):
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_task_action_edit_comment(client, data, data_task):
public_url = "{}?id={}".format(
reverse('task-history-edit-comment', kwargs={"pk": data_task.public_task.pk}),
data_task.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('task-history-edit-comment', kwargs={"pk": data_task.private_task1.pk}),
data_task.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('task-history-edit-comment', kwargs={"pk": data_task.private_task2.pk}),
data_task.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
data = json.dumps({"comment": "testing update comment"})
results = helper_test_http_method(client, 'post', public_url, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url1, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url2, data, users)
assert results == [401, 403, 403, 200, 200]
def test_task_action_delete_comment(client, data, data_task):
public_url = "{}?id={}".format(
reverse('task-history-delete-comment', kwargs={"pk": data_task.public_task.pk}),
data_task.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('task-history-delete-comment', kwargs={"pk": data_task.private_task1.pk}),
data_task.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('task-history-delete-comment', kwargs={"pk": data_task.private_task2.pk}),
data_task.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_task.public_history_entry.delete_comment_date = None
data_task.public_history_entry.delete_comment_user = None
data_task.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_task.private_history_entry1.delete_comment_date = None
data_task.private_history_entry1.delete_comment_user = None
data_task.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_task.private_history_entry2.delete_comment_date = None
data_task.private_history_entry2.delete_comment_user = None
data_task.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_task_action_undelete_comment(client, data, data_task):
public_url = "{}?id={}".format(
reverse('task-history-undelete-comment', kwargs={"pk": data_task.public_task.pk}),
data_task.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('task-history-undelete-comment', kwargs={"pk": data_task.private_task1.pk}),
data_task.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('task-history-undelete-comment', kwargs={"pk": data_task.private_task2.pk}),
data_task.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_task.public_history_entry.delete_comment_date = timezone.now()
data_task.public_history_entry.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_task.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_task.private_history_entry1.delete_comment_date = timezone.now()
data_task.private_history_entry1.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_task.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_task.private_history_entry2.delete_comment_date = timezone.now()
data_task.private_history_entry2.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_task.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_task_action_comment_versions(client, data, data_task):
public_url = "{}?id={}".format(
reverse('task-history-comment-versions', kwargs={"pk": data_task.public_task.pk}),
data_task.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('task-history-comment-versions', kwargs={"pk": data_task.private_task1.pk}),
data_task.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('task-history-comment-versions', kwargs={"pk": data_task.private_task2.pk}),
data_task.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner,
]
results = helper_test_http_method(client, 'get', public_url, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url1, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200]
#########################################################
## Issues
#########################################################
@pytest.fixture
def data_issue(data):
m = type("Models", (object,), {})
m.public_issue = f.IssueFactory(project=data.public_project, ref=3)
m.public_history_entry = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing public",
key=make_key_from_model_object(m.public_issue),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_issue1 = f.IssueFactory(project=data.private_project1, ref=7)
m.private_history_entry1 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 1",
key=make_key_from_model_object(m.private_issue1),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_issue2 = f.IssueFactory(project=data.private_project2, ref=11)
m.private_history_entry2 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 2",
key=make_key_from_model_object(m.private_issue2),
diff={},
user={"pk": data.project_member_with_perms.pk})
return m
def test_issue_history_retrieve(client, data, data_issue): def test_issue_history_retrieve(client, data, data_issue):
public_url = reverse('issue-history-detail', kwargs={"pk": data_issue.public_issue.pk}) public_url = reverse('issue-history-detail', kwargs={"pk": data_issue.public_issue.pk})
private_url1 = reverse('issue-history-detail', kwargs={"pk": data_issue.private_issue1.pk}) private_url1 = reverse('issue-history-detail', kwargs={"pk": data_issue.private_issue1.pk})
@ -175,6 +606,222 @@ def test_issue_history_retrieve(client, data, data_issue):
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_issue_action_edit_comment(client, data, data_issue):
public_url = "{}?id={}".format(
reverse('issue-history-edit-comment', kwargs={"pk": data_issue.public_issue.pk}),
data_issue.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('issue-history-edit-comment', kwargs={"pk": data_issue.private_issue1.pk}),
data_issue.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('issue-history-edit-comment', kwargs={"pk": data_issue.private_issue2.pk}),
data_issue.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
data = json.dumps({"comment": "testing update comment"})
results = helper_test_http_method(client, 'post', public_url, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url1, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url2, data, users)
assert results == [401, 403, 403, 200, 200]
def test_issue_action_delete_comment(client, data, data_issue):
public_url = "{}?id={}".format(
reverse('issue-history-delete-comment', kwargs={"pk": data_issue.public_issue.pk}),
data_issue.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('issue-history-delete-comment', kwargs={"pk": data_issue.private_issue1.pk}),
data_issue.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('issue-history-delete-comment', kwargs={"pk": data_issue.private_issue2.pk}),
data_issue.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_issue.public_history_entry.delete_comment_date = None
data_issue.public_history_entry.delete_comment_user = None
data_issue.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_issue.private_history_entry1.delete_comment_date = None
data_issue.private_history_entry1.delete_comment_user = None
data_issue.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_issue.private_history_entry2.delete_comment_date = None
data_issue.private_history_entry2.delete_comment_user = None
data_issue.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_issue_action_undelete_comment(client, data, data_issue):
public_url = "{}?id={}".format(
reverse('issue-history-undelete-comment', kwargs={"pk": data_issue.public_issue.pk}),
data_issue.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('issue-history-undelete-comment', kwargs={"pk": data_issue.private_issue1.pk}),
data_issue.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('issue-history-undelete-comment', kwargs={"pk": data_issue.private_issue2.pk}),
data_issue.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_issue.public_history_entry.delete_comment_date = timezone.now()
data_issue.public_history_entry.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_issue.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_issue.private_history_entry1.delete_comment_date = timezone.now()
data_issue.private_history_entry1.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_issue.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_issue.private_history_entry2.delete_comment_date = timezone.now()
data_issue.private_history_entry2.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_issue.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_issue_action_comment_versions(client, data, data_issue):
public_url = "{}?id={}".format(
reverse('issue-history-comment-versions', kwargs={"pk": data_issue.public_issue.pk}),
data_issue.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('issue-history-comment-versions', kwargs={"pk": data_issue.private_issue1.pk}),
data_issue.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('issue-history-comment-versions', kwargs={"pk": data_issue.private_issue2.pk}),
data_issue.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner,
]
results = helper_test_http_method(client, 'get', public_url, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url1, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200]
#########################################################
## Wiki pages
#########################################################
@pytest.fixture
def data_wiki(data):
m = type("Models", (object,), {})
m.public_wiki = f.WikiPageFactory(project=data.public_project, slug=4)
m.public_history_entry = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing public",
key=make_key_from_model_object(m.public_wiki),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_wiki1 = f.WikiPageFactory(project=data.private_project1, slug=8)
m.private_history_entry1 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 1",
key=make_key_from_model_object(m.private_wiki1),
diff={},
user={"pk": data.project_member_with_perms.pk})
m.private_wiki2 = f.WikiPageFactory(project=data.private_project2, slug=12)
m.private_history_entry2 = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing 2",
key=make_key_from_model_object(m.private_wiki2),
diff={},
user={"pk": data.project_member_with_perms.pk})
return m
def test_wiki_history_retrieve(client, data, data_wiki): def test_wiki_history_retrieve(client, data, data_wiki):
public_url = reverse('wiki-history-detail', kwargs={"pk": data_wiki.public_wiki.pk}) public_url = reverse('wiki-history-detail', kwargs={"pk": data_wiki.public_wiki.pk})
private_url1 = reverse('wiki-history-detail', kwargs={"pk": data_wiki.private_wiki1.pk}) private_url1 = reverse('wiki-history-detail', kwargs={"pk": data_wiki.private_wiki1.pk})
@ -194,3 +841,189 @@ def test_wiki_history_retrieve(client, data, data_wiki):
assert results == [200, 200, 200, 200, 200] assert results == [200, 200, 200, 200, 200]
results = helper_test_http_method(client, 'get', private_url2, None, users) results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200] assert results == [401, 403, 403, 200, 200]
def test_wiki_action_edit_comment(client, data, data_wiki):
public_url = "{}?id={}".format(
reverse('wiki-history-edit-comment', kwargs={"pk": data_wiki.public_wiki.pk}),
data_wiki.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('wiki-history-edit-comment', kwargs={"pk": data_wiki.private_wiki1.pk}),
data_wiki.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('wiki-history-edit-comment', kwargs={"pk": data_wiki.private_wiki2.pk}),
data_wiki.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner
]
data = json.dumps({"comment": "testing update comment"})
results = helper_test_http_method(client, 'post', public_url, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url1, data, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'post', private_url2, data, users)
assert results == [401, 403, 403, 200, 200]
def test_wiki_action_delete_comment(client, data, data_wiki):
public_url = "{}?id={}".format(
reverse('wiki-history-delete-comment', kwargs={"pk": data_wiki.public_wiki.pk}),
data_wiki.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('wiki-history-delete-comment', kwargs={"pk": data_wiki.private_wiki1.pk}),
data_wiki.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('wiki-history-delete-comment', kwargs={"pk": data_wiki.private_wiki2.pk}),
data_wiki.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_wiki.public_history_entry.delete_comment_date = None
data_wiki.public_history_entry.delete_comment_user = None
data_wiki.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_wiki.private_history_entry1.delete_comment_date = None
data_wiki.private_history_entry1.delete_comment_user = None
data_wiki.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_wiki.private_history_entry2.delete_comment_date = None
data_wiki.private_history_entry2.delete_comment_user = None
data_wiki.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_wiki_action_undelete_comment(client, data, data_wiki):
public_url = "{}?id={}".format(
reverse('wiki-history-undelete-comment', kwargs={"pk": data_wiki.public_wiki.pk}),
data_wiki.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('wiki-history-undelete-comment', kwargs={"pk": data_wiki.private_wiki1.pk}),
data_wiki.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('wiki-history-undelete-comment', kwargs={"pk": data_wiki.private_wiki2.pk}),
data_wiki.private_history_entry2.id
)
users_and_statuses = [
(None, 401),
(data.registered_user, 403),
(data.project_member_without_perms, 403),
(data.project_member_with_perms, 200),
(data.project_owner, 200),
]
for user, status_code in users_and_statuses:
data_wiki.public_history_entry.delete_comment_date = timezone.now()
data_wiki.public_history_entry.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_wiki.public_history_entry.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(public_url)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_wiki.private_history_entry1.delete_comment_date = timezone.now()
data_wiki.private_history_entry1.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_wiki.private_history_entry1.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url1)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
for user, status_code in users_and_statuses:
data_wiki.private_history_entry2.delete_comment_date = timezone.now()
data_wiki.private_history_entry2.delete_comment_user = {"pk": data.project_member_with_perms.pk}
data_wiki.private_history_entry2.save()
if user:
client.login(user)
else:
client.logout()
response = client.json.post(private_url2)
error_mesage = "{} != {} for {}".format(response.status_code, status_code, user)
assert response.status_code == status_code, error_mesage
def test_wiki_action_comment_versions(client, data, data_wiki):
public_url = "{}?id={}".format(
reverse('wiki-history-comment-versions', kwargs={"pk": data_wiki.public_wiki.pk}),
data_wiki.public_history_entry.id
)
private_url1 = "{}?id={}".format(
reverse('wiki-history-comment-versions', kwargs={"pk": data_wiki.private_wiki1.pk}),
data_wiki.private_history_entry1.id
)
private_url2 = "{}?id={}".format(
reverse('wiki-history-comment-versions', kwargs={"pk": data_wiki.private_wiki2.pk}),
data_wiki.private_history_entry2.id
)
users = [
None,
data.registered_user,
data.project_member_without_perms,
data.project_member_with_perms,
data.project_owner,
]
results = helper_test_http_method(client, 'get', public_url, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url1, None, users)
assert results == [401, 403, 403, 200, 200]
results = helper_test_http_method(client, 'get', private_url2, None, users)
assert results == [401, 403, 403, 200, 200]

View File

@ -17,6 +17,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest import pytest
import datetime
from unittest.mock import patch from unittest.mock import patch
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -235,3 +237,84 @@ def test_delete_comment_by_project_owner(client):
url = "%s?id=%s" % (url, history_entry.id) url = "%s?id=%s" % (url, history_entry.id)
response = client.post(url, content_type="application/json") response = client.post(url, content_type="application/json")
assert 200 == response.status_code, response.status_code assert 200 == response.status_code, response.status_code
def test_edit_comment(client):
project = f.create_project()
us = f.create_userstory(project=project)
f.MembershipFactory.create(project=project, user=project.owner, is_admin=True)
key = make_key_from_model_object(us)
history_entry = f.HistoryEntryFactory.create(type=HistoryType.change,
comment="testing",
key=key,
diff={},
user={"pk": project.owner.id})
history_entry_created_at = history_entry.created_at
assert history_entry.comment_versions == None
assert history_entry.edit_comment_date == None
client.login(project.owner)
url = reverse("userstory-history-edit-comment", args=(us.id,))
url = "%s?id=%s" % (url, history_entry.id)
data = json.dumps({"comment": "testing update comment"})
response = client.post(url, data, content_type="application/json")
assert 200 == response.status_code, response.status_code
history_entry = HistoryEntry.objects.get(id=history_entry.id)
assert len(history_entry.comment_versions) == 1
assert history_entry.comment == "testing update comment"
assert history_entry.comment_versions[0]["comment"] == "testing"
assert history_entry.edit_comment_date != None
assert history_entry.comment_versions[0]["user"]["id"] == project.owner.id
def test_get_comment_versions(client):
project = f.create_project()
us = f.create_userstory(project=project)
f.MembershipFactory.create(project=project, user=project.owner, is_admin=True)
key = make_key_from_model_object(us)
history_entry = f.HistoryEntryFactory.create(
type=HistoryType.change,
comment="testing",
key=key,
diff={},
user={"pk": project.owner.id},
edit_comment_date=datetime.datetime.now(),
comment_versions = [{
"comment_html": "<p>test</p>",
"date": "2016-05-09T09:34:27.221Z",
"comment": "test",
"user": {
"id": project.owner.id,
}}])
client.login(project.owner)
url = reverse("userstory-history-comment-versions", args=(us.id,))
url = "%s?id=%s" % (url, history_entry.id)
response = client.get(url, content_type="application/json")
assert 200 == response.status_code, response.status_code
assert response.data[0]["user"]["username"] == project.owner.username
def test_get_comment_versions_from_history_entry_without_comment(client):
project = f.create_project()
us = f.create_userstory(project=project)
f.MembershipFactory.create(project=project, user=project.owner, is_admin=True)
key = make_key_from_model_object(us)
history_entry = f.HistoryEntryFactory.create(
type=HistoryType.change,
key=key,
diff={},
user={"pk": project.owner.id})
client.login(project.owner)
url = reverse("userstory-history-comment-versions", args=(us.id,))
url = "%s?id=%s" % (url, history_entry.id)
response = client.get(url, content_type="application/json")
assert 200 == response.status_code, response.status_code
assert response.data == None