fix some bugs
This commit is contained in:
1 parent
b8b3aba855
commit
963fd839dc
22 files changed
+570
-33
No files matched your search
@@ -178,3 +178,24 @@ def test_dispatch_report_presents_delivery_and_engagement_professionally(live_se
|
||||
page.set_viewport_size({"width":390,"height":844})
|
||||
expect(page.locator(".dispatch-detail-table tbody tr").first).to_be_visible()
|
||||
assert page.evaluate("document.documentElement.scrollWidth <= document.documentElement.clientWidth + 1")
|
||||
|
||||
page.goto(f"{live_server.url}{reverse('staff_tickets:detail',args=[ticket.public_id])}", wait_until="domcontentloaded")
|
||||
expect(page.locator(".ticket-dispatch-context")).to_contain_text("استعلام حرفهای")
|
||||
dismiss_context = page.get_by_role("button", name="بستن پیام ارسال گروهی")
|
||||
expect(dismiss_context).to_be_visible()
|
||||
launch = page.locator(".composer-launch")
|
||||
expect(launch).to_be_visible()
|
||||
box = launch.bounding_box()
|
||||
assert box is not None
|
||||
assert box["x"] >= 0 and box["x"] + box["width"] <= 390
|
||||
assert box["y"] >= 0 and box["y"] + box["height"] <= 844
|
||||
assert page.evaluate("document.documentElement.scrollWidth <= document.documentElement.clientWidth + 1")
|
||||
launch.click()
|
||||
close_composer = page.get_by_role("button", name="بستن", exact=True)
|
||||
expect(close_composer).to_be_visible()
|
||||
close_box = close_composer.bounding_box()
|
||||
assert close_box is not None
|
||||
assert close_box["x"] >= 0 and close_box["x"] + close_box["width"] <= 390
|
||||
assert close_box["y"] >= 0 and close_box["y"] + close_box["height"] <= 844
|
||||
dismiss_context.click()
|
||||
expect(page.locator(".ticket-dispatch-context")).to_have_count(0)
|
||||
@@ -49,6 +49,23 @@ def test_developer_credit_html_requires_explicit_trusted_html_switch(client):
|
||||
assert '<a href="https://example.com" style="color:red"><span>★</span> توسعه نمونه</a>' in rendered
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_customer_new_renders_developer_credit_once_directly_below_wizard(client):
|
||||
customer = User.objects.create_user(
|
||||
username="wizard-credit-customer", mobile="09120000404", account_type=User.AccountType.CUSTOMER
|
||||
)
|
||||
branding = SiteBranding.load()
|
||||
branding.developer_credit_text = "برنامه نویسی و توسعه: محمد جواد فصاحت | 09202202129"
|
||||
branding.save()
|
||||
client.force_login(customer)
|
||||
|
||||
content = client.get(reverse("tickets:new")).content.decode()
|
||||
assert content.count(branding.developer_credit_text) == 1
|
||||
assert '<footer class="ticket-wizard-credit">' in content
|
||||
assert content.index('</form>') < content.index('<footer class="ticket-wizard-credit">')
|
||||
assert '<footer class="site-footer">' not in content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_staff_sidebar_brand_is_database_backed(client):
|
||||
user = User.objects.create_superuser(username="brand-admin", password="safe-password", account_type=User.AccountType.STAFF)
|
||||
|
||||
+89
-1
@@ -140,10 +140,11 @@ def test_unit_notification_destinations_normalize_and_reject_duplicate_superviso
|
||||
slug="notification-destinations",
|
||||
supervisor_mobile_1="0912 111 2233",
|
||||
supervisor_mobile_2="0935 222 3344",
|
||||
supervisor_mobile_4="0990 444 5566",
|
||||
)
|
||||
unit.full_clean()
|
||||
unit.save()
|
||||
assert unit.supervisor_mobiles == ("+989121112233", "+989352223344")
|
||||
assert unit.supervisor_mobiles == ("+989121112233", "+989352223344", "+989904445566")
|
||||
|
||||
unit.supervisor_mobile_3 = "09121112233"
|
||||
with pytest.raises(ValidationError, match="قبلاً"):
|
||||
@@ -158,6 +159,7 @@ def test_new_ticket_sms_is_queued_for_each_unit_supervisor_only_on_creation(cate
|
||||
unit.supervisor_mobile_1 = "09121112233"
|
||||
unit.supervisor_mobile_2 = "09352223344"
|
||||
unit.supervisor_mobile_3 = "09903334455"
|
||||
unit.supervisor_mobile_4 = "09214445566"
|
||||
unit.save()
|
||||
ticket = create_ticket(customer=customer, category=category, subject=" پیگیری بارگیری ", body="متن")
|
||||
jobs = list(NotificationJob.objects.filter(ticket=ticket, event_type="UNIT_SUPERVISOR_NEW_TICKET").order_by("id"))
|
||||
@@ -180,12 +182,98 @@ def test_new_ticket_sms_is_queued_for_each_unit_supervisor_only_on_creation(cate
|
||||
assert customer.local_mobile in message
|
||||
assert "موضوع: پیگیری بارگیری" in message
|
||||
assert f"دسته: {category.title}" in message
|
||||
assert "ارجاع: صف عمومی" in message
|
||||
|
||||
supervisor_job_count = NotificationJob.objects.filter(event_type="UNIT_SUPERVISOR_NEW_TICKET").count()
|
||||
reply_ticket(ticket_id=ticket.pk, user=customer, body="پاسخ جدید")
|
||||
assert NotificationJob.objects.filter(event_type="UNIT_SUPERVISOR_NEW_TICKET").count() == supervisor_job_count
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unit_supervisor_sms_uses_editable_unit_template_and_selected_expert(category, customer, monkeypatch):
|
||||
from apps.notifications.management.commands.process_notifications import _send_sms
|
||||
from apps.notifications.models import SMSTemplate
|
||||
from apps.customers.models import CustomerProfile
|
||||
|
||||
unit = category.unit
|
||||
unit.supervisor_mobile_1 = "09125556677"
|
||||
unit.save()
|
||||
expert = make_staff("selected-supervisor-sms-expert")
|
||||
expert.staff_profile.display_name = "کارشناس انتخابی پیامک"
|
||||
expert.staff_profile.primary_unit = unit
|
||||
expert.staff_profile.save()
|
||||
CustomerProfile.objects.create(user=customer, first_name="سارا", last_name="احمدی")
|
||||
template = SMSTemplate.objects.create(
|
||||
unit=unit,
|
||||
event_type=SMSTemplate.Event.UNIT_SUPERVISOR_NEW_TICKET,
|
||||
title="الگوی سفارشی سرپرستان",
|
||||
body="{first_name} {last_name} | {unit_name} | {ticket_number} | {customer_mobile} | {category_name} | {expert_name}",
|
||||
)
|
||||
template.full_clean()
|
||||
ticket = create_ticket(
|
||||
customer=customer, category=category, subject="تست الگوی قابل تنظیم",
|
||||
selected_expert=expert, body="متن",
|
||||
)
|
||||
job = NotificationJob.objects.get(ticket=ticket, event_type=SMSTemplate.Event.UNIT_SUPERVISOR_NEW_TICKET)
|
||||
sent = []
|
||||
|
||||
class Provider:
|
||||
def send_message(self, mobile, message):
|
||||
sent.append((mobile, message))
|
||||
return type("Result", (), {"success": True})()
|
||||
|
||||
monkeypatch.setattr("apps.notifications.management.commands.process_notifications.get_sms_provider", lambda: Provider())
|
||||
_send_sms(job)
|
||||
assert sent == [(
|
||||
"+989125556677",
|
||||
f"سارا احمدی | {unit.name} | {ticket.ticket_number} | {customer.local_mobile} | {category.title} | کارشناس انتخابی پیامک",
|
||||
)]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unit_supervisor_sms_handles_missing_customer_names_and_general_queue(category, customer, monkeypatch):
|
||||
from apps.notifications.management.commands.process_notifications import _send_sms
|
||||
from apps.notifications.models import SMSTemplate
|
||||
|
||||
category.unit.supervisor_mobile_1 = "09125556677"
|
||||
category.unit.save()
|
||||
SMSTemplate.objects.create(
|
||||
unit=category.unit,
|
||||
event_type=SMSTemplate.Event.UNIT_SUPERVISOR_NEW_TICKET,
|
||||
title="الگوی نام خالی سرپرستان",
|
||||
body="نام: {first_name} {last_name}\nنام جایگزین: {recipient_name}\nارجاع: {expert_name}",
|
||||
)
|
||||
ticket = create_ticket(customer=customer, category=category, subject="مشتری بدون نام", body="متن")
|
||||
job = NotificationJob.objects.get(ticket=ticket, event_type=SMSTemplate.Event.UNIT_SUPERVISOR_NEW_TICKET)
|
||||
sent = []
|
||||
|
||||
class Provider:
|
||||
def send_message(self, mobile, message):
|
||||
sent.append((mobile, message))
|
||||
return type("Result", (), {"success": True})()
|
||||
|
||||
monkeypatch.setattr("apps.notifications.management.commands.process_notifications.get_sms_provider", lambda: Provider())
|
||||
_send_sms(job)
|
||||
|
||||
assert sent == [(
|
||||
"+989125556677",
|
||||
"نام: \nنام جایگزین: ثبت نشده\nارجاع: صف عمومی",
|
||||
)]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_global_supervisor_sms_template_is_seeded_and_editable():
|
||||
from apps.notifications.models import SMSTemplate
|
||||
|
||||
template = SMSTemplate.objects.get(
|
||||
unit__isnull=True, event_type=SMSTemplate.Event.UNIT_SUPERVISOR_NEW_TICKET
|
||||
)
|
||||
assert "{expert_name}" in template.body
|
||||
assert "{customer_mobile}" in template.body
|
||||
assert "{category_name}" in template.body
|
||||
assert {"expert_name", "customer_mobile", "category_name"}.issubset(template.allowed_tags)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_staff_created_ticket_also_notifies_owning_unit_supervisors(category, customer):
|
||||
category.unit.supervisor_mobile_1 = "09124445566"
|
||||
|
||||
@@ -12,12 +12,83 @@ from apps.attachments.models import AttachmentPolicy
|
||||
from apps.customers.models import ContactGroup, CustomerProfile
|
||||
from apps.notifications.models import NotificationJob
|
||||
from apps.staff.models import OrganizationalUnit, StaffProfile
|
||||
from apps.tickets.models import GroupDispatch, Ticket, TicketCategory, TicketTag
|
||||
from apps.tickets.models import GroupDispatch, Ticket, TicketCategory, TicketEvent, TicketTag
|
||||
from apps.tickets.policies import TicketPolicy
|
||||
from apps.tickets.selectors import staff_ticket_rows
|
||||
from apps.tickets.services import create_ticket, dispatch_group_tickets, refresh_group_dispatch_status
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_dispatch_owner_can_resolve_all_open_group_tickets_from_report_or_ticket(client):
|
||||
unit = OrganizationalUnit.objects.create(name="حل گروهی", slug="resolve-dispatch")
|
||||
unit.permissions.add(*Permission.objects.filter(
|
||||
content_type__app_label="tickets",
|
||||
codename__in=("view_ticket", "dispatch_group_tickets", "change_ticket"),
|
||||
))
|
||||
staff = make_staff("dispatch-resolver", unit)
|
||||
first = make_contact("resolve-first", "09120000401")
|
||||
second = make_contact("resolve-second", "09120000402")
|
||||
group = ContactGroup.objects.create(name="گروه قابل حل", unit=unit)
|
||||
first.customer_profile.groups.add(group)
|
||||
second.customer_profile.groups.add(group)
|
||||
category = TicketCategory.objects.create(unit=unit, title="پیگیری گروه", slug="resolve-group")
|
||||
dispatch, tickets = dispatch_group_tickets(
|
||||
user=staff, unit=unit, contact_group=group, category=category,
|
||||
subject="پیگیری پاسخ گروه", body="لطفاً پاسخ دهید.",
|
||||
)
|
||||
tickets[1].status = Ticket.Status.CLOSED
|
||||
tickets[1].closed_at = timezone.now()
|
||||
tickets[1].save(update_fields=["status", "closed_at", "updated_at"])
|
||||
client.force_login(staff)
|
||||
|
||||
report = client.get(reverse("staff_tickets:dispatch_detail", args=[dispatch.public_id]))
|
||||
report_text = report.content.decode()
|
||||
assert report.context["open_ticket_count"] == 1
|
||||
assert "حلشدن همه تیکتها (1)" in report_text
|
||||
ticket_page = client.get(reverse("staff_tickets:detail", args=[tickets[0].public_id]))
|
||||
assert "وابسته به ارسال گروهی" in ticket_page.content.decode()
|
||||
assert dispatch.subject in ticket_page.content.decode()
|
||||
assert "حلشدن تمامی تیکتهای گروه (1)" in ticket_page.content.decode()
|
||||
|
||||
response = client.post(
|
||||
reverse("staff_tickets:dispatch_resolve", args=[dispatch.public_id]),
|
||||
{"return_ticket": tickets[0].public_id},
|
||||
)
|
||||
assert response.status_code == 302
|
||||
assert response.url == reverse("staff_tickets:detail", args=[tickets[0].public_id])
|
||||
tickets[0].refresh_from_db()
|
||||
tickets[1].refresh_from_db()
|
||||
assert tickets[0].status == Ticket.Status.RESOLVED
|
||||
assert tickets[0].resolved_at is not None
|
||||
assert tickets[1].status == Ticket.Status.CLOSED
|
||||
assert TicketEvent.objects.filter(
|
||||
ticket=tickets[0], event_type=TicketEvent.Type.STATUS_CHANGED,
|
||||
metadata__group_dispatch_id=dispatch.pk,
|
||||
).exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_dispatch_bulk_resolve_requires_change_ticket_permission(client):
|
||||
unit = OrganizationalUnit.objects.create(name="گروه فقط مشاهده", slug="read-only-dispatch")
|
||||
unit.permissions.add(*Permission.objects.filter(
|
||||
content_type__app_label="tickets", codename__in=("view_ticket", "dispatch_group_tickets")
|
||||
))
|
||||
staff = make_staff("read-only-dispatcher", unit)
|
||||
customer = make_contact("read-only-recipient", "09120000403")
|
||||
group = ContactGroup.objects.create(name="گروه فقط خواندنی", unit=unit)
|
||||
customer.customer_profile.groups.add(group)
|
||||
category = TicketCategory.objects.create(unit=unit, title="فقط مشاهده", slug="read-only-group")
|
||||
dispatch, tickets = dispatch_group_tickets(
|
||||
user=staff, unit=unit, contact_group=group, category=category,
|
||||
subject="عملیات فقط مشاهده", body="متن عملیات",
|
||||
)
|
||||
client.force_login(staff)
|
||||
assert client.get(reverse("staff_tickets:dispatch_detail", args=[dispatch.public_id])).context["can_resolve_dispatch"] is False
|
||||
client.post(reverse("staff_tickets:dispatch_resolve", args=[dispatch.public_id]))
|
||||
tickets[0].refresh_from_db()
|
||||
assert tickets[0].status != Ticket.Status.RESOLVED
|
||||
|
||||
|
||||
def make_staff(username, unit):
|
||||
user = User.objects.create_user(username=username, account_type=User.AccountType.STAFF)
|
||||
StaffProfile.objects.create(user=user, display_name=username, primary_unit=unit)
|
||||
|
||||
Reference in new issue
Block a user