Issue#2943: Regenerate refs for tasks, issues and user stories on project change

remotes/origin/enhancement/email-actions
Jesús Espino 2015-06-23 17:24:17 +02:00
parent 8167439828
commit aaf89ebb04
14 changed files with 575 additions and 47 deletions

View File

@ -31,7 +31,8 @@ from taiga.projects.notifications.mixins import WatchedResourceMixin
from taiga.projects.occ import OCCResourceMixin
from taiga.projects.history.mixins import HistoryResourceMixin
from taiga.projects.models import Project
from taiga.projects.models import Project, IssueStatus, Severity, Priority, IssueType
from taiga.projects.milestones.models import Milestone
from taiga.projects.votes.utils import attach_votescount_to_queryset
from taiga.projects.votes import services as votes_service
from taiga.projects.votes import serializers as votes_serializers
@ -121,6 +122,60 @@ class IssueViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
"assigned_to",
"subject")
def update(self, request, *args, **kwargs):
self.object = self.get_object_or_none()
project_id = request.DATA.get('project', None)
if project_id and self.object and self.object.project.id != project_id:
try:
new_project = Project.objects.get(pk=project_id)
self.check_permissions(request, "destroy", self.object)
self.check_permissions(request, "create", new_project)
sprint_id = request.DATA.get('milestone', None)
if sprint_id is not None and new_project.milestones.filter(pk=sprint_id).count() == 0:
request.DATA['milestone'] = None
status_id = request.DATA.get('status', None)
if status_id is not None:
try:
old_status = self.object.project.issue_statuses.get(pk=status_id)
new_status = new_project.issue_statuses.get(slug=old_status.slug)
request.DATA['status'] = new_status.id
except IssueStatus.DoesNotExist:
request.DATA['status'] = new_project.default_issue_status.id
priority_id = request.DATA.get('priority', None)
if priority_id is not None:
try:
old_priority = self.object.project.priorities.get(pk=priority_id)
new_priority = new_project.priorities.get(name=old_priority.name)
request.DATA['priority'] = new_priority.id
except Priority.DoesNotExist:
request.DATA['priority'] = new_project.default_priority.id
severity_id = request.DATA.get('severity', None)
if severity_id is not None:
try:
old_severity = self.object.project.severities.get(pk=severity_id)
new_severity = new_project.severities.get(name=old_severity.name)
request.DATA['severity'] = new_severity.id
except Severity.DoesNotExist:
request.DATA['severity'] = new_project.default_severity.id
type_id = request.DATA.get('type', None)
if type_id is not None:
try:
old_type = self.object.project.issue_types.get(pk=type_id)
new_type = new_project.issue_types.get(name=old_type.name)
request.DATA['type'] = new_type.id
except IssueType.DoesNotExist:
request.DATA['type'] = new_project.default_issue_type.id
except Project.DoesNotExist:
return response.BadRequest(_("The project doesn't exist"))
return super().update(request, *args, **kwargs)
def get_queryset(self):
qs = models.Issue.objects.all()
qs = qs.prefetch_related("attachments")
@ -130,6 +185,7 @@ class IssueViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
def pre_save(self, obj):
if not obj.id:
obj.owner = self.request.user
super().pre_save(obj)
def pre_conditions_on_save(self, obj):

View File

@ -80,8 +80,17 @@ def delete_sequence(sender, instance, **kwargs):
seq.delete(seqname)
def store_previous_project(sender, instance, **kwargs):
try:
prev_instance = sender.objects.get(pk=instance.pk)
instance.prev_project = prev_instance.project
except sender.DoesNotExist:
instance.prev_project = None
def attach_sequence(sender, instance, created, **kwargs):
if created and not instance._importing:
if not instance._importing:
if created or instance.prev_project != instance.project:
# Create a reference object. This operation should be
# used in transaction context, otherwise it can
# create a lot of phantom reference objects.
@ -93,6 +102,9 @@ def attach_sequence(sender, instance, created, **kwargs):
models.signals.post_save.connect(create_sequence, sender=Project, dispatch_uid="refproj")
models.signals.pre_save.connect(store_previous_project, sender=UserStory, dispatch_uid="refus")
models.signals.pre_save.connect(store_previous_project, sender=Issue, dispatch_uid="refissue")
models.signals.pre_save.connect(store_previous_project, sender=Task, dispatch_uid="reftask")
models.signals.post_save.connect(attach_sequence, sender=UserStory, dispatch_uid="refus")
models.signals.post_save.connect(attach_sequence, sender=Issue, dispatch_uid="refissue")
models.signals.post_save.connect(attach_sequence, sender=Task, dispatch_uid="reftask")

