Skip to content

Commit

Permalink
issue(story): #4114 validate not being updated both workflow and status
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-herrero committed Nov 17, 2023
1 parent fa99003 commit 78fc24e
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 1 deletion.
8 changes: 8 additions & 0 deletions python/apps/taiga/src/taiga/stories/stories/api/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Any

from pydantic import ConstrainedStr, conlist, validator
from pydantic.class_validators import root_validator
from pydantic.types import PositiveInt
from taiga.base.validators import B64UUID, BaseModel

Expand All @@ -31,6 +32,13 @@ class UpdateStoryValidator(BaseModel):
status: B64UUID | None
workflow: str | None

@root_validator
def status_or_workflow(cls, values: dict[Any, Any]) -> dict[Any, Any]:
status = values.get("status")
workflow = values.get("workflow")
assert not (status and workflow), "It's not allowed to update both the status and workspace"
return values


class ReorderValidator(BaseModel):
place: str
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ async def _validate_and_process_values_to_update(
status = await workflows_repositories.get_workflow_status(
filters={"workflow_id": story.workflow_id, "id": status_id}
)
if not status:
if not status or output.get("workflow", None):
raise ex.InvalidStatusError("The provided status is not valid.")

if status.id != story.status_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,15 @@ async def test_update_story_422_unprocessable_story_ref(client):
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY, response.text


async def test_update_story_422_unprocessable_both_workflow_and_status(client):
project = await f.create_project()

data = {"version": 1, "workflow": "workflow-slug", "status": project.b64id}
client.login(project.created_by)
response = client.patch(f"/projects/{project.b64id}/stories/1", json=data)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY, response.text


async def test_update_story_404_not_found_project_b64id(client):
project = await f.create_project()
story = await f.create_story(project=project)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,22 @@ async def test_validate_and_process_values_to_update_error_workflow_without_stat
fake_stories_repo.list_stories.assert_not_awaited()


async def test_validate_and_process_values_to_update_error_workflow_and_status():
user = f.build_user()
project = f.build_project()
workflow1 = f.build_workflow(project=project)
status1 = f.build_workflow_status(workflow=workflow1)
story = f.build_story(project=project, workflow=workflow1, status=status1)
workflow2 = f.build_workflow(project=project, statuses=None)
values = {"version": story.version, "status": status1, "workflow": workflow2.slug}

with (patch("taiga.stories.stories.services.workflows_repositories", autospec=True) as fake_workflows_repo,):
fake_workflows_repo.get_workflow_status.return_value = workflow2

with pytest.raises(ex.InvalidStatusError):
await services._validate_and_process_values_to_update(story=story, values=values, updated_by=user)


#######################################################
# _calculate_offset
#######################################################
Expand Down

1 comment on commit 78fc24e

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/taiga
   __main__.py71710%17–155
src/taiga/attachments
   admin.py27390%25, 28, 70
   events.py8275%15, 20
   models.py19289%61, 64
   repositories.py49197%62
src/taiga/auth/services
   __init__.py47098%90–>93
src/taiga/base
   mocks.py741280%93–94, 107–118, 143–>exit
src/taiga/base/api
   permissions.py49199%22
   requests.py11380%15, 21–23
src/taiga/base/db
   __init__.py4175%15
   commands.py52520%8–269
   sequences.py45297%91–92
src/taiga/base/db/admin
   forms.py14838%17–25
   utils.py11736%17–23
src/taiga/base/db/models
   fields.py15188%20
src/taiga/base/django
   __init__.py5260%17–19
   settings.py30293%16–17
   urls.py330%8–11
src/taiga/base/i18n
   __init__.py102988%171–>170, 173–>170, 192–193, 203–205, 215, 268, 279, 283
   choices.py34291%80, 87
   commands.py74740%8–108
src/taiga/base/logging
   formatters.py241050%22–>exit, 38, 44–45, 51–60
   middlewares.py23196%20
src/taiga/base/repositories
   neighbors.py39391%43–44, 65
src/taiga/base/sampledata
   commands.py11110%8–40
   constants.py15150%14–51
   demo_data.py2732730%8–529
   factories.py1221220%9–353
   test_data.py2902900%8–634
src/taiga/base/serializers
   fields.py34393%22, 47, 61
src/taiga/base/utils
   commands.py11110%8–30
   datetime.py441860%54, 67, 126–147
   enum.py14192%43
   images.py26387%21–22, 30
   json.py33963%31–>33, 33–>35, 37, 39–44, 46, 50
   pprint.py660%8–17
   slug.py23485%22–25
src/taiga/base/validators/fields
   i18n.py15195%19
   uuid.py14195%19
src/taiga/comments
   admin.py29392%16, 20, 24
   events.py11373%15, 20, 25
   models.py20291%43, 46
   notifications.py6183%16
src/taiga/commons/storage
   commands.py13130%8–40
   models.py16288%38, 41
   services.py9092%17–>16
   tasks.py990%8–19
src/taiga/conf
   __init__.py94395%112, 128–129
   tokens.py17190%34
src/taiga/emails
   commands.py35350%9–68
   sender.py18571%48–50, 54–73
   tasks.py39490%44–45, 53–54
src/taiga/events
   app.py18192%21
   events.py16288%31–32
   logging.py392331%18–>exit, 32–48, 51–60
   manager.py1171190%78–79, 223–233, 239–242
   responses.py33684%33, 37–41
   subscriber.py80495%51, 55, 88, 91, 108–>120
src/taiga/events/actions
   auth.py231144%27–32, 39–45
   event_handlers.py9456%18–20, 28–30
   projects.py553038%36–40, 48–64, 72–80, 88–96
   workspaces.py553038%36–40, 48–64, 72–80, 88–96
src/taiga/events/pubsub/backends
   base.py30198%53
   redis.py66594%41–43, 85–86
src/taiga/exceptions/api
   __init__.py27097%28–>30
   handlers.py27290%27–28
   middlewares.py26287%37, 41
src/taiga/integrations/auth
   services.py39782%50–56
src/taiga/integrations/github
   services.py40098%63–>68
src/taiga/mediafiles
   admin.py20291%24, 27
   models.py26292%84, 87
src/taiga/notifications
   admin.py11285%20, 23
   api.py33195%95
   repositories.py39196%80
   services.py30097%50–>53
src/taiga/permissions
   services.py103198%28, 106–>109
src/taiga/permissions/validators
   fields.py24388%18–19, 45
src/taiga/projects/invitations
   models.py25292%89, 92
   repositories.py84198%135
src/taiga/projects/invitations/api
   validators.py65789%38–40, 65–66, 84–85
src/taiga/projects/invitations/events
   __init__.py33191%37–>exit, 49–>exit, 74–>exit, 102
src/taiga/projects/invitations/services
   __init__.py183199%58–>53, 286
src/taiga/projects/memberships
   models.py16288%51, 54
   repositories.py86297%91, 124
src/taiga/projects/memberships/events
   __init__.py16288%18–24
src/taiga/projects/memberships/services
   __init__.py45195%64–>69, 111
src/taiga/projects/projects
   admin.py531275%33–34, 39–42, 50–51, 56–59, 90, 94
   models.py61886%64, 67, 78, 113, 116, 119–121
   repositories.py115496%125, 126–>129, 155, 254–255
   tasks.py6188%17
src/taiga/projects/projects/services
   __init__.py107592%78, 87, 199, 205–>208, 213, 235
src/taiga/projects/references
   mixins.py13093%25–>28
src/taiga/projects/roles
   api.py35393%46–48
   models.py26386%50, 53, 57
   repositories.py44196%92
src/taiga/projects/roles/services
   __init__.py25194%24, 57–>62
src/taiga/stories/assignments
   models.py15287%42, 45
   repositories.py52197%49
src/taiga/stories/assignments/notifications
   __init__.py18091%25–>27, 44–>46
src/taiga/stories/attachments
   api.py51197%159
   serializers.py11093%20–>28
src/taiga/stories/comments
   api.py59197%188
src/taiga/stories/comments/notifications
   __init__.py12094%19–>21
src/taiga/stories/stories
   admin.py25584%76–81, 85, 89
   models.py25292%73, 76
src/taiga/stories/stories/notifications
   __init__.py25091%27–>29, 49–>51, 72–>74
src/taiga/stories/stories/services
   __init__.py150298%251–>268, 312, 336
src/taiga/tasksqueue
   app.py20286%29–30
   commands.py65650%8–122
   logging.py331740%18–>exit, 29–39, 42–51
   manager.py561377%37, 41, 45, 49, 94, 163, 177, 186, 191, 198, 202, 209, 213
   task.py12192%23
src/taiga/tokens
   admin.py441081%67, 70, 73, 76, 104, 108, 112, 116, 120, 124
   models.py30487%59, 62, 78, 81
src/taiga/users
   admin.py51781%32, 41, 50, 87–95
   commands.py990%8–26
   models.py651086%71, 74, 90, 93, 97, 100, 103, 106, 127, 130
   repositories.py204398%209–>212, 335, 428–429
src/taiga/users/api
   __init__.py66296%216, 304
src/taiga/users/api/validators
   __init__.py42392%39–41
src/taiga/users/services
   __init__.py244795%75, 259, 262–>257, 297–>280, 306–>280, 322–>318, 345–>341, 366, 494–>499, 513–520, 521–>526, 524–525
src/taiga/workflows
   models.py40490%42, 45, 85, 88
src/taiga/workflows/services
   __init__.py156595%54, 233, 329, 373–>403, 380, 466–>475, 482
src/taiga/workspaces/invitations
   models.py24292%84, 87
   permissions.py9182%19
   repositories.py77198%123
src/taiga/workspaces/invitations/api
   validators.py18288%24–25
src/taiga/workspaces/invitations/events
   __init__.py25191%36–>exit, 60–>exit, 71
src/taiga/workspaces/invitations/services
   __init__.py123199%222
src/taiga/workspaces/memberships
   api.py43196%126
   models.py15287%43, 46
   repositories.py63295%72, 105
src/taiga/workspaces/memberships/services
   __init__.py46197%117
src/taiga/workspaces/workspaces
   admin.py571962%25–26, 31–34, 49, 52–57, 61, 65, 73–74, 79–82
   models.py18290%32, 35
   repositories.py127299%232–233
src/taiga/workspaces/workspaces/services
   __init__.py54294%113, 116
TOTAL10338154484% 

Tests Skipped Failures Errors Time
1190 1 💤 0 ❌ 0 🔥 11m 11s ⏱️

Please sign in to comment.