dana-medical-site/web/scripts/test-dentistry.mjs

56 lines
4.4 KiB
JavaScript

// 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('<html><body><div id="root"></div></body></html>');
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();
}