56 lines
4.4 KiB
JavaScript
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();
|
|
}
|