View File

@ -21,7 +21,7 @@ from taiga.base import filters, response
from taiga.base import exceptions as exc
from taiga.base.decorators import list_route
from taiga.base.api import ModelCrudViewSet
from taiga.projects.models import Project
from taiga.projects.models import Project, TaskStatus
from django.http import HttpResponse
from taiga.projects.notifications.mixins import WatchedResourceMixin
@ -44,6 +44,38 @@ class TaskViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
filter_fields = ["user_story", "milestone", "project", "assigned_to",
"status__is_closed", "watchers"]
def update(self, request, *args, **kwargs):
self.object = self.get_object_or_none()
project_id = request.DATA.get('project', None)
if project_id and self.object and self.object.project.id != project_id:
try:
new_project = Project.objects.get(pk=project_id)
self.check_permissions(request, "destroy", self.object)
self.check_permissions(request, "create", new_project)
sprint_id = request.DATA.get('milestone', None)
if sprint_id is not None and new_project.milestones.filter(pk=sprint_id).count() == 0:
request.DATA['milestone'] = None
us_id = request.DATA.get('user_story', None)
if us_id is not None and new_project.user_stories.filter(pk=us_id).count() == 0:
request.DATA['user_story'] = None
status_id = request.DATA.get('status', None)
if status_id is not None:
try:
old_status = self.object.project.task_statuses.get(pk=status_id)
new_status = new_project.task_statuses.get(slug=old_status.slug)
request.DATA['status'] = new_status.id
except TaskStatus.DoesNotExist:
request.DATA['status'] = new_project.default_task_status.id
except Project.DoesNotExist:
return response.BadRequest(_("The project doesn't exist"))
return super().update(request, *args, **kwargs)
def pre_save(self, obj):
if obj.user_story:
obj.milestone = obj.user_story.milestone
@ -55,16 +87,16 @@ class TaskViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMixin,
super().pre_conditions_on_save(obj)
if obj.milestone and obj.milestone.project != obj.project:
raise exc.WrongArguments(_("You don't have permissions for add/modify this task."))
raise exc.WrongArguments(_("You don't have permissions to set this sprint to this task."))
if obj.user_story and obj.user_story.project != obj.project:
raise exc.WrongArguments(_("You don't have permissions for add/modify this task."))
raise exc.WrongArguments(_("You don't have permissions to set this user story to this task."))
if obj.status and obj.status.project != obj.project:
raise exc.WrongArguments(_("You don't have permissions for add/modify this task."))
raise exc.WrongArguments(_("You don't have permissions to set this status to this task."))
if obj.milestone and obj.user_story and obj.milestone != obj.user_story.milestone:
raise exc.WrongArguments(_("You don't have permissions for add/modify this task."))
raise exc.WrongArguments(_("You don't have permissions to set this sprint to this task."))
@list_route(methods=["GET"])
def by_ref(self, request):

View File

