2026-08-28 20:49:55 +02:00
|
|
|
import re
|
2026-11-03 01:16:12 +01:00
|
|
|
from html.parser import HTMLParser
|
2026-08-28 20:49:55 +02:00
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_customer_email_patterns_are_exact():
|
|
|
|
|
from app.customers.backend.router import _email_address_pattern, _email_domain_pattern
|
|
|
|
|
|
|
|
|
|
address = re.compile(_email_address_pattern("info@example.com"))
|
|
|
|
|
assert address.search("Info <info@example.com>")
|
|
|
|
|
assert not address.search("otherinfo@example.com")
|
|
|
|
|
|
|
|
|
|
domain = re.compile(_email_domain_pattern("example.com"))
|
|
|
|
|
assert domain.search("person@example.com")
|
|
|
|
|
assert not domain.search("person@example.com.evil.test")
|
|
|
|
|
assert not domain.search("person@notexample.com")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_customer_detail_exposes_email_tab_and_supplier_service_checkbox():
|
|
|
|
|
template = Path("app/customers/frontend/customer_detail.html").read_text(encoding="utf-8")
|
|
|
|
|
assert 'href="#emails"' in template
|
|
|
|
|
assert 'id="supplierServiceEnrolled"' in template
|
|
|
|
|
assert "supplier_service_enrolled: checkbox.checked" in template
|
|
|
|
|
assert "/emails?limit=${customerEmailsLimit}" in template
|
2026-11-03 01:16:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_customer_detail_tab_links_work_without_bootstrap_and_keep_deep_links():
|
|
|
|
|
template = Path("app/customers/frontend/customer_detail.html").read_text(encoding="utf-8")
|
|
|
|
|
|
|
|
|
|
assert "function initialiseCustomerTabs()" in template
|
|
|
|
|
assert "function activateCustomerTab(tab" in template
|
|
|
|
|
assert "event.stopImmediatePropagation();" in template
|
|
|
|
|
assert "tab.dispatchEvent(new Event('shown.bs.tab'));" in template
|
|
|
|
|
assert "showCustomerTab(tab)" in template
|
|
|
|
|
assert "window.addEventListener('hashchange', openHashTab)" in template
|
|
|
|
|
assert "history.replaceState(null, '', `${window.location.pathname}${window.location.search}${hash}`)" in template
|
|
|
|
|
assert 'id="customerTabContent"' in template
|
|
|
|
|
assert "#customerTabContent > .tab-pane {" in template
|
|
|
|
|
assert "#customerTabContent > .tab-pane.active {" in template
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_rendered_customer_tabs_keep_content_inside_the_correct_pane():
|
|
|
|
|
from jinja2 import Environment, FileSystemLoader
|
|
|
|
|
|
|
|
|
|
class DivTree(HTMLParser):
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.stack = []
|
|
|
|
|
self.nodes = {}
|
|
|
|
|
|
|
|
|
|
def handle_starttag(self, tag, attrs):
|
|
|
|
|
attrs = dict(attrs)
|
|
|
|
|
if attrs.get('id'):
|
|
|
|
|
self.nodes[attrs['id']] = list(self.stack)
|
|
|
|
|
if tag == 'div':
|
|
|
|
|
self.stack.append(attrs.get('id'))
|
|
|
|
|
|
|
|
|
|
def handle_endtag(self, tag):
|
|
|
|
|
if tag == 'div' and self.stack:
|
|
|
|
|
self.stack.pop()
|
|
|
|
|
|
|
|
|
|
source = Path('app/customers/frontend/customer_detail.html').read_text()
|
|
|
|
|
content = source.split('{% block content %}', 1)[1].split('{% endblock %}', 1)[0]
|
|
|
|
|
rendered = Environment(loader=FileSystemLoader('app')).from_string(content).render(customer_id=1)
|
|
|
|
|
tree = DivTree()
|
|
|
|
|
tree.feed(rendered)
|
|
|
|
|
targets = re.findall(r'data-bs-toggle="tab" href="#([^"]+)"', rendered)
|
|
|
|
|
assert len(targets) == 20
|
|
|
|
|
for target in targets:
|
|
|
|
|
assert tree.nodes[target][-1] == 'customerTabContent', target
|
|
|
|
|
for element in ['contactsContainer', 'contactsSearchInput', 'contactsResultCount']:
|
|
|
|
|
assert 'contacts' in tree.nodes[element], element
|
|
|
|
|
assert 'cases' in tree.nodes['customerCasesContainer']
|
|
|
|
|
assert 'kontakt' in tree.nodes['customerKontaktContainer']
|