Add internal mix tag input for calculator and goal tree formulas
All checks were successful
Deploy Sokko G / deploy (push) Successful in 15s

This commit is contained in:
Shinuwa 2026-08-24 13:24:44 +02:00
parent 5c8148c905
commit ae503c7260
13 changed files with 929 additions and 23 deletions

View file

@ -3,6 +3,7 @@ import { test } from "node:test";
import assert from "node:assert/strict";
import { evaluateTableCell } from "../website/src/features/toolboxes/modules/tableFormulaEngine.js";
import { exportModuleText, importModuleText, parseColonImportLines } from "../website/src/features/toolboxes/modules/textImport.js";
import { buildInsertedMixTagValue, normalizeMixTagSpacing, normalizeMixTagText, removeMixTagAtOffset, tokenizeMixTagValue } from "../website/src/utils/mixTagsInputUtils.js";
import { calculateGoalTreeFormula, evaluateGoalTreeNodes } from "../website/src/features/toolboxes/modules/goalTreeUtils.js";
import { getTimePatternRecurrenceMs, getTimePatternTargetMs } from "../website/src/features/toolboxes/modules/timerUtils.js";
import { compactModuleDataForStorage, createToolboxExportPayload, normalizeCalculatorData, normalizeChecklistData, normalizeCombosData, normalizeCountersData, normalizeEquipmentPlannerData, normalizeGoalTreeData, normalizeImageAnnotationData, normalizeLinksData, normalizeModuleOrder, normalizeNotepadData, normalizeTableData, normalizeTaskPlannerData, normalizeTimerData, normalizeToolbox, normalizeUrl, summarizeEquipmentPlannerData } from "../website/src/features/toolboxes/storage/toolboxStorage.js";
@ -41,6 +42,35 @@ test("colon text import accepts labels without value", () => {
]);
});
test("mix tags input parses isolated token values only", () => {
const tokens = [{ value: "base", label: "Valeur du parent" }, { value: "loot", label: "Butin" }];
assert.deepEqual(tokenizeMixTagValue("base * 3", tokens).map((segment) => segment.type), ["token", "text"]);
assert.deepEqual(tokenizeMixTagValue("X - Base", tokens).map((segment) => segment.type), ["text", "token"]);
assert.deepEqual(tokenizeMixTagValue("database", tokens).map((segment) => ({ type: segment.type, text: segment.text })), [{ type: "text", text: "database" }]);
assert.deepEqual(tokenizeMixTagValue("base + loot", tokens).map((segment) => segment.type), ["token", "text", "token"]);
assert.deepEqual(tokenizeMixTagValue("", tokens), []);
assert.deepEqual(tokenizeMixTagValue("base * 2,5", tokens).map((segment) => segment.type), ["token", "text"]);
assert.equal(normalizeMixTagText("X - Base", tokens), "X - base");
assert.equal(normalizeMixTagText("database", tokens), "database");
assert.equal(normalizeMixTagSpacing(" 1 base + 2 "), "1 base + 2");
});
test("mix tags input insertion preserves formula spacing when requested", () => {
assert.deepEqual(buildInsertedMixTagValue("* 3", 0, 0, "base", { formulaSpacing: true }), { value: "base* 3", cursor: 4 });
assert.deepEqual(buildInsertedMixTagValue("2", 1, 1, "base", { formulaSpacing: true }), { value: "2 base", cursor: 6 });
assert.deepEqual(buildInsertedMixTagValue("2+3", 2, 2, "base", { formulaSpacing: true }), { value: "2+base 3", cursor: 7 });
assert.deepEqual(buildInsertedMixTagValue("2+old*3", 2, 5, "base", { formulaSpacing: true }), { value: "2+base*3", cursor: 6 });
assert.deepEqual(buildInsertedMixTagValue("route", 5, 5, "@item"), { value: "route@item", cursor: 10 });
});
test("mix tags input deletion removes the whole token", () => {
const tokens = [{ value: "base", label: "Valeur du parent" }];
assert.deepEqual(removeMixTagAtOffset("base * 3", 4, 4, tokens, "backward"), { value: " * 3", cursor: 0 });
assert.deepEqual(removeMixTagAtOffset("2 + base", 4, 4, tokens, "forward"), { value: "2 + ", cursor: 4 });
assert.deepEqual(removeMixTagAtOffset("2 + base * 3", 6, 8, tokens, "backward"), { value: "2 + * 3", cursor: 4 });
assert.equal(removeMixTagAtOffset("2 + 3", 5, 5, tokens, "backward"), null);
});
test("text exchange round trips simple toolbox modules and resets checklist progress", () => {
const context = createTextImportContext();
const notepad = normalizeNotepadData({