test: remove v1 test, later need impl new ones

This commit is contained in:
2026-09-12 19:48:22 +05:00
parent 939038ffc0
commit dda5711a33
5 changed files with 1 additions and 324 deletions
+1 -50
View File
@@ -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");
}
});
});
});
-25
View File
@@ -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");
});
});
-96
View File
@@ -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");
});
});
-63
View File
@@ -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,
]),
};
}
-90
View File
@@ -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();
}
}
});
});