US #55: Custom fields - Import/Export custom attributes values
parent
32ff494ddd
commit
56b9fe42e3
|
@ -333,6 +333,93 @@ class IssueCustomAttributeExportSerializer(serializers.ModelSerializer):
|
||||||
exclude = ('id', 'project')
|
exclude = ('id', 'project')
|
||||||
|
|
||||||
|
|
||||||
|
class CustomAttributesValuesExportSerializerMixin:
|
||||||
|
custom_attributes_values = serializers.SerializerMethodField("get_custom_attributes_values")
|
||||||
|
|
||||||
|
def custom_attributes_queryset(self, project):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_custom_attributes_values(self, obj):
|
||||||
|
def _use_name_instead_id_as_key_in_custom_attributes_values(custom_attributes, values):
|
||||||
|
ret = {}
|
||||||
|
for attr in custom_attributes:
|
||||||
|
value = values.get(str(attr["id"]), None)
|
||||||
|
if value is not None:
|
||||||
|
ret[attr["name"]] = value
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
try:
|
||||||
|
values = obj.custom_attributes_values.values
|
||||||
|
custom_attributes = self.custom_attribute_queryset(obj.project).values('id', 'name')
|
||||||
|
|
||||||
|
return _use_name_instead_id_as_key_in_custom_attributes_values(custom_attributes, values)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class BaseCustomAttributesValuesExportSerializer:
|
||||||
|
values = JsonField(source="values", label="values", required=True)
|
||||||
|
_custom_attribute_model = None
|
||||||
|
_container_field = None
|
||||||
|
|
||||||
|
def validate_values(self, attrs, source):
|
||||||
|
# values must be a dict
|
||||||
|
data_values = attrs.get("values", None)
|
||||||
|
if self.object:
|
||||||
|
data_values = (data_values or self.object.values)
|
||||||
|
|
||||||
|
if type(data_values) is not dict:
|
||||||
|
raise ValidationError(_("Invalid content. It must be {\"key\": \"value\",...}"))
|
||||||
|
|
||||||
|
# Values keys must be in the container object project
|
||||||
|
data_container = attrs.get(self._container_field, None)
|
||||||
|
if data_container:
|
||||||
|
project_id = data_container.project_id
|
||||||
|
elif self.object:
|
||||||
|
project_id = getattr(self.object, self._container_field).project_id
|
||||||
|
else:
|
||||||
|
project_id = None
|
||||||
|
|
||||||
|
values_ids = list(data_values.keys())
|
||||||
|
qs = self._custom_attribute_model.objects.filter(project=project_id,
|
||||||
|
id__in=values_ids)
|
||||||
|
if qs.count() != len(values_ids):
|
||||||
|
raise ValidationError(_("It contain invalid custom fields."))
|
||||||
|
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
class UserStoryCustomAttributesValuesExportSerializer(BaseCustomAttributesValuesExportSerializer,
|
||||||
|
serializers.ModelSerializer):
|
||||||
|
_custom_attribute_model = custom_attributes_models.UserStoryCustomAttribute
|
||||||
|
_container_model = "userstories.UserStory"
|
||||||
|
_container_field = "user_story"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = custom_attributes_models.UserStoryCustomAttributesValues
|
||||||
|
exclude = ("id",)
|
||||||
|
|
||||||
|
|
||||||
|
class TaskCustomAttributesValuesExportSerializer(BaseCustomAttributesValuesExportSerializer,
|
||||||
|
serializers.ModelSerializer):
|
||||||
|
_custom_attribute_model = custom_attributes_models.TaskCustomAttribute
|
||||||
|
_container_field = "task"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = custom_attributes_models.TaskCustomAttributesValues
|
||||||
|
exclude = ("id",)
|
||||||
|
|
||||||
|
|
||||||
|
class IssueCustomAttributesValuesExportSerializer(BaseCustomAttributesValuesExportSerializer,
|
||||||
|
serializers.ModelSerializer):
|
||||||
|
_custom_attribute_model = custom_attributes_models.IssueCustomAttribute
|
||||||
|
_container_field = "issue"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = custom_attributes_models.IssueCustomAttributesValues
|
||||||
|
exclude = ("id",)
|
||||||
|
|
||||||
|
|
||||||
class MembershipExportSerializer(serializers.ModelSerializer):
|
class MembershipExportSerializer(serializers.ModelSerializer):
|
||||||
user = UserRelatedField(required=False)
|
user = UserRelatedField(required=False)
|
||||||
role = ProjectRelatedField(slug_field="name")
|
role = ProjectRelatedField(slug_field="name")
|
||||||
|
@ -382,8 +469,8 @@ class MilestoneExportSerializer(serializers.ModelSerializer):
|
||||||
exclude = ('id', 'project')
|
exclude = ('id', 'project')
|
||||||
|
|
||||||
|
|
||||||
class TaskExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerializerMixin,
|
class TaskExportSerializer(CustomAttributesValuesExportSerializerMixin, HistoryExportSerializerMixin,
|
||||||
serializers.ModelSerializer):
|
AttachmentExportSerializerMixin, serializers.ModelSerializer):
|
||||||
owner = UserRelatedField(required=False)
|
owner = UserRelatedField(required=False)
|
||||||
status = ProjectRelatedField(slug_field="name")
|
status = ProjectRelatedField(slug_field="name")
|
||||||
user_story = ProjectRelatedField(slug_field="ref", required=False)
|
user_story = ProjectRelatedField(slug_field="ref", required=False)
|
||||||
|
@ -396,9 +483,12 @@ class TaskExportSerializer(HistoryExportSerializerMixin, AttachmentExportSeriali
|
||||||
model = tasks_models.Task
|
model = tasks_models.Task
|
||||||
exclude = ('id', 'project')
|
exclude = ('id', 'project')
|
||||||
|
|
||||||
|
def custom_attributes_queryset(self, project):
|
||||||
|
return project.taskcustomattributes.all()
|
||||||
|
|
||||||
class UserStoryExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerializerMixin,
|
|
||||||
serializers.ModelSerializer):
|
class UserStoryExportSerializer(CustomAttributesValuesExportSerializerMixin, HistoryExportSerializerMixin,
|
||||||
|
AttachmentExportSerializerMixin, serializers.ModelSerializer):
|
||||||
role_points = RolePointsExportSerializer(many=True, required=False)
|
role_points = RolePointsExportSerializer(many=True, required=False)
|
||||||
owner = UserRelatedField(required=False)
|
owner = UserRelatedField(required=False)
|
||||||
assigned_to = UserRelatedField(required=False)
|
assigned_to = UserRelatedField(required=False)
|
||||||
|
@ -412,9 +502,12 @@ class UserStoryExportSerializer(HistoryExportSerializerMixin, AttachmentExportSe
|
||||||
model = userstories_models.UserStory
|
model = userstories_models.UserStory
|
||||||
exclude = ('id', 'project', 'points', 'tasks')
|
exclude = ('id', 'project', 'points', 'tasks')
|
||||||
|
|
||||||
|
def custom_attributes_queryset(self, project):
|
||||||
|
return project.userstorycustomattributes.all()
|
||||||
|
|
||||||
class IssueExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerializerMixin,
|
|
||||||
serializers.ModelSerializer):
|
class IssueExportSerializer(CustomAttributesValuesExportSerializerMixin, HistoryExportSerializerMixin,
|
||||||
|
AttachmentExportSerializerMixin, serializers.ModelSerializer):
|
||||||
owner = UserRelatedField(required=False)
|
owner = UserRelatedField(required=False)
|
||||||
status = ProjectRelatedField(slug_field="name")
|
status = ProjectRelatedField(slug_field="name")
|
||||||
assigned_to = UserRelatedField(required=False)
|
assigned_to = UserRelatedField(required=False)
|
||||||
|
@ -426,13 +519,16 @@ class IssueExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerial
|
||||||
votes = serializers.SerializerMethodField("get_votes")
|
votes = serializers.SerializerMethodField("get_votes")
|
||||||
modified_date = serializers.DateTimeField(required=False)
|
modified_date = serializers.DateTimeField(required=False)
|
||||||
|
|
||||||
def get_votes(self, obj):
|
|
||||||
return [x.email for x in votes_service.get_voters(obj)]
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = issues_models.Issue
|
model = issues_models.Issue
|
||||||
exclude = ('id', 'project')
|
exclude = ('id', 'project')
|
||||||
|
|
||||||
|
def get_votes(self, obj):
|
||||||
|
return [x.email for x in votes_service.get_voters(obj)]
|
||||||
|
|
||||||
|
def custom_attributes_queryset(self, project):
|
||||||
|
return project.issuecustomattributes.all()
|
||||||
|
|
||||||
|
|
||||||
class WikiPageExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerializerMixin,
|
class WikiPageExportSerializer(HistoryExportSerializerMixin, AttachmentExportSerializerMixin,
|
||||||
serializers.ModelSerializer):
|
serializers.ModelSerializer):
|
||||||
|
|
|
@ -108,6 +108,30 @@ def store_custom_attributes(project, data, field, serializer):
|
||||||
result.append(_store_custom_attribute(project, custom_attribute_data, field, serializer))
|
result.append(_store_custom_attribute(project, custom_attribute_data, field, serializer))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def store_custom_attributes_values(obj, data_values, obj_field, serializer_class):
|
||||||
|
data = {
|
||||||
|
obj_field: obj.id,
|
||||||
|
"values": data_values,
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer = serializer_class(data=data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return serializer
|
||||||
|
|
||||||
|
add_errors("custom_attributes_values", serializer.errors)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _use_id_instead_name_as_key_in_custom_attributes_values(custom_attributes, values):
|
||||||
|
ret = {}
|
||||||
|
for attr in custom_attributes:
|
||||||
|
value = values.get(attr["name"], None)
|
||||||
|
if value is not None:
|
||||||
|
ret[str(attr["id"])] = value
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def store_role(project, role):
|
def store_role(project, role):
|
||||||
serialized = serializers.RoleExportSerializer(data=role)
|
serialized = serializers.RoleExportSerializer(data=role)
|
||||||
|
@ -122,7 +146,7 @@ def store_role(project, role):
|
||||||
|
|
||||||
def store_roles(project, data):
|
def store_roles(project, data):
|
||||||
results = []
|
results = []
|
||||||
for role in data.get('roles', []):
|
for role in data.get("roles", []):
|
||||||
results.append(store_role(project, role))
|
results.append(store_role(project, role))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@ -164,16 +188,16 @@ def store_membership(project, membership):
|
||||||
|
|
||||||
def store_memberships(project, data):
|
def store_memberships(project, data):
|
||||||
results = []
|
results = []
|
||||||
for membership in data.get('memberships', []):
|
for membership in data.get("memberships", []):
|
||||||
results.append(store_membership(project, membership))
|
results.append(store_membership(project, membership))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def store_task(project, task):
|
def store_task(project, data):
|
||||||
if 'status' not in task and project.default_task_status:
|
if "status" not in data and project.default_task_status:
|
||||||
task['status'] = project.default_task_status.name
|
data["status"] = project.default_task_status.name
|
||||||
|
|
||||||
serialized = serializers.TaskExportSerializer(data=task, context={"project": project})
|
serialized = serializers.TaskExportSerializer(data=data, context={"project": project})
|
||||||
if serialized.is_valid():
|
if serialized.is_valid():
|
||||||
serialized.object.project = project
|
serialized.object.project = project
|
||||||
if serialized.object.owner is None:
|
if serialized.object.owner is None:
|
||||||
|
@ -192,12 +216,20 @@ def store_task(project, task):
|
||||||
serialized.object.ref, _ = refs.make_reference(serialized.object, project)
|
serialized.object.ref, _ = refs.make_reference(serialized.object, project)
|
||||||
serialized.object.save()
|
serialized.object.save()
|
||||||
|
|
||||||
for task_attachment in task.get('attachments', []):
|
for task_attachment in data.get("attachments", []):
|
||||||
store_attachment(project, serialized.object, task_attachment)
|
store_attachment(project, serialized.object, task_attachment)
|
||||||
|
|
||||||
for history in task.get('history', []):
|
for history in data.get("history", []):
|
||||||
store_history(project, serialized.object, history)
|
store_history(project, serialized.object, history)
|
||||||
|
|
||||||
|
custom_attributes_values = data.get("custom_attributes_values", None)
|
||||||
|
if custom_attributes_values:
|
||||||
|
custom_attributes = serialized.object.project.taskcustomattributes.all().values('id', 'name')
|
||||||
|
custom_attributes_values = _use_id_instead_name_as_key_in_custom_attributes_values(custom_attributes,
|
||||||
|
custom_attributes_values)
|
||||||
|
store_custom_attributes_values(serialized.object, custom_attributes_values,
|
||||||
|
"task", serializers.TaskCustomAttributesValuesExportSerializer)
|
||||||
|
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
add_errors("tasks", serialized.errors)
|
add_errors("tasks", serialized.errors)
|
||||||
|
@ -211,8 +243,8 @@ def store_milestone(project, milestone):
|
||||||
serialized.object._importing = True
|
serialized.object._importing = True
|
||||||
serialized.save()
|
serialized.save()
|
||||||
|
|
||||||
for task_without_us in milestone.get('tasks_without_us', []):
|
for task_without_us in milestone.get("tasks_without_us", []):
|
||||||
task_without_us['user_story'] = None
|
task_without_us["user_story"] = None
|
||||||
store_task(project, task_without_us)
|
store_task(project, task_without_us)
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
|
@ -251,7 +283,7 @@ def store_history(project, obj, history):
|
||||||
|
|
||||||
|
|
||||||
def store_wiki_page(project, wiki_page):
|
def store_wiki_page(project, wiki_page):
|
||||||
wiki_page['slug'] = slugify(unidecode(wiki_page.get('slug', '')))
|
wiki_page["slug"] = slugify(unidecode(wiki_page.get("slug", "")))
|
||||||
serialized = serializers.WikiPageExportSerializer(data=wiki_page)
|
serialized = serializers.WikiPageExportSerializer(data=wiki_page)
|
||||||
if serialized.is_valid():
|
if serialized.is_valid():
|
||||||
serialized.object.project = project
|
serialized.object.project = project
|
||||||
|
@ -261,10 +293,10 @@ def store_wiki_page(project, wiki_page):
|
||||||
serialized.object._not_notify = True
|
serialized.object._not_notify = True
|
||||||
serialized.save()
|
serialized.save()
|
||||||
|
|
||||||
for attachment in wiki_page.get('attachments', []):
|
for attachment in wiki_page.get("attachments", []):
|
||||||
store_attachment(project, serialized.object, attachment)
|
store_attachment(project, serialized.object, attachment)
|
||||||
|
|
||||||
for history in wiki_page.get('history', []):
|
for history in wiki_page.get("history", []):
|
||||||
store_history(project, serialized.object, history)
|
store_history(project, serialized.object, history)
|
||||||
|
|
||||||
return serialized
|
return serialized
|
||||||
|
@ -295,61 +327,12 @@ def store_role_point(project, us, role_point):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def store_user_story(project, userstory):
|
def store_user_story(project, data):
|
||||||
if 'status' not in userstory and project.default_us_status:
|
if "status" not in data and project.default_us_status:
|
||||||
userstory['status'] = project.default_us_status.name
|
data["status"] = project.default_us_status.name
|
||||||
|
|
||||||
userstory_data = {}
|
data_data = {key: value for key, value in data.items() if key not in ["role_points", "custom_attributes_values"]}
|
||||||
for key, value in userstory.items():
|
serialized = serializers.UserStoryExportSerializer(data=data_data, context={"project": project})
|
||||||
if key != 'role_points':
|
|
||||||
userstory_data[key] = value
|
|
||||||
serialized_us = serializers.UserStoryExportSerializer(data=userstory_data, context={"project": project})
|
|
||||||
if serialized_us.is_valid():
|
|
||||||
serialized_us.object.project = project
|
|
||||||
if serialized_us.object.owner is None:
|
|
||||||
serialized_us.object.owner = serialized_us.object.project.owner
|
|
||||||
serialized_us.object._importing = True
|
|
||||||
serialized_us.object._not_notify = True
|
|
||||||
|
|
||||||
serialized_us.save()
|
|
||||||
|
|
||||||
if serialized_us.object.ref:
|
|
||||||
sequence_name = refs.make_sequence_name(project)
|
|
||||||
if not seq.exists(sequence_name):
|
|
||||||
seq.create(sequence_name)
|
|
||||||
seq.set_max(sequence_name, serialized_us.object.ref)
|
|
||||||
else:
|
|
||||||
serialized_us.object.ref, _ = refs.make_reference(serialized_us.object, project)
|
|
||||||
serialized_us.object.save()
|
|
||||||
|
|
||||||
for us_attachment in userstory.get('attachments', []):
|
|
||||||
store_attachment(project, serialized_us.object, us_attachment)
|
|
||||||
|
|
||||||
for role_point in userstory.get('role_points', []):
|
|
||||||
store_role_point(project, serialized_us.object, role_point)
|
|
||||||
|
|
||||||
for history in userstory.get('history', []):
|
|
||||||
store_history(project, serialized_us.object, history)
|
|
||||||
|
|
||||||
return serialized_us
|
|
||||||
add_errors("user_stories", serialized_us.errors)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def store_issue(project, data):
|
|
||||||
serialized = serializers.IssueExportSerializer(data=data, context={"project": project})
|
|
||||||
|
|
||||||
if 'type' not in data and project.default_issue_type:
|
|
||||||
data['type'] = project.default_issue_type.name
|
|
||||||
|
|
||||||
if 'status' not in data and project.default_issue_status:
|
|
||||||
data['status'] = project.default_issue_status.name
|
|
||||||
|
|
||||||
if 'priority' not in data and project.default_priority:
|
|
||||||
data['priority'] = project.default_priority.name
|
|
||||||
|
|
||||||
if 'severity' not in data and project.default_severity:
|
|
||||||
data['severity'] = project.default_severity.name
|
|
||||||
|
|
||||||
if serialized.is_valid():
|
if serialized.is_valid():
|
||||||
serialized.object.project = project
|
serialized.object.project = project
|
||||||
|
@ -369,10 +352,77 @@ def store_issue(project, data):
|
||||||
serialized.object.ref, _ = refs.make_reference(serialized.object, project)
|
serialized.object.ref, _ = refs.make_reference(serialized.object, project)
|
||||||
serialized.object.save()
|
serialized.object.save()
|
||||||
|
|
||||||
for attachment in data.get('attachments', []):
|
for us_attachment in data.get("attachments", []):
|
||||||
store_attachment(project, serialized.object, attachment)
|
store_attachment(project, serialized.object, us_attachment)
|
||||||
for history in data.get('history', []):
|
|
||||||
|
for role_point in data.get("role_points", []):
|
||||||
|
store_role_point(project, serialized.object, role_point)
|
||||||
|
|
||||||
|
for history in data.get("history", []):
|
||||||
store_history(project, serialized.object, history)
|
store_history(project, serialized.object, history)
|
||||||
|
|
||||||
|
custom_attributes_values = data.get("custom_attributes_values", None)
|
||||||
|
if custom_attributes_values:
|
||||||
|
custom_attributes = serialized.object.project.userstorycustomattributes.all().values('id', 'name')
|
||||||
|
custom_attributes_values = _use_id_instead_name_as_key_in_custom_attributes_values(custom_attributes,
|
||||||
|
custom_attributes_values)
|
||||||
|
store_custom_attributes_values(serialized.object, custom_attributes_values,
|
||||||
|
"user_story", serializers.UserStoryCustomAttributesValuesExportSerializer)
|
||||||
|
|
||||||
return serialized
|
return serialized
|
||||||
|
|
||||||
|
add_errors("user_stories", serialized.errors)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def store_issue(project, data):
|
||||||
|
serialized = serializers.IssueExportSerializer(data=data, context={"project": project})
|
||||||
|
|
||||||
|
if "type" not in data and project.default_issue_type:
|
||||||
|
data["type"] = project.default_issue_type.name
|
||||||
|
|
||||||
|
if "status" not in data and project.default_issue_status:
|
||||||
|
data["status"] = project.default_issue_status.name
|
||||||
|
|
||||||
|
if "priority" not in data and project.default_priority:
|
||||||
|
data["priority"] = project.default_priority.name
|
||||||
|
|
||||||
|
if "severity" not in data and project.default_severity:
|
||||||
|
data["severity"] = project.default_severity.name
|
||||||
|
|
||||||
|
if serialized.is_valid():
|
||||||
|
serialized.object.project = project
|
||||||
|
if serialized.object.owner is None:
|
||||||
|
serialized.object.owner = serialized.object.project.owner
|
||||||
|
serialized.object._importing = True
|
||||||
|
serialized.object._not_notify = True
|
||||||
|
|
||||||
|
serialized.save()
|
||||||
|
|
||||||
|
if serialized.object.ref:
|
||||||
|
sequence_name = refs.make_sequence_name(project)
|
||||||
|
if not seq.exists(sequence_name):
|
||||||
|
seq.create(sequence_name)
|
||||||
|
seq.set_max(sequence_name, serialized.object.ref)
|
||||||
|
else:
|
||||||
|
serialized.object.ref, _ = refs.make_reference(serialized.object, project)
|
||||||
|
serialized.object.save()
|
||||||
|
|
||||||
|
for attachment in data.get("attachments", []):
|
||||||
|
store_attachment(project, serialized.object, attachment)
|
||||||
|
|
||||||
|
for history in data.get("history", []):
|
||||||
|
store_history(project, serialized.object, history)
|
||||||
|
|
||||||
|
custom_attributes_values = data.get("custom_attributes_values", None)
|
||||||
|
if custom_attributes_values:
|
||||||
|
custom_attributes = serialized.object.project.issuecustomattributes.all().values('id', 'name')
|
||||||
|
custom_attributes_values = _use_id_instead_name_as_key_in_custom_attributes_values(custom_attributes,
|
||||||
|
custom_attributes_values)
|
||||||
|
store_custom_attributes_values(serialized.object, custom_attributes_values,
|
||||||
|
"issue", serializers.IssueCustomAttributesValuesExportSerializer)
|
||||||
|
|
||||||
|
return serialized
|
||||||
|
|
||||||
add_errors("issues", serialized.errors)
|
add_errors("issues", serialized.errors)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -22,6 +22,8 @@ from django.core.files.base import ContentFile
|
||||||
|
|
||||||
from .. import factories as f
|
from .. import factories as f
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
from taiga.projects.models import Project
|
from taiga.projects.models import Project
|
||||||
from taiga.projects.issues.models import Issue
|
from taiga.projects.issues.models import Issue
|
||||||
|
@ -256,6 +258,30 @@ def test_valid_user_story_import(client):
|
||||||
assert response_data["finish_date"] == "2014-10-24T00:00:00+0000"
|
assert response_data["finish_date"] == "2014-10-24T00:00:00+0000"
|
||||||
|
|
||||||
|
|
||||||
|
def test_valid_user_story_import_with_custom_attributes_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
membership = f.MembershipFactory(project=project, user=user, is_owner=True)
|
||||||
|
project.default_us_status = f.UserStoryStatusFactory.create(project=project)
|
||||||
|
project.save()
|
||||||
|
custom_attr = f.UserStoryCustomAttributeFactory(project=project)
|
||||||
|
|
||||||
|
url = reverse("importer-us", args=[project.pk])
|
||||||
|
data = {
|
||||||
|
"subject": "Test Custom Attrs Values User Story",
|
||||||
|
"custom_attributes_values": {
|
||||||
|
custom_attr.name: "test_value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
custom_attributes_values = apps.get_model("custom_attributes.UserStoryCustomAttributesValues").objects.get(
|
||||||
|
user_story__subject=response.data["subject"])
|
||||||
|
assert custom_attributes_values.values == {str(custom_attr.id): "test_value"}
|
||||||
|
|
||||||
|
|
||||||
def test_valid_issue_import_without_extra_data(client):
|
def test_valid_issue_import_without_extra_data(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(owner=user)
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
@ -279,6 +305,33 @@ def test_valid_issue_import_without_extra_data(client):
|
||||||
assert response_data["ref"] is not None
|
assert response_data["ref"] is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_valid_issue_import_with_custom_attributes_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
membership = f.MembershipFactory(project=project, user=user, is_owner=True)
|
||||||
|
project.default_issue_type = f.IssueTypeFactory.create(project=project)
|
||||||
|
project.default_issue_status = f.IssueStatusFactory.create(project=project)
|
||||||
|
project.default_severity = f.SeverityFactory.create(project=project)
|
||||||
|
project.default_priority = f.PriorityFactory.create(project=project)
|
||||||
|
project.save()
|
||||||
|
custom_attr = f.IssueCustomAttributeFactory(project=project)
|
||||||
|
|
||||||
|
url = reverse("importer-issue", args=[project.pk])
|
||||||
|
data = {
|
||||||
|
"subject": "Test Custom Attrs Values Issues",
|
||||||
|
"custom_attributes_values": {
|
||||||
|
custom_attr.name: "test_value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
custom_attributes_values = apps.get_model("custom_attributes.IssueCustomAttributesValues").objects.get(
|
||||||
|
issue__subject=response.data["subject"])
|
||||||
|
assert custom_attributes_values.values == {str(custom_attr.id): "test_value"}
|
||||||
|
|
||||||
|
|
||||||
def test_valid_issue_import_with_extra_data(client):
|
def test_valid_issue_import_with_extra_data(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(owner=user)
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
@ -536,6 +589,30 @@ def test_valid_task_import_without_extra_data(client):
|
||||||
assert response_data["ref"] is not None
|
assert response_data["ref"] is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_valid_task_import_with_custom_attributes_values(client):
|
||||||
|
user = f.UserFactory.create()
|
||||||
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
membership = f.MembershipFactory(project=project, user=user, is_owner=True)
|
||||||
|
project.default_task_status = f.TaskStatusFactory.create(project=project)
|
||||||
|
project.save()
|
||||||
|
custom_attr = f.TaskCustomAttributeFactory(project=project)
|
||||||
|
|
||||||
|
url = reverse("importer-task", args=[project.pk])
|
||||||
|
data = {
|
||||||
|
"subject": "Test Custom Attrs Values Tasks",
|
||||||
|
"custom_attributes_values": {
|
||||||
|
custom_attr.name: "test_value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.login(user)
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201
|
||||||
|
custom_attributes_values = apps.get_model("custom_attributes.TaskCustomAttributesValues").objects.get(
|
||||||
|
task__subject=response.data["subject"])
|
||||||
|
assert custom_attributes_values.values == {str(custom_attr.id): "test_value"}
|
||||||
|
|
||||||
|
|
||||||
def test_valid_task_import_with_extra_data(client):
|
def test_valid_task_import_with_extra_data(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(owner=user)
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
@ -735,6 +812,7 @@ def test_valid_wiki_link_import(client):
|
||||||
json.loads(response.content.decode("utf-8"))
|
json.loads(response.content.decode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_milestone_import(client):
|
def test_invalid_milestone_import(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(owner=user)
|
project = f.ProjectFactory.create(owner=user)
|
||||||
|
@ -766,6 +844,7 @@ def test_valid_milestone_import(client):
|
||||||
json.loads(response.content.decode("utf-8"))
|
json.loads(response.content.decode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_milestone_import_duplicated_milestone(client):
|
def test_milestone_import_duplicated_milestone(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