// Fictional service and doctors only; no production submissions. import assert from 'node:assert/strict'; import { parseHTML } from 'linkedom'; import { createServer } from 'vite'; const { window } = parseHTML('
'); Object.assign(globalThis, { window, document: window.document, HTMLElement: window.HTMLElement, IS_REACT_ACT_ENVIRONMENT: true }); window.location = new URL('https://test.invalid/services/stomatologiya/'); document.oninput = null; const { default: React, act } = await import('react'); const { createRoot } = await import('react-dom/client'); const { MemoryRouter, Routes, Route } = await import('react-router-dom'); const vite = await createServer({ server: { middlewareMode: true, hmr: false }, appType: 'custom' }); const { api } = await vite.ssrLoadModule('/src/api.js'); const { default: ServicePage } = await vite.ssrLoadModule('/src/pages/ServicePage.jsx'); const { default: ServicesPage } = await vite.ssrLoadModule('/src/pages/ServicesPage.jsx'); const { LeadModalProvider } = await vite.ssrLoadModule('/src/context/LeadModalContext.jsx'); const { renderService } = await vite.ssrLoadModule('/src/entry-server.jsx'); const { servicePriceSection, priceDirection } = await vite.ssrLoadModule('/src/lib/serviceNavigation.js'); const dentist = { id: 20, slug: 'test-dentist', full_name: 'Тестовый стоматолог', position: 'Детский стоматолог', specialties: [{ slug: 'detskie-vrachi', name: 'Детские врачи' }], booking: { provider: 'none' } }; const service = { id: 99, slug: 'stomatologiya', path: 'stomatologiya', name: 'Стоматология', doctors: [dentist], blocks: [], seo: {}, children: [] }; const prices = [{ id: 21, slug: 'stomatologiya', name: 'Стоматология', items: [{ id: 1, name: 'Тестовая консультация', price: 1000 }] }]; api.services = async () => ({ data: [service] }); api.service = async () => ({ data: service }); api.prices = async () => ({ data: prices }); api.branches = api.settings = async () => ({ data: [] }); api.bookingAvailability = async () => ({ data: { enabled: true, days: [] } }); api.doctors = () => { throw new Error('Dentistry must not load the whole pediatric catalog'); }; api.createLead = api.createAppointment = () => { throw new Error('Submissions forbidden'); }; const container = document.getElementById('root'); const root = createRoot(container); const click = async (node) => { assert.ok(node); await act(async () => node.dispatchEvent(new window.Event('click', { bubbles: true }))); }; try { assert.equal(servicePriceSection(service.path, prices).id, 21); assert.equal(priceDirection('stomatologiya', [service]).id, service.id); await act(async () => root.render(React.createElement(MemoryRouter, { key: 'list', initialEntries: ['/services/'] }, React.createElement(ServicesPage)))); assert.ok(container.querySelector('a[href="/services/stomatologiya/"]')); assert.ok(container.querySelector('.svc-tile__image img')); await act(async () => root.render(React.createElement(MemoryRouter, { key: 'detail', initialEntries: ['/services/stomatologiya/'] }, React.createElement(LeadModalProvider, {}, React.createElement(Routes, {}, React.createElement(Route, { path: '/services/*', element: React.createElement(ServicePage) })))))); assert.match(container.querySelector('h1').textContent, /Стоматология/); assert.ok(container.querySelector('.service-hero__image img')); assert.ok(container.querySelector('a[href="/price/stomatologiya/"]')); assert.match(container.querySelector('.service-doctors').textContent, /Тестовый стоматолог/); await click(container.querySelector('.service-hero__btn')); await click(container.querySelector('.doctor-picker__trigger')); assert.deepEqual([...container.querySelectorAll('[data-doctor-id]')].map((node) => node.dataset.doctorId), ['20']); const rendered = renderService(service, null, { doctors: [dentist], specialties: [], prices, site: { addresses: [], branches: [] } }, 'https://test.invalid'); assert.match(rendered.html, /Стоматология/); assert.match(rendered.html, /Тестовый стоматолог/); assert.match(rendered.html, /\/price\/stomatologiya\//); console.log('PASS: dentistry directory tile, styled service page, existing price links both ways, SSR and only the explicitly linked dentist in booking'); } finally { await act(async () => root.unmount()); await vite.close(); }