fix sms and ticket user frindly

This commit is contained in:
javad committed 2026-09-14 15:48:13 +03:30
1 parent 1ee83374fd
commit b8b3aba855
30 files changed
+2220 -119

No files matched your search

@@ -1,4 +1,5 @@
import io
import re
import pytest
from django.core.management import call_command
@@ -133,6 +134,8 @@ def test_e2e_subject_stays_empty_for_manual_and_search_routing_until_user_types(
with browser_page() as page:
form = open_form(page, live_server, customer)
subject_input = page.locator("[data-ticket-subject]")
page.locator(".ticket-manual-routing summary").click()
expect(form.unit).to_be_visible()
unit_box = form.unit.bounding_box()
category_box = form.category.bounding_box()
assert unit_box and category_box
@@ -159,6 +162,115 @@ def test_e2e_subject_stays_empty_for_manual_and_search_routing_until_user_types(
)
def test_e2e_customer_wizard_validation_preview_edit_and_floating_submit(
live_server, browser_page, public_workflow
):
customer, units, categories = public_workflow
subject = "بازبینی مرحله‌ای و ویرایش E2E"
with browser_page() as page:
page.set_viewport_size({"width": 390, "height": 640})
form = open_form(page, live_server, customer)
expect(page.locator('[data-wizard-step="1"]')).to_be_visible()
expect(page.locator('[data-wizard-step="2"]')).to_be_hidden()
expect(page.locator('[data-ticket-search-results]')).to_be_hidden()
page.locator('[data-wizard-step="1"] [data-wizard-next]').click()
error = page.locator('[data-wizard-error="1"]')
expect(error).to_be_visible()
expect(error).to_be_in_viewport()
expect(page.locator('[data-ticket-subject]')).to_have_attribute("aria-invalid", "true")
expect(form.category).to_be_visible()
assert page.evaluate("document.activeElement === document.querySelector('[data-wizard-error=\"1\"]')")
form.select_search_result("عمومی فروش", "عمومی فروش")
expect(page.locator('[data-ticket-subject]')).to_have_value("")
page.locator('[data-ticket-subject]').fill(subject)
expect(page.locator('[data-ticket-subject]')).to_have_value(subject)
page.locator('[data-wizard-step="1"] [data-wizard-next]').click()
page.locator('[data-wizard-step="2"] [data-wizard-next]').click()
page.locator('[data-wizard-step="3"] [data-wizard-next]').click()
page.locator('textarea[name="body"]').fill("شرح خوانا برای پیش‌نمایش مرحله پنجم")
page.locator('[data-wizard-step="4"] [data-wizard-next]').click()
expect(page.locator('[data-wizard-step="5"]')).to_be_visible()
expect(page.locator('[data-review-subject]')).to_have_text(subject)
expect(page.locator('[data-review-body]')).to_contain_text("شرح خوانا")
final_submit = page.get_by_role("button", name="ثبت و ارسال نهایی")
expect(final_submit).to_be_visible()
submit_box = final_submit.bounding_box()
assert submit_box and submit_box["y"] + submit_box["height"] <= page.viewport_size["height"]
assert page.locator('[data-review-subject]').evaluate("node => parseFloat(getComputedStyle(node).fontSize)") >= 16
assert page.locator('[data-review-body]').evaluate("node => parseFloat(getComputedStyle(node).fontSize)") >= 14
page.locator('[data-wizard-edit="1"]').click()
expect(page.locator('[data-ticket-subject]')).to_have_value(subject)
expect(page.locator('[data-ticket-unit]')).to_have_value(str(units["sales"].pk))
expect(page.locator('[data-ticket-category]')).to_have_value(str(categories["sales_general"].pk))
def test_e2e_customer_wizard_auto_stops_voice_and_submits_audio_only_ticket(
live_server, browser_page, public_workflow
):
customer, units, categories = public_workflow
subject = "ثبت تیکت فقط با پیام صوتی E2E"
with browser_page() as page:
page.add_init_script(
"""
window.__microphoneTrackStops = 0;
Object.defineProperty(navigator, 'mediaDevices', {
configurable: true,
value: {getUserMedia: async () => ({getTracks: () => [{stop: () => {window.__microphoneTrackStops += 1;}}]})},
});
class FakeMediaRecorder {
constructor(stream, options = {}) {this.stream = stream; this.mimeType = options.mimeType || 'audio/wav'; this.state = 'inactive';}
start() {this.state = 'recording';}
pause() {this.state = 'paused';}
resume() {this.state = 'recording';}
stop() {
this.state = 'inactive';
const wav = new Uint8Array([
82,73,70,70,40,0,0,0,87,65,86,69,102,109,116,32,
16,0,0,0,1,0,1,0,68,172,0,0,136,88,1,0,
2,0,16,0,100,97,116,97,4,0,0,0,0,0,0,0,
]);
this.ondataavailable?.({data: new Blob([wav], {type: this.mimeType})});
setTimeout(() => this.onstop?.(), 0);
}
static isTypeSupported(type) {return type === 'audio/wav';}
}
Object.defineProperty(window, 'MediaRecorder', {configurable: true, value: FakeMediaRecorder});
"""
)
form = open_form(page, live_server, customer)
form.select_unit(units["sales"].pk)
form.select_category(categories["sales_general"].pk)
form.select_general_queue()
page.locator('[data-ticket-subject]').fill(subject)
page.locator('[data-wizard-step="1"] [data-wizard-next]').click()
page.locator('[data-wizard-step="2"] [data-wizard-next]').click()
page.locator('[data-wizard-step="3"] [data-wizard-next]').click()
expect(page.locator('[data-wizard-step="4"]')).to_be_visible()
page.get_by_role("button", name="شروع ضبط صدا").click()
expect(page.locator('[data-voice-live]')).to_be_visible()
page.get_by_role("button", name="مشاهده پیش‌نمایش").click()
expect(page.locator('[data-wizard-step="5"]')).to_be_visible()
expect(page.locator('[data-review-audio]')).to_be_visible()
assert page.evaluate("window.__microphoneTrackStops") == 1
with page.expect_navigation(wait_until="domcontentloaded"):
page.get_by_role("button", name="ثبت و ارسال نهایی").click()
expect(page).to_have_url(re.compile(r"/tickets/(?!new/)[^/]+/$"))
ticket = Ticket.objects.get(subject=subject)
assert ticket.owning_unit == units["sales"]
assert ticket.category == categories["sales_general"]
attachments = list(ticket.ticket_messages.get().attachments.all())
assert len(attachments) == 1
assert attachments[0].mime_type.startswith("audio/")
assert attachments[0].original_name.startswith("voice-")
def test_e2e_experts_follow_configured_numeric_order(live_server, browser_page, public_workflow):
customer, units, _ = public_workflow
configured = {