From dda5711a331d43aff00481a1efcc0cfda983a8bc Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sat, 12 Sep 2026 19:48:22 +0500 Subject: [PATCH] test: remove v1 test, later need impl new ones --- web/src/lib/i18n/matching.test.ts | 51 +------------ web/src/lib/i18n/search-coverage.test.ts | 25 ------ web/src/lib/i18n/smoke-i18n.test.ts | 96 ------------------------ web/src/lib/i18n/tool-strings.ts | 63 ---------------- web/src/lib/i18n/tools-i18n.test.ts | 90 ---------------------- 5 files changed, 1 insertion(+), 324 deletions(-) delete mode 100644 web/src/lib/i18n/search-coverage.test.ts delete mode 100644 web/src/lib/i18n/smoke-i18n.test.ts delete mode 100644 web/src/lib/i18n/tool-strings.ts delete mode 100644 web/src/lib/i18n/tools-i18n.test.ts diff --git a/web/src/lib/i18n/matching.test.ts b/web/src/lib/i18n/matching.test.ts index 42a0c8f..924dc38 100644 --- a/web/src/lib/i18n/matching.test.ts +++ b/web/src/lib/i18n/matching.test.ts @@ -1,8 +1,5 @@ import { describe, expect, it } from "vitest"; -import { TOOLS } from "../v1/registry"; -import { setLocale } from "./locale.svelte"; import { normalizeForSearch, scoreDoc, type SearchDoc } from "./matching"; -import { toolSearchDoc } from "./tool-strings"; describe("normalizeForSearch", () => { it("нижний регистр", () => { @@ -52,50 +49,4 @@ describe("scoreDoc", () => { it("запрос с опечаткой ё/е всё равно находит", () => { expect(scoreDoc(doc, normalizeForSearch("повёрнут"))).not.toBeNull(); }); -}); - -describe("кросс-языковой поиск на реальном реестре", () => { - it("английский запрос находит инструмент при русской локали", () => { - setLocale("ru"); - const hits = TOOLS.filter((tool) => { - const s = scoreDoc(toolSearchDoc(tool), normalizeForSearch("rotate")); - return s !== null && s > 0; - }).map((tool) => tool.id); - expect(hits).toContain("rotate-png"); - expect(hits).toContain("rotate-free-png"); - }); - - it("русский запрос находит инструмент при английской локали", () => { - setLocale("en"); - try { - for (const q of ["повернуть", "пово"]) { - const hits = TOOLS.filter((tool) => { - const s = scoreDoc(toolSearchDoc(tool), normalizeForSearch(q)); - return s !== null && s > 0; - }).map((tool) => tool.id); - expect(hits, `запрос «${q}» при en-локали`).toContain("rotate-png"); - expect(hits, `запрос «${q}» при en-локали`).toContain( - "rotate-free-png", - ); - } - } finally { - setLocale("ru"); - } - }); - - it("поиск работает и по описанию, не только по названию", () => { - setLocale("en"); - try { - const hits = TOOLS.filter((tool) => { - const s = scoreDoc( - toolSearchDoc(tool), - normalizeForSearch("полупрозрачные"), - ); - return s !== null && s > 0; - }).map((tool) => tool.id); - expect(hits).toContain("png-is-transparent"); - } finally { - setLocale("ru"); - } - }); -}); +}); \ No newline at end of file diff --git a/web/src/lib/i18n/search-coverage.test.ts b/web/src/lib/i18n/search-coverage.test.ts deleted file mode 100644 index 214692b..0000000 --- a/web/src/lib/i18n/search-coverage.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { isChainable, TOOLS } from "../v1/registry"; -import { normalizeForSearch, scoreDoc } from "./matching"; -import { toolSearchDoc } from "./tool-strings"; - -function hits(q: string): string[] { - const nq = normalizeForSearch(q); - return TOOLS.filter((t) => { - const s = scoreDoc(toolSearchDoc(t), nq); - return s !== null && s > 0; - }).map((t) => t.id); -} - -describe("полнота поиска", () => { - it("генератор (не chainable) находится поиском — раньше отфильтровывался", () => { - expect(isChainable(TOOLS.find((t) => t.id === "color-wheel-png")!)).toBe( - false, - ); - expect(hits("color wheel")).toContain("color-wheel-png"); - }); - - it("анализатор-маска тоже ищется", () => { - expect(hits("уникальных цветов")).toContain("unique-color-mask-png"); - }); -}); diff --git a/web/src/lib/i18n/smoke-i18n.test.ts b/web/src/lib/i18n/smoke-i18n.test.ts deleted file mode 100644 index e4e11ba..0000000 --- a/web/src/lib/i18n/smoke-i18n.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; -import { TOOLS } from "../v1/registry"; -import { LOCALE_TAGS } from "./dict"; -import { setLocale } from "./locale.svelte"; -import { normalizeForSearch, scoreDoc } from "./matching"; -import { t } from "./t"; -import { toolSearchDoc } from "./tool-strings"; - -afterEach(() => { - setLocale("ru"); - vi.unstubAllGlobals(); -}); - -describe("Смоук §6 i18n", () => { - it("1. html lang следует за локалью", () => { - const doc = { documentElement: { lang: "" } }; - vi.stubGlobal("document", doc); - setLocale("en"); - expect(doc.documentElement.lang).toBe("en"); - setLocale("ru"); - expect(doc.documentElement.lang).toBe("ru"); - }); - - it("3. Ключевые секции переведены без смеси языков", () => { - const samples: Array<[string, string, string]> = [ - ["header.workspace", "Рабочая область", "Workspace"], - ["catalog.heading", "Каталог инструментов", "Tool catalog"], - [ - "home.heroTitle", - "Что делаем с изображением?", - "What do you want to do", - ], - ["chain.inputLegend", "Вход", "Input"], - ["resultCard.nextTool", "Следующий инструмент", "Next tool"], - ["download.busy", "Готовим файл", "Preparing file"], - ]; - for (const [key, ruPart, enPart] of samples) { - setLocale("ru"); - expect(t(key), key + " @ru").toContain(ruPart); - setLocale("en"); - expect(t(key), key + " @en").toContain(enPart); - } - }); - - it("5. Ошибки с vars локализуются на оба языка", () => { - setLocale("ru"); - expect(t("errors.badHex", { value: "#zz" })).toBe( - 'Некорректный HEX-цвет: "#zz"', - ); - expect(t("errors.toolNotFound", { id: "x" })).toContain("не найден"); - setLocale("en"); - expect(t("errors.badHex", { value: "#zz" })).toBe( - 'Invalid HEX color: "#zz"', - ); - }); - - it("6. Поиск кросс-языковой в обе стороны", () => { - const ids = (q: string) => - TOOLS.filter((tool) => { - const s = scoreDoc(toolSearchDoc(tool), normalizeForSearch(q)); - return s !== null && s > 0; - }).map((tool) => tool.id); - - setLocale("ru"); - let hits = ids("rotate"); - expect(hits).toContain("rotate-png"); - hits = ids("повер"); - expect(hits).toContain("rotate-png"); - - setLocale("en"); - hits = ids("пово"); - expect(hits).toContain("rotate-free-png"); - hits = ids("rotate"); - expect(hits).toContain("rotate-png"); - }); - - it("6b. Ё не мешает совпадению", () => { - const blackWhite = TOOLS.find((tool) => tool.id === "black-and-white-png")!; - setLocale("ru"); - const hit = scoreDoc( - toolSearchDoc(blackWhite), - normalizeForSearch("ЧЁРНО"), - ); - expect(hit).not.toBeNull(); - const withoutYo = scoreDoc( - toolSearchDoc(blackWhite), - normalizeForSearch("черно"), - ); - expect(withoutYo).not.toBeNull(); - }); - - it("7. Теги локалей для форматирования чисел корректны", () => { - expect(LOCALE_TAGS.ru).toBe("ru-RU"); - expect(LOCALE_TAGS.en).toBe("en-US"); - }); -}); diff --git a/web/src/lib/i18n/tool-strings.ts b/web/src/lib/i18n/tool-strings.ts deleted file mode 100644 index ffc66ac..0000000 --- a/web/src/lib/i18n/tool-strings.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { ParamDef, ToolEntry } from "$lib/v1/registry"; -import { getMergedDict } from "./locale.svelte"; -import type { SearchDoc } from "./matching"; -import { ru } from "./ru"; - -/** - * Строки инструмента на активной локали. - * Русский текст живёт в самом реестре (базовая локаль), - * переводы — в секции tools словарей; отсутствие ключа даёт фолбэк на реестр. - */ -export function toolTitle(tool: ToolEntry): string { - return getMergedDict().tools[tool.id]?.title ?? tool.title; -} - -export function toolDescription(tool: ToolEntry): string { - return getMergedDict().tools[tool.id]?.description ?? tool.description; -} - -export function paramLabel(tool: ToolEntry, param: ParamDef): string { - const viaDict = getMergedDict().tools[tool.id]?.params?.[param.id]; - if (viaDict) return viaDict; - const viaDef = param as { label?: string }; - return viaDef.label ?? param.id; -} - -export function optionLabel( - tool: ToolEntry, - param: ParamDef, - value: string, -): string { - const viaDict = getMergedDict().tools[tool.id]?.options?.[param.id]?.[value]; - if (viaDict) return viaDict; - if (param.type === "select") { - return param.options.find((o) => o.value === value)?.label ?? value; - } - return value; -} - -function dedupe(values: string[]): string[] { - return [...new Set(values.filter((v) => v.length > 0))]; -} - -/** - * Поисковый документ инструмента: строки активной локали, русского и английского - * (реестр) вместе — запрос находит инструмент по любому из языков независимо - * от того, какой сейчас включён. - */ -export function toolSearchDoc(tool: ToolEntry): SearchDoc { - const active = getMergedDict().tools[tool.id]; - return { - id: tool.id, - titles: dedupe([ - active?.title ?? "", - ru.tools[tool.id]?.title ?? "", - tool.title, - ]), - descriptions: dedupe([ - active?.description ?? "", - ru.tools[tool.id]?.description ?? "", - tool.description, - ]), - }; -} diff --git a/web/src/lib/i18n/tools-i18n.test.ts b/web/src/lib/i18n/tools-i18n.test.ts deleted file mode 100644 index 42e2fd5..0000000 --- a/web/src/lib/i18n/tools-i18n.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { TOOLS } from "../v1/registry"; -import { en } from "./en"; -import { ru } from "./ru"; - -describe("секция tools словарей покрывает реестр", () => { - it("у каждого инструмента есть перевод ru с непустыми title/description", () => { - for (const tool of TOOLS) { - const strings = ru.tools[tool.id]; - expect(strings, `нет перевода для ${tool.id}`).toBeDefined(); - expect(strings?.title, `${tool.id}: title`).toBeTruthy(); - expect(strings?.description, `${tool.id}: description`).toBeTruthy(); - } - }); - - it("переведены подписи всех параметров", () => { - for (const tool of TOOLS) { - const params = ru.tools[tool.id]?.params ?? {}; - for (const param of tool.params) { - const label = params[param.id]; - expect( - label, - `${tool.id}.${param.id}: нет перевода подписи`, - ).toBeDefined(); - expect(label?.length).toBeGreaterThan(0); - } - } - }); - - it("переведены подписи всех опций select", () => { - for (const tool of TOOLS) { - const options = ru.tools[tool.id]?.options ?? {}; - for (const param of tool.params) { - if (param.type !== "select") continue; - const labels = options[param.id] ?? {}; - for (const option of param.options) { - const label = labels[option.value]; - expect( - label, - `${tool.id}.${param.id}[${option.value}]: нет перевода`, - ).toBeDefined(); - expect(label.length).toBeGreaterThan(0); - } - } - } - }); - - it("в словарях нет лишних ключей инструментов и параметров", () => { - const ids = new Set(TOOLS.map((tool) => tool.id)); - for (const dict of [ru.tools, en.tools]) { - for (const id of Object.keys(dict)) { - expect(ids.has(id), `лишний инструмент в словаре: ${id}`).toBe(true); - const tool = TOOLS.find((t) => t.id === id)!; - const paramIds = new Set(tool.params.map((p) => p.id)); - for (const paramId of Object.keys(dict[id].params ?? {})) { - expect( - paramIds.has(paramId), - `${id}: лишний параметр ${paramId}`, - ).toBe(true); - } - const selectIds = new Set( - tool.params.filter((p) => p.type === "select").map((p) => p.id), - ); - for (const paramId of Object.keys(dict[id].options ?? {})) { - expect( - selectIds.has(paramId), - `${id}: options у не-select параметра ${paramId}`, - ).toBe(true); - } - } - } - }); - - it("тексты-результаты анализаторов переведены в обоих словарях", () => { - const expectations: Array<[string, string[]]> = [ - ["png-is-grayscale", ["grayscaleYes", "grayscaleNo"]], - ["png-is-transparent", ["transparentYes", "transparentNo"]], - [ - "png-orientation", - ["orientationPortrait", "orientationLandscape", "orientationSquare"], - ], - ]; - for (const [id, keys] of expectations) { - for (const key of keys) { - expect(en.tools[id]?.results?.[key], `${id}.${key} (en)`).toBeDefined(); - expect(ru.tools[id]?.results?.[key], `${id}.${key} (ru)`).toBeDefined(); - } - } - }); -});