1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-01 13:47:06 +01:00
metamask-extension/shared/modules/i18n.test.ts
2023-06-20 13:44:11 +01:00

336 lines
9.1 KiB
TypeScript

import log from 'loglevel';
import {
FALLBACK_LOCALE,
I18NMessageDict,
clearCaches,
fetchLocale,
getMessage,
loadRelativeTimeFormatLocaleData,
} from './i18n';
const localeCodeMock = 'te';
const keyMock = 'testKey';
const errorLocaleMock = 'testLocaleError';
const errorMock = 'TestError';
jest.mock('loglevel');
jest.mock('./fetch-with-timeout', () =>
jest.fn(() => (url: string) => {
return Promise.resolve({
json: () => {
if (url.includes(errorLocaleMock)) {
throw new Error(errorMock);
}
return { url };
},
});
}),
);
describe('I18N Module', () => {
beforeEach(() => {
jest.resetAllMocks();
clearCaches();
process.env.IN_TEST = 'true';
});
describe('getMessage', () => {
describe('on error', () => {
it('returns null if no messages', () => {
expect(
getMessage(
localeCodeMock,
null as unknown as I18NMessageDict,
keyMock,
),
).toBeNull();
});
describe('if missing key', () => {
describe('if not using fallback locale', () => {
it('logs warning', () => {
expect(
getMessage(
localeCodeMock,
{} as unknown as I18NMessageDict,
keyMock,
),
).toBeNull();
expect(log.warn).toHaveBeenCalledTimes(1);
expect(log.warn).toHaveBeenCalledWith(
`Translator - Unable to find value of key "${keyMock}" for locale "${localeCodeMock}"`,
);
});
it('does not log warning if warning already created', () => {
expect(
getMessage(
localeCodeMock,
{} as unknown as I18NMessageDict,
keyMock,
),
).toBeNull();
expect(
getMessage(
localeCodeMock,
{} as unknown as I18NMessageDict,
keyMock,
),
).toBeNull();
expect(log.warn).toHaveBeenCalledTimes(1);
expect(log.warn).toHaveBeenCalledWith(
`Translator - Unable to find value of key "${keyMock}" for locale "${localeCodeMock}"`,
);
});
});
describe('if using fallback locale', () => {
it('logs error', () => {
delete process.env.IN_TEST;
expect(
getMessage(
FALLBACK_LOCALE,
{} as unknown as I18NMessageDict,
keyMock,
),
).toBeNull();
expect(log.error).toHaveBeenCalledTimes(1);
expect(log.error).toHaveBeenCalledWith(
new Error(
`Unable to find value of key "${keyMock}" for locale "${FALLBACK_LOCALE}"`,
),
);
});
it('throws if test env set', () => {
expect(() =>
getMessage(
FALLBACK_LOCALE,
{} as unknown as I18NMessageDict,
keyMock,
),
).toThrow(
`Unable to find value of key "${keyMock}" for locale "${FALLBACK_LOCALE}"`,
);
});
it('calls onError callback', () => {
const onErrorMock = jest.fn();
try {
getMessage(
FALLBACK_LOCALE,
{} as unknown as I18NMessageDict,
keyMock,
[],
onErrorMock,
);
} catch {
// Expected
}
expect(onErrorMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledWith(
new Error(
`Unable to find value of key "${keyMock}" for locale "${FALLBACK_LOCALE}"`,
),
);
});
it('does nothing if error already created', () => {
const onErrorMock = jest.fn();
try {
getMessage(
FALLBACK_LOCALE,
{} as unknown as I18NMessageDict,
keyMock,
[],
onErrorMock,
);
} catch {
// Expected
}
getMessage(
FALLBACK_LOCALE,
{} as unknown as I18NMessageDict,
keyMock,
[],
onErrorMock,
);
expect(log.error).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(1);
});
});
});
describe('if missing substitution', () => {
it('logs error', () => {
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1'],
),
).toStrictEqual('test1 a1 test2 test3');
expect(log.error).toHaveBeenCalledTimes(1);
expect(log.error).toHaveBeenCalledWith(
new Error(
`Insufficient number of substitutions for key "${keyMock}" with locale "${localeCodeMock}"`,
),
);
});
it('calls onError callback', () => {
const onErrorMock = jest.fn();
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1'],
onErrorMock,
),
).toStrictEqual('test1 a1 test2 test3');
expect(onErrorMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledWith(
new Error(
`Insufficient number of substitutions for key "${keyMock}" with locale "${localeCodeMock}"`,
),
);
});
it('does nothing if error already created', () => {
const onErrorMock = jest.fn();
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1'],
onErrorMock,
),
).toStrictEqual('test1 a1 test2 test3');
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1'],
onErrorMock,
),
).toStrictEqual('test1 a1 test2 test3');
expect(log.error).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(1);
});
});
});
it('returns text only if no substitutions', () => {
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'testValue' } },
keyMock,
),
).toStrictEqual('testValue');
});
it('returns text including substitutions', () => {
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1', 'b2'],
),
).toStrictEqual('test1 a1 test2 b2 test3');
});
it('returns text including substitutions using custom join', () => {
expect(
getMessage(
localeCodeMock,
{ [keyMock]: { message: 'test1 $1 test2 $2 test3' } },
keyMock,
['a1', 'b2'],
undefined,
(substitutions) => substitutions.join(','),
),
).toStrictEqual('test1 ,a1, test2 ,b2, test3');
});
});
describe('fetchLocale', () => {
it('returns json from locale file', async () => {
const result = await fetchLocale(localeCodeMock);
expect(result).toStrictEqual({
url: `./_locales/${localeCodeMock}/messages.json`,
});
});
it('logs if fetch fails', async () => {
await fetchLocale(errorLocaleMock);
expect(log.error).toHaveBeenCalledTimes(1);
expect(log.error).toHaveBeenCalledWith(
`failed to fetch testLocaleError locale because of Error: ${errorMock}`,
);
});
it('returns empty object if fetch fails', async () => {
expect(await fetchLocale(errorLocaleMock)).toStrictEqual({});
});
});
describe('loadRelativeTimeFormatLocaleData', () => {
it('adds locale data if function exists', async () => {
const addMock = jest.fn();
global.Intl = {
RelativeTimeFormat: {
__addLocaleData: addMock,
},
} as any;
await loadRelativeTimeFormatLocaleData(`${localeCodeMock}_test`);
expect(addMock).toHaveBeenCalledTimes(1);
expect(addMock).toHaveBeenCalledWith({
url: `./intl/${localeCodeMock}/relative-time-format-data.json`,
});
});
it('does not add locale data if language tag already processed', async () => {
const addMock = jest.fn();
global.Intl = {
RelativeTimeFormat: {
__addLocaleData: addMock,
},
} as any;
await loadRelativeTimeFormatLocaleData(`${localeCodeMock}_test`);
await loadRelativeTimeFormatLocaleData(`${localeCodeMock}_test`);
expect(addMock).toHaveBeenCalledTimes(1);
});
});
});