import re from html.parser import HTMLParser 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 ") 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 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']