Add estimated_start, estimated_finish filters to tasks, userstories and milestones

remotes/origin/github-import
Michael Jurke 2016-11-08 21:40:02 +01:00 committed by David Barragán Merino
parent e3226f4cb9
commit 421a213f5e
8 changed files with 189 additions and 1 deletions

View File

@ -10,6 +10,7 @@
- Ability to create rich text custom fields in Epics, User Stories, Tasks and Isues. - Ability to create rich text custom fields in Epics, User Stories, Tasks and Isues.
### Misc ### Misc
- API: Filter milestones, user stories and tasks by estimated_start and estimated_finish dates.
- Lots of small and not so small bugfixes. - Lots of small and not so small bugfixes.

View File

@ -526,6 +526,22 @@ class FinishDateFilter(BaseDateFilter):
filter_name_base = "finish_date" filter_name_base = "finish_date"
class EstimatedStartFilter(BaseDateFilter):
filter_name_base = "estimated_start"
class EstimatedFinishFilter(BaseDateFilter):
filter_name_base = "estimated_finish"
class MilestoneEstimatedStartFilter(BaseDateFilter):
filter_name_base = "milestone__estimated_start"
class MilestoneEstimatedFinishFilter(BaseDateFilter):
filter_name_base = "milestone__estimated_finish"
##################################################################### #####################################################################
# Text search filters # Text search filters
##################################################################### #####################################################################

View File

