Files
customerTicket/tests/e2e/test_dispatch_workspace_e2e.py
T

109 lines
6.8 KiB
Python

import pytest
from django.contrib.auth.models import Permission
from django.urls import reverse
from django.utils import timezone
from playwright.sync_api import expect
from apps.accounts.models import TicketMagicLink, User
from apps.customers.models import ContactGroup, CustomerProfile
from apps.messaging.models import Message
from apps.notifications.models import NotificationJob, SMSTemplate
from apps.staff.models import OrganizationalUnit, StaffProfile
from apps.tickets.models import TicketCategory
from apps.tickets.services import create_group_dispatch
from tests.e2e.pages.auth import AuthenticationPage
from tests.e2e.pages.dispatches import DispatchWorkspacePage
pytestmark = [pytest.mark.e2e, pytest.mark.django_db(transaction=True)]
PASSWORD = "Dispatch-E2E-safe-2026"
@pytest.fixture
def dispatch_case():
unit = OrganizationalUnit.objects.create(name="فروش رابط گروهی", slug="dispatch-ui")
unit.permissions.add(*Permission.objects.filter(content_type__app_label="tickets", codename__in=("view_ticket", "change_ticket", "dispatch_group_tickets")))
staff = User.objects.create_user(username="dispatch-ui-agent", password=PASSWORD, account_type="STAFF")
StaffProfile.objects.create(user=staff, display_name="کارشناس ارسال", primary_unit=unit)
group = ContactGroup.objects.create(unit=unit, name="مخاطبان منتخب فروش")
empty_group = ContactGroup.objects.create(unit=unit, name="گروه بدون مخاطب")
category = TicketCategory.objects.create(unit=unit, title="هماهنگی فروش", slug="dispatch-ui-category")
customers = []
for index, name in enumerate(("مخاطب پاسخ‌دهنده", "مخاطب بدون پاسخ")):
customer = User.objects.create_user(username=f"dispatch-ui-customer-{index}", mobile=f"0912000980{index}", account_type="CUSTOMER")
CustomerProfile.objects.create(user=customer, first_name=name).groups.add(group)
customers.append(customer)
return staff, unit, group, category, empty_group, customers
@pytest.mark.parametrize("width", [1440, 390, 320])
def test_review_preserves_draft_and_requires_confirmation_before_group_send(live_server, browser_page, dispatch_case, width):
staff, unit, group, category, _, _ = dispatch_case
subject = "هماهنگی زمان تحویل گروهی"
body = "لطفاً زمان پیشنهادی تحویل را در گفت‌وگوی خصوصی اعلام کنید."
with browser_page() as page:
page.set_viewport_size({"width": width, "height": 900 if width == 1440 else 844})
AuthenticationPage(page, live_server.url).login_staff(staff, PASSWORD)
workspace = DispatchWorkspacePage(page, live_server.url)
workspace.open_composer()
workspace.compose(unit, group, category, subject, body)
expect(page.get_by_label("خلاصه ارسال جدید")).to_contain_text("۲ نفر")
workspace.open_history()
expect(page.get_by_text("هنوز ارسال گروهی ثبت نشده است")).to_be_visible()
workspace.return_to_composer()
expect(page.get_by_label("متن پیام", exact=False)).to_have_value(body)
workspace.review()
dialog = page.get_by_role("dialog")
expect(dialog).to_contain_text("۲ نفر")
expect(dialog).to_contain_text(subject)
workspace.cancel_review()
expect(page.get_by_role("button", name="بررسی و ادامه")).to_be_enabled()
workspace.save_screenshot(f"compose-{width}.png")
workspace.review()
workspace.save_screenshot(f"review-{width}.png")
workspace.send()
expect(page.locator("[data-recipient-row]")).to_have_count(2)
expect(page.locator(".sms-state-card").first).to_contain_text("در صف ارسال")
expect(page.get_by_text("تحویل پیامک به معنی مشاهده لینک یا دریافت پاسخ نیست.")).to_be_visible()
workspace.expect_fits_viewport()
@pytest.mark.parametrize("width", [1440, 390, 320])
def test_report_filters_search_and_private_reply_navigation(live_server, browser_page, dispatch_case, width):
staff, unit, group, category, _, customers = dispatch_case
dispatch, tickets = create_group_dispatch(user=staff, unit=unit, contact_group=group, category=category, subject="پیگیری پاسخ مخاطبان منتخب", body="پیام اصلی با پاسخ‌های خصوصی مستقل.", response_mode="INDIVIDUAL")
first = tickets[0]
Message.objects.create(ticket=first, author=customers[0], body="زمان پیشنهادی ما ساعت ده صبح است.")
first.last_customer_message_at = timezone.now()
first.save(update_fields=["last_customer_message_at"])
link = TicketMagicLink.issue_with_record(first, created_by=staff)[1]
link.view_count = 2
link.save(update_fields=["view_count"])
NotificationJob.objects.filter(ticket=first, event_type=SMSTemplate.Event.STAFF_TICKET_CREATED).update(status="SENT", attempts=1, delivery_status="DELIVERED")
NotificationJob.objects.filter(ticket=tickets[1], event_type=SMSTemplate.Event.STAFF_TICKET_CREATED).update(status="FAILED", attempts=1, last_error="خطای آزمایشی درگاه")
with browser_page() as page:
page.set_viewport_size({"width": width, "height": 900 if width == 1440 else 844})
AuthenticationPage(page, live_server.url).login_staff(staff, PASSWORD)
workspace = DispatchWorkspacePage(page, live_server.url)
workspace.open_report(dispatch)
expect(workspace.visible_recipients()).to_have_count(2)
workspace.filter_recipients("دارای پاسخ")
expect(workspace.visible_recipients()).to_have_count(1)
expect(workspace.visible_recipients()).to_contain_text("زمان پیشنهادی ما ساعت ده صبح است.")
workspace.reset_recipients()
workspace.filter_recipients("پیامک نیازمند اقدام")
expect(workspace.visible_recipients()).to_have_count(1)
expect(workspace.visible_recipients()).to_contain_text("ارسال ناموفق")
# One failed attempt is not a successful first attempt.
expect(workspace.visible_recipients()).not_to_contain_text("موفق در اولین تلاش")
workspace.reset_recipients()
workspace.search_recipient("۰۹۱۲۰۰۰۹۸۰۰")
expect(workspace.visible_recipients()).to_have_count(1)
workspace.search_recipient("وجود ندارد")
expect(page.get_by_role("heading", name="مخاطبی با این شرایط پیدا نشد")).to_be_visible()
workspace.reset_recipients()
workspace.expect_fits_viewport()
workspace.save_screenshot(f"report-{width}.png")
workspace.filter_recipients("دارای پاسخ")
workspace.open_conversation()
expect(page).to_have_url(workspace.url(reverse("staff_tickets:detail", args=[first.public_id])))