@ -62,6 +62,33 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi
# Specific filter used for filtering neighbor user stories
_neighbor_tags_filter = filters.TagsFilter('neighbor_tags')
def update(self, request, *args, **kwargs):
self.object = self.get_object_or_none()
project_id = request.DATA.get('project', None)
if project_id and self.object and self.object.project.id != project_id:
try:
new_project = Project.objects.get(pk=project_id)
self.check_permissions(request, "destroy", self.object)
self.check_permissions(request, "create", new_project)
sprint_id = request.DATA.get('milestone', None)
if sprint_id is not None and new_project.milestones.filter(pk=sprint_id).count() == 0:
request.DATA['milestone'] = None
status_id = request.DATA.get('status', None)
if status_id is not None:
try:
old_status = self.object.project.us_statuses.get(pk=status_id)
new_status = new_project.us_statuses.get(slug=old_status.slug)
request.DATA['status'] = new_status.id
except UserStoryStatus.DoesNotExist:
request.DATA['status'] = new_project.default_us_status.id
except Project.DoesNotExist:
return response.BadRequest(_("The project doesn't exist"))
return super().update(request, *args, **kwargs)
def get_queryset(self):
qs = self.model.objects.all()
qs = qs.prefetch_related("role_points",
@ -100,6 +127,17 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi
super().post_save(obj, created)
def pre_conditions_on_save(self, obj):
super().pre_conditions_on_save(obj)
if obj.milestone and obj.milestone.project != obj.project:
raise exc.PermissionDenied(_("You don't have permissions to set this sprint "
"to this user story."))
if obj.status and obj.status.project != obj.project:
raise exc.PermissionDenied(_("You don't have permissions to set this status "
"to this user story."))
@list_route(methods=["GET"])
def by_ref(self, request):
ref = request.QUERY_PARAMS.get("ref", None)

View File

@ -231,6 +231,7 @@ class UserStoryFactory(Factory):
subject = factory.Sequence(lambda n: "User Story {}".format(n))
description = factory.Sequence(lambda n: "User Story {} description".format(n))
status = factory.SubFactory("tests.factories.UserStoryStatusFactory")
milestone = factory.SubFactory("tests.factories.MilestoneFactory")
class UserStoryStatusFactory(Factory):

View File

@ -160,6 +160,119 @@ def test_issue_update(client, data):
assert results == [401, 403, 403, 200, 200]
def test_issue_update_with_project_change(client):
user1 = f.UserFactory.create()
user2 = f.UserFactory.create()
user3 = f.UserFactory.create()
user4 = f.UserFactory.create()
project1 = f.ProjectFactory()
project2 = f.ProjectFactory()
issue_status1 = f.IssueStatusFactory.create(project=project1)
issue_status2 = f.IssueStatusFactory.create(project=project2)
priority1 = f.PriorityFactory.create(project=project1)
priority2 = f.PriorityFactory.create(project=project2)
severity1 = f.SeverityFactory.create(project=project1)
severity2 = f.SeverityFactory.create(project=project2)
issue_type1 = f.IssueTypeFactory.create(project=project1)
issue_type2 = f.IssueTypeFactory.create(project=project2)
project1.default_issue_status = issue_status1
project2.default_issue_status = issue_status2
project1.default_priority = priority1
project2.default_priority = priority2
project1.default_severity = severity1
project2.default_severity = severity2
project1.default_issue_type = issue_type1
project2.default_issue_type = issue_type2
project1.save()
project2.save()
membership1 = f.MembershipFactory(project=project1,
user=user1,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership2 = f.MembershipFactory(project=project2,
user=user1,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership3 = f.MembershipFactory(project=project1,
user=user2,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership4 = f.MembershipFactory(project=project2,
user=user3,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
issue = f.IssueFactory.create(project=project1)
url = reverse('issues-detail', kwargs={"pk": issue.pk})
# Test user with permissions in both projects
client.login(user1)
issue_data = IssueSerializer(issue).data
issue_data["project"] = project2.id
issue_data = json.dumps(issue_data)
response = client.put(url, data=issue_data, content_type="application/json")
assert response.status_code == 200
issue.project = project1
issue.save()
# Test user with permissions in only origin project
client.login(user2)
issue_data = IssueSerializer(issue).data
issue_data["project"] = project2.id
issue_data = json.dumps(issue_data)
response = client.put(url, data=issue_data, content_type="application/json")
assert response.status_code == 403
issue.project = project1
issue.save()
# Test user with permissions in only destionation project
client.login(user3)
issue_data = IssueSerializer(issue).data
issue_data["project"] = project2.id
issue_data = json.dumps(issue_data)
response = client.put(url, data=issue_data, content_type="application/json")
assert response.status_code == 403
issue.project = project1
issue.save()
# Test user without permissions in the projects
client.login(user4)
issue_data = IssueSerializer(issue).data
issue_data["project"] = project2.id
issue_data = json.dumps(issue_data)
response = client.put(url, data=issue_data, content_type="application/json")
assert response.status_code == 403
issue.project = project1
issue.save()
def test_issue_delete(client, data):
public_url = reverse('issues-detail', kwargs={"pk": data.public_issue.pk})
private_url1 = reverse('issues-detail', kwargs={"pk": data.private_issue1.pk})

View File

@ -83,18 +83,25 @@ def data():
user=m.project_owner,
is_owner=True)
milestone_public_task = f.MilestoneFactory(project=m.public_project)
milestone_private_task1 = f.MilestoneFactory(project=m.private_project1)
milestone_private_task2 = f.MilestoneFactory(project=m.private_project2)
m.public_task = f.TaskFactory(project=m.public_project,
status__project=m.public_project,
milestone__project=m.public_project,
user_story__project=m.public_project)
milestone=milestone_public_task,
user_story__project=m.public_project,
user_story__milestone=milestone_public_task)
m.private_task1 = f.TaskFactory(project=m.private_project1,
status__project=m.private_project1,
milestone__project=m.private_project1,
user_story__project=m.private_project1)
milestone=milestone_private_task1,
user_story__project=m.private_project1,
user_story__milestone=milestone_private_task1)
m.private_task2 = f.TaskFactory(project=m.private_project2,
status__project=m.private_project2,
milestone__project=m.private_project2,
user_story__project=m.private_project2)
milestone=milestone_private_task2,
user_story__project=m.private_project2,
user_story__milestone=milestone_private_task2)
m.public_project.default_task_status = m.public_task.status
m.public_project.save()
@ -160,6 +167,101 @@ def test_task_update(client, data):
assert results == [401, 403, 403, 200, 200]
def test_task_update_with_project_change(client):
user1 = f.UserFactory.create()
user2 = f.UserFactory.create()
user3 = f.UserFactory.create()
user4 = f.UserFactory.create()
project1 = f.ProjectFactory()
project2 = f.ProjectFactory()
task_status1 = f.TaskStatusFactory.create(project=project1)
task_status2 = f.TaskStatusFactory.create(project=project2)
project1.default_task_status = task_status1
project2.default_task_status = task_status2
project1.save()
project2.save()
membership1 = f.MembershipFactory(project=project1,
user=user1,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership2 = f.MembershipFactory(project=project2,
user=user1,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership3 = f.MembershipFactory(project=project1,
user=user2,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership4 = f.MembershipFactory(project=project2,
user=user3,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
task = f.TaskFactory.create(project=project1)
url = reverse('tasks-detail', kwargs={"pk": task.pk})
# Test user with permissions in both projects
client.login(user1)
task_data = TaskSerializer(task).data
task_data["project"] = project2.id
task_data = json.dumps(task_data)
response = client.put(url, data=task_data, content_type="application/json")
assert response.status_code == 200
task.project = project1
task.save()
# Test user with permissions in only origin project
client.login(user2)
task_data = TaskSerializer(task).data
task_data["project"] = project2.id
task_data = json.dumps(task_data)
response = client.put(url, data=task_data, content_type="application/json")
assert response.status_code == 403
task.project = project1
task.save()
# Test user with permissions in only destionation project
client.login(user3)
task_data = TaskSerializer(task).data
task_data["project"] = project2.id
task_data = json.dumps(task_data)
response = client.put(url, data=task_data, content_type="application/json")
assert response.status_code == 403
task.project = project1
task.save()
# Test user without permissions in the projects
client.login(user4)
task_data = TaskSerializer(task).data
task_data["project"] = project2.id
task_data = json.dumps(task_data)
response = client.put(url, data=task_data, content_type="application/json")
assert response.status_code == 403
task.project = project1
task.save()
def test_task_delete(client, data):
public_url = reverse('tasks-detail', kwargs={"pk": data.public_task.pk})
private_url1 = reverse('tasks-detail', kwargs={"pk": data.private_task1.pk})

View File

@ -89,13 +89,19 @@ def data():
m.public_role_points = f.RolePointsFactory(role=m.public_project.roles.all()[0],
points=m.public_points,
user_story__project=m.public_project)
user_story__project=m.public_project,
user_story__milestone__project=m.public_project,
user_story__status__project=m.public_project)
m.private_role_points1 = f.RolePointsFactory(role=m.private_project1.roles.all()[0],
points=m.private_points1,
user_story__project=m.private_project1)
user_story__project=m.private_project1,
user_story__milestone__project=m.private_project1,
user_story__status__project=m.private_project1)
m.private_role_points2 = f.RolePointsFactory(role=m.private_project2.roles.all()[0],
points=m.private_points2,
user_story__project=m.private_project2)
user_story__project=m.private_project2,
user_story__milestone__project=m.private_project2,
user_story__status__project=m.private_project2)
m.public_user_story = m.public_role_points.user_story
m.private_user_story1 = m.private_role_points1.user_story
@ -158,6 +164,101 @@ def test_user_story_update(client, data):
assert results == [401, 403, 403, 200, 200]
def test_user_story_update_with_project_change(client):
user1 = f.UserFactory.create()
user2 = f.UserFactory.create()
user3 = f.UserFactory.create()
user4 = f.UserFactory.create()
project1 = f.ProjectFactory()
project2 = f.ProjectFactory()
us_status1 = f.UserStoryStatusFactory.create(project=project1)
us_status2 = f.UserStoryStatusFactory.create(project=project2)
project1.default_us_status = us_status1
project2.default_us_status = us_status2
project1.save()
project2.save()
membership1 = f.MembershipFactory(project=project1,
user=user1,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership2 = f.MembershipFactory(project=project2,
user=user1,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership3 = f.MembershipFactory(project=project1,
user=user2,
role__project=project1,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
membership4 = f.MembershipFactory(project=project2,
user=user3,
role__project=project2,
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
us = f.UserStoryFactory.create(project=project1)
url = reverse('userstories-detail', kwargs={"pk": us.pk})
# Test user with permissions in both projects
client.login(user1)
us_data = UserStorySerializer(us).data
us_data["project"] = project2.id
us_data = json.dumps(us_data)
response = client.put(url, data=us_data, content_type="application/json")
assert response.status_code == 200
us.project = project1
us.save()
# Test user with permissions in only origin project
client.login(user2)
us_data = UserStorySerializer(us).data
us_data["project"] = project2.id
us_data = json.dumps(us_data)
response = client.put(url, data=us_data, content_type="application/json")
assert response.status_code == 403
us.project = project1
us.save()
# Test user with permissions in only destionation project
client.login(user3)
us_data = UserStorySerializer(us).data
us_data["project"] = project2.id
us_data = json.dumps(us_data)
response = client.put(url, data=us_data, content_type="application/json")
assert response.status_code == 403
us.project = project1
us.save()
# Test user without permissions in the projects
client.login(user4)
us_data = UserStorySerializer(us).data
us_data["project"] = project2.id
us_data = json.dumps(us_data)
response = client.put(url, data=us_data, content_type="application/json")
assert response.status_code == 403
us.project = project1
us.save()
def test_user_story_delete(client, data):
public_url = reverse('userstories-detail', kwargs={"pk": data.public_user_story.pk})
private_url1 = reverse('userstories-detail', kwargs={"pk": data.private_user_story1.pk})

View File

@ -199,7 +199,7 @@ def test_take_hidden_snapshot():
def test_history_with_only_comment_shouldnot_be_hidden(client):
project = f.create_project()
us = f.create_userstory(project=project)
us = f.create_userstory(project=project, status__project=project)
f.MembershipFactory.create(project=project, user=project.owner, is_owner=True)
qs_all = HistoryEntry.objects.all()
@ -213,7 +213,7 @@ def test_history_with_only_comment_shouldnot_be_hidden(client):
client.login(project.owner)
response = client.patch(url, data, content_type="application/json")
assert response.status_code == 200, response.content
assert response.status_code == 200, str(response.content)
assert qs_all.count() == 1
assert qs_hidden.count() == 0

View File

@ -32,6 +32,7 @@ from taiga.projects.history.services import take_snapshot
from taiga.projects.issues.serializers import IssueSerializer
from taiga.projects.userstories.serializers import UserStorySerializer
from taiga.projects.tasks.serializers import TaskSerializer
from taiga.permissions.permissions import MEMBERS_PERMISSIONS
pytestmark = pytest.mark.django_db
@ -317,7 +318,7 @@ def test_watchers_assignation_for_issue(client):
url = reverse("issues-detail", args=[issue.pk])
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200, response.content
assert response.status_code == 200, str(response.content)
issue = f.create_issue(project=project1, owner=user1)
data = {"version": issue.version,
@ -356,22 +357,22 @@ def test_watchers_assignation_for_task(client):
user2 = f.UserFactory.create()
project1 = f.ProjectFactory.create(owner=user1)
project2 = f.ProjectFactory.create(owner=user2)
role1 = f.RoleFactory.create(project=project1)
role1 = f.RoleFactory.create(project=project1, permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
role2 = f.RoleFactory.create(project=project2)
f.MembershipFactory.create(project=project1, user=user1, role=role1, is_owner=True)
f.MembershipFactory.create(project=project2, user=user2, role=role2)
client.login(user1)
task = f.create_task(project=project1, owner=user1)
task = f.create_task(project=project1, owner=user1, status__project=project1, milestone__project=project1, user_story=None)
data = {"version": task.version,
"watchers": [user1.pk]}
url = reverse("tasks-detail", args=[task.pk])
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200, response.content
assert response.status_code == 200, str(response.content)
task = f.create_task(project=project1, owner=user1)
task = f.create_task(project=project1, owner=user1, status__project=project1, milestone__project=project1)
data = {"version": task.version,
"watchers": [user1.pk, user2.pk]}
@ -379,7 +380,7 @@ def test_watchers_assignation_for_task(client):
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400
task = f.create_task(project=project1, owner=user1)
task = f.create_task(project=project1, owner=user1, status__project=project1, milestone__project=project1)
data = dict(TaskSerializer(task).data)
data["id"] = None
data["version"] = None
@ -391,7 +392,7 @@ def test_watchers_assignation_for_task(client):
# Test the impossible case when project is not
# exists in create request, and validator works as expected
task = f.create_task(project=project1, owner=user1)
task = f.create_task(project=project1, owner=user1, status__project=project1, milestone__project=project1)
data = dict(TaskSerializer(task).data)
data["id"] = None
@ -415,15 +416,15 @@ def test_watchers_assignation_for_us(client):
client.login(user1)
us = f.create_userstory(project=project1, owner=user1)
us = f.create_userstory(project=project1, owner=user1, status__project=project1)
data = {"version": us.version,
"watchers": [user1.pk]}
url = reverse("userstories-detail", args=[us.pk])
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200
assert response.status_code == 200, str(response.content)
us = f.create_userstory(project=project1, owner=user1)
us = f.create_userstory(project=project1, owner=user1, status__project=project1)
data = {"version": us.version,
"watchers": [user1.pk, user2.pk]}
@ -431,7 +432,7 @@ def test_watchers_assignation_for_us(client):
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400
us = f.create_userstory(project=project1, owner=user1)
us = f.create_userstory(project=project1, owner=user1, status__project=project1)
data = dict(UserStorySerializer(us).data)
data["id"] = None
data["version"] = None
@ -443,7 +444,7 @@ def test_watchers_assignation_for_us(client):
# Test the impossible case when project is not
# exists in create request, and validator works as expected
us = f.create_userstory(project=project1, owner=user1)
us = f.create_userstory(project=project1, owner=user1, status__project=project1)
data = dict(UserStorySerializer(us).data)
data["id"] = None
@ -463,4 +464,4 @@ def test_retrieve_notify_policies_by_anonymous_user(client):
url = reverse("notifications-detail", args=[policy.pk])
response = client.get(url, content_type="application/json")
assert response.status_code == 404, response.status_code
assert response.data["_error_message"] == "No NotifyPolicy matches the given query.", response.content
assert response.data["_error_message"] == "No NotifyPolicy matches the given query.", str(response.content)

View File

@ -74,3 +74,70 @@ def test_unique_reference_per_project(seq, refmodels):
project.delete()
assert not seq.exists(seqname)
@pytest.mark.django_db
def test_regenerate_us_reference_on_project_change(seq, refmodels):
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
seqname2 = refmodels.make_sequence_name(project2)
seq.alter(seqname1, 100)
seq.alter(seqname2, 200)
user_story = factories.UserStoryFactory.create(project=project1)
assert user_story.ref == 101
user_story.subject = "other"
user_story.save()
assert user_story.ref == 101
user_story.project = project2
user_story.save()
assert user_story.ref == 201
@pytest.mark.django_db
def test_regenerate_task_reference_on_project_change(seq, refmodels):
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
seqname2 = refmodels.make_sequence_name(project2)
seq.alter(seqname1, 100)
seq.alter(seqname2, 200)
task = factories.TaskFactory.create(project=project1)
assert task.ref == 101
task.subject = "other"
task.save()
assert task.ref == 101
task.project = project2
task.save()
assert task.ref == 201
@pytest.mark.django_db
def test_regenerate_issue_reference_on_project_change(seq, refmodels):
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
seqname2 = refmodels.make_sequence_name(project2)
seq.alter(seqname1, 100)
seq.alter(seqname2, 200)
issue = factories.IssueFactory.create(project=project1)
assert issue.ref == 101
issue.subject = "other"
issue.save()
assert issue.ref == 101
issue.project = project2
issue.save()
assert issue.ref == 201

View File

@ -37,19 +37,23 @@ def data():
m.role_points1 = f.RolePointsFactory(role=m.role1,
points=m.points1,
user_story__project=m.project,
user_story__status=m.open_status)
user_story__status=m.open_status,
user_story__milestone=None)
m.role_points2 = f.RolePointsFactory(role=m.role1,
points=m.points2,
user_story__project=m.project,
user_story__status=m.open_status)
user_story__status=m.open_status,
user_story__milestone=None)
m.role_points3 = f.RolePointsFactory(role=m.role1,
points=m.points3,
user_story__project=m.project,
user_story__status=m.open_status)
user_story__status=m.open_status,
user_story__milestone=None)
m.role_points4 = f.RolePointsFactory(role=m.project.roles.all()[0],
points=m.points4,
user_story__project=m.project,
user_story__status=m.open_status)
user_story__status=m.open_status,
user_story__milestone=None)
m.user_story1 = m.role_points1.user_story
m.user_story2 = m.role_points2.user_story

View File

@ -54,8 +54,9 @@ def test_create_task_without_status(client):
def test_api_update_task_tags(client):
task = f.create_task()
f.MembershipFactory.create(project=task.project, user=task.owner, is_owner=True)
project = f.ProjectFactory.create()
task = f.create_task(project=project, status__project=project, milestone=None, user_story=None)
f.MembershipFactory.create(project=project, user=task.owner, is_owner=True)
url = reverse("tasks-detail", kwargs={"pk": task.pk})
data = {"tags": ["back", "front"], "version": task.version}

View File

@ -152,7 +152,7 @@ def test_update_userstory_points(client):
f.PointsFactory.create(project=project, value=1)
points3 = f.PointsFactory.create(project=project, value=2)
us = f.UserStoryFactory.create(project=project, owner=user1)
us = f.UserStoryFactory.create(project=project, owner=user1, status__project=project, milestone__project=project)
usdata = UserStorySerializer(us).data
url = reverse("userstories-detail", args=[us.pk])
@ -166,7 +166,7 @@ def test_update_userstory_points(client):
data["points"].update({'2000': points3.pk})
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200
assert response.status_code == 200, str(response.content)
assert response.data["points"] == usdata['points']
# Api should save successful