@ -46,7 +46,13 @@ class MilestoneViewSet(HistoryResourceMixin, WatchedResourceMixin,
serializer_class = serializers.MilestoneSerializer serializer_class = serializers.MilestoneSerializer
validator_class = validators.MilestoneValidator validator_class = validators.MilestoneValidator
permission_classes = (permissions.MilestonePermission,) permission_classes = (permissions.MilestonePermission,)
filter_backends = (filters.CanViewMilestonesFilterBackend,) filter_backends = (
filters.CanViewMilestonesFilterBackend,
filters.CreatedDateFilter,
filters.ModifiedDateFilter,
filters.EstimatedStartFilter,
filters.EstimatedFinishFilter,
)
filter_fields = ( filter_fields = (
"project", "project",
"project__slug", "project__slug",

View File

@ -59,6 +59,8 @@ class TaskViewSet(OCCResourceMixin, VotedResourceMixin, HistoryResourceMixin, Wa
filters.QFilter, filters.QFilter,
filters.CreatedDateFilter, filters.CreatedDateFilter,
filters.ModifiedDateFilter, filters.ModifiedDateFilter,
filters.MilestoneEstimatedStartFilter,
filters.MilestoneEstimatedFinishFilter,
filters.FinishedDateFilter) filters.FinishedDateFilter)
filter_fields = ["user_story", filter_fields = ["user_story",
"milestone", "milestone",

View File

@ -70,6 +70,8 @@ class UserStoryViewSet(OCCResourceMixin, VotedResourceMixin, HistoryResourceMixi
base_filters.CreatedDateFilter, base_filters.CreatedDateFilter,
base_filters.ModifiedDateFilter, base_filters.ModifiedDateFilter,
base_filters.FinishDateFilter, base_filters.FinishDateFilter,
base_filters.MilestoneEstimatedStartFilter,
base_filters.MilestoneEstimatedFinishFilter,
base_filters.OrderByFilterMixin) base_filters.OrderByFilterMixin)
filter_fields = ["project", filter_fields = ["project",
"project__slug", "project__slug",

View File

@ -18,6 +18,10 @@
# 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 pytz
from datetime import datetime, timedelta
from urllib.parse import quote
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -82,3 +86,97 @@ def test_list_milestones_taiga_info_headers(client):
assert response2.has_header("Taiga-Info-Total-Opened-Milestones") == True assert response2.has_header("Taiga-Info-Total-Opened-Milestones") == True
assert response2["taiga-info-total-closed-milestones"] == "3" assert response2["taiga-info-total-closed-milestones"] == "3"
assert response2["taiga-info-total-opened-milestones"] == "1" assert response2["taiga-info-total-opened-milestones"] == "1"
def test_api_filter_by_created_date__lte(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
role = f.RoleFactory.create(project=project)
f.MembershipFactory.create(
project=project, user=user, role=role, is_admin=True
)
one_day_ago = datetime.now(pytz.utc) - timedelta(days=1)
old_milestone = f.MilestoneFactory.create(
project=project, owner=user, created_date=one_day_ago
)
milestone = f.MilestoneFactory.create(project=project, owner=user)
url = reverse("milestones-list") + "?created_date__lte=%s" % (
quote(milestone.created_date.isoformat())
)
client.login(milestone.owner)
response = client.get(url)
number_of_milestones = len(response.data)
assert response.status_code == 200
assert number_of_milestones == 2
def test_api_filter_by_modified_date__gte(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
role = f.RoleFactory.create(project=project)
f.MembershipFactory.create(
project=project, user=user, role=role, is_admin=True
)
one_day_ago = datetime.now(pytz.utc) - timedelta(days=1)
older_milestone = f.MilestoneFactory.create(
project=project, owner=user, created_date=one_day_ago
)
milestone = f.MilestoneFactory.create(project=project, owner=user)
# we have to refresh as it slightly differs
milestone.refresh_from_db()
assert older_milestone.modified_date < milestone.modified_date
url = reverse("milestones-list") + "?modified_date__gte=%s" % (
quote(milestone.modified_date.isoformat())
)
client.login(milestone.owner)
response = client.get(url)
number_of_milestones = len(response.data)
assert response.status_code == 200
assert number_of_milestones == 1
assert response.data[0]["slug"] == milestone.slug
@pytest.mark.parametrize("field_name", [
"estimated_start", "estimated_finish"
])
def test_api_filter_by_milestone__estimated_start_and_end(client, field_name):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
role = f.RoleFactory.create(project=project)
f.MembershipFactory.create(
project=project, user=user, role=role, is_admin=True
)
milestone = f.MilestoneFactory.create(project=project, owner=user)
assert hasattr(milestone, field_name)
date = getattr(milestone, field_name)
before = (date - timedelta(days=1)).isoformat()
after = (date + timedelta(days=1)).isoformat()
client.login(milestone.owner)
expections = {
field_name + "__gte=" + quote(before): 1,
field_name + "__gte=" + quote(after): 0,
field_name + "__lte=" + quote(before): 0,
field_name + "__lte=" + quote(after): 1
}
for param, expection in expections.items():
url = reverse("milestones-list") + "?" + param
response = client.get(url)
number_of_milestones = len(response.data)
assert response.status_code == 200
assert number_of_milestones == expection, param
if number_of_milestones > 0:
assert response.data[0]["slug"] == milestone.slug

View File

@ -702,6 +702,38 @@ def test_api_filter_by_finished_date(client):
assert response.data[0]["subject"] == finished_task.subject assert response.data[0]["subject"] == finished_task.subject
@pytest.mark.parametrize("field_name", ["estimated_start", "estimated_finish"])
def test_api_filter_by_milestone__estimated_start_and_end(client, field_name):
user = f.UserFactory(is_superuser=True)
task = f.create_task(owner=user)
assert task.milestone
assert hasattr(task.milestone, field_name)
date = getattr(task.milestone, field_name)
before = (date - timedelta(days=1)).isoformat()
after = (date + timedelta(days=1)).isoformat()
client.login(task.owner)
full_field_name = "milestone__" + field_name
expections = {
full_field_name + "__gte=" + quote(before): 1,
full_field_name + "__gte=" + quote(after): 0,
full_field_name + "__lte=" + quote(before): 0,
full_field_name + "__lte=" + quote(after): 1
}
for param, expection in expections.items():
url = reverse("tasks-list") + "?" + param
response = client.get(url)
number_of_tasks = len(response.data)
assert response.status_code == 200
assert number_of_tasks == expection, param
if number_of_tasks > 0:
assert response.data[0]["subject"] == task.subject
def test_api_filters_data(client): def test_api_filters_data(client):
project = f.ProjectFactory.create() project = f.ProjectFactory.create()
user1 = f.UserFactory.create(is_superuser=True) user1 = f.UserFactory.create(is_superuser=True)

View File

@ -655,6 +655,37 @@ def test_api_filter_by_finish_date(client):
assert number_of_userstories == 1 assert number_of_userstories == 1
assert response.data[0]["subject"] == userstory_to_finish.subject assert response.data[0]["subject"] == userstory_to_finish.subject
@pytest.mark.parametrize("field_name", ["estimated_start", "estimated_finish"])
def test_api_filter_by_milestone__estimated_start_and_end(client, field_name):
user = f.UserFactory(is_superuser=True)
userstory = f.create_userstory(owner=user)
assert userstory.milestone
assert hasattr(userstory.milestone, field_name)
date = getattr(userstory.milestone, field_name)
before = (date - timedelta(days=1)).isoformat()
after = (date + timedelta(days=1)).isoformat()
client.login(userstory.owner)
full_field_name = "milestone__" + field_name
expections = {
full_field_name + "__gte=" + quote(before): 1,
full_field_name + "__gte=" + quote(after): 0,
full_field_name + "__lte=" + quote(before): 0,
full_field_name + "__lte=" + quote(after): 1
}
for param, expection in expections.items():
url = reverse("userstories-list") + "?" + param
response = client.get(url)
number_of_userstories = len(response.data)
assert response.status_code == 200
assert number_of_userstories == expection, param
if number_of_userstories > 0:
assert response.data[0]["subject"] == userstory.subject
def test_api_filters_data(client): def test_api_filters_data(client):
project = f.ProjectFactory.create() project = f.ProjectFactory.create()