Release govoplan-views v0.1.22: unify interface contracts and documentation
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import vm from "node:vm";
|
||||
|
||||
const require = createRequire(new URL("../../../govoplan-core/webui/package.json", import.meta.url));
|
||||
const ts = require("typescript");
|
||||
const read = (path) => readFileSync(new URL(path, import.meta.url), "utf8");
|
||||
const plain = (value) => JSON.parse(JSON.stringify(value));
|
||||
|
||||
function evaluate(source, fileName) {
|
||||
const exports = {};
|
||||
const compiled = ts.transpileModule(source, {
|
||||
fileName,
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX }
|
||||
}).outputText;
|
||||
vm.runInNewContext(compiled, { exports, require: () => ({}) }, { filename: fileName });
|
||||
return exports;
|
||||
}
|
||||
|
||||
const api = evaluate(read("../src/api/views.ts"), "views.ts");
|
||||
const admin = read("../src/features/views/ViewsAdminPanel.tsx");
|
||||
// Exercise the real private revision/dirty-state functions without mounting or making API calls.
|
||||
const helpers = evaluate(`${admin}\nexport { revisionPresentation, presentationKey };`, "ViewsAdminPanel.tsx");
|
||||
const layout = {
|
||||
contract_version: "1",
|
||||
order: ["separator:work", "files.nav.files", "tasks.nav.tasks"],
|
||||
hidden: ["mail.nav.mail"],
|
||||
locked: [],
|
||||
separators: [{ id: "separator:work", label: "Meine Arbeit" }]
|
||||
};
|
||||
for (const navigation of [null, layout, { ...layout, separators: [] }, { contract_version: "1", order: [], hidden: [] }]) {
|
||||
const presentation = { navigation, navigationMode: "grouped" };
|
||||
const wire = api.presentationToApi(presentation);
|
||||
assert.deepEqual(plain(api.presentationFromApi(wire).navigation), navigation, "Effective API projection preserves null, inherited groups, explicit flat, labels and ordered entries");
|
||||
const revision = helpers.revisionPresentation(wire, []);
|
||||
assert.deepEqual(plain(revision.navigation), navigation, "Opening a saved revision preserves its navigation preferences");
|
||||
assert.equal(helpers.presentationKey(revision), helpers.presentationKey(presentation), "Round-trip does not invent dirty state");
|
||||
}
|
||||
assert.equal(helpers.revisionPresentation(undefined, []).navigation, null, "Legacy revisions inherit navigation");
|
||||
const saved = helpers.presentationKey({ navigation: layout });
|
||||
for (const changed of [
|
||||
{ ...layout, order: [...layout.order].reverse() },
|
||||
{ ...layout, hidden: [] },
|
||||
{ ...layout, separators: [] },
|
||||
{ ...layout, separators: [{ ...layout.separators[0], label: "Changed" }] },
|
||||
null
|
||||
]) {
|
||||
assert.notEqual(helpers.presentationKey({ navigation: changed }), saved, "Every navigation edit or inheritance reset participates in Save/dirty guards");
|
||||
}
|
||||
assert.match(admin, /<NavigationPreferenceEditor\s+scope="view"/);
|
||||
assert.ok(admin.includes("configurableNavigationItemsForModules(modules)"));
|
||||
assert.ok(admin.includes("productAreas={navigationProductAreas}"));
|
||||
assert.ok(admin.includes("disabled={disabled || customNavigation}"), "Conflicting legacy layout controls disable while custom navigation is configured");
|
||||
assert.ok(admin.includes("disabled={disabled || required}"), "Surface visibility remains separate from navigation ordering");
|
||||
for (const key of ["navigation_editor_help", "product_areas_custom_navigation_help"]) {
|
||||
assert.equal(read("../src/i18n/generatedTranslations.ts").split(`"i18n:govoplan-views.${key}":`).length - 1, 2, "Shared layout guidance has English and German text");
|
||||
}
|
||||
console.log("Views shared navigation revision, inheritance, API and dirty-state contract passed.");
|
||||
Reference in New Issue
Block a user