Files
grafana/public/app/features/plugins/plugin_loader.test.ts
Hugo Häggmark 8a2af6166c i18n: adds @grafana/i18n package (#104603)
* i18n: adds grafana/i18n

* Trigger build

* chore: fix frontend lint

* chore: refactor

* chore: refactor

* chore: expose getI18nInstance in shared deps

* chore: refactors away second init

* Trigger build

* chore: updates after PR feedback

* chore: sync with enterprise

* chore: adds shouldUnescape

* Trigger build

* chore: makes functions internal

* Trigger build

* chore: fix for Pseudo locale

* chore: bumps package version

* chore: fix the version of i18n package
2025-05-09 05:45:20 +02:00

144 lines
5.1 KiB
TypeScript

import { i18n } from 'i18next';
import * as i18nModule from '@grafana/i18n/internal';
import { server } from './loader/pluginLoader.mock';
import { SystemJS } from './loader/systemjs';
import { SystemJSWithLoaderHooks } from './loader/types';
import { addTranslationsToI18n } from './plugin_loader';
describe('plugin_loader', () => {
describe('addTranslationsToI18n', () => {
const systemJSPrototype: SystemJSWithLoaderHooks = SystemJS.constructor.prototype;
const originalFetch = systemJSPrototype.fetch;
const originalResolve = systemJSPrototype.resolve;
let addResourceBundleSpy: jest.SpyInstance;
beforeAll(() => {
server.listen();
systemJSPrototype.resolve = (moduleId: string) => moduleId;
systemJSPrototype.shouldFetch = () => true;
// because server.listen() patches fetch, we need to reassign this to the systemJSPrototype
// this is identical to what happens in the original code: https://github.com/systemjs/systemjs/blob/main/src/features/fetch-load.js#L12
systemJSPrototype.fetch = window.fetch;
});
beforeEach(() => {
addResourceBundleSpy = jest
.spyOn(i18nModule, 'addResourceBundle')
.mockImplementation(() => ({}) as unknown as i18n);
});
afterEach(() => {
server.resetHandlers();
jest.clearAllMocks();
});
afterAll(() => {
SystemJS.constructor.prototype.resolve = originalResolve;
SystemJS.constructor.prototype.fetch = originalFetch;
server.close();
});
it('should add translations that match the resolved language first', async () => {
const translations = {
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
};
await addTranslationsToI18n({
resolvedLanguage: 'pt-BR',
fallbackLanguage: 'en-US',
pluginId: 'test-panel',
translations,
});
expect(addResourceBundleSpy).toHaveBeenCalledTimes(1);
expect(addResourceBundleSpy).toHaveBeenNthCalledWith(1, 'pt-BR', 'test-panel', { testKey: 'valorDeTeste' });
});
it('should add translations that match the fallback language if the resolved language is not in the translations', async () => {
const translations = {
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
};
await addTranslationsToI18n({
resolvedLanguage: 'sv-SE',
fallbackLanguage: 'en-US',
pluginId: 'test-panel',
translations,
});
expect(addResourceBundleSpy).toHaveBeenCalledTimes(1);
expect(addResourceBundleSpy).toHaveBeenNthCalledWith(1, 'en-US', 'test-panel', { testKey: 'testValue' });
});
it('should warn if no translations are found', async () => {
const translations = {
'en-US': '/public/plugins/test-panel/locales/en-US/test-panel.json',
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/test-panel.json',
};
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
await addTranslationsToI18n({
resolvedLanguage: 'sv-SE',
fallbackLanguage: 'sv-SE',
pluginId: 'test-panel',
translations,
});
expect(consoleSpy).toHaveBeenCalledWith('Could not find any translation for plugin test-panel', {
resolvedLanguage: 'sv-SE',
fallbackLanguage: 'sv-SE',
});
});
it('should warn if no exported default is found', async () => {
const translations = {
'en-US': '/public/plugins/test-panel/locales/en-US/no-default-export.json',
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/no-default-export.json',
};
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
await addTranslationsToI18n({
resolvedLanguage: 'en-US',
fallbackLanguage: 'en-US',
pluginId: 'test-panel',
translations,
});
expect(consoleSpy).toHaveBeenCalledWith('Could not find default export for plugin test-panel', {
resolvedLanguage: 'en-US',
fallbackLanguage: 'en-US',
path: '/public/plugins/test-panel/locales/en-US/no-default-export.json',
});
});
it('should warn if translations cannot be loaded', async () => {
const translations = {
'en-US': '/public/plugins/test-panel/locales/en-US/unknown.json',
'pt-BR': '/public/plugins/test-panel/locales/pt-BR/unknown.json',
};
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
await addTranslationsToI18n({
resolvedLanguage: 'en-US',
fallbackLanguage: 'pt-BR',
pluginId: 'test-panel',
translations,
});
expect(consoleSpy).toHaveBeenCalledWith('Could not load translation for plugin test-panel', {
resolvedLanguage: 'en-US',
fallbackLanguage: 'pt-BR',
error: new TypeError('Failed to fetch'),
path: '/public/plugins/test-panel/locales/en-US/unknown.json',
});
});
});
});