Answer stability round 1: 0 🔴, 4 🟡 (0 misread); own-key rename lookup, test the host translator, name both id kinds in the conflict, keep admin unreserved
This commit is contained in:
@@ -114,7 +114,7 @@ test("profile menu entries are gated like nav nodes, translated by their plugin
|
||||
assert.deepEqual(entries({ signedIn: false }).map((e) => e.label), []); // an anonymous visitor has no profile menu
|
||||
});
|
||||
|
||||
test("the central override hides and renames a profile-menu entry by its id, which is not rendered", () => {
|
||||
test("the central override hides and renames a profile-menu entry by its id; the host translates the new label", () => {
|
||||
const links = buildPluginChrome({
|
||||
menu: { ...DEFAULT_MENU, override: { hide: ["help"], rename: { settings: "Preferences" } } },
|
||||
plugins: [{
|
||||
@@ -122,9 +122,13 @@ test("the central override hides and renames a profile-menu entry by its id, whi
|
||||
profileMenu: [
|
||||
{ href: "/account/settings", id: "settings", label: "account.settings", session: true },
|
||||
{ href: "/account/help", id: "help", label: "Help", public: true },
|
||||
{ href: "/account/keys", id: "toString", label: "Keys", session: true },
|
||||
],
|
||||
}],
|
||||
t: (key) => `host:${key}`,
|
||||
translatorFor: () => (key) => `plugin:${key}`,
|
||||
user: { email: "ada@x.io", id: "u1", permissions: [] },
|
||||
}).user.profileLinks;
|
||||
assert.deepEqual(links, [{ href: "/account/settings", label: "Preferences" }]);
|
||||
// An id that names an Object.prototype member is renamed only when the override says so.
|
||||
assert.deepEqual(links, [{ href: "/account/settings", label: "host:Preferences" }, { href: "/account/keys", label: "plugin:Keys" }]);
|
||||
});
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ function profileLinks(opts: ChromeOptions, t: Translate, carryLocale: (href: str
|
||||
const pluginT = opts.translatorFor?.(plugin.id) ?? t;
|
||||
const shown = (plugin.profileMenu ?? []).filter((entry) => allows(entry, user) && !(entry.id != null && hide.includes(entry.id)));
|
||||
return shown.map((entry) => {
|
||||
const renamed = entry.id != null ? rename[entry.id] : undefined;
|
||||
const renamed = entry.id != null && Object.hasOwn(rename, entry.id) ? rename[entry.id] : undefined;
|
||||
return {
|
||||
href: carryLocale(entry.href),
|
||||
...(entry.icon != null ? { icon: entry.icon } : {}),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Central menu config: config/menu.ts lets an operator set branding (app name, logo,
|
||||
// default theme) and reorder/rename/group/hide nav nodes across all plugins. The reorder/rename/
|
||||
// default theme), reorder/rename/group/hide nav nodes and rename/hide profile-menu entries across
|
||||
// all plugins. The reorder/rename/
|
||||
// group/hide part is the NavOverride composeNav already applies (the override always wins, before
|
||||
// the per-user permission filter). Authored as TypeScript (defineMenu types it); loaded once at
|
||||
// boot — fail-loud on a malformed file, defaults when absent (clean clone needs no config).
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ export function composeNav(
|
||||
|
||||
function renameTree(nodes: NavNode[], rename: Record<string, string>): NavNode[] {
|
||||
return nodes.map((n) => {
|
||||
const renamed = n.id != null ? rename[n.id] : undefined;
|
||||
const renamed = n.id != null && Object.hasOwn(rename, n.id) ? rename[n.id] : undefined;
|
||||
return {
|
||||
...n,
|
||||
label: renamed != null ? renamed : n.label,
|
||||
|
||||
Reference in New Issue
Block a user