Files
customerTicket/tests/e2e/test_staff_operations_ui.py
T

118 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import base64
import pytest
from django.contrib.auth.models import Permission
from django.urls import reverse
from playwright.sync_api import expect
from apps.accounts.models import TicketMagicLink, User
from apps.customers.models import ContactGroup, CustomerProfile
from apps.core.models import PageTitle, SiteBranding
from apps.notifications.models import SMSTemplate
from apps.staff.models import OrganizationalUnit, StaffProfile
from apps.tickets.models import TicketCategory
from apps.tickets.services import create_ticket
from tests.e2e.pages.auth import AuthenticationPage
pytestmark = [pytest.mark.e2e, pytest.mark.django_db(transaction=True)]
PASSWORD = "E2e-safe-password-2026"
def test_staff_operations_pages_are_authorized_and_visually_styled(live_server, browser_page):
branding = SiteBranding.load()
branding.staff_brand_title = "مرکز عملیات E2E"
branding.staff_brand_subtitle = "ارتباطات یکپارچه E2E"
branding.login_intro_eyebrow = "معرفی ورود E2E"
branding.developer_credit_text = "توسعه E2E | 09120000000"
branding.staff_sidebar_credit_text = "امضای مستقل sidebar E2E"
branding.save()
PageTitle.objects.update_or_create(route_name="staff_tickets:dispatch_create", defaults={"title": "ردیابی E2E"})
SMSTemplate.objects.update_or_create(unit=None, event_type=SMSTemplate.Event.STAFF_REPLY, defaults={"title": "الگوی E2E", "body": "{ticket_number}: {magic_link}"})
unit = OrganizationalUnit.objects.create(name="عملیات E2E", slug="operations-e2e")
permissions = {
"customers": {"view_customerprofile", "add_customerprofile", "change_customerprofile", "view_contactgroup", "add_contactgroup", "change_contactgroup"},
"tickets": {"view_ticket", "add_ticket", "dispatch_group_tickets"},
"notifications": {"view_smstemplate", "add_smstemplate", "change_smstemplate"},
"accounts": {"view_ticketmagiclink"},
}
query = None
from django.db.models import Q
for app_label, codenames in permissions.items():
part = Q(content_type__app_label=app_label, codename__in=codenames)
query = part if query is None else query | part
unit.permissions.add(*Permission.objects.filter(query))
staff = User.objects.create_user(username="e2e-operations", password=PASSWORD, account_type=User.AccountType.STAFF)
StaffProfile.objects.create(user=staff, display_name="کارشناس عملیات", primary_unit=unit)
customer = User.objects.create_user(username="e2e-carrier", mobile="09120009121", account_type=User.AccountType.CUSTOMER)
profile = CustomerProfile.objects.create(user=customer, first_name="باربری", stakeholder_type=CustomerProfile.StakeholderType.CARRIER)
group = ContactGroup.objects.create(unit=unit, name="باربری‌ها")
secondary_group = ContactGroup.objects.create(unit=unit, name="مخاطبان منتخب")
profile.groups.add(group)
category = TicketCategory.objects.create(title="استعلام E2E", slug="operations-e2e")
ticket = create_ticket(customer=customer, created_by=staff, unit=unit, category=category, subject="استعلام آزمایشی", body="قیمت را اعلام کنید")
TicketMagicLink.issue_with_record(ticket, created_by=staff)
with browser_page() as page:
page.goto(f"{live_server.url}{reverse('accounts:login')}", wait_until="domcontentloaded")
expect(page.locator(".auth-brand strong")).to_have_count(0)
expect(page.locator(".auth-intro .eyebrow")).to_have_text("معرفی ورود E2E")
expect(page.locator(".auth-footer")).to_contain_text("توسعه E2E")
AuthenticationPage(page, live_server.url).login_staff(staff, PASSWORD)
for route, heading in (
("staff_tickets:contacts", "مخاطبان و مشتریان"),
("staff_tickets:groups", "گروه‌های مخاطبان"),
("staff_tickets:contact_create", "ثبت مخاطب بیرونی"),
("staff_tickets:sms_templates", "الگوهای پیامک واحدها"),
("staff_tickets:dispatch_create", "ارسال گروهی ایزوله"),
("staff_tickets:magic_audit", "ممیزی لینک‌های جادویی"),
):
page.goto(f"{live_server.url}{reverse(route)}", wait_until="domcontentloaded")
expect(page.get_by_role("heading", name=heading, level=1)).to_be_visible()
expect(page.locator('link[href*="operations.css"]')).to_have_count(1)
assert page.evaluate("getComputedStyle(document.querySelector('.operations-page')).display") == "grid"
assert page.evaluate("document.documentElement.scrollWidth <= document.documentElement.clientWidth + 1")
page.goto(f"{live_server.url}{reverse('staff_tickets:dispatch_create')}", wait_until="domcontentloaded")
expect(page).to_have_title("ردیابی E2E")
expect(page.locator(".staff-brand-copy b")).to_have_text("مرکز عملیات E2E")
expect(page.locator(".staff-developer-credit")).to_contain_text("امضای مستقل sidebar E2E")
expect(page.get_by_role("searchbox", name="جستجو")).to_be_visible()
expect(page.locator('link[href*="dispatches.css"]')).to_have_count(1)
page.goto(f"{live_server.url}{reverse('staff_tickets:sms_templates')}", wait_until="domcontentloaded")
expect(page.get_by_text("الگوی عمومی سیستم").first).to_be_visible()
page.goto(f"{live_server.url}{reverse('staff_tickets:contact_create')}", wait_until="domcontentloaded")
province = page.locator('select[name="province"]')
city = page.locator('select[name="city"]')
expect(province.locator("option")).not_to_have_count(1)
province.select_option(label="اصفهان")
expect(city.locator("option", has_text="کاشان")).to_have_count(1)
page.goto(f"{live_server.url}{reverse('staff_tickets:contact_edit', args=[customer.public_id])}", wait_until="domcontentloaded")
first_group = page.locator(f'input[name="groups"][value="{group.pk}"]')
second_group = page.locator(f'input[name="groups"][value="{secondary_group.pk}"]')
expect(first_group).to_be_checked()
expect(second_group).not_to_be_checked()
second_group.check()
first_group.uncheck()
expect(page.locator("[data-group-selection-count]")).to_contain_text("۱")
page.get_by_role("button", name="ذخیره مخاطب").click()
page.wait_for_url(f"**{reverse('staff_tickets:contacts')}")
page.goto(f"{live_server.url}{reverse('staff_tickets:contact_edit', args=[customer.public_id])}", wait_until="domcontentloaded")
expect(page.locator(f'input[name="groups"][value="{group.pk}"]')).not_to_be_checked()
expect(page.locator(f'input[name="groups"][value="{secondary_group.pk}"]')).to_be_checked()
page.goto(f"{live_server.url}{reverse('staff_tickets:create')}", wait_until="domcontentloaded")
tiny_png = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=")
page.locator("#staff-ticket-gallery-input").set_input_files([
{"name": "first.png", "mimeType": "image/png", "buffer": tiny_png},
{"name": "second.png", "mimeType": "image/png", "buffer": tiny_png},
])
expect(page.locator("[data-file-preview] .file-chip")).to_have_count(2)
expect(page.locator("[data-file-preview] .file-chip img")).to_have_count(2)
page.locator("[data-file-preview] .file-chip button").first.click()
expect(page.locator("[data-file-preview] .file-chip")).to_have_count(1)
assert page.locator('input[name="files"]').evaluate("input => input.files.length") == 1