dana-medical-site/web/scripts/test-service-specialty.mjs

63 lines
5.0 KiB
JavaScript

// Fictional doctors only; no external network or appointment 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/detskaya-klinika/priem-detskogo-oftalmologa/');
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 { LeadModalProvider } = await vite.ssrLoadModule('/src/context/LeadModalContext.jsx');
const { serviceSpecialty } = await vite.ssrLoadModule('/src/lib/media.js');
const { renderService, renderPage } = await vite.ssrLoadModule('/src/entry-server.jsx');
const path = 'detskaya-klinika/priem-detskogo-oftalmologa';
const service = { id: 17, path, slug: 'priem-detskogo-oftalmologa', name: 'Тестовый детский офтальмолог', doctors: [], blocks: [], seo: {} };
const parent = { id: 1, path: 'detskaya-klinika', name: 'Детская клиника', children: [service], blocks: [], seo: {} };
const doctors = [
{ id: 1, slug: 'eye-test', full_name: 'Тестовый офтальмолог', last_name: 'Тестовый', first_name: 'Офтальмолог', position: 'Офтальмолог', specialties: [{ slug: 'oftalmologi', name: 'Офтальмологи', name_plural: 'Офтальмологи' }], booking: { provider: 'none' } },
{ id: 2, slug: 'uzi-test', full_name: 'Посторонний врач УЗИ', last_name: 'Посторонний', first_name: 'Врач', position: 'Врач УЗИ', specialties: [{ slug: 'detskie-vrachi', name: 'Детские врачи' }], booking: { provider: 'none' } },
];
const requested = [];
api.service = async (requestedPath) => ({ data: requestedPath === path ? service : parent });
api.prices = async () => ({ data: [] });
api.specialties = async () => ({ data: [{ slug: 'oftalmologi', name: 'Офтальмологи' }] });
api.doctors = async (params = {}) => {
requested.push(params.specialty);
return { data: doctors.filter((doctor) => !params.specialty || doctor.specialties.some((s) => s.slug === params.specialty)) };
};
api.bookingAvailability = async () => ({ data: { enabled: true, days: [] } });
api.createLead = api.createAppointment = () => { throw new Error('Submissions forbidden'); };
const container = document.getElementById('root');
const root = createRoot(container);
const click = async (node) => act(async () => node.dispatchEvent(new window.Event('click', { bubbles: true })));
try {
assert.equal(serviceSpecialty(path), 'oftalmologi');
assert.equal(serviceSpecialty('detskaya-klinika'), 'detskie-vrachi');
assert.equal(serviceSpecialty('oko'), 'oftalmologi');
assert.equal(serviceSpecialty('ginekologiya/test'), 'ginekologi');
assert.equal(serviceSpecialty('unknown/test'), undefined);
await act(async () => root.render(React.createElement(MemoryRouter, { initialEntries: [`/services/${path}/`] },
React.createElement(LeadModalProvider, {}, React.createElement(Routes, {}, React.createElement(Route, { path: '/services/*', element: React.createElement(ServicePage) }))))));
assert.match(container.querySelector('.service-doctors').textContent, /Тестовый офтальмолог/);
assert.doesNotMatch(container.querySelector('.service-doctors').textContent, /Посторонний/);
await click(container.querySelector('button.service-hero__btn'));
await click(container.querySelector('.doctor-picker__trigger'));
assert.deepEqual([...container.querySelectorAll('[data-doctor-id]')].map((node) => node.dataset.doctorId), ['1']);
assert.ok(requested.length >= 2);
assert.ok(requested.every((specialty) => specialty === 'oftalmologi'), 'Both service cards and booking must request ophthalmologists');
const common = { doctors, specialties: [], prices: [], site: { branches: [], addresses: [], phone: '', hours: '' } };
const server = renderService(service, parent, common, 'https://test.invalid');
assert.deepEqual(JSON.parse(server.initial)['doctors:oftalmologi'].data.map((d) => d.id), [1]);
const runtime = renderPage(`/services/${path}/`, { [`service:${path}`]: { data: service }, doctors: { data: doctors } }, 'https://test.invalid');
assert.deepEqual(JSON.parse(runtime.initial)['doctors:oftalmologi'].data.map((d) => d.id), [1]);
console.log('PASS: service doctor cards, booking picker, runtime SSR and prerender use the specific ophthalmology specialty');
} finally {
await act(async () => root.unmount());
await vite.close();
}