153 lines
7.9 KiB
JavaScript
153 lines
7.9 KiB
JavaScript
import { chromium } from "playwright-core";
|
|
import { existsSync } from "node:fs";
|
|
|
|
const baseUrl = process.env.SFERA_WEB_URL ?? "http://localhost:3000";
|
|
const projectId = process.env.SFERA_PROJECT_ID ?? "default";
|
|
const browserPath =
|
|
process.env.SFERA_BROWSER_PATH ??
|
|
[
|
|
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe"
|
|
].find((path) => existsSync(path));
|
|
|
|
if (!browserPath) {
|
|
throw new Error("No installed Chrome or Edge browser found. Set SFERA_BROWSER_PATH.");
|
|
}
|
|
|
|
await prepareIndexedProject();
|
|
|
|
const runtimeErrors = [];
|
|
const browser = await chromium.launch({
|
|
executablePath: browserPath,
|
|
headless: true
|
|
});
|
|
|
|
try {
|
|
const page = await browser.newPage();
|
|
page.on("pageerror", (error) => {
|
|
runtimeErrors.push(`pageerror: ${error.message}`);
|
|
});
|
|
page.on("console", (message) => {
|
|
if (message.type() === "error") {
|
|
runtimeErrors.push(`console: ${message.text()}`);
|
|
}
|
|
});
|
|
|
|
const response = await page.goto(`${baseUrl}/project-settings`, { waitUntil: "load", timeout: 60000 });
|
|
if (!response?.ok()) {
|
|
throw new Error(`project setup smoke: ${response?.status()} ${response?.statusText()}`);
|
|
}
|
|
|
|
await page.locator("[data-project-import-center]").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByRole("heading", { name: "Project Settings" }).waitFor({ state: "visible", timeout: 15000 });
|
|
for (const section of ["Пользователи и доступ", "Интеграции задач", "Docker/runtime adapter", "Audit", "Backup/restore"]) {
|
|
await page.getByText(section).first().waitFor({ state: "visible", timeout: 15000 });
|
|
}
|
|
for (const sectionMarker of ["docker-runtime-adapter", "its-documentation-access"]) {
|
|
await page.locator(`[data-settings-section="${sectionMarker}"]`).waitFor({ state: "visible", timeout: 15000 });
|
|
}
|
|
await page.getByText("ITS/documentation access").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_URL").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_USERNAME").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_PASSWORD").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator("input[value*='its.1c.ru/db/v838doc']").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText(".env.local").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator("input[value='<set locally>']").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator("select").filter({ hasText: "REFERENCE_CONFIGURATION" }).first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByRole("button", { name: /Reference config/ }).waitFor({ state: "visible", timeout: 15000 });
|
|
const hasMetadataOnlyPrivacy = await page.locator("select").evaluateAll((selects) => {
|
|
return selects.some((select) => select.value === "METADATA_ONLY" || [...select.options].some((option) => option.value === "METADATA_ONLY"));
|
|
});
|
|
if (!hasMetadataOnlyPrivacy) {
|
|
throw new Error("project setup smoke: missing METADATA_ONLY privacy mode");
|
|
}
|
|
await page.getByText("Project Setup / Import Center").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("Режим работы с конфигурацией 1С").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator('[data-import-mode="FULL_REPLACE"]').waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator('[data-run-import-mode="SYNC_PREVIEW"]').click();
|
|
const importMode = await page.evaluate(() => window.localStorage.getItem("sfera.import.mode"));
|
|
if (importMode !== "SYNC_PREVIEW") {
|
|
throw new Error(`project setup smoke: import mode was not persisted, got ${importMode}`);
|
|
}
|
|
await page.locator('[data-run-import-mode="FULL_REPLACE"]').click();
|
|
await page.locator("[data-import-validation-panel]").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("Не заполнен путь к источнику").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator('input[placeholder*="/mnt/share/project"]').fill("/tmp/nonexistent-smoke-import");
|
|
await page.locator('[data-run-import-mode="FULL_REPLACE"]').click();
|
|
await page.getByText("Подтвердите полное обновление").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByRole("button", { name: "Отмена" }).click();
|
|
await page.locator('[data-run-import-mode="SYNC_PREVIEW"]').click();
|
|
await page.locator('[data-import-action="XML_DUMP:check"]').click();
|
|
await page.locator("[data-import-check-panel]").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("Source preflight").waitFor({ state: "visible", timeout: 15000 });
|
|
|
|
const englishResponse = await page.goto(`${baseUrl}/project-settings?lang=en`, { waitUntil: "load", timeout: 60000 });
|
|
if (!englishResponse?.ok()) {
|
|
throw new Error(`project setup smoke (en): ${englishResponse?.status()} ${englishResponse?.statusText()}`);
|
|
}
|
|
await page.getByRole("heading", { name: "Project Settings" }).waitFor({ state: "visible", timeout: 15000 });
|
|
for (const section of ["Task/session policy", "Docker/runtime adapter", "ITS/documentation access", "Audit", "Backup/restore"]) {
|
|
await page.getByText(section).first().waitFor({ state: "visible", timeout: 15000 });
|
|
}
|
|
for (const sectionMarker of ["task-session-policy", "docker-runtime-adapter", "its-documentation-access"]) {
|
|
await page.locator(`[data-settings-section="${sectionMarker}"]`).waitFor({ state: "visible", timeout: 15000 });
|
|
}
|
|
await page.locator("select").filter({ hasText: "REFERENCE_CONFIGURATION" }).first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByRole("button", { name: /Reference config/ }).waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_URL").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_USERNAME").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("SFERA_ITS_PASSWORD").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText(".env.local").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator("input[value='<set locally>']").first().waitFor({ state: "visible", timeout: 15000 });
|
|
await page.locator('[data-import-action="XML_DUMP:check"]').click();
|
|
await page.locator("[data-import-check-panel]").waitFor({ state: "visible", timeout: 15000 });
|
|
await page.getByText("Source preflight").waitFor({ state: "visible", timeout: 15000 });
|
|
|
|
assertNoFatalRuntimeErrors();
|
|
console.log("ok project setup runtime");
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
|
|
async function prepareIndexedProject() {
|
|
await postJson(`/api/sfera/projects/${encodeURIComponent(projectId)}/settings`, {
|
|
name: "SFERA Smoke Project",
|
|
structure_source: "XML_DUMP",
|
|
platform_version: "8.3.24",
|
|
compatibility_mode: "8.3.20"
|
|
});
|
|
await postJson(`/api/sfera/projects/${encodeURIComponent(projectId)}/imports/XML_DUMP`, {
|
|
source: "XML_DUMP",
|
|
metadata: {
|
|
platform_version: "8.3.24",
|
|
compatibility_mode: "8.3.20"
|
|
}
|
|
});
|
|
}
|
|
|
|
async function postJson(path, body) {
|
|
const response = await fetch(`${baseUrl}${path}`, {
|
|
method: "POST",
|
|
headers: { Accept: "application/json", "Content-Type": "application/json" },
|
|
body: JSON.stringify(body)
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error(`${path}: ${response.status} ${await response.text()}`);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
function assertNoFatalRuntimeErrors() {
|
|
const fatalErrors = runtimeErrors.filter((message) => {
|
|
return (
|
|
message.includes("Runtime TypeError") ||
|
|
message.includes("Cannot read properties") ||
|
|
message.includes("Unhandled Runtime Error")
|
|
);
|
|
});
|
|
if (fatalErrors.length > 0) {
|
|
throw new Error(`project setup runtime smoke failed:\n${fatalErrors.join("\n")}`);
|
|
}
|
|
}
|