ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: additive read-layer двусторонней доски внешних контуров
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
# See the LICENSE file for details.
|
||||
|
||||
import pytest
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from plane.db.models import Intake, IntakeIssue, Issue, Project, ProjectMember, State, WorkspaceMember
|
||||
from plane.db.models.intake import IntakeIssueStatus
|
||||
from plane.db.models.project import ROLE
|
||||
from plane.db.models.state import StateGroup
|
||||
|
||||
|
||||
@pytest.mark.contract
|
||||
class TestExternalContoursBoardAPI:
|
||||
def get_board_url(self, workspace_slug: str, project_id) -> str:
|
||||
return f"/api/workspaces/{workspace_slug}/projects/{project_id}/external-contours/board/"
|
||||
|
||||
def get_board_item_url(self, workspace_slug: str, project_id, request_id) -> str:
|
||||
return f"/api/workspaces/{workspace_slug}/projects/{project_id}/external-contours/board-items/{request_id}/"
|
||||
|
||||
def create_project_with_member(self, workspace, user, name: str, identifier: str, intake_view: bool = False) -> Project:
|
||||
project = Project.objects.create(
|
||||
name=name,
|
||||
identifier=identifier,
|
||||
workspace=workspace,
|
||||
intake_view=intake_view,
|
||||
)
|
||||
ProjectMember.objects.create(project=project, member=user, role=ROLE.ADMIN.value, is_active=True)
|
||||
return project
|
||||
|
||||
def create_state(self, project: Project, name: str, group: str, color: str, default: bool = False) -> State:
|
||||
return State.objects.create(
|
||||
project=project,
|
||||
workspace=project.workspace,
|
||||
name=name,
|
||||
group=group,
|
||||
color=color,
|
||||
sequence=1000,
|
||||
default=default,
|
||||
)
|
||||
|
||||
def create_external_contour_request(self, source_project: Project, target_project: Project, requested_by, state: State):
|
||||
intake = Intake.objects.create(
|
||||
name="External Contours Bridge",
|
||||
project=target_project,
|
||||
is_default=False,
|
||||
)
|
||||
issue = Issue.objects.create(
|
||||
project=target_project,
|
||||
state=state,
|
||||
name="Cross-project request",
|
||||
description_html="<p>Need help</p>",
|
||||
priority="high",
|
||||
created_by=requested_by,
|
||||
)
|
||||
return IntakeIssue.objects.create(
|
||||
intake=intake,
|
||||
project=target_project,
|
||||
issue=issue,
|
||||
status=IntakeIssueStatus.ACCEPTED.value,
|
||||
extra={
|
||||
"bridge": "external-contours",
|
||||
"source_project_id": str(source_project.id),
|
||||
"source_project_name": source_project.name,
|
||||
"target_project_id": str(target_project.id),
|
||||
"target_project_name": target_project.name,
|
||||
"requested_by_id": str(requested_by.id),
|
||||
"requested_by_name": requested_by.display_name,
|
||||
"requested_at": issue.created_at.isoformat() if issue.created_at else None,
|
||||
},
|
||||
)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_source_project_member_gets_outgoing_board_items(self, workspace, create_user):
|
||||
source_user = create_user
|
||||
target_user = type(source_user).objects.create_user(email="target-board@example.com", username="target-board")
|
||||
WorkspaceMember.objects.create(workspace=workspace, member=target_user, role=ROLE.ADMIN.value, is_active=True)
|
||||
|
||||
source_project = self.create_project_with_member(workspace, source_user, "Source Board", "SRCBRD")
|
||||
target_project = self.create_project_with_member(workspace, target_user, "Target Board", "TGTBRD", intake_view=True)
|
||||
open_state = self.create_state(target_project, "Todo", StateGroup.UNSTARTED.value, "#cccccc", default=True)
|
||||
contour_request = self.create_external_contour_request(source_project, target_project, source_user, open_state)
|
||||
|
||||
client = APIClient()
|
||||
client.force_authenticate(user=source_user)
|
||||
response = client.get(self.get_board_url(workspace.slug, source_project.id), format="json")
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
columns = {column["key"]: column for column in response.data["columns"]}
|
||||
|
||||
assert columns["outgoing"]["total_count"] == 1
|
||||
assert columns["incoming"]["total_count"] == 0
|
||||
assert columns["outgoing"]["results"][0]["id"] == str(contour_request.id)
|
||||
assert columns["outgoing"]["results"][0]["direction"] == "outgoing"
|
||||
assert columns["outgoing"]["results"][0]["capabilities"]["can_open_target_issue"] is False
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_target_project_member_gets_incoming_board_items(self, workspace, create_user):
|
||||
source_user = create_user
|
||||
target_user = type(source_user).objects.create_user(email="incoming-board@example.com", username="incoming-board")
|
||||
WorkspaceMember.objects.create(workspace=workspace, member=target_user, role=ROLE.ADMIN.value, is_active=True)
|
||||
|
||||
source_project = self.create_project_with_member(workspace, source_user, "Source Incoming", "SRCINC")
|
||||
target_project = self.create_project_with_member(workspace, target_user, "Target Incoming", "TGTINC", intake_view=True)
|
||||
open_state = self.create_state(target_project, "Todo", StateGroup.UNSTARTED.value, "#cccccc", default=True)
|
||||
contour_request = self.create_external_contour_request(source_project, target_project, source_user, open_state)
|
||||
|
||||
client = APIClient()
|
||||
client.force_authenticate(user=target_user)
|
||||
response = client.get(self.get_board_url(workspace.slug, target_project.id), format="json")
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
columns = {column["key"]: column for column in response.data["columns"]}
|
||||
|
||||
assert columns["outgoing"]["total_count"] == 0
|
||||
assert columns["incoming"]["total_count"] == 1
|
||||
assert columns["incoming"]["results"][0]["id"] == str(contour_request.id)
|
||||
assert columns["incoming"]["results"][0]["direction"] == "incoming"
|
||||
assert columns["incoming"]["results"][0]["capabilities"]["can_open_target_issue"] is True
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_board_item_detail_resolves_perspective_and_capabilities(self, workspace, create_user):
|
||||
source_user = create_user
|
||||
target_user = type(source_user).objects.create_user(email="detail-board@example.com", username="detail-board")
|
||||
WorkspaceMember.objects.create(workspace=workspace, member=target_user, role=ROLE.ADMIN.value, is_active=True)
|
||||
|
||||
source_project = self.create_project_with_member(workspace, source_user, "Source Detail", "SRCDET")
|
||||
target_project = self.create_project_with_member(workspace, target_user, "Target Detail", "TGTDET", intake_view=True)
|
||||
closed_state = self.create_state(target_project, "Done", StateGroup.COMPLETED.value, "#00ff00", default=True)
|
||||
contour_request = self.create_external_contour_request(source_project, target_project, source_user, closed_state)
|
||||
|
||||
source_client = APIClient()
|
||||
source_client.force_authenticate(user=source_user)
|
||||
source_response = source_client.get(
|
||||
self.get_board_item_url(workspace.slug, source_project.id, contour_request.id),
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert source_response.status_code == status.HTTP_200_OK
|
||||
assert source_response.data["direction"] == "outgoing"
|
||||
assert source_response.data["capabilities"]["can_source_decide"] is True
|
||||
assert source_response.data["capabilities"]["can_open_target_issue"] is False
|
||||
|
||||
target_client = APIClient()
|
||||
target_client.force_authenticate(user=target_user)
|
||||
target_response = target_client.get(
|
||||
self.get_board_item_url(workspace.slug, target_project.id, contour_request.id),
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert target_response.status_code == status.HTTP_200_OK
|
||||
assert target_response.data["direction"] == "incoming"
|
||||
assert target_response.data["capabilities"]["can_source_decide"] is False
|
||||
assert target_response.data["capabilities"]["can_open_target_issue"] is True
|
||||
Reference in New Issue
Block a user