const baseUrl = process.env.SFERA_WEB_URL ?? "http://192.168.200.60:3000"; const projectId = process.env.SFERA_PROJECT_ID ?? "demo"; const routine = encodeURIComponent(process.env.SFERA_ROUTINE ?? "Проведение"); const attempts = Number(process.env.SFERA_SMOKE_ATTEMPTS ?? "5"); const checks = [ { name: "root opens IDE workspace", url: `${baseUrl}/?lang=ru&project=${projectId}`, mustInclude: [ "SFERA", "data-top-project-bar", "data-top-bar-logo", "data-top-bar-selector=\"workspace\"", "data-top-bar-selector=\"project\"", "data-top-bar-selector=\"environment\"", "data-top-bar-selector=\"active-task\"", "data-top-bar-action=\"project-settings\"", "data-top-bar-action=\"create-project\"", "data-top-bar-badge=\"api-status\"", "data-top-bar-badge=\"agent-status\"", "data-top-bar-language", "data-top-bar-button=\"profile\"", "Ctrl+K", "data-status-bar", "data-status-item=\"current-user\"" ], mustNotInclude: ["Открыть в редакторе"] }, { name: "root opens IDE workspace (en)", url: `${baseUrl}/?lang=en&project=${projectId}`, mustInclude: [ "SFERA", "data-top-project-bar", "data-top-bar-logo", "data-top-bar-selector=\"workspace\"", "data-top-bar-selector=\"project\"", "data-top-bar-selector=\"environment\"", "data-top-bar-selector=\"active-task\"", "data-top-bar-action=\"project-settings\"", "data-top-bar-action=\"create-project\"", "data-top-bar-badge=\"api-status\"", "data-top-bar-badge=\"agent-status\"", "data-top-bar-language", "data-top-bar-button=\"profile\"", "Ctrl+K", "data-status-bar", "data-status-item=\"current-user\"" ], mustNotInclude: ["Open in editor"] }, { name: "project settings route", url: `${baseUrl}/project-settings`, mustInclude: [ "Project Settings", "Import Center", "REFERENCE_CONFIGURATION", "Reference config", "data-import-action=\"REFERENCE_CONFIGURATION:import\"", "data-import-action=\"XML_DUMP:check\"", "data-settings-section=\"docker-runtime-adapter\"", "data-settings-section=\"its-documentation-access\"", "Пользователи и доступ", "Интеграции задач", "Docker/runtime adapter", "ITS/documentation access", "Audit", "Backup/restore", "SFERA_ITS_URL", "SFERA_ITS_USERNAME", "SFERA_ITS_PASSWORD", "https://its.1c.ru/db/v838doc#browse:13:-1:7", ".env.local", "<set locally>" ], mustNotInclude: ["Открыть в редакторе"] }, { name: "project settings route (en)", url: `${baseUrl}/project-settings?lang=en`, mustInclude: [ "Project Settings", "Import Center", "REFERENCE_CONFIGURATION", "Reference config", "data-import-action=\"REFERENCE_CONFIGURATION:import\"", "data-import-action=\"XML_DUMP:check\"", "data-settings-section=\"task-session-policy\"", "data-settings-section=\"docker-runtime-adapter\"", "data-settings-section=\"its-documentation-access\"", "Task/session policy", "Docker/runtime adapter", "ITS/documentation access", "Audit", "Backup/restore", "SFERA_ITS_URL", "SFERA_ITS_USERNAME", "SFERA_ITS_PASSWORD", ".env.local", "<set locally>" ], mustNotInclude: ["Open in editor"] }, { name: "module mode", url: `${baseUrl}/editor?lang=ru&project=${projectId}&mode=module&routine=${routine}`, mustInclude: ["data-ide-workspace", "data-left-navigation-panel", "data-right-context-inspector", "data-open-objects-bar", "data-open-document-pin", "data-open-document-close", "data-fallback-tree-search", "data-fallback-tree-filters", "Alt+1 Alt+2 Alt+3", "Редактор BSL", "Код модуля не загружен", "Выберите реальный модуль", "Основная конфигурация", "Расширение: <Имя>", "SFERA", "Среды"] }, { name: "form mode", url: `${baseUrl}/editor?lang=ru&project=${projectId}&mode=form&routine=${routine}`, mustInclude: ["Дизайнер формы", "Провести и закрыть", "Товары"] }, { name: "events mode", url: `${baseUrl}/editor?lang=ru&project=${projectId}&mode=events&routine=${routine}`, mustInclude: ["Инспектор событий", "ПриСозданииНаСервере", "ПередЗаписью"] }, { name: "learning mode", url: `${baseUrl}/editor?lang=ru&project=${projectId}&mode=learning&routine=${routine}`, mustInclude: ["Обучение", "переменные доступны", "стандарты команды"] } ]; for (const check of checks) { let lastError; for (let attempt = 1; attempt <= attempts; attempt += 1) { try { await runCheck(check); console.log(`ok ${check.name}`); lastError = undefined; break; } catch (error) { lastError = error; if (attempt < attempts) { await new Promise((resolve) => setTimeout(resolve, 1000)); } } } if (lastError) { throw lastError; } } async function runCheck(check) { const response = await fetch(check.url, { headers: { Accept: "text/html" } }); if (!response.ok) { throw new Error(`${check.name}: ${response.status} ${response.statusText}`); } const html = await response.text(); for (const expected of check.mustInclude ?? []) { if (!html.includes(expected)) { throw new Error(`${check.name}: missing "${expected}"`); } } for (const forbidden of check.mustNotInclude ?? []) { if (html.includes(forbidden)) { throw new Error(`${check.name}: unexpected "${forbidden}"`); } } }