refactor(editor): Make the otel module descriptor import-light (no-changelog) (#37768)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Alex Grozav 2026-09-04 19:48:22 +00:00 committed by GitHub
parent 44d9d908b2
commit 909a6bc60a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 5 deletions

View File

@ -1,3 +1,4 @@
import { i18nInstance, setLanguage } from '@n8n/i18n';
import type { Scope } from '@n8n/permissions';
import { useRBACStore } from '@n8n/stores/rbac.store';
import { createPinia, setActivePinia } from 'pinia';
@ -51,6 +52,44 @@ describe('OtelModule', () => {
});
});
describe('label', () => {
const OTEL_LABEL_KEY = 'settings.opentelemetry';
afterEach(() => {
setLanguage('en');
});
it('should read the label from i18n', () => {
expect(settingsPage()?.label).toBe('OpenTelemetry');
});
it('should follow a language change after registration', () => {
const item = settingsPage();
expect(item?.label).toBe('OpenTelemetry');
// `Object.fromEntries`, because a dotted i18n key is not a lintable
// object-literal property name.
i18nInstance.global.mergeLocaleMessage(
'de',
Object.fromEntries([[OTEL_LABEL_KEY, 'OpenTelemetrie']]),
);
setLanguage('de');
expect(item?.label).toBe('OpenTelemetrie');
});
it('should read i18n lazily, not when the descriptor is imported', () => {
// The descriptor is imported by the shell manifest at boot, before `App.vue`
// calls `setLanguage`. A resolved string here would freeze the boot locale,
// and would put an i18n read at module scope — which the import-light rule
// for `*.module.ts` bans.
const descriptor = Object.getOwnPropertyDescriptor(settingsPage(), 'label');
expect(typeof descriptor?.get).toBe('function');
expect(descriptor?.value).toBeUndefined();
});
});
describe('route', () => {
it('should keep routing to the unchanged SettingsOpenTelemetryView route name', () => {
expect(OTEL_SETTINGS_VIEW).toBe('SettingsOpenTelemetryView');

View File

@ -4,8 +4,6 @@ import { useRBACStore } from '@n8n/stores/rbac.store';
import { OTEL_SETTINGS_VIEW } from './otel.constants';
const i18n = useI18n();
// typescript-eslint reads an SFC import as `any`, because only vue-tsc can type one.
// `pnpm turbo typecheck` is what checks this component for real.
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
@ -39,11 +37,11 @@ export const OtelModule: FrontendModuleDescription = {
{
id: 'settings-opentelemetry',
icon: 'telescope',
label: i18n.baseText('settings.opentelemetry'),
get label() {
return useI18n().baseText('settings.opentelemetry');
},
position: 'top',
route: { to: { name: OTEL_SETTINGS_VIEW } },
// Getter, not a value: the item is registered once at init, but the
// scope check must re-run whenever the sidebar recomputes.
get available() {
return useRBACStore().hasScope('otel:manage